{"version":3,"file":"grokkoli/static/js/build/common_manipulatives.js","mappings":"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","sources":["webpack:///./js/src/question/manipulatives/baseTenBlocks.ts","webpack:///./js/src/question/manipulatives/baseTenBlocksSlot.ts","webpack:///./js/src/question/manipulatives/baseTenBlocksControl.ts","webpack:///./js/src/question/manipulatives/baseTenBlocksMenu.ts","webpack:///./js/src/question/manipulatives/linearBlocks.ts","webpack:///./js/src/question/manipulatives/linearBlocksControl.ts","webpack:///./js/src/question/manipulatives/linearBlocksMenu.ts","webpack:///./js/src/question/manipulatives/linearBlocksSlot.ts","webpack:///./js/src/question/manipulatives/tile.ts","webpack:///./js/src/question/manipulatives/tileSlot.ts","webpack:///./js/src/question/manipulatives/simpleBlock.ts","webpack:///./js/src/question/manipulatives/simpleBlockSlot.ts","webpack:///./js/src/question/manipulatives/simpleBlockFillSlot.ts","webpack:///./js/src/question/manipulatives/numberline.ts","webpack:///./js/src/question/manipulatives/hop.ts","webpack:///./js/src/question/manipulatives/selectorControl.ts","webpack:///./js/src/question/manipulatives/trash.ts","webpack:///./js/src/question/manipulatives/timesTable.ts","webpack:///./js/src/question/manipulatives/rekenrek.ts","webpack:///./js/src/question/manipulatives/clock.ts","webpack:///./js/src/question/manipulatives/entryField.ts","webpack:///./js/src/question/manipulatives/rekenrekControl.ts","webpack:///./js/src/question/manipulatives/rekenrekMenu.ts","webpack:///./js/src/question/manipulatives/timesTableControl.ts","webpack:///./js/src/question/manipulatives/timesTableMenu.ts","webpack:///./js/src/question/manipulatives/trashControl.ts","webpack:///./js/src/question/manipulatives/customSlot.ts","webpack:///./js/src/question/manipulatives/templateManipulative.ts","webpack:///./js/src/question/manipulatives/poly.ts","webpack:///./js/src/question/manipulatives/lineManipulative.ts","webpack:///./js/src/question/manipulatives/splittableShape.ts","webpack:///./js/src/question/manipulatives/solid3d.ts","webpack:///./js/src/question/manipulatives/cube.ts","webpack:///./js/src/question/manipulatives/cylinder.ts","webpack:///./js/src/question/manipulatives/cone.ts","webpack:///./js/src/question/manipulatives/sphere.ts","webpack:///./js/src/question/manipulatives/pyramid.ts","webpack:///./js/src/question/manipulatives/prism.ts","webpack:///./js/src/question/manipulatives/patternBlocks.ts","webpack:///./js/src/question/manipulatives/patternBlocksSlot.ts","webpack:///./js/src/question/manipulatives/htmlRuler.ts","webpack:///./js/src/question/manipulatives/addManipulative.ts","webpack:///./js/src/question/manipulatives/addPalette.tsx","webpack:///./js/src/question/manipulatives/answerContainer.ts","webpack:///./js/src/question/manipulatives/answerInput.ts","webpack:///./js/src/question/manipulatives/manage.ts","webpack:///./js/src/question/manipulatives/selector.ts","webpack:///./js/src/question/manipulatives/snapGrid.ts","webpack:///./js/src/question/manipulatives/tools.ts"],"sourcesContent":["import { snapPointToPoint } from '../tools/snap';\nimport { setupManipulative, incrementManipulativeIndex, getManipulativeIndex, checkAnswerContainers, highlightAnswerContainer, removeFromContainer, getAllBaseTenBlocksSlots, suppressManipulativeTouch, releaseManipulativeTouch, POOL_PARK_POSITION, } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\nimport { darken, lighten } from '../tools/color';\nimport { getManipulatives, getSelectedSelector } from './manage';\n// Decimal places computeState() serializes a position to. Anything comparing a\n// live position against a saved one has to round to the same precision first --\n// a raw position and its saved form differ by up to 5e-4 per axis, which is\n// enough to make an untouched block look moved.\nvar STATE_POSITION_PRECISION = 3;\n// True if `live` serializes to the same position as the already-saved `saved`.\n// Both sides are rounded so the comparison holds whichever one has been through\n// computeState().\nfunction samePositionAsSaved(live, saved) {\n    var a = Fig.parsePoint(live);\n    var b = Fig.parsePoint(saved);\n    return Fig.round(a.x, STATE_POSITION_PRECISION)\n        === Fig.round(b.x, STATE_POSITION_PRECISION)\n        && Fig.round(a.y, STATE_POSITION_PRECISION)\n            === Fig.round(b.y, STATE_POSITION_PRECISION);\n}\nfunction createBaseTenBlocks(fig, eqn_name, toElement, o, boundMove) {\n    var newO = Fig.joinObjects({}, o, {\n        name: \"\".concat(o.name, \"_\").concat(getManipulativeIndex('baseTenBlocks', o.n)),\n        scale: o.createScale,\n        fromPalette: true,\n        boundMove: boundMove,\n    });\n    // element.custom.count += 1;\n    var to = toElement;\n    if (to == null) {\n        to = eqn_name;\n    }\n    return baseTenBlocks(to, newO, fig);\n}\nvar baseTenBlocks = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    // const BLOCK_COLORS: { [num: number]: [number, number, number, number] } = {\n    //   100: [0, 0.478, 0.823, 0.95],\n    //   10: [0, 0.478, 0.823, 0.95],\n    //   1: [0, 0.478, 0.823, 0.95],\n    //   // 10: [0.682, 0.831, 0.756, 0.95],\n    //   // 1: [0.274, 0.114, 0, 0.95],\n    // };\n    // const HIGHLIGHT_BLOCK_COLORS: {\n    //   [num: number]: [number, number, number, number];\n    // } = {\n    //   100: [0, 0.278, 0.623, 0.95],\n    //   10: [0, 0.278, 0.623, 0.95],\n    //   1: [0, 0.278, 0.623, 0.95],\n    // };\n    var o = Fig.joinObjects({\n        size: 0.1,\n        scale: 1,\n        color: [0, 0.478, 0.823, 0.95],\n        // colorHighlight: [0, 0.478, 0.823, 0.8],\n        // colorDim: null,\n        // colorHighlight: [0, 0.278, 0.623, 0.95],\n        // colorDim: [0, 0.478, 0.823, 0.2],\n        line: true,\n        createScale: 1,\n        createdFrom: null,\n        xAlign: 'center',\n        appear: 'left',\n        orientation: 'h',\n        border: true,\n        canRotate: true,\n        yAlign: 'bottom',\n        yOffset: 0,\n        fromPalette: false,\n        preserveChildColor: true,\n        isSelectable: false,\n        isTouchable: true,\n        snap: false,\n        selectLine: {\n            width: 0.02,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            space: 0.04,\n        },\n        debug: false,\n        boundMove: true,\n        returnToInitial: false,\n        maxBreaks: {\n            10: 4,\n            100: 4,\n            1000: 4,\n        },\n        maxBreaksTotal: 4,\n        radius: null,\n    }, options);\n    // 3D blocks overlap one another (diagonal stacks, drag-overs); the default\n    // fill's 0.95 alpha would let the block behind show through. When no explicit\n    // color is supplied, make the default fully opaque for 3D blocks. This must\n    // run before `color` is destructured and the face fills are derived so they\n    // all inherit the opaque alpha. An explicit color is left as the caller set\n    // it. Mirrors the dimension default computed below (`is3D`).\n    var willRender3D = (o.dimension != null ? o.dimension : o.n >= 1000 ? 3 : 2) === 3;\n    if (willRender3D && options.color == null) {\n        o.color = [o.color[0], o.color[1], o.color[2], 1];\n    }\n    var name = o.name, color = o.color, n = o.n, size = o.size, scale = o.scale, position = o.position, xAlign = o.xAlign, canRotate = o.canRotate, yOffset = o.yOffset, yAlign = o.yAlign;\n    // Normalize border option: boolean or { width, color, highlight, dim }\n    var borderEnabled = o.border !== false && o.border != null;\n    var borderOpts = typeof o.border === 'object' && o.border !== null ? o.border : {};\n    // Normalize line option: boolean or { width, color, highlight, dim }\n    var lineEnabled = o.line !== false && o.line != null;\n    var lineOpts = typeof o.line === 'object' && o.line !== null ? o.line : {};\n    var lineWidth = lineOpts.width != null ? lineOpts.width : 0.003;\n    var lineColor = lineOpts.color != null ? lineOpts.color : [1, 1, 1, 1];\n    var s = size * scale;\n    var orientation = n == 10 ? o.orientation : 'h';\n    // Inset spacing for fill/border rectangles (preserves original 0.01 * scale)\n    var line = 0.01 * scale;\n    var width = s;\n    var height = s;\n    if (n > 1) {\n        width = s * 10;\n    }\n    if (n > 10) {\n        height = s * 10;\n    }\n    // Render dimension: 2 = flat, 3 = oblique (cavalier-style) projection with the\n    // depth receding up and to the right. Defaults to 3 for the thousand-cube and\n    // 2 for the smaller blocks, but is overridable so a 1/10/100 can be drawn in\n    // 3D to sit consistently beside a cube.\n    var dimension = o.dimension != null ? o.dimension : n >= 1000 ? 3 : 2;\n    var is3D = dimension === 3;\n    // Cells of depth in the base-ten solid: a 1 is 1×1×1, a 10 is 10×1×1, a 100\n    // is 10×10×1, and a 1000 is 10×10×10 — so depth is 1 cell for 1/10/100 and 10\n    // cells for the cube. `depth` is the total oblique offset of the back face\n    // from the front, applied equally in x and y for a 45° recession.\n    var depthCells = n >= 1000 ? 10 : 1;\n    var depth = is3D ? depthCells * s * 0.25 : 0;\n    // For vertical n=10 blocks, the visual height is `width` (the long\n    // dimension). For a 3D block, the visible top extends up by `depth`.\n    var visualHeight = (orientation === 'v' ? width : height) + depth;\n    var yBorderDelta = 0;\n    if (yAlign === 'middle') {\n        yBorderDelta -= visualHeight / 2;\n    }\n    else if (yAlign === 'top') {\n        yBorderDelta -= visualHeight;\n    }\n    // if (o.colorDim == null) {\n    //   o.colorDim = [...o.color];\n    //   for (let i = 0; i < o.color.length - 1; i += 1) {\n    //     o.colorDim[i] = Math.min(o.color[i] * 2, 1);\n    //   }\n    // }\n    if (o.colorHighlight == null) {\n        o.colorHighlight = darken(o.color);\n    }\n    if (o.colorDim == null) {\n        // o.colorDim = desaturate(o.color, 0.8);\n        o.colorDim = [0.8, 0.8, 0.8, 1];\n    }\n    yBorderDelta += yOffset;\n    var hBorder = [\n        [\n            new Fig.Point(0, 0 + yBorderDelta),\n            new Fig.Point(width, 0 + yBorderDelta),\n            new Fig.Point(width, height + yBorderDelta),\n            new Fig.Point(0, height + yBorderDelta),\n        ],\n    ];\n    var vBorder = [\n        [\n            new Fig.Point(0, 0 + yBorderDelta),\n            new Fig.Point(height, 0 + yBorderDelta),\n            new Fig.Point(height, width + yBorderDelta),\n            new Fig.Point(0, width + yBorderDelta),\n        ],\n    ];\n    // Hexagonal silhouette of the oblique 3D solid (front face plus the visible\n    // top and right faces), used for move bounds and the bounding rect. The depth\n    // always recedes up and to the right on screen, so the silhouette uses the\n    // on-screen front-face footprint (width/height swap for a vertical ten).\n    var fw = orientation === 'v' ? height : width;\n    var fh = orientation === 'v' ? width : height;\n    var cubeBorder = [\n        [\n            new Fig.Point(0, 0 + yBorderDelta),\n            new Fig.Point(fw, 0 + yBorderDelta),\n            new Fig.Point(fw + depth, depth + yBorderDelta),\n            new Fig.Point(fw + depth, fh + depth + yBorderDelta),\n            new Fig.Point(depth, fh + depth + yBorderDelta),\n            new Fig.Point(0, fh + yBorderDelta),\n        ],\n    ];\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n        border: is3D ? cubeBorder : orientation === 'h' ? hBorder : vBorder,\n    });\n    element.custom.s = s;\n    element.custom.n = n;\n    // Expose render dimension so slots/layouts can adapt (e.g. a 3D block's\n    // diagonal stack recedes up-and-right and draws back-to-front).\n    element.custom.dimension = dimension;\n    element.custom.is3D = is3D;\n    element.notificationHelper = new NotificationHelper();\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [s / 2, s / 2 + yBorderDelta],\n    });\n    if (orientation === 'v') {\n        container.setRotation(Math.PI / 2);\n    }\n    var block = container.add({\n        name: 'block',\n        make: 'collection',\n        position: [-s / 2 + line / 2, -s / 2 + line / 2],\n    });\n    var radius = s * 0.2;\n    if (o.radius != null) {\n        radius = o.radius;\n    }\n    else if (is3D) {\n        // Sharp corners read better as a cube; the faces meet at crisp edges.\n        radius = 0;\n    }\n    var frontRect = block.add({\n        name: \"block\",\n        make: 'rectangle',\n        width: width - line,\n        height: height - line,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        corner: {\n            radius: radius,\n            sides: 10,\n        },\n        position: [0, 0],\n        color: o.color,\n    });\n    // Border styling, derived once and shared by the front-face `borderLine`\n    // (added below) and the cube's back/depth edges (added in the block below).\n    var borderWidth = borderOpts.width != null ? borderOpts.width : 0.003;\n    var borderColor = borderOpts.color != null ? borderOpts.color : [0.2, 0.2, 0.2, 1];\n    // ── 3D block faces ─────────────────────────────────────────────────\n    // The front face is `frontRect` above. Here we add the visible top and right\n    // faces as oblique parallelograms, their grid lines, and the back/depth\n    // edges. All are added to `block` so they move and are touchable with the\n    // front face. Face fills are shaded (top lighter, right darker) for a 3D\n    // read, and each face's grid lines are shaded to match; `shade3D` re-applies\n    // the fill shading so highlight()/dim() keep the block looking dimensional. Works for any solid: a 1 (1×1×1 cube), 10 (rod), 100\n    // (slab), or 1000 (cube) — the cell counts below drive how each face grids.\n    var topFace;\n    var rightFace;\n    var shade3D = null;\n    if (is3D) {\n        var W = width - line; // front face width (block-local)\n        var H = height - line; // front face height (block-local)\n        // Oblique depth vector. It must read as \"up and to the right\" on screen.\n        // A vertical ten lives in a container rotated +90°, so its block-local\n        // depth is sign-flipped in y to land up-right again after that rotation.\n        var Dx_1 = depth;\n        var Dy_1 = orientation === 'v' ? -depth : depth;\n        // Unit-cell counts along each front axis (1 or 10) drive face subdivisions.\n        var wCells = Math.round(width / s);\n        var hCells = Math.round(height / s);\n        // Front-rect corners (block-local).\n        var FL = [0, 0];\n        var FR = [W, 0];\n        var TR = [W, H];\n        var TL = [0, H];\n        var back_1 = function (p) { return [p[0] + Dx_1, p[1] + Dy_1]; };\n        // Grid segments are collected first, then drawn after the fills so they\n        // sit on top of them. Each segment carries its own color so a face's grid\n        // lines share that face's shading (top lighter, side darker).\n        var gridSegs_1 = [];\n        // Add a parallelogram face by extruding the front edge p1→p2 back along the\n        // depth vector, with `baseCells` divisions along the edge and `depthCells`\n        // along the depth. `gridColor` shades this face's grid lines to match its\n        // fill.\n        var addFace = function (name, p1, p2, baseCells, color, gridColor) {\n            var face = block.add({\n                name: name,\n                make: 'generic',\n                points: [p1, p2, back_1(p2), back_1(p1)],\n                drawType: 'FAN',\n                color: color,\n            });\n            if (lineEnabled) {\n                // Depth-wise lines, one per division along the front edge.\n                for (var i = 1; i < baseCells; i += 1) {\n                    var t = i / baseCells;\n                    var b = [\n                        p1[0] + t * (p2[0] - p1[0]),\n                        p1[1] + t * (p2[1] - p1[1]),\n                    ];\n                    gridSegs_1.push([b, back_1(b), gridColor]);\n                }\n                // Edge-parallel lines, one per depth layer.\n                for (var j = 1; j < depthCells; j += 1) {\n                    var t = j / depthCells;\n                    gridSegs_1.push([\n                        [p1[0] + t * Dx_1, p1[1] + t * Dy_1],\n                        [p2[0] + t * Dx_1, p2[1] + t * Dy_1],\n                        gridColor,\n                    ]);\n                }\n            }\n            return face;\n        };\n        // The two visible faces are always the screen-top (lighter) and screen-right\n        // (darker). Which front edges those map to depends on orientation: for a\n        // horizontal block the top edge is the top face and the right edge the side;\n        // a vertical ten is rotated +90°, so its right edge reads as the top face\n        // and its bottom edge as the side.\n        var light = lighten(o.color, 0.25);\n        var dark = darken(o.color, 0.25);\n        // Grid lines on each face get the same shading as that face's fill, so they\n        // read as belonging to the face (and keep even contrast against it).\n        var lightLine = lighten(lineColor, 0.25);\n        var darkLine = darken(lineColor, 0.25);\n        if (orientation === 'v') {\n            rightFace = addFace('rightFace', FL, FR, wCells, dark, darkLine); // bottom edge → side\n            topFace = addFace('topFace', FR, TR, hCells, light, lightLine); // right edge → top\n        }\n        else {\n            rightFace = addFace('rightFace', FR, TR, hCells, dark, darkLine); // right edge → side\n            topFace = addFace('topFace', TL, TR, wCells, light, lightLine); // top edge → top\n        }\n        // Grid on top of the fills, each segment in its face's shaded line color.\n        if (lineEnabled && gridSegs_1.length > 0) {\n            var cubeGrid_1 = block.add({ name: 'cubeGrid', make: 'collection' });\n            gridSegs_1.forEach(function (_a) {\n                var p1 = _a[0], p2 = _a[1], color = _a[2];\n                return cubeGrid_1.add({\n                    make: 'line',\n                    p1: p1,\n                    p2: p2,\n                    width: lineWidth,\n                    color: color,\n                });\n            });\n        }\n        // Back/depth edges of the wireframe (the front face is already outlined by\n        // `borderLine` below): one open path tracing the back silhouette, plus the\n        // interior depth edge from the shared front corner. The visible edges, like\n        // the faces, depend on orientation.\n        var cubeEdges = block.add({ name: 'cubeEdges', make: 'collection' });\n        if (borderEnabled) {\n            var backPath = orientation === 'v'\n                ? [TR, back_1(TR), back_1(FR), back_1(FL), FL]\n                : [TL, back_1(TL), back_1(TR), back_1(FR), FR];\n            var interior = orientation === 'v'\n                ? [FR, back_1(FR)]\n                : [TR, back_1(TR)];\n            cubeEdges.add({\n                make: 'polyline', points: backPath, width: borderWidth, color: borderColor,\n            });\n            cubeEdges.add({\n                make: 'polyline', points: interior, width: borderWidth, color: borderColor,\n            });\n        }\n        shade3D = function (base) {\n            frontRect.setColor(base);\n            topFace.setColor(lighten(base, 0.12));\n            rightFace.setColor(darken(base, 0.12));\n        };\n    }\n    var selectBorder;\n    if (o.isSelectable) {\n        selectBorder = container.add({\n            name: 'selectBorder',\n            make: 'rectangle',\n            width: width + o.selectLine.space * 2,\n            height: height + o.selectLine.space * 2,\n            corner: {\n                radius: s * 0.3 + o.selectLine.space,\n                sides: 10,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: o.selectLine.width },\n            position: [-s / 2 - o.selectLine.space, -s / 2 - o.selectLine.space],\n            // position: [, 0],\n            color: o.selectLine.color,\n        });\n        selectBorder.hide();\n    }\n    var linesY;\n    var linesX;\n    if (lineEnabled && n >= 100) {\n        linesY = container.add({\n            name: 'linesY',\n            make: 'line',\n            p1: [-s / 2 + line / 2, s / 2],\n            p2: [width - s / 2 - line / 2, s / 2],\n            color: lineColor,\n            width: lineWidth,\n            copy: {\n                along: 'y',\n                step: s,\n                num: 8,\n            },\n        });\n    }\n    if (lineEnabled && n >= 10) {\n        linesX = container.add({\n            name: 'linesX',\n            make: 'line',\n            p1: [s / 2, -s / 2 + line / 2],\n            p2: [s / 2, height - s / 2 - line / 2],\n            color: lineColor,\n            width: lineWidth,\n            copy: {\n                along: 'x',\n                step: s,\n                num: 8,\n            },\n        });\n    }\n    var borderLine;\n    if (borderEnabled) {\n        borderLine = container.add({\n            make: 'rectangle',\n            name: 'border',\n            width: width - line,\n            height: height - line,\n            corner: {\n                radius: radius,\n                sides: 10,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: borderWidth },\n            position: [-s / 2 + line / 2, -s / 2 + line / 2],\n            color: borderColor,\n        });\n    }\n    element.snaps = [];\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    // computeState() builds the serializable block state. Kept as a local function\n    // (not only element.custom.getState) because internal handlers keep\n    // element.custom.state up to date even when the public method is gated off.\n    function computeState() {\n        var p = element.getPosition();\n        var r = container.getRotation() === 0 ? 'h' : 'v';\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        var regex = new RegExp('^' + e_name);\n        var createdFrom = o.createdFrom\n            ? o.createdFrom.replace(regex, '').slice(1)\n            : null;\n        return {\n            c: createdFrom,\n            e: e_name,\n            p: [\n                Fig.round(p.x, STATE_POSITION_PRECISION),\n                Fig.round(p.y, STATE_POSITION_PRECISION),\n            ],\n            r: Fig.round(r, 4),\n            s: scale,\n            sel: element.custom.selected,\n            n: o.n,\n            // Visibility, so setState can restore a hidden block as hidden (see the\n            // note there). Blocks a slot's add-a-block buttons haven't dissolved in\n            // yet sit hidden at their never-positioned default, and are otherwise\n            // indistinguishable from ones the learner placed.\n            sh: element.isShown,\n        };\n    }\n    // States saved before `sh` was recorded carry no visibility at all, so a\n    // regenerated snapshot showed every block the state mentioned. Recover it for\n    // the one case where it is recoverable: a slot's add-a-block button pool. A\n    // pool block is only ever visible while snapped in its slot -- it is created\n    // hidden, is not draggable (onButtonPress clears isMovable), and is parked at\n    // POOL_PARK_POSITION when tapped away. So a saved position that is either the\n    // park position or the block's untouched default means the learner never\n    // placed it (or removed it), and it must come back hidden.\n    //\n    // Returns undefined when there is nothing to go on -- a block that isn't pool\n    // sourced, or whose default position isn't known yet because the figure\n    // hasn't published 'ready'. The caller then leaves visibility alone, which is\n    // exactly how these states behaved before.\n    function inferShownFromPosition(p) {\n        if (!element.custom.buttonSourced) {\n            return undefined;\n        }\n        if (samePositionAsSaved([POOL_PARK_POSITION[0], POOL_PARK_POSITION[1]], p)) {\n            return false;\n        }\n        var initial = element.custom.initialPosition;\n        if (initial == null) {\n            return undefined;\n        }\n        return !samePositionAsSaved(initial, p);\n    }\n    // Only define the public getState/setState — the save/restore opt-in the\n    // manage.ts layer checks for — when the block is actually manipulable. A block\n    // with isTouchable: false is static/display-only (laid out in the equation,\n    // can't be dragged or selected), so its position/rotation/selection never\n    // change. It then defines neither method, so getManipulativesState /\n    // setManipulatives skip it: it adds nothing to the answer payload and is never\n    // restored from a snapshot.\n    var tracksState = o.isTouchable !== false;\n    if (tracksState) {\n        element.custom.getState = computeState;\n        element.custom.setState = function (stats) {\n            element.setPosition(Fig.parsePoint(stats.p));\n            // element.setScale(stats.s)\n            element.custom.setBlockRotation(stats.r, false);\n            element.custom.state = stats;\n            element.custom.moved = true;\n            if (o.isSelectable && stats.sel) {\n                element.custom.select();\n            }\n            // Restore visibility, undoing setManipulatives()'s unconditional show()\n            // for a block that was hidden when the state was captured -- a button\n            // pool block the learner never used would otherwise appear in the\n            // snapshot at its default position, on top of the question.\n            var shown = stats.sh === undefined\n                ? inferShownFromPosition(stats.p)\n                : stats.sh;\n            if (shown === false) {\n                element.hide();\n            }\n            else if (shown === true) {\n                element.show();\n            }\n        };\n    }\n    setupManipulative(element, selectBorder, o);\n    element.custom.state = computeState();\n    // element.setColor = (color: FigureOneColor) => {\n    //   block._block.setColor(color);\n    // };\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    if (fig.custom.breakBaseTenBlocks == null) {\n        fig.custom.breakBaseTenBlocks = { 10: 0, 100: 0, 1000: 0 };\n    }\n    function checkBreakCount() {\n        if (fig.custom.breakBaseTenBlocks == null) {\n            return;\n        }\n        var manipulatives = getManipulatives(false, toAdd, fig);\n        var totalBreaks = fig.custom.breakBaseTenBlocks[10]\n            + fig.custom.breakBaseTenBlocks[100]\n            + fig.custom.breakBaseTenBlocks[1000];\n        [10, 100, 1000].forEach(function (N) {\n            manipulatives.forEach(function (m) {\n                if (m.custom.manipulativeType === 'b10_blocks' && m.custom.n === N) {\n                    if (fig.custom.breakBaseTenBlocks[N] >= o.maxBreaks[N] ||\n                        totalBreaks >= o.maxBreaksTotal) {\n                        m.custom.worksWith['break'] = false;\n                    }\n                    else {\n                        m.custom.worksWith['break'] = true;\n                    }\n                }\n            });\n        });\n    }\n    // Splitting only works on workPad elements (not in equations likes expression\n    // as when the equations get a relayout - the original element is gone and the new\n    // elements will be hidden)\n    element.break = function () {\n        var blockRotation = element.custom.getBlockRotation();\n        if (n == 10) {\n            var _loop_1 = function (i) {\n                var oneBlock = createBaseTenBlocks(fig, eqn_name, options.toElement, Fig.joinObjects({}, o, {\n                    n: 1,\n                    color: o.color,\n                    name: \"__M_B1B1\",\n                }), o.boundMove);\n                oneBlock.notificationHelper.add(toAdd, 'layoutForms', function () {\n                    oneBlock.showAll();\n                });\n                oneBlock.setPositionToElement(element);\n                if (blockRotation === 'h') {\n                    oneBlock.setPosition(oneBlock.getPosition().add(s * i, 0));\n                }\n                else {\n                    oneBlock.setPosition(oneBlock.getPosition().add(0, s * i));\n                }\n            };\n            for (var i = 0; i < 10; i += 1) {\n                _loop_1(i);\n            }\n            // Defer trash to after stopBeingMoved() completes - break is called\n            // from a stopBeingMoved notification, and synchronous remove() would\n            // null out recorder/figure while stopBeingMoved is still executing.\n            setTimeout(function () { return element.trash(); }, 0);\n            fig.custom.breakBaseTenBlocks[10] += 1;\n        }\n        if (n == 100) {\n            var _loop_2 = function (i) {\n                var tenBlock = createBaseTenBlocks(fig, eqn_name, options.toElement, Fig.joinObjects({}, o, {\n                    n: 10,\n                    color: o.color,\n                    name: \"__M_B10B10\",\n                    orientation: 'v',\n                }), o.boundMove);\n                tenBlock.notificationHelper.add(toAdd, 'layoutForms', function () {\n                    tenBlock.showAll();\n                });\n                tenBlock.setPositionToElement(element);\n                tenBlock.setPosition(tenBlock.getPosition().add(s * i, 0));\n            };\n            for (var i = 0; i < 10; i += 1) {\n                _loop_2(i);\n            }\n            // Defer trash to after stopBeingMoved() completes - break is called\n            // from a stopBeingMoved notification, and synchronous remove() would\n            // null out recorder/figure while stopBeingMoved is still executing.\n            setTimeout(function () { return element.trash(); }, 0);\n            fig.custom.breakBaseTenBlocks[100] += 1;\n        }\n        if (n == 1000) {\n            var _loop_3 = function (i) {\n                var hundredBlock = createBaseTenBlocks(fig, eqn_name, options.toElement, Fig.joinObjects({}, o, {\n                    n: 100,\n                    color: o.color,\n                    name: \"__M_B100B100\",\n                }), o.boundMove);\n                hundredBlock.notificationHelper.add(toAdd, 'layoutForms', function () {\n                    hundredBlock.showAll();\n                });\n                hundredBlock.setPositionToElement(element);\n                hundredBlock.setPosition(hundredBlock.getPosition().add(s * 10 * i, 0));\n            };\n            for (var i = 0; i < 10; i += 1) {\n                _loop_3(i);\n            }\n            // Defer trash to after stopBeingMoved() completes - break is called\n            // from a stopBeingMoved notification, and synchronous remove() would\n            // null out recorder/figure while stopBeingMoved is still executing.\n            setTimeout(function () { return element.trash(); }, 0);\n            fig.custom.breakBaseTenBlocks[1000] += 1;\n        }\n        checkBreakCount();\n        var breaks = fig.custom.breakBaseTenBlocks;\n        // The total cap is the real governor (and the only clause that accounts for\n        // 1000s). The per-size clause intentionally tracks only 10 and 100: ANDing\n        // in `breaks[1000] >= maxBreaks[1000]` would suppress this clause for any\n        // 10/100-only question, since an unused size never reaches its budget. Per-\n        // block breakability across all three sizes is handled by checkBreakCount().\n        if ((breaks[10] >= o.maxBreaks[10] && breaks[100] >= o.maxBreaks[100]) ||\n            breaks[10] + breaks[100] + breaks[1000] >= o.maxBreaksTotal) {\n            return {\n                disable: true,\n            };\n        }\n        return {};\n    };\n    element.getContainerBounds = function () {\n        return { rect: element.custom.getBoundingRect('local') };\n    };\n    element.custom.worksWith = {\n        trash: true,\n    };\n    if (o.n === 1) {\n        element.custom.worksWith['break'] = false;\n    }\n    else {\n        element.custom.worksWith['break'] = true;\n    }\n    element.custom.getBoundingRect = function (space) {\n        var bounds = element.getBoundingRect(space);\n        var width = bounds.width > bounds.height ? bounds.width : bounds.height;\n        var height = bounds.width < bounds.height ? bounds.width : bounds.height;\n        if (element.custom.getBlockRotation() === 'h') {\n            return new Fig.Rect(bounds.left, bounds.bottom, width, height);\n        }\n        return new Fig.Rect(bounds.left, bounds.bottom, height, width);\n    };\n    element.ignoreSetColor = 'form';\n    if (o.preserveChildColor === false) {\n        element.setColor = function (c) {\n            if (is3D) {\n                shade3D(c);\n            }\n            else {\n                block.setColor(c);\n            }\n        };\n    }\n    element.setColor(color);\n    // Re-assert the per-face shading: the default setColor preserves child colors,\n    // so make the cube's dimensional shading authoritative regardless. When\n    // preserveChildColor is false the override above already called shade3D, so\n    // skip the redundant re-apply in that path.\n    if (is3D && o.preserveChildColor !== false) {\n        shade3D(color);\n    }\n    incrementManipulativeIndex('baseTenBlocks', n);\n    if (o.isSelectable) {\n        block.setTouchable();\n    }\n    else {\n        block.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    element.custom.manipulativeAid = {\n        style: 'linear_blocks',\n        n: n,\n    };\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n        element.highlightContainer();\n    });\n    element._container._block.custom.secondaryTouchBounds = 0.1;\n    element.notificationHelper.add(element._container._block, 'onClick', function () {\n        var selector = getSelectedSelector(fig);\n        if (selector != null) {\n            element.custom.clickStart = null;\n            if (selector.custom.method === 'trash') {\n                element.trash();\n                selector.highlightWorksWith();\n                selector.checkDeselect();\n                return;\n            }\n        }\n        // Tapping a snapped block claims its slot as the to-snap target for\n        // subsequent tap-snaps. The eviction (tryTapSlotReturn, fired later\n        // from the moved handler) still runs as before — this just updates the\n        // shared ref so a fresh tap-snap from outside lands here.\n        if (element.custom.isSnapped\n            && element.custom.snappedSlot != null\n            && typeof element.custom.snappedSlot.setAsToSnap === 'function') {\n            element.custom.snappedSlot.setAsToSnap();\n        }\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n        if (o.isSelectable) {\n            element.custom.toggleSelect();\n        }\n        var workPad = fig.get('workPad');\n        if (workPad != null) {\n            if (workPad._controls != null &&\n                workPad._controls._delete != null &&\n                workPad._controls._delete.custom.selected) {\n                element.hideAll();\n                element.setPosition(10000, 10000);\n                element.isTouchable = false;\n                element.parent.remove(element.name);\n                // workPad.custom.clearControls([]);\n            }\n        }\n    });\n    element.answerContainers = [];\n    element.checkAnswerContainers = function () { return checkAnswerContainers(o, element); };\n    element.highlightContainer = function () { return highlightAnswerContainer(o, element); };\n    element.removeFromContainer = function () { return removeFromContainer(o, element); };\n    // ── baseTenBlocksSlot integration ──────────────────────────────\n    // snapTo: 'b10_blocks_slot' wires the block to a baseTenBlocksSlot.\n    // The slot does the geometry + animation; the block just routes events.\n    element.snapPositionDelta = null;\n    element.custom.isSnapped = false;\n    element.custom.snappedSlot = null;\n    var wantsSlotSnap = function () {\n        if (o.snapTo == null)\n            return false;\n        if (Array.isArray(o.snapTo)) {\n            return o.snapTo.indexOf('b10_blocks_slot') !== -1;\n        }\n        return o.snapTo === 'b10_blocks_slot';\n    };\n    element.unsnap = function () {\n        if (!element.custom.isSnapped)\n            return;\n        var slot = element.custom.snappedSlot;\n        if (slot != null) {\n            slot.unsnap(element);\n        }\n        else {\n            element.custom.isSnapped = false;\n        }\n    };\n    // After a drag, check if the block was dropped over a slot. If accepted,\n    // commitSnap atomically commits the state and the slot animates the block\n    // into place via its own layoutAll. If rejected (won't fit), animate the\n    // block back to where the drag started. Returns true if the slot handled\n    // the drop (caller should stop further processing).\n    //\n    // commitSnap is the atomic operation — rapid concurrent calls see updated\n    // capacity and either land at a different spot or are rejected. (Without\n    // that, three rapid taps when only one slot remains would all reserve the\n    // same target.)\n    element.checkSlotSnaps = function () {\n        if (!wantsSlotSnap())\n            return false;\n        var slots = getAllBaseTenBlocksSlots(toAdd);\n        var attempted = false;\n        for (var i = 0; i < slots.length; i += 1) {\n            var r = slots[i].tryAutoSnap(element);\n            if (r.inBounds)\n                attempted = true;\n            if (r.accepted) {\n                if (slots[i].commitSnap(element))\n                    return true;\n            }\n        }\n        if (attempted && element.custom.startMovePosition != null) {\n            element.stopAnimating();\n            suppressManipulativeTouch(element);\n            fig.elements.animations\n                .new()\n                .position({\n                element: element,\n                target: element.custom.startMovePosition,\n                duration: 0.3,\n            })\n                .trigger(function () {\n                element.custom.state.p = element.getPosition();\n                releaseManipulativeTouch(element);\n            })\n                .start();\n            return true;\n        }\n        return false;\n    };\n    // Called after a block finishes returning to its initial position from a\n    // slot. The slot's reflow brought the moved block to the front during\n    // its outbound animation; now that it's back on the initial-position\n    // pile it can end up below other unsnapped blocks that overlap there,\n    // making the pile awkward to pick from. Walk the equation for every\n    // unsnapped b10_blocks resting at its initial position and bring it to\n    // the front so the topmost pickable block stays pickable. Button-pool\n    // blocks are skipped — they're hidden and shouldn't reorder.\n    var bringUnsnappedBlocksToFront = function () {\n        var epsilon = 0.001;\n        var all = [];\n        var walk = function (root) {\n            if (root == null || root.elements == null)\n                return;\n            var names = Object.keys(root.elements);\n            for (var i = 0; i < names.length; i += 1) {\n                var el = root.elements[names[i]];\n                if (el == null)\n                    continue;\n                all.push(el);\n                if (el.elements != null)\n                    walk(el);\n            }\n        };\n        walk(toAdd);\n        for (var i = 0; i < all.length; i += 1) {\n            var el = all[i];\n            if (el == null || el.custom == null)\n                continue;\n            if (el.custom.manipulativeType !== 'b10_blocks')\n                continue;\n            if (el.custom.isSnapped)\n                continue;\n            if (el.custom.buttonSourced)\n                continue;\n            if (el.custom.initialPosition == null)\n                continue;\n            if (el.getPosition().sub(el.custom.initialPosition).distance() > epsilon)\n                continue;\n            if (el.parent != null)\n                el.parent.toFront(el);\n        }\n    };\n    // Exposed so peers (the slot's animateBlock 'init' path) can run the same\n    // reordering after they return a block to its initial position.\n    element.custom.bringUnsnappedBlocksToFront = bringUnsnappedBlocksToFront;\n    // Tap-from-outside path: same atomic commit as drag-end. The slot's\n    // commitSnap kicks off the inbound animation via layoutAll. The to-snap\n    // slot (tracked on toAdd.custom.toSnapBaseTenBlocksSlot) is tried first;\n    // if the block doesn't fit there, fall through to the others in order.\n    element.tryTapSlotSnap = function () {\n        if (!wantsSlotSnap())\n            return false;\n        var slots = getAllBaseTenBlocksSlots(toAdd);\n        var preferred = toAdd.custom != null\n            ? toAdd.custom.toSnapBaseTenBlocksSlot\n            : null;\n        if (preferred != null && slots.indexOf(preferred) !== -1) {\n            if (preferred.commitSnap(element))\n                return true;\n        }\n        for (var i = 0; i < slots.length; i += 1) {\n            if (slots[i] === preferred)\n                continue;\n            if (slots[i].commitSnap(element))\n                return true;\n        }\n        return false;\n    };\n    element.tryTapSlotReturn = function () {\n        if (!wantsSlotSnap())\n            return false;\n        // Button-pool blocks dissolve out and hide instead of returning to an\n        // initial position. The sequence is dissolve → unsnap → hide so the\n        // block stays in the slot's container (isSnapped=true) during the fade,\n        // which keeps it from being re-picked by a concurrent button press.\n        if (element.custom.buttonSourced) {\n            if (!element.custom.isSnapped)\n                return true;\n            element.isTouchable = false;\n            element.stopAnimating();\n            fig.elements.animations\n                .new()\n                .opacity({ element: element, target: 0, duration: 0.3 })\n                .trigger(function () {\n                if (typeof element.hide === 'function') {\n                    element.hide();\n                }\n                else {\n                    element.isShown = false;\n                }\n                element.setPosition(POOL_PARK_POSITION[0], POOL_PARK_POSITION[1]);\n                element.unsnap();\n            })\n                .start();\n            return true;\n        }\n        if (element.custom.initialPosition == null)\n            return false;\n        if (element.custom.isSnapped)\n            element.unsnap();\n        var target = element.custom.initialPosition;\n        element.stopAnimating();\n        suppressManipulativeTouch(element);\n        fig.elements.animations\n            .new()\n            .position({ element: element, target: target, duration: 0.3 })\n            .trigger(function () {\n            element.custom.state.p = element.getPosition();\n            releaseManipulativeTouch(element);\n            bringUnsnappedBlocksToFront();\n        })\n            .start();\n        return true;\n    };\n    element.notificationHelper.add(element, 'startBeingMoved', function () {\n        element.custom.startMovePosition = element.getPosition();\n        if (element.custom.isSnapped) {\n            element.custom.snappedAtMoveStart = true;\n            // Button-pool blocks stay in the slot's container until their\n            // dissolve-out completes (tryTapSlotReturn handles that). Unsnap-now\n            // would defeat the sequential dissolve→unsnap ordering and let a\n            // concurrent button press re-pick this block mid-fade.\n            if (!element.custom.buttonSourced)\n                element.unsnap();\n        }\n        else {\n            element.custom.snappedAtMoveStart = false;\n        }\n    });\n    element.unhighlight = function () {\n        if (element.custom.disabled) {\n            return;\n        }\n        if (is3D) {\n            shade3D(o.color);\n        }\n        else {\n            block.setColor(o.color);\n        }\n        if (borderLine) {\n            borderLine.setColor(borderColor);\n        }\n        if (linesX)\n            linesX.setColor(lineColor);\n        if (linesY)\n            linesY.setColor(lineColor);\n    };\n    element.highlight = function () {\n        if (is3D) {\n            shade3D(o.colorHighlight);\n        }\n        else {\n            block.setColor(o.colorHighlight);\n        }\n        if (borderLine && borderOpts.highlight != null) {\n            borderLine.setColor(borderOpts.highlight);\n        }\n        if (lineOpts.highlight != null) {\n            if (linesX)\n                linesX.setColor(lineOpts.highlight);\n            if (linesY)\n                linesY.setColor(lineOpts.highlight);\n        }\n    };\n    element.dim = function () {\n        if (is3D) {\n            shade3D(o.colorDim);\n        }\n        else {\n            block.setColor(o.colorDim);\n        }\n        if (borderLine && borderOpts.dim != null) {\n            borderLine.setColor(borderOpts.dim);\n        }\n        if (lineOpts.dim != null) {\n            if (linesX)\n                linesX.setColor(lineOpts.dim);\n            if (linesY)\n                linesY.setColor(lineOpts.dim);\n        }\n    };\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        var answerContainerMoved = element.checkAnswerContainers();\n        var wasTap = element.custom.clickStart != null &&\n            performance.now() - element.custom.clickStart < 200;\n        var wasSnappedAtMoveStart = element.custom.snappedAtMoveStart === true;\n        element.custom.snappedAtMoveStart = false;\n        if (answerContainerMoved === 'notConfigured' &&\n            wasTap) {\n            var selector = getSelectedSelector(fig);\n            if (selector != null) {\n                element.custom.clickStart = null;\n                if (selector.custom.method === 'break') {\n                    var result = element.break();\n                    selector.executedMethod(result);\n                    if (result.disable !== true) {\n                        selector.highlightWorksWith();\n                        selector.checkDeselect();\n                    }\n                    return;\n                }\n                // if (selector.custom.method === 'trash') {\n                //   element.trash();\n                //   selector.highlightWorksWith();\n                //   selector.checkDeselect();\n                //   return;\n                // }\n            }\n        }\n        // Tap on a slot-snapped block: return it to its initial position.\n        if (answerContainerMoved === 'notConfigured' &&\n            wasTap &&\n            wasSnappedAtMoveStart &&\n            element.tryTapSlotReturn()) {\n            element.custom.clickStart = null;\n            return;\n        }\n        // Tap on an unsnapped block: try to send it into the first available\n        // slot anchor.\n        if (answerContainerMoved === 'notConfigured' &&\n            wasTap &&\n            !wasSnappedAtMoveStart &&\n            element.tryTapSlotSnap()) {\n            element.custom.clickStart = null;\n            return;\n        }\n        if (answerContainerMoved === 'notConfigured' &&\n            wasTap &&\n            canRotate &&\n            n === 10) {\n            var r = Fig.round(container.getRotation(), 8);\n            var target = Math.PI / 2;\n            if (r !== 0) {\n                target = 0;\n            }\n            element.custom.clickStart = null;\n            element.stopAnimating();\n            fig.elements.animations\n                .new()\n                .rotation({ target: target, duration: 0.3, element: container })\n                .trigger(function () {\n                element.checkAnswerContainers();\n                if (element.isShown) {\n                    element.setMoveBounds();\n                }\n            })\n                .start();\n            return;\n        }\n        if (element.custom.startMove != null &&\n            performance.now() - element.custom.startMove < 200) {\n            return;\n        }\n        // Button-pool blocks stay in the slot's container during drag (dragstart\n        // skips unsnap), so on release they're still \"in\" the slot — just visually\n        // displaced. Ask the slot to reflow so layoutAll animates this block back\n        // to its container-derived target along with any siblings that depend on\n        // it. Skips the snap-to-grid + checkSlotSnaps bounce-back below.\n        if (element.custom.buttonSourced &&\n            element.custom.isSnapped &&\n            element.custom.snappedSlot != null) {\n            element.custom.snappedSlot.reflowAfterRemove();\n            return;\n        }\n        if (o.snap) {\n            element.setPosition(snapPointToPoint(element.getPosition(), [0, 0], s / 2, s / 2));\n        }\n        // Drag-end (non-tap) into a baseTenBlocksSlot: accept or bounce back.\n        if (element.checkSlotSnaps()) {\n            element.custom.state.p = element.getPosition();\n            return;\n        }\n        // Nothing snapped — optionally animate back to the figure-ready initial\n        // position. Gated on no answer container being configured so we don't\n        // override a container that just accepted/rejected the drop above.\n        if (o.returnToInitial &&\n            answerContainerMoved === 'notConfigured' &&\n            element.custom.initialPosition != null) {\n            element.stopAnimating();\n            suppressManipulativeTouch(element);\n            fig.elements.animations\n                .new()\n                .position({\n                element: element,\n                target: element.custom.initialPosition,\n                duration: 0.3,\n            })\n                .trigger(function () {\n                element.custom.state.p = element.getPosition();\n                releaseManipulativeTouch(element);\n                bringUnsnappedBlocksToFront();\n            })\n                .start();\n            return;\n        }\n        element.custom.state.p = element.getPosition();\n        // element.checkAnswerContainers();\n    });\n    element.custom.manipulativeType = 'b10_blocks';\n    element.custom.setBlockRotation = function (orient, setBorder) {\n        if (setBorder === void 0) { setBorder = true; }\n        if (orient === 'v') {\n            container.setRotation(Math.PI / 2);\n            if (setBorder) {\n                element.border = is3D ? cubeBorder : vBorder;\n            }\n        }\n        else {\n            container.setRotation(0);\n            if (setBorder) {\n                element.border = is3D ? cubeBorder : hBorder;\n            }\n        }\n        element.setMoveBounds();\n    };\n    element.custom.getBlockRotation = function () {\n        return container.getRotation() === 0 ? 'h' : 'v';\n    };\n    element.custom.setBlockRotation(orientation);\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    return element;\n};\nexport { baseTenBlocks, createBaseTenBlocks, };\n","import { joinObjects } from '../tools/joinObjects';\nimport { doRectsOverlap } from '../workpad_new/tools';\nimport { setAtlasId } from '../tools/equation';\nimport { roundNum } from '../tools/math';\nimport { darken, lighten } from '../tools/color';\nimport { suppressManipulativeTouch, releaseManipulativeTouch, POOL_PARK_POSITION, } from './tools';\nvar makeRowContainer = function (unitWidth, cell, max, groupSize, groupSpace) {\n    var blocks = [];\n    // Cells per block in the grid (1 for tens/ones, 10 for hundreds).\n    var cellsPerBlock = Math.max(1, Math.round(unitWidth / cell));\n    // Extra x offset accumulated by the time block index `i` is placed:\n    // one `groupSpace` for each complete subgroup left of it.\n    var subOffset = function (i) {\n        if (groupSize <= 0 || groupSpace <= 0)\n            return 0;\n        return Math.floor(i / groupSize) * groupSpace;\n    };\n    var c = {\n        blocks: blocks,\n        add: function (block) {\n            if (blocks.length >= max)\n                return false;\n            if (blocks.indexOf(block) !== -1)\n                return false;\n            blocks.push(block);\n            return true;\n        },\n        remove: function (block) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return false;\n            blocks.splice(i, 1);\n            return true;\n        },\n        canAdd: function () {\n            return blocks.length < max;\n        },\n        width: function () {\n            if (blocks.length === 0)\n                return 0;\n            return blocks.length * unitWidth + subOffset(blocks.length - 1);\n        },\n        widthIfAdded: function () {\n            var n = blocks.length + 1;\n            return n * unitWidth + subOffset(n - 1);\n        },\n        positionFor: function (block, originX, originY) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return null;\n            return new Fig.Point(originX + i * unitWidth + subOffset(i), originY);\n        },\n        nextPosition: function (originX, originY) {\n            var i = blocks.length;\n            return new Fig.Point(originX + i * unitWidth + subOffset(i), originY);\n        },\n        orderedBlocks: function () {\n            return blocks.slice();\n        },\n        cols: function () {\n            return blocks.length * cellsPerBlock;\n        },\n        colsIfAdded: function () {\n            return (blocks.length + 1) * cellsPerBlock;\n        },\n        colOf: function (block) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return null;\n            return i * cellsPerBlock;\n        },\n        nextCol: function () {\n            return blocks.length * cellsPerBlock;\n        },\n    };\n    return c;\n};\nvar makePackContainer = function (unitWidth, cell, height, max, groupSize, groupSpace) {\n    var blocks = [];\n    var cells = new Map();\n    // Snap-cells consumed per pack-column (1 for ones with unitWidth=cell).\n    var cellsPerCol = Math.max(1, Math.round(unitWidth / cell));\n    // groupSize is in blocks; convert to columns. Using floor means a\n    // non-multiple-of-height groupSize lands the gap at a column boundary\n    // close to (but at most) the requested count.\n    var subCols = groupSize > 0 ? Math.floor(groupSize / height) : 0;\n    var subOffset = function (col) {\n        if (subCols <= 0 || groupSpace <= 0)\n            return 0;\n        return Math.floor(col / subCols) * groupSpace;\n    };\n    var columnHeights = function () {\n        var h = {};\n        cells.forEach(function (cell) {\n            var cur = h[cell.col] || 0;\n            if (cell.row + 1 > cur)\n                h[cell.col] = cell.row + 1;\n        });\n        return h;\n    };\n    var numCols = function () {\n        var max = -1;\n        cells.forEach(function (cell) {\n            if (cell.col > max)\n                max = cell.col;\n        });\n        return max + 1;\n    };\n    // Find the cell the next-to-be-added block would occupy: leftmost column\n    // that still has room, bottom row of that column.\n    var findNextCell = function () {\n        var h = columnHeights();\n        var used = numCols();\n        for (var c = 0; c < used; c += 1) {\n            if ((h[c] || 0) < height)\n                return { col: c, row: h[c] || 0 };\n        }\n        return { col: used, row: 0 };\n    };\n    return {\n        blocks: blocks,\n        add: function (block) {\n            if (blocks.length >= max)\n                return false;\n            if (blocks.indexOf(block) !== -1)\n                return false;\n            var cell = findNextCell();\n            blocks.push(block);\n            cells.set(block, cell);\n            return true;\n        },\n        remove: function (block) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return false;\n            blocks.splice(i, 1);\n            cells.delete(block);\n            // Compact so the leftmost columns are always full. Take every\n            // remaining block in column-major order (left-to-right, bottom-to-top)\n            // and re-assign it to the first n cells in that same order. When the\n            // freed slot is in column k, this pulls the bottom block of column\n            // k+1 across to fill the top of column k (it visually jumps), then\n            // collapses everything in column k+1 and to its right by one slot.\n            var remaining = [];\n            cells.forEach(function (cell, blk) {\n                remaining.push({ block: blk, col: cell.col, row: cell.row });\n            });\n            remaining.sort(function (a, b) { return a.col - b.col || a.row - b.row; });\n            cells.clear();\n            for (var idx = 0; idx < remaining.length; idx += 1) {\n                cells.set(remaining[idx].block, {\n                    col: Math.floor(idx / height),\n                    row: idx % height,\n                });\n            }\n            return true;\n        },\n        canAdd: function () {\n            return blocks.length < max;\n        },\n        width: function () {\n            var cols = numCols();\n            if (cols === 0)\n                return 0;\n            return cols * unitWidth + subOffset(cols - 1);\n        },\n        widthIfAdded: function () {\n            var h = columnHeights();\n            var used = numCols();\n            for (var c = 0; c < used; c += 1) {\n                if ((h[c] || 0) < height) {\n                    return used * unitWidth + subOffset(used - 1);\n                }\n            }\n            return (used + 1) * unitWidth + subOffset(used);\n        },\n        positionFor: function (block, originX, originY) {\n            var cell = cells.get(block);\n            if (cell == null)\n                return null;\n            return new Fig.Point(originX + cell.col * unitWidth + subOffset(cell.col), originY + cell.row * unitWidth);\n        },\n        nextPosition: function (originX, originY) {\n            var cell = findNextCell();\n            return new Fig.Point(originX + cell.col * unitWidth + subOffset(cell.col), originY + cell.row * unitWidth);\n        },\n        orderedBlocks: function () {\n            var arr = [];\n            cells.forEach(function (cell, block) {\n                arr.push({ block: block, col: cell.col, row: cell.row });\n            });\n            arr.sort(function (a, b) { return a.col - b.col || a.row - b.row; });\n            return arr.map(function (x) { return x.block; });\n        },\n        cols: function () {\n            return numCols() * cellsPerCol;\n        },\n        colsIfAdded: function () {\n            var h = columnHeights();\n            var used = numCols();\n            for (var c = 0; c < used; c += 1) {\n                if ((h[c] || 0) < height)\n                    return used * cellsPerCol;\n            }\n            return (used + 1) * cellsPerCol;\n        },\n        colOf: function (block) {\n            var cell = cells.get(block);\n            if (cell == null)\n                return null;\n            return cell.col * cellsPerCol;\n        },\n        nextCol: function () {\n            return findNextCell().col * cellsPerCol;\n        },\n    };\n};\nvar makeDiagonalContainer = function (unitWidth, cell, offsetX, offsetY, maxPerStack, stackGap, max) {\n    var blocks = [];\n    var infinite = maxPerStack <= 0;\n    var per = infinite ? Number.MAX_SAFE_INTEGER : maxPerStack;\n    // Footprint of one full stack of `per` blocks along x.\n    var fullStackWidth = unitWidth + (per - 1) * offsetX;\n    // 3D blocks use an oblique projection that recedes up-and-right, so their\n    // diagonal stack must step UP regardless of the configured offsetY sign;\n    // 2D blocks keep the configured direction (e.g. down-right for 2D hundreds).\n    // A container is homogeneous, so the first block's dimensionality governs\n    // the whole stack. The slot reserves vertical pad for both directions where\n    // the stack can flip (see verticalPadFor's `bidirectional`).\n    var effectiveOffsetY = function () {\n        var threeD = blocks.length > 0\n            && blocks[0].custom != null\n            && blocks[0].custom.is3D === true;\n        return threeD ? Math.abs(offsetY) : offsetY;\n    };\n    var offsetFor = function (i) {\n        var oy = effectiveOffsetY();\n        if (infinite) {\n            return { x: i * offsetX, y: i * oy };\n        }\n        var stack = Math.floor(i / per);\n        var pos = i % per;\n        return {\n            x: stack * (fullStackWidth + stackGap) + pos * offsetX,\n            y: pos * oy,\n        };\n    };\n    var widthForN = function (n) {\n        if (n <= 0)\n            return 0;\n        if (infinite)\n            return unitWidth + (n - 1) * offsetX;\n        var lastIdx = n - 1;\n        var lastStack = Math.floor(lastIdx / per);\n        var lastPos = lastIdx % per;\n        return (lastStack * (fullStackWidth + stackGap)\n            + unitWidth\n            + lastPos * offsetX);\n    };\n    return {\n        blocks: blocks,\n        add: function (block) {\n            if (blocks.length >= max)\n                return false;\n            if (blocks.indexOf(block) !== -1)\n                return false;\n            blocks.push(block);\n            return true;\n        },\n        remove: function (block) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return false;\n            blocks.splice(i, 1);\n            return true;\n        },\n        canAdd: function () {\n            return blocks.length < max;\n        },\n        width: function () {\n            return widthForN(blocks.length);\n        },\n        widthIfAdded: function () {\n            return widthForN(blocks.length + 1);\n        },\n        positionFor: function (block, originX, originY) {\n            var i = blocks.indexOf(block);\n            if (i === -1)\n                return null;\n            var o = offsetFor(i);\n            return new Fig.Point(originX + o.x, originY + o.y);\n        },\n        nextPosition: function (originX, originY) {\n            var o = offsetFor(blocks.length);\n            return new Fig.Point(originX + o.x, originY + o.y);\n        },\n        orderedBlocks: function () {\n            return blocks.slice();\n        },\n        // Report total footprint in cells. All blocks expose colOf=0 so the\n        // `group` gap never subdivides the diagonal — only its right edge is\n        // visible to the slot's column accounting.\n        cols: function () {\n            if (blocks.length === 0)\n                return 0;\n            return Math.ceil(widthForN(blocks.length) / cell);\n        },\n        colsIfAdded: function () {\n            return Math.ceil(widthForN(blocks.length + 1) / cell);\n        },\n        colOf: function (block) {\n            if (blocks.indexOf(block) === -1)\n                return null;\n            return 0;\n        },\n        nextCol: function () {\n            return 0;\n        },\n    };\n};\n// Analytic max-column-count: what `cols()` returns when the container is\n// filled to `mode.max` (or 10 if max is unset). Used to derive `num` before\n// any containers are built. `unitWidth` is the container's per-block width\n// (cell for tens/ones, 10*cell for hundreds); `cell` is the slot's cell.\nvar colsAtMax = function (mode, unitWidth, cell) {\n    var max = mode.max != null ? mode.max : 10;\n    if (max <= 0)\n        return 0;\n    var cellsPerBlock = Math.max(1, Math.round(unitWidth / cell));\n    if (mode.type === 'row') {\n        return max * cellsPerBlock;\n    }\n    if (mode.type === 'pack') {\n        return Math.ceil(max / mode.height) * cellsPerBlock;\n    }\n    // diagonal: project the full-capacity x-footprint onto the cell grid.\n    var offsetX = mode.offsetX;\n    var mps = mode.maxPerStack != null ? mode.maxPerStack : 0;\n    var sg = mode.stackGap != null ? mode.stackGap : 0;\n    var infinite = mps <= 0;\n    var widthAtMax = infinite\n        ? unitWidth + (max - 1) * offsetX\n        : Math.floor((max - 1) / mps) * (unitWidth + (mps - 1) * offsetX + sg)\n            + unitWidth + ((max - 1) % mps) * offsetX;\n    return Math.ceil(widthAtMax / cell);\n};\n// How much extra vertical space (above/below the standard slot height)\n// blocks in this container can occupy. Only diagonal stacks ever need pad —\n// row and pack stay within the 10-cell slot. `blockHeight` is the height of\n// one block of the container's type; `slotBaseHeight` is the slot's standard\n// numY * cell height (typically 1.0). Returns positive values that the slot\n// should add below baseY (`below`) and above the standard slot top (`above`).\n//\n// `bidirectional` is for stacks whose vertical direction is decided at layout\n// time (a diagonal whose blocks may be 2D — stepping down — or 3D — stepping\n// up; see makeDiagonalContainer.effectiveOffsetY). Because the slot's\n// rectangles are sized once at construction, before blocks load, such a stack\n// reserves pad on BOTH sides so either runtime direction fits. Fixed-direction\n// stacks (e.g. always-3D thousands) pass false and reserve only the side their\n// configured sign points to, avoiding wasted space. Callers also pass false\n// when the slot can't receive 3D blocks at all (no thousands container and no\n// depthSeparation), since a purely-2D diagonal never flips — see the\n// mayContain3D gate where accumulatePad is called.\nvar verticalPadFor = function (mode, blockHeight, slotBaseHeight, bidirectional) {\n    if (mode.type !== 'diagonal')\n        return { below: 0, above: 0 };\n    var max = mode.max != null ? mode.max : 10;\n    var mps = mode.maxPerStack != null ? mode.maxPerStack : 0;\n    var infinite = mps <= 0;\n    var per = infinite ? max : Math.min(mps, max);\n    if (per <= 1)\n        return { below: 0, above: 0 };\n    var mag = Math.abs(mode.offsetY);\n    if (mag === 0)\n        return { below: 0, above: 0 };\n    var stack = (per - 1) * mag;\n    var downPad = { below: stack, above: 0 };\n    var upPad = { below: 0, above: Math.max(0, stack + blockHeight - slotBaseHeight) };\n    if (bidirectional) {\n        return { below: downPad.below, above: upPad.above };\n    }\n    return mode.offsetY < 0 ? downPad : upPad;\n};\nvar makeContainer = function (unitWidth, cell, mode) {\n    var max = mode.max != null ? mode.max : 10;\n    if (mode.type === 'row') {\n        return makeRowContainer(unitWidth, cell, max, mode.groupSize != null ? mode.groupSize : 0, mode.groupSpace != null ? mode.groupSpace : 0);\n    }\n    if (mode.type === 'pack') {\n        return makePackContainer(unitWidth, cell, mode.height, max, mode.groupSize != null ? mode.groupSize : 0, mode.groupSpace != null ? mode.groupSpace : 0);\n    }\n    return makeDiagonalContainer(unitWidth, cell, mode.offsetX, mode.offsetY, mode.maxPerStack != null ? mode.maxPerStack : 0, mode.stackGap != null ? mode.stackGap : 0, max);\n};\nvar baseTenBlocksSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var style = options.style != null ? options.style : 'spaced';\n    var defaults = {\n        cell: 0.1,\n        fill: false,\n        yOffset: 0,\n        radius: -1,\n        sides: 10,\n        debug: false,\n        label: null,\n        xLabelOffset: 0,\n        yLabelOffset: 0,\n        font: {\n            size: 0.15,\n            color: [0.6, 0.6, 0.6, 1],\n            family: defaultFontFamilyMath,\n        },\n        border: {\n            color: [0.6, 0.6, 0.6, 1],\n            dash: [0.05, 0.01],\n            width: 0.005,\n            space: 0.01,\n        },\n        snapBorder: 0,\n        borderInSize: false,\n        correctness: true,\n        animationDuration: 0.3,\n        orderSpace: 0,\n        depthSeparation: false,\n        grid: false,\n        group: null,\n    };\n    // Per-style overrides merged in between `defaults` and user `options`.\n    // Each entry is a partial of the merged options shape; missing keys fall\n    // through to `defaults`, and any key the user passes still wins.\n    var styleNormalDefaults = {};\n    var styleGridDefaults = {\n        grid: true,\n        border: {\n            dash: false,\n            width: 0.007,\n        },\n    };\n    var styleFlatDefaults = {};\n    var styleSpacedDefaults = {\n        orderSpace: 0.05,\n    };\n    var styleStackedDefaults = {\n        orderSpace: 0.05,\n    };\n    var styleHundredsDefaults = {\n        orderSpace: 0,\n        grid: true,\n        group: { num: 10, space: 0.1 },\n        border: {\n            dash: false,\n            width: 0.007,\n        },\n    };\n    var styleThousandsDefaults = {\n        orderSpace: 0.05,\n        depthSeparation: true,\n    };\n    var stylePresets = {\n        normal: styleNormalDefaults,\n        grid: styleGridDefaults,\n        flat: styleFlatDefaults,\n        spaced: styleSpacedDefaults,\n        stacked: styleStackedDefaults,\n        hundreds: styleHundredsDefaults,\n        thousands: styleThousandsDefaults,\n    };\n    var o = Fig.joinObjects(defaults, stylePresets[style], options);\n    if (o.radius == -1) {\n        console.log(o.cell);\n        o.radius = o.cell * 0.25;\n    }\n    var numY = 10;\n    var styleOrderSpace = typeof stylePresets[style].orderSpace\n        === 'number'\n        ? stylePresets[style].orderSpace\n        : defaults.orderSpace;\n    var rawOrderSpace = options.orderSpace != null ? options.orderSpace : styleOrderSpace;\n    var orderSpaceFor = function (place) {\n        if (typeof rawOrderSpace === 'number')\n            return rawOrderSpace;\n        if (rawOrderSpace == null)\n            return 0;\n        var v = rawOrderSpace[place];\n        if (v != null)\n            return v;\n        return rawOrderSpace.default != null ? rawOrderSpace.default : 0;\n    };\n    var alwaysCenter = options.alwaysCenter != null ? options.alwaysCenter : false;\n    // Per-type default StackMode used when the spec is `true` or omitted-and-\n    // enabled. Like the option presets above, each style picks its own modes\n    // from this registry. Ones is always a pack of height 10.\n    //\n    // `diagOffset` is the diagonal step for a hundred (a 1-cell-deep slab). For a\n    // 3D block this step is the *visible* peek between blocks PLUS the block's\n    // own oblique depth — the projection eats into the step, so a deeper block\n    // needs a proportionally larger step to leave the same peek.\n    var diagOffset = 0.08;\n    var diagonalHundreds = {\n        type: 'diagonal',\n        offsetX: diagOffset,\n        offsetY: -diagOffset,\n        max: 3,\n        maxPerStack: 5,\n        stackGap: 0.03,\n    };\n    // Thousands are always 3D (oblique projection receding up-and-right), so\n    // their diagonal stack steps UP-and-right (positive offsetY) rather than\n    // down. The positive offsetY makes verticalPadFor reserve space above the\n    // slot, and layoutAll draws the stack back-to-front (newest behind) so each\n    // block's front face stays visible. See the 3D note in layoutAll.\n    //\n    // Oblique depth per place is depthCells * cell * 0.25 — a thousand cube is 10\n    // cells deep vs a hundred slab's 1. That extra depth (9 cells * 0.25 =\n    // 2.25 cells) is added to the thousands step so the VISIBLE peek between\n    // cubes (step minus depth) matches the hundreds' — equal offsets once depth\n    // is accounted for. Scales with `cell` so it holds at any block size.\n    var cubeDepthOffset = diagOffset + (10 - 1) * o.cell * 0.25;\n    var diagonalThousands = {\n        type: 'diagonal',\n        offsetX: cubeDepthOffset,\n        offsetY: cubeDepthOffset,\n        max: 3,\n        maxPerStack: 5,\n        stackGap: 0.03,\n    };\n    var groupedRow = {\n        type: 'row',\n        groupSize: 5,\n        groupSpace: 0.03,\n    };\n    var plainRow = { type: 'row' };\n    var onesPack = { type: 'pack', height: numY };\n    // Thousands mirrors hundreds in every style: diagonal where hundreds is\n    // diagonal (normal/stacked), plain/grouped row otherwise.\n    var styleModePresets = {\n        normal: {\n            thousands: diagonalThousands, hundreds: diagonalHundreds,\n            tens: groupedRow, ones: onesPack,\n        },\n        grid: {\n            thousands: plainRow, hundreds: plainRow, tens: plainRow, ones: onesPack,\n        },\n        flat: {\n            thousands: plainRow, hundreds: plainRow, tens: plainRow, ones: onesPack,\n        },\n        spaced: {\n            thousands: groupedRow, hundreds: groupedRow,\n            tens: groupedRow, ones: onesPack,\n        },\n        stacked: {\n            thousands: diagonalThousands, hundreds: diagonalHundreds,\n            tens: groupedRow, ones: onesPack,\n        },\n        hundreds: {\n            thousands: plainRow, hundreds: plainRow, tens: plainRow, ones: onesPack,\n        },\n        thousands: {\n            thousands: diagonalThousands, hundreds: diagonalHundreds,\n            tens: groupedRow, ones: onesPack,\n        },\n    };\n    var defaultModes = styleModePresets[style];\n    var normalizeSpec = function (spec, enabledByDefault, defaultMode) {\n        if (spec === undefined)\n            return enabledByDefault ? defaultMode : null;\n        if (spec === false)\n            return null;\n        if (spec === true)\n            return defaultMode;\n        if (typeof spec === 'number') {\n            return Object.assign({}, defaultMode, { max: spec });\n        }\n        return spec;\n    };\n    var thousandsMode = normalizeSpec(o.thousands, false, defaultModes.thousands);\n    var hundredsMode = normalizeSpec(o.hundreds, false, defaultModes.hundreds);\n    var tensMode = normalizeSpec(o.tens, true, defaultModes.tens);\n    var onesMode = normalizeSpec(o.ones, true, defaultModes.ones);\n    // Per-type unit width: thousands and hundreds blocks span 10 cells,\n    // tens/ones one.\n    var unitWidthFor = function (type) {\n        return type === 'thousands' || type === 'hundreds' ? 10 * o.cell : o.cell;\n    };\n    // If `num` wasn't passed, derive it from the enabled containers' max\n    // column counts. `orderSpace` is purely visual and doesn't consume\n    // column budget; `group.space` likewise — both only inflate the\n    // rendered footprint.\n    var num;\n    if (o.num != null) {\n        num = o.num;\n    }\n    else {\n        var colsList = [];\n        if (thousandsMode != null) {\n            colsList.push(colsAtMax(thousandsMode, unitWidthFor('thousands'), o.cell));\n        }\n        if (hundredsMode != null) {\n            colsList.push(colsAtMax(hundredsMode, unitWidthFor('hundreds'), o.cell));\n        }\n        if (tensMode != null) {\n            colsList.push(colsAtMax(tensMode, unitWidthFor('tens'), o.cell));\n        }\n        if (onesMode != null) {\n            colsList.push(colsAtMax(onesMode, unitWidthFor('ones'), o.cell));\n        }\n        num = Math.max(1, colsList.reduce(function (a, b) { return a + b; }, 0));\n    }\n    // Normalize `group`: apply field defaults (num=10, space=0), then treat\n    // a zero-or-negative result as no-gap so the renderer can short-circuit.\n    var groupNum = o.group != null && o.group.num != null ? o.group.num : 10;\n    var groupSpaceVal = o.group != null && o.group.space != null\n        ? o.group.space\n        : 0;\n    var group = o.group != null && groupNum > 0 && groupSpaceVal > 0\n        ? { num: groupNum, space: groupSpaceVal }\n        : null;\n    // Optional name filter applied slot-wide: a block is only treated as\n    // available (for buttons and programmatic animateBlock) when its element\n    // `name` matches this regex. Accepts a RegExp or a string (compiled here).\n    // Null when unset.\n    var nameRegex = o.nameRegex == null\n        ? null\n        : (o.nameRegex instanceof RegExp ? o.nameRegex : new RegExp(o.nameRegex));\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var borderDefaults = {\n        color: [0.6, 0.6, 0.6, 1],\n        width: 0.02,\n        space: 0.01,\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n    };\n    var fillDefaults = {\n        color: [0, 0, 0, 0],\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n    };\n    var gridDefaults = {\n        color: [0.8, 0.8, 0.8, 1],\n        width: 0.005,\n        dash: undefined,\n        // Highlight defaults (n: 10, border-styled) are applied by the\n        // normalization block below rather than here, so user values flow\n        // through joinObjects without type collisions when highlight is set\n        // as a boolean.\n    };\n    if (o.border === true) {\n        o.border = borderDefaults;\n    }\n    else if (o.border) {\n        o.border = joinObjects(borderDefaults, o.border);\n    }\n    if (o.fill === true) {\n        o.fill = fillDefaults;\n    }\n    else if (o.fill) {\n        o.fill = joinObjects(fillDefaults, o.fill);\n    }\n    if (o.grid === true) {\n        o.grid = gridDefaults;\n    }\n    else if (o.grid && typeof o.grid === 'object') {\n        o.grid = joinObjects({}, gridDefaults, o.grid);\n    }\n    // Normalize highlight: false → off, true → defaults, object → overrides.\n    // Color/width/dash inherit from the border (o.border) when one is configured;\n    // otherwise fall back to the base grid's values. `n` defaults to 10.\n    if (o.grid && typeof o.grid === 'object') {\n        if (o.grid.highlight === false) {\n            o.grid.highlight = { n: 0 };\n        }\n        else {\n            var hl = (o.grid.highlight === true || o.grid.highlight == null)\n                ? {}\n                : o.grid.highlight;\n            var border_1 = o.border && typeof o.border === 'object' ? o.border : null;\n            var fb = function (onHl, onBorder, onGrid) { return (onHl != null ? onHl : (border_1 != null ? onBorder : onGrid)); };\n            o.grid.highlight = {\n                n: hl.n != null ? hl.n : 10,\n                color: fb(hl.color, border_1 != null ? border_1.color : undefined, o.grid.color),\n                width: fb(hl.width, border_1 != null ? border_1.width : undefined, o.grid.width),\n                dash: fb(hl.dash, border_1 != null ? border_1.dash : undefined, o.grid.dash),\n            };\n        }\n    }\n    // Group count and rendered footprint. `num` is the column budget;\n    // `renderedWidth` adds the (G-1) inter-group gaps when `group` is set.\n    var numGroups = group ? Math.ceil(num / group.num) : 1;\n    var gapSpacing = group ? group.space : 0;\n    var renderedWidth = num * o.cell + Math.max(0, numGroups - 1) * gapSpacing;\n    // Compute extra vertical pad from diagonal stacks. The slot's visual area\n    // expands by padBelow below baseY and padAbove above the standard slot top.\n    // Block placement (contentOrigin) stays anchored at o.yOffset; only the\n    // rendered rectangles (fill/border/snapBorder), the label center, and the\n    // button strip's anchor shift.\n    var slotBaseHeight = o.cell * numY;\n    var padBelow = 0;\n    var padAbove = 0;\n    var accumulatePad = function (mode, blockH, bidirectional) {\n        if (mode == null)\n            return;\n        var p = verticalPadFor(mode, blockH, slotBaseHeight, bidirectional);\n        if (p.below > padBelow)\n            padBelow = p.below;\n        if (p.above > padAbove)\n            padAbove = p.above;\n    };\n    // A diagonal stack of lower places (hundreds/tens/ones) flips its vertical\n    // direction at layout time only if its blocks turn out to be 3D (down for\n    // 2D, up for 3D — see makeDiagonalContainer.effectiveOffsetY). Reserving pad\n    // on both sides is therefore only needed when this slot can actually receive\n    // 3D blocks; for a purely-2D slot it would just add empty headroom and make\n    // the border taller. We can't introspect block dimensionality at construction\n    // (blocks aren't attached yet), so we gate on the construction-time signals\n    // that imply 3D: a thousands container (thousands are always 3D, so hundreds\n    // alongside them are too) or depthSeparation (set by the 'thousands' style).\n    var mayContain3D = thousandsMode != null || o.depthSeparation === true;\n    // Thousands are always 3D → fixed up-right, so reserve pad above only.\n    accumulatePad(thousandsMode, 10 * o.cell, false);\n    accumulatePad(hundredsMode, 10 * o.cell, mayContain3D);\n    accumulatePad(tensMode, 10 * o.cell, mayContain3D);\n    accumulatePad(onesMode, o.cell, mayContain3D);\n    var height = slotBaseHeight + padBelow + padAbove;\n    var slotYBase = o.yOffset - padBelow;\n    var borderOffset = o.border && o.border.show !== false ? o.border.width / 2 : 0;\n    var borderSpace = o.border ? (o.border.space != null ? o.border.space : 0.01) : 0;\n    // World x of the left edge of group `g` (relative to the element).\n    var groupXAt = function (g) {\n        return borderOffset + g * group.num * o.cell + g * gapSpacing;\n    };\n    // For the single-group case (no `group` gap), the whole slot is one group.\n    var singleGroupX = borderOffset;\n    // Per-group fill/grid/border arrays. Length always matches numGroups;\n    // showCorrectness iterates these so all groups recolor in lockstep.\n    var fills = [];\n    var borders = [];\n    // \"To-snap\" slot overlays. One per group; rendered behind grid lines\n    // (toSnapFills) and on top of the normal border (toSnapBorders). Hidden\n    // via .hide() until this slot becomes the to-snap target, then .show().\n    // (Initial color-alpha-0 doesn't work for line-only rectangles in\n    // FigureOne — the line still anti-aliases its outline into the canvas.)\n    // A separate transparent tapCapture rectangle handles the \"tap the slot\n    // itself\" interaction since hidden elements aren't touchable.\n    var toSnapFills = [];\n    var toSnapBorders = [];\n    // `toSnapSlot: false` disables the highlight: the overlays are never built,\n    // so nothing renders, while tap/snap routing to the to-snap target stays\n    // intact (it lives on tapCaptures and setAsToSnap, not these overlays).\n    var toSnapDisabled = o.toSnapSlot === false;\n    var toSnapOpt = (o.toSnapSlot != null && o.toSnapSlot !== false)\n        ? o.toSnapSlot\n        : {};\n    var toSnapFillColor = toSnapOpt.fillColor != null\n        ? toSnapOpt.fillColor\n        : [0.88, 0.94, 1, 0];\n    var toSnapBorderColor = toSnapOpt.borderColor != null\n        ? toSnapOpt.borderColor\n        : [0, 0.478, 0.823, 1];\n    // The to-snap border defaults to mirror the actual border (when one is\n    // configured): same dash pattern, line width scaled up 20% so the\n    // highlight reads as a \"thicker version\" of the slot's normal outline.\n    var regularBorderWidth = o.border && o.border.width != null ? o.border.width : 0;\n    var regularBorderDash = o.border && o.border.dash != null && o.border.dash !== false\n        ? o.border.dash\n        : undefined;\n    var toSnapBorderWidth = toSnapOpt.borderWidth != null\n        ? toSnapOpt.borderWidth\n        : (regularBorderWidth > 0 ? regularBorderWidth * 1.4 : 0.007);\n    // Default space sits the two border lines edge-to-edge: outer edge of\n    // the regular border meets the inner edge of the to-snap border.\n    var toSnapBorderSpace = toSnapOpt.space != null\n        ? toSnapOpt.space\n        : 0;\n    // Default radius keeps the to-snap border's corners parallel to the\n    // regular border by growing the slot radius by the same outset.\n    var toSnapBorderRadius = toSnapOpt.radius != null\n        ? toSnapOpt.radius\n        : o.radius + toSnapBorderSpace;\n    var toSnapBorderDash = toSnapOpt.dash != null\n        ? toSnapOpt.dash\n        : regularBorderDash;\n    var tapCaptures = [];\n    for (var g = 0; g < numGroups; g += 1) {\n        var startCol = group ? g * group.num : 0;\n        var endCol = group ? Math.min(startCol + group.num, num) : num;\n        var colsInGroup = roundNum(endCol - startCol);\n        var groupW = colsInGroup * o.cell;\n        var groupX = group ? groupXAt(g) : singleGroupX;\n        var nameSuffix = numGroups > 1 ? \"_\".concat(g) : '';\n        if (o.fill) {\n            var f = element.add({\n                make: 'rectangle',\n                name: \"fill\".concat(nameSuffix),\n                width: groupW,\n                height: height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                color: o.fill.color,\n                corner: { radius: o.radius, sides: o.sides },\n                position: [groupX, slotYBase],\n            });\n            fills.push(f);\n        }\n        // Transparent tap-capture rectangle. Always shown but fully transparent\n        // (color [0,0,0,0]) so it contributes no visible pixels but still\n        // receives click events. This is the \"tap the slot itself\" interaction\n        // target; the toSnap overlays behind it can be hidden/shown without\n        // affecting touch.\n        var tc = element.add({\n            make: 'rectangle',\n            name: \"tapCapture\".concat(nameSuffix),\n            width: groupW,\n            height: height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: [0, 0, 0, 0],\n            corner: { radius: o.radius, sides: o.sides },\n            position: [groupX, slotYBase],\n            touch: true,\n        });\n        tc.border = [[]];\n        tapCaptures.push(tc);\n        // To-snap fill overlay. Visible when this slot is the to-snap target;\n        // hidden otherwise. Added after the regular fill so it can show\n        // through when shown; grid lines render on top. Skipped entirely when\n        // the highlight is disabled.\n        if (!toSnapDisabled) {\n            var tsf = element.add({\n                make: 'rectangle',\n                name: \"toSnapFill\".concat(nameSuffix),\n                width: groupW,\n                height: height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                color: toSnapFillColor,\n                corner: { radius: o.radius, sides: o.sides },\n                position: [groupX, slotYBase],\n            });\n            tsf.border = [[]];\n            tsf.hide();\n            toSnapFills.push(tsf);\n        }\n        // Grid lines for this group. Interior verticals span the group's column\n        // range; horizontals span the group's width. Highlight lines are skipped\n        // when there's more than one group — per-group rendering already provides\n        // its own visual emphasis through the inter-group whitespace.\n        if (o.grid && typeof o.grid === 'object') {\n            if (colsInGroup >= 2) {\n                element.add({\n                    make: 'line',\n                    color: o.grid.color,\n                    p1: [groupX + o.cell, o.yOffset],\n                    p2: [groupX + o.cell, o.yOffset + slotBaseHeight],\n                    width: o.grid.width,\n                    dash: o.grid.dash,\n                    copy: { along: 'x', step: o.cell, num: colsInGroup - 2 },\n                });\n            }\n            if (numY > 1) {\n                element.add({\n                    make: 'line',\n                    color: o.grid.color,\n                    p1: [groupX, o.yOffset + o.cell],\n                    p2: [groupX + groupW, o.yOffset + o.cell],\n                    width: o.grid.width,\n                    dash: o.grid.dash,\n                    copy: { along: 'y', step: o.cell, num: numY - 2 },\n                });\n            }\n            var hl = o.grid.highlight;\n            if (numGroups === 1 && hl != null && hl.n > 0) {\n                var vCount = Math.floor((colsInGroup - 1) / hl.n);\n                if (vCount >= 1) {\n                    element.add({\n                        make: 'line',\n                        color: hl.color,\n                        p1: [groupX + hl.n * o.cell, o.yOffset],\n                        p2: [groupX + hl.n * o.cell, o.yOffset + slotBaseHeight],\n                        width: hl.width,\n                        dash: hl.dash,\n                        copy: { along: 'x', step: hl.n * o.cell, num: vCount - 1 },\n                    });\n                }\n                var hCount = Math.floor((numY - 1) / hl.n);\n                if (hCount >= 1) {\n                    element.add({\n                        make: 'line',\n                        color: hl.color,\n                        p1: [groupX, o.yOffset + hl.n * o.cell],\n                        p2: [groupX + colsInGroup * o.cell, o.yOffset + hl.n * o.cell],\n                        width: hl.width,\n                        dash: hl.dash,\n                        copy: { along: 'y', step: hl.n * o.cell, num: hCount - 1 },\n                    });\n                }\n            }\n        }\n        if (o.border) {\n            var b = element.add({\n                make: 'rectangle',\n                name: \"border\".concat(nameSuffix),\n                width: groupW + borderSpace * 2,\n                height: height + borderSpace * 2,\n                color: o.border.color,\n                line: { width: o.border.width, dash: o.border.dash },\n                xAlign: 'left',\n                yAlign: 'bottom',\n                corner: { radius: o.radius, sides: o.sides },\n                position: [groupX - borderSpace, -borderSpace + slotYBase],\n            });\n            b.custom.initialColor = b.color.slice();\n            if (o.borderInSize === false) {\n                b.border = [\n                    [\n                        new Fig.Point(0, 0),\n                        new Fig.Point(groupW + borderSpace * 2, 0),\n                        new Fig.Point(groupW + borderSpace * 2, height + borderSpace * 2),\n                        new Fig.Point(0, height + borderSpace * 2),\n                    ],\n                ];\n            }\n            borders.push(b);\n        }\n        // To-snap border overlay. Sits on top of the normal border so it can\n        // visually replace it when the slot is the to-snap target. `space`\n        // pushes the highlight further out from the regular border. Hidden\n        // initially. Skipped entirely when the highlight is disabled.\n        if (!toSnapDisabled) {\n            var tsbSpace = borderSpace + toSnapBorderSpace;\n            var tsb = element.add({\n                make: 'rectangle',\n                name: \"toSnapBorder\".concat(nameSuffix),\n                width: groupW + tsbSpace * 2,\n                height: height + tsbSpace * 2,\n                color: toSnapBorderColor,\n                line: { width: toSnapBorderWidth, dash: toSnapBorderDash },\n                xAlign: 'left',\n                yAlign: 'bottom',\n                corner: { radius: toSnapBorderRadius, sides: o.sides },\n                position: [groupX - tsbSpace, -tsbSpace + slotYBase],\n            });\n            tsb.border = [[]];\n            tsb.hide();\n            toSnapBorders.push(tsb);\n        }\n    }\n    if (o.label) {\n        var label = typeof o.label === 'number' ? o.label.toString() : o.label;\n        var slotFont = {\n            size: o.font.size,\n            family: o.font.family,\n            render: 'gl',\n            color: o.font.color,\n        };\n        setAtlasId(slotFont);\n        element.add({\n            make: 'equation',\n            forms: { '0': label },\n            formDefaults: {\n                alignment: { xAlign: 'center', yAlign: 'middle' },\n            },\n            font: slotFont,\n            xAlign: 'center',\n            yAlign: 'middle',\n            position: [\n                borderOffset + renderedWidth / 2 + o.xLabelOffset,\n                height / 2 + o.yLabelOffset + slotYBase,\n            ],\n            scale: 1,\n        });\n    }\n    element.preserveChildColor = true;\n    if (o.debug) {\n        for (var i = 0; i < num; i += 1) {\n            // Markers track column position including any gap spacings absorbed.\n            var groupIdx = group ? Math.floor(i / group.num) : 0;\n            var xCell = borderOffset + i * o.cell + groupIdx * gapSpacing;\n            for (var j = 0; j < numY; j += 1) {\n                element.add({\n                    make: 'polygon',\n                    sides: 10,\n                    radius: 0.005,\n                    color: [0, 0, 0, 1],\n                    position: [\n                        xCell + o.cell / 2,\n                        j * o.cell + o.cell / 2 + o.yOffset,\n                    ],\n                });\n            }\n        }\n        element.add({\n            make: 'rectangle',\n            name: 'snapBorder',\n            width: renderedWidth + o.snapBorder * 2,\n            height: height + o.snapBorder * 2,\n            color: o.border ? o.border.color : [0.6, 0.6, 0.6, 1],\n            line: { width: 0.005, dash: [0.02, 0.02] },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            position: [borderOffset - o.snapBorder, -o.snapBorder + o.yOffset],\n        });\n    }\n    element.custom.manipulativeType = 'baseTenBlocksSlot';\n    // Each enabled container owns one block type and lays out its blocks\n    // according to its configured stacking mode. Hundreds blocks span 10 cell\n    // units; tens and ones span 1. Disabled containers (mode === null) are\n    // omitted entirely — `containers` only iterates the enabled set, and\n    // `containerFor` returns null for any block whose type was disabled.\n    var thousandsContainer = thousandsMode != null\n        ? makeContainer(10 * o.cell, o.cell, thousandsMode)\n        : null;\n    var hundredsContainer = hundredsMode != null\n        ? makeContainer(10 * o.cell, o.cell, hundredsMode)\n        : null;\n    var tensContainer = tensMode != null\n        ? makeContainer(o.cell, o.cell, tensMode)\n        : null;\n    var onesContainer = onesMode != null\n        ? makeContainer(o.cell, o.cell, onesMode)\n        : null;\n    var containers = [];\n    if (thousandsContainer != null)\n        containers.push(thousandsContainer);\n    if (hundredsContainer != null)\n        containers.push(hundredsContainer);\n    if (tensContainer != null)\n        containers.push(tensContainer);\n    if (onesContainer != null)\n        containers.push(onesContainer);\n    // snappedBlocks mirrors the union of container.blocks in insertion order;\n    // kept for back-compat with code that iterates the slot's snapped blocks.\n    element.snappedBlocks = [];\n    // refreshButtons defaults to a no-op; replaced with the real implementation\n    // below if any buttons are enabled. The snap/unsnap/commitSnap methods\n    // call it after every state change to keep button enabled state current.\n    element.refreshButtons = function () { };\n    // ── To-snap slot tracking ────────────────────────────────────────\n    // The \"to-snap\" slot is the one tap-snapped blocks land in. Stored on\n    // the parent equation (toAdd) so all sibling slots share one ref.\n    var getSiblingSlots = function () {\n        var out = [];\n        var els = toAdd.elements;\n        if (els == null)\n            return out;\n        var names = Object.keys(els);\n        for (var i = 0; i < names.length; i += 1) {\n            var el = els[names[i]];\n            if (el != null\n                && el.custom != null\n                && el.custom.manipulativeType === 'baseTenBlocksSlot') {\n                out.push(el);\n            }\n        }\n        return out;\n    };\n    // Re-render this slot's to-snap overlays based on shared state. Hidden\n    // when fewer than two slots exist, when this slot isn't the chosen\n    // to-snap target, or while a correctness color is being shown\n    // (correctness wins). Uses .hide()/.show() rather than alpha-0 —\n    // line-only rectangles in FigureOne still anti-alias their outline into\n    // the canvas when colored alpha 0, which produces visible snapshot diffs.\n    element.custom.refreshToSnapHighlight = function () {\n        var siblings = getSiblingSlots();\n        var multi = siblings.length >= 2;\n        var isToSnap = multi && toAdd.custom != null\n            && toAdd.custom.toSnapBaseTenBlocksSlot === element;\n        var visible = isToSnap && !element.custom.showingCorrectness;\n        for (var i = 0; i < toSnapFills.length; i += 1) {\n            if (visible) {\n                toSnapFills[i].show();\n            }\n            else {\n                toSnapFills[i].hide();\n            }\n        }\n        for (var i = 0; i < toSnapBorders.length; i += 1) {\n            if (visible) {\n                toSnapBorders[i].show();\n            }\n            else {\n                toSnapBorders[i].hide();\n            }\n        }\n        element.custom.isToSnap = isToSnap;\n    };\n    element.setAsToSnap = function () {\n        if (toAdd.custom == null)\n            toAdd.custom = {};\n        toAdd.custom.toSnapBaseTenBlocksSlot = element;\n        var siblings = getSiblingSlots();\n        for (var i = 0; i < siblings.length; i += 1) {\n            var s = siblings[i];\n            if (s.custom != null && typeof s.custom.refreshToSnapHighlight === 'function') {\n                s.custom.refreshToSnapHighlight();\n            }\n        }\n    };\n    for (var i = 0; i < tapCaptures.length; i += 1) {\n        tapCaptures[i].notifications.add('onClick', function () {\n            element.setAsToSnap();\n        });\n    }\n    // Expose the per-type arrays as live references to the container's blocks.\n    // Disabled types return an empty array so callers reading e.g.\n    // element.hundreds.length always get a number.\n    Object.defineProperty(element, 'thousands', {\n        get: function () { return (thousandsContainer != null ? thousandsContainer.blocks : []); },\n    });\n    Object.defineProperty(element, 'hundreds', {\n        get: function () { return (hundredsContainer != null ? hundredsContainer.blocks : []); },\n    });\n    Object.defineProperty(element, 'tens', {\n        get: function () { return (tensContainer != null ? tensContainer.blocks : []); },\n    });\n    Object.defineProperty(element, 'ones', {\n        get: function () { return (onesContainer != null ? onesContainer.blocks : []); },\n    });\n    var blockType = function (block) {\n        if (block.custom.n === 1000)\n            return 'thousand';\n        if (block.custom.n === 100)\n            return 'hundred';\n        if (block.custom.n === 10)\n            return 'ten';\n        if (block.custom.n === 1)\n            return 'one';\n        return null;\n    };\n    // Returns null for blocks whose type is disabled — callers (cell,\n    // commitSnap, getTargetPositionFor, unsnap) already treat null as\n    // \"rejected\" / \"no-op\", so a disabled type just falls through unchanged.\n    var containerFor = function (block) {\n        var t = blockType(block);\n        if (t === 'thousand')\n            return thousandsContainer;\n        if (t === 'hundred')\n            return hundredsContainer;\n        if (t === 'ten')\n            return tensContainer;\n        if (t === 'one')\n            return onesContainer;\n        return null;\n    };\n    // Inner content origin in world coordinates (bottom-left of the area\n    // where blocks are placed, just inside the border).\n    var contentOrigin = function () {\n        var p = element.getPosition();\n        return { x: p.x + borderOffset, y: p.y + o.yOffset };\n    };\n    // Cumulative column-gap offset at absolute column `absCol`. The gap is\n    // inserted BEFORE the column (e.g. with num=10 the boundary between cols\n    // 9 and 10 absorbs one space). When `group` is unset, always 0.\n    var colGapAt = function (absCol) {\n        if (group == null)\n            return 0;\n        return Math.floor(absCol / group.num) * group.space;\n    };\n    // Cumulative columns consumed by all containers strictly preceding\n    // `target`. If `hypothetical` is set, that container is treated as if one\n    // more block had been added (so its colsIfAdded() is used).\n    var containerStartCol = function (target, hypothetical) {\n        var n = 0;\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            if (c === target)\n                return n;\n            var len = c === hypothetical ? c.blocks.length + 1 : c.blocks.length;\n            if (len > 0) {\n                n += c === hypothetical ? c.colsIfAdded() : c.cols();\n            }\n        }\n        return n;\n    };\n    // Total column footprint across all containers. With `hypothetical`,\n    // that container contributes colsIfAdded() instead of cols().\n    var totalCols = function (hypothetical) {\n        var n = 0;\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            var len = c === hypothetical ? c.blocks.length + 1 : c.blocks.length;\n            if (len > 0) {\n                n += c === hypothetical ? c.colsIfAdded() : c.cols();\n            }\n        }\n        return n;\n    };\n    // Oblique depth a container's 3D blocks project up-and-right beyond their\n    // footprint: depthCells * cell * 0.25 (matching baseTenBlocks — a thousand\n    // cube is 10 deep, every other place 1). 0 for an empty container or 2D\n    // blocks. Drives the depthSeparation gap (see gapAfter).\n    var containerDepth = function (c) {\n        if (c.blocks.length === 0)\n            return 0;\n        var b0 = c.blocks[0];\n        if (b0.custom == null || b0.custom.is3D !== true)\n            return 0;\n        var depthCells = b0.custom.n >= 1000 ? 10 : 1;\n        return depthCells * o.cell * 0.25;\n    };\n    // Place identity of a container, used to look up its per-place orderSpace.\n    var containerPlace = function (c) {\n        if (c === thousandsContainer)\n            return 'thousands';\n        if (c === hundredsContainer)\n            return 'hundreds';\n        if (c === tensContainer)\n            return 'tens';\n        if (c === onesContainer)\n            return 'ones';\n        return null;\n    };\n    // World x of a container's bottom-left, including any column-gap absorbed\n    // before its starting column plus orderSpace (and, when depthSeparation is\n    // on, a depth-scaled gap) accumulated across non-empty prior containers.\n    // positionFor/nextPosition then add the per-block local x and the slot adds\n    // the per-block `group` delta on top.\n    //\n    // The gap after a container is its place's orderSpace (so e.g.\n    // `orderSpace.thousands` widens only the thousands→hundreds boundary) plus,\n    // when depthSeparation is on, a depth term added TWICE: once to clear the\n    // block's oblique projection (the next place would otherwise sit inside the\n    // cube), and once more as a visible gap that scales with depth. Without the\n    // second depth term a single low cube clears by only orderSpace and reads as\n    // \"no separation\", since its projection sits at the next place's height; with\n    // it, even one cube has a depth-sized gap. The container's width() already\n    // grows with block count, so the total separation tracks both depth AND\n    // block count.\n    var gapAfter = function (prevPlace, prevDepth) {\n        return (prevPlace != null ? orderSpaceFor(prevPlace) : 0)\n            + (o.depthSeparation ? 1 * prevDepth : 0);\n    };\n    // Total left-anchored width of the snapped content: container footprints plus\n    // the gaps between them, independent of any centering offset. Used by\n    // centerOffsetX to decide how far to shift everything. `hypothetical` counts\n    // that container as if one more block had been added (its widthIfAdded()), so\n    // a block being placed is centered for the post-add content — otherwise it\n    // would animate from the pre-add centering to the post-add one (most visible\n    // on the very first block, which has no siblings reflowing to mask it).\n    var contentWidth = function (hypothetical) {\n        var w = 0;\n        var prevNonEmpty = false;\n        var prevDepth = 0;\n        var prevPlace = null;\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            var len = c === hypothetical ? c.blocks.length + 1 : c.blocks.length;\n            if (len === 0)\n                continue;\n            if (prevNonEmpty)\n                w += gapAfter(prevPlace, prevDepth);\n            w += c === hypothetical ? c.widthIfAdded() : c.width();\n            prevNonEmpty = true;\n            prevDepth = containerDepth(c);\n            prevPlace = containerPlace(c);\n        }\n        return w;\n    };\n    // Single global x shift applied to every block so the content sits centered\n    // in the slot (see the `alwaysCenter` option). false → 0 (left-anchored).\n    // true → content continuously centered. number N → centered, but the shift\n    // only changes when the content width crosses a multiple of N cells, so small\n    // additions don't reflow the layout.\n    var centerOffsetX = function (hypothetical) {\n        if (alwaysCenter === false)\n            return 0;\n        var w = contentWidth(hypothetical);\n        if (w <= 0)\n            return 0;\n        var effW = w;\n        if (typeof alwaysCenter === 'number' && alwaysCenter > 0) {\n            var step = alwaysCenter * o.cell;\n            effW = Math.ceil(w / step) * step;\n        }\n        return (renderedWidth - effW) / 2;\n    };\n    var containerOriginX = function (target, hypothetical) {\n        var baseX = contentOrigin().x;\n        var x = baseX + centerOffsetX(hypothetical);\n        var prevNonEmpty = false;\n        var prevDepth = 0;\n        var prevPlace = null;\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            if (c === target) {\n                if (prevNonEmpty)\n                    x += gapAfter(prevPlace, prevDepth);\n                return x + colGapAt(containerStartCol(target, hypothetical));\n            }\n            var willBeNonEmpty = c.blocks.length > 0 || c === hypothetical;\n            if (willBeNonEmpty) {\n                if (prevNonEmpty)\n                    x += gapAfter(prevPlace, prevDepth);\n                x += c === hypothetical ? c.widthIfAdded() : c.width();\n                prevNonEmpty = true;\n                prevDepth = containerDepth(c);\n                prevPlace = containerPlace(c);\n            }\n        }\n        return x;\n    };\n    // World x of `block` within container `c`. Wraps c.positionFor with the\n    // per-block `group` delta — the extra figure units of gap-space that\n    // accumulated between the container's starting column and the block's\n    // own column.\n    var blockWorldPosition = function (block, c) {\n        var baseY = contentOrigin().y;\n        var base = c.positionFor(block, containerOriginX(c), baseY);\n        if (base == null)\n            return null;\n        var col = c.colOf(block);\n        if (col == null || group == null)\n            return base;\n        var startCol = containerStartCol(c);\n        var extra = colGapAt(startCol + col) - colGapAt(startCol);\n        return new Fig.Point(base.x + extra, base.y);\n    };\n    // World x of the next-to-be-added position for container `c`.\n    var containerNextWorldPosition = function (c) {\n        var baseY = contentOrigin().y;\n        var base = c.nextPosition(containerOriginX(c, c), baseY);\n        if (base == null)\n            return null;\n        if (group == null)\n            return base;\n        var startCol = containerStartCol(c, c);\n        var nextCol = c.nextCol();\n        var extra = colGapAt(startCol + nextCol) - colGapAt(startCol);\n        return new Fig.Point(base.x + extra, base.y);\n    };\n    var slotBorderBounds = function () {\n        var p = element.getPosition();\n        return new Fig.Rect(p.x + borderOffset - (o.debug ? 0 : o.snapBorder), p.y + o.yOffset - (o.debug ? 0 : o.snapBorder), renderedWidth + o.snapBorder * 2, height + o.snapBorder * 2);\n    };\n    // Animate `block` to `target`. If close enough or duration is 0, snap to\n    // it synchronously.\n    var animateBlockTo = function (block, target, duration, onArrive) {\n        if (duration === 0 ||\n            block.getPosition().sub(target).distance() < 0.001) {\n            block.setPosition(target);\n            block.custom.state.p = block.getPosition();\n            if (onArrive)\n                onArrive();\n            return;\n        }\n        block.stopAnimating();\n        suppressManipulativeTouch(block);\n        // Name the completion trigger via fnMap (owner = fig.elements) so the state-commit +\n        // touch-release survive speech pause/resume: an inline .trigger is dropped from\n        // figure.getState(), so a pause mid-move would land the block but leave state.p stale\n        // and touch suppressed. Keyed by block name so the concurrent reflow in layoutAll\n        // (every block animates at once) never clobbers another block's callback. beforeFrame\n        // stays inline (can't be an fnMap string; doesn't block the position step serializing).\n        var arriveKey = \"btBlockArrive:\".concat(block.name);\n        fig.elements.fnMap.add(arriveKey, function () {\n            block.custom.state.p = block.getPosition();\n            releaseManipulativeTouch(block);\n            if (onArrive)\n                onArrive();\n        });\n        fig.elements.animations\n            .new()\n            .position({\n            element: block,\n            target: target,\n            duration: duration,\n            beforeFrame: function () {\n                block.custom.state.p = block.getPosition();\n            },\n        })\n            .trigger({ callback: arriveKey })\n            .start();\n    };\n    // Map a container back to its StackMode (null for the unreachable case of a\n    // container with no matching mode).\n    var modeOf = function (c) {\n        if (c === thousandsContainer)\n            return thousandsMode;\n        if (c === hundredsContainer)\n            return hundredsMode;\n        if (c === tensContainer)\n            return tensMode;\n        if (c === onesContainer)\n            return onesMode;\n        return null;\n    };\n    // A 3D diagonal stack must draw back-to-front: the newest block sits up-and-\n    // right and BEHIND the older ones, so every block's front face stays\n    // visible. Detected from the blocks (custom.is3D) rather than the mode,\n    // since 3D-ness is a property of the block, not the container. (Diagonal 3D\n    // stacks also step up via the up-right diagonal mode — e.g. diagonalThousands\n    // — so the cube's oblique depth and the stacking direction agree.)\n    var drawsBackToFront = function (c) {\n        var m = modeOf(c);\n        if (m == null || m.type !== 'diagonal')\n            return false;\n        return c.blocks.length > 0\n            && c.blocks[0].custom != null\n            && c.blocks[0].custom.is3D === true;\n    };\n    // Re-animate every snapped block to its container-derived position and\n    // refresh its snapPositionDelta so the setTransform handler tracks the\n    // current layout (not a pre-shift one).\n    var layoutAll = function (duration) {\n        var slotPos = element.getPosition();\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            if (c.blocks.length === 0)\n                continue;\n            // For 3D diagonal stacks, issue toFront newest-first so the OLDEST block\n            // (front-most, lower-left) ends up on top and newer blocks recede behind.\n            // Position assignment is order-independent (positionFor uses the block's\n            // index in c.blocks), so the reversed walk only affects draw order.\n            var order = drawsBackToFront(c) ? c.blocks.slice().reverse() : c.blocks;\n            for (var j = 0; j < order.length; j += 1) {\n                var block = order[j];\n                expression.toFront(block);\n                var target = blockWorldPosition(block, c);\n                if (target == null)\n                    continue;\n                block.snapPositionDelta = slotPos.sub(target);\n                animateBlockTo(block, target, duration);\n            }\n        }\n    };\n    // World position the block would land at if accepted right now. Returns\n    // null if either constraint rejects it: the container's intrinsic `max`,\n    // or the slot's `num` column budget.\n    element.getTargetPositionFor = function (block) {\n        var c = containerFor(block);\n        if (c == null)\n            return null;\n        if (!c.canAdd())\n            return null;\n        // Column budget is an integer comparison — no IEEE-754 drift.\n        if (totalCols(c) > num)\n            return null;\n        return containerNextWorldPosition(c);\n    };\n    // Internal: actually commit the block into its container and update the\n    // mirror list. Does not check width budget; caller must have done so.\n    var insertBlock = function (block) {\n        var c = containerFor(block);\n        if (c == null)\n            return false;\n        if (!c.add(block))\n            return false;\n        if (element.snappedBlocks.indexOf(block) === -1) {\n            element.snappedBlocks.push(block);\n        }\n        block.custom.snappedSlot = element;\n        block.custom.isSnapped = true;\n        // Mark the block moved so the equation's `layoutForms` relayout re-pins it\n        // to state.p (the snapped position) rather than resetting it to its\n        // equation-default (initial) position on the next relayout (e.g. an async\n        // font reload). A drag sets this via the block's 'moved' notification, but\n        // none of the programmatic snap paths (tap-snap commitSnap, the `snap` API,\n        // or a drag-style `animateBlock`) fire that — so every path that lands a\n        // block in a slot must set it here.\n        block.custom.moved = true;\n        return true;\n    };\n    // Synchronous variant: insert and place the block instantly. Other\n    // affected blocks animate via layoutAll. Returns false if it won't fit.\n    // `snap` is the programmatic write API (used by tests, content setup,\n    // etc.) and intentionally does NOT claim default-slot status — that's\n    // reserved for user-interaction paths (commitSnap and explicit tap).\n    element.snap = function (block) {\n        if (element.getTargetPositionFor(block) == null)\n            return false;\n        if (!insertBlock(block))\n            return false;\n        var c = containerFor(block);\n        if (c != null) {\n            var target = blockWorldPosition(block, c);\n            if (target != null)\n                block.setPosition(target);\n        }\n        block.custom.state.p = block.getPosition();\n        block.snapPositionDelta = element.getPosition().sub(block.getPosition());\n        layoutAll(o.animationDuration);\n        element.refreshButtons();\n        return true;\n    };\n    // Atomic commit + animate-in. State mutation happens BEFORE the animation\n    // so concurrent rapid taps see the updated capacity and either land at a\n    // different spot or are rejected.\n    element.commitSnap = function (block) {\n        if (element.getTargetPositionFor(block) == null)\n            return false;\n        if (!insertBlock(block))\n            return false;\n        // insertBlock sets block.custom.moved so this snap survives a layoutForms\n        // relayout (e.g. a font reload); a tap-snap never fires the block's 'moved'\n        // notification that a drag would.\n        // layoutAll sets snapPositionDelta for every block including this one,\n        // and animates each from its current position to its zone-derived\n        // target. Setting the delta now (rather than on-arrive) means the\n        // setTransform handler tracks the slot correctly mid-animation.\n        layoutAll(o.animationDuration);\n        element.refreshButtons();\n        element.setAsToSnap();\n        return true;\n    };\n    // Remove block from its container; ones above a removed one drop down,\n    // then reflow. For button-pool blocks, the caller (baseTenBlocks.ts\n    // tryTapSlotReturn) runs a dissolve-out animation before invoking this,\n    // so unsnap stays synchronous and dissolve-free.\n    element.unsnap = function (block) {\n        var c = containerFor(block);\n        if (c == null)\n            return;\n        if (!c.remove(block))\n            return;\n        var idx = element.snappedBlocks.indexOf(block);\n        if (idx !== -1)\n            element.snappedBlocks.splice(idx, 1);\n        block.custom.snappedSlot = null;\n        block.custom.isSnapped = false;\n        block.snapPositionDelta = null;\n        layoutAll(o.animationDuration);\n        element.refreshButtons();\n    };\n    // When a tap or drag drops a block over the slot, decide accept vs. bounce.\n    // inBounds = the block visually overlaps the slot at all; target is the\n    // world position it would land at, or null if it doesn't fit.\n    element.tryAutoSnap = function (block) {\n        var blockBounds = block.custom.getBoundingRect\n            ? block.custom.getBoundingRect('local')\n            : block.getBoundingRect('local');\n        if (!doRectsOverlap(slotBorderBounds(), blockBounds)) {\n            return { accepted: false, target: null, inBounds: false };\n        }\n        var target = element.getTargetPositionFor(block);\n        if (target == null) {\n            return { accepted: false, target: null, inBounds: true };\n        }\n        return { accepted: true, target: target, inBounds: true };\n    };\n    // Reflow API for callers that mutate state externally (e.g. tests).\n    element.reflowAfterRemove = function () {\n        layoutAll(o.animationDuration);\n    };\n    // Synchronous reflow used after a state restore (see the interface note).\n    // Duration 0 matters as much as the reflow itself: commitSnap's animated\n    // layoutAll is cancelled in place by the `figure.stop('freeze')` the\n    // snapshot page runs immediately afterwards, which is what leaves restored\n    // blocks sitting at their saved coordinates instead of in the slot.\n    element.refreshSnaps = function () {\n        layoutAll(0);\n    };\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    element.unhighlight = function () { };\n    // Pulse every block currently snapped to this slot with the given pulse\n    // options. Mirrors simpleBlockSlot.toPulse so callers that pulse a slot\n    // get the snapped blocks pulsing too.\n    element.custom.toPulse = function (pulseOptions) {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            block.animations.new().pulse(pulseOptions).start();\n        }\n    };\n    // Pulse only the snapped blocks of a single place, addressed by its block\n    // value (1/10/100/1000). Useful from speech as |e:Slot,pulsePlace,10| to\n    // wiggle just the tens (or ones) the learner built while narrating \"and you\n    // have 3\".\n    element.pulsePlace = function (place, pulseOptions) {\n        var blocks = place === 1000\n            ? element.thousands\n            : place === 100\n                ? element.hundreds\n                : place === 10 ? element.tens : element.ones;\n        for (var i = 0; i < blocks.length; i += 1) {\n            var block = blocks[i];\n            var opts = pulseOptions;\n            if (opts == null) {\n                // Default: a vertical (translation) wiggle matching speech's |v:|\n                // vpulse — translate up by `mag` figure units, converted to the\n                // block's draw space, oscillating at the same frequency.\n                var mag = 0.03;\n                var p1 = block.pointFromSpaceToSpace([0, 0], 'figure', 'draw');\n                var p2 = block.pointFromSpaceToSpace([0, mag], 'figure', 'draw');\n                var delta = p2.y - p1.y;\n                opts = {\n                    duration: 1,\n                    translation: delta,\n                    min: -delta,\n                    angle: Math.PI / 2,\n                    frequency: 2.5,\n                };\n            }\n            block.animations.new().pulse(opts).start();\n        }\n    };\n    // Keep snapped blocks aligned with the slot as it moves.\n    element.notifications.add('setTransform', function () {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            if (block.snapPositionDelta != null) {\n                block.setPosition(element.getPosition().sub(block.snapPositionDelta));\n                block.custom.state.p = block.getPosition();\n            }\n        }\n    });\n    element.custom.getState = function () {\n        var full = [];\n        for (var i = 0; i < containers.length; i += 1) {\n            var ordered = containers[i].orderedBlocks();\n            for (var j = 0; j < ordered.length; j += 1)\n                full.push(ordered[j].name);\n        }\n        return {\n            full: full,\n            partial: [],\n            order: full.slice(),\n            thousands: thousandsContainer != null ? thousandsContainer.blocks.length : 0,\n            hundreds: hundredsContainer != null ? hundredsContainer.blocks.length : 0,\n            tens: tensContainer != null ? tensContainer.blocks.length : 0,\n            ones: onesContainer != null ? onesContainer.blocks.length : 0,\n        };\n    };\n    // Walk every named child of the equation containing this slot. We use\n    // `.elements` rather than `getAllElements()` because equation collections\n    // rebuild drawOrder per-form, so elements not referenced by the current\n    // form (e.g. hidden b10_blocks while another form is active) would be\n    // missed; the dictionary holds every named child regardless of form\n    // state or visibility. Scoping to `toAdd` (rather than `fig.elements`)\n    // keeps unrelated b10_blocks elsewhere in the figure out of scope.\n    var walkAll = function (root, out) {\n        if (root == null)\n            return;\n        var els = root.elements;\n        if (els == null)\n            return;\n        var names = Object.keys(els);\n        for (var i = 0; i < names.length; i += 1) {\n            var el = els[names[i]];\n            if (el == null)\n                continue;\n            out.push(el);\n            if (el.elements != null)\n                walkAll(el, out);\n        }\n    };\n    // Every b10 block of type `n` in scope. When the slot is configured with a\n    // `nameRegex`, blocks whose `name` doesn't match are excluded here so the\n    // slot never operates on them anywhere — claiming, selection, and button\n    // state all draw from this single filtered pool.\n    var allBlocksOfType = function (n) {\n        var out = [];\n        var all = [];\n        walkAll(toAdd, all);\n        for (var i = 0; i < all.length; i += 1) {\n            var el = all[i];\n            if (el != null\n                && el.custom != null\n                && el.custom.manipulativeType === 'b10_blocks'\n                && el.custom.n === n\n                && (nameRegex == null || nameRegex.test(el.name))) {\n                out.push(el);\n            }\n        }\n        return out;\n    };\n    // Find an unsnapped block of type `n`. For button-pool blocks (hidden,\n    // opacity 0) this is the next one ready to dissolve in; for free blocks\n    // it's the first available candidate to pull into the slot. `nameRegex`\n    // filtering is already applied by allBlocksOfType.\n    var findAvailableBlockOfType = function (n) {\n        var all = allBlocksOfType(n);\n        for (var i = 0; i < all.length; i += 1) {\n            if (all[i].custom.isSnapped)\n                continue;\n            return all[i];\n        }\n        return null;\n    };\n    // Resolve a block by its element name. A `nameRegex` confines this slot to\n    // its own pool, so a name that doesn't match is treated as not found.\n    var findBlockByName = function (name) {\n        if (nameRegex != null && !nameRegex.test(name))\n            return null;\n        var all = [];\n        walkAll(toAdd, all);\n        for (var i = 0; i < all.length; i += 1) {\n            var el = all[i];\n            if (el != null\n                && el.custom != null\n                && el.custom.manipulativeType === 'b10_blocks'\n                && el.name === name) {\n                return el;\n            }\n        }\n        return null;\n    };\n    // First unsnapped block whose container has both intrinsic capacity and\n    // remaining column budget. Iterates enabled containers in their natural\n    // thousands → hundreds → tens → ones order.\n    var findNextAvailableBlock = function () {\n        for (var i = 0; i < containers.length; i += 1) {\n            var c = containers[i];\n            if (!c.canAdd())\n                continue;\n            var n = c === thousandsContainer\n                ? 1000\n                : c === hundredsContainer\n                    ? 100\n                    : c === tensContainer ? 10 : 1;\n            var bl = findAvailableBlockOfType(n);\n            if (bl == null)\n                continue;\n            if (element.getTargetPositionFor(bl) == null)\n                continue;\n            return bl;\n        }\n        return null;\n    };\n    // Last block (in container ordering) currently snapped to this slot of\n    // type `n`. For row/diagonal containers that's the rightmost block; for\n    // the ones pack it's the topmost in the rightmost column. Used as the\n    // default target for eviction-style animations (`to: 'init'` / [x,y]).\n    var findLastSnappedBlockOfType = function (n) {\n        var c = n === 1000\n            ? thousandsContainer\n            : n === 100\n                ? hundredsContainer\n                : n === 10 ? tensContainer\n                    : n === 1 ? onesContainer : null;\n        if (c == null)\n            return null;\n        var ordered = c.orderedBlocks();\n        if (ordered.length === 0)\n            return null;\n        return ordered[ordered.length - 1];\n    };\n    // Last snapped block across all enabled containers, iterating in reverse\n    // (ones → tens → hundreds → thousands) so the visually-rightmost block wins.\n    var findLastSnappedBlock = function () {\n        for (var i = containers.length - 1; i >= 0; i -= 1) {\n            var ordered = containers[i].orderedBlocks();\n            if (ordered.length === 0)\n                continue;\n            return ordered[ordered.length - 1];\n        }\n        return null;\n    };\n    // ── Optional add-a-block buttons ───────────────────────────────────\n    // For each enabled button type, claim all blocks of that type in the\n    // surrounding equation as the button's pool: mark them buttonSourced,\n    // disable dragging, and hide any that aren't currently snapped. Pressing\n    // the button picks a hidden block, positions it at its slot target, and\n    // dissolves it in. Tap-to-remove (handled in baseTenBlocks.ts) dissolves\n    // back to opacity 0 and returns the block to the pool.\n    // `buttons` is now boolean | ButtonStyle. The all-or-none rule: when\n    // truthy, a button is rendered for every enabled container. There's no\n    // per-type opt-in/out beyond the container being enabled.\n    var buttonsOpt = o.buttons;\n    var buttonsEnabled = buttonsOpt === true\n        || (buttonsOpt != null && buttonsOpt !== false);\n    // Buttons (and the blocks they place) are touchable unless explicitly\n    // turned off. They are still built and styled identically when false — only\n    // touch handling is skipped — so they look active but ignore taps.\n    var buttonsInteractive = o.buttonsInteractive !== false;\n    if (buttonsEnabled) {\n        var buttonDefaults = {\n            width: 0.35,\n            height: 0.35,\n            spacing: 0.05,\n            offset: [0, 0],\n            xPosition: 'center',\n            yPosition: -0.2,\n            xAlign: 'mid',\n            yAlign: 'top',\n            layout: 'row',\n            inSize: false,\n            backgroundColor: [0.85, 0.85, 0.85, 1],\n            disabledBackgroundColor: [0.9, 0.9, 0.9, 0.7],\n            radius: 0.04,\n            // color: [0, 0.478, 0.823, 1] as FigureOneColor,\n            color: [0.2, 0.2, 0.2, 1],\n            disabledColor: [0.8, 0.8, 0.8, 1],\n            lineColor: [0, 0, 0, 0],\n            disabledLineColor: [0.6, 0.6, 0.6, 1],\n            label: false,\n            labelFont: {},\n        };\n        // String shorthand: `buttons: 'label'` is sugar for a wider text-label\n        // button — equivalent to `buttons: { label: true, width: 0.6 }`.\n        var buttonOverrides = buttonsOpt === 'label'\n            ? { label: true, width: 0.6 }\n            : (typeof buttonsOpt === 'object' ? buttonsOpt : {});\n        var b_1 = Fig.joinObjects({}, buttonDefaults, buttonOverrides);\n        // Resolve the text label for a button of value `n`, or null when this\n        // button should render its block icon. `label` is false/true/string/\n        // per-place-object (keys thousands/hundreds/tens/ones); an unset place in\n        // the object form falls back to the default '+N'.\n        var labelFor = function (n) {\n            var lbl = b_1.label;\n            if (!lbl)\n                return null;\n            var dflt = \"+\".concat(n);\n            if (lbl === true)\n                return dflt;\n            if (typeof lbl === 'string')\n                return lbl;\n            var perType = n === 1000 ? lbl.thousands\n                : n === 100 ? lbl.hundreds\n                    : n === 10 ? lbl.tens\n                        : lbl.ones;\n            return perType != null ? perType : dflt;\n        };\n        // Button visibility tracks container enablement. hundredsMode/tensMode/\n        // onesMode were normalized earlier; mode != null means container exists.\n        var allKeys = [\n            { key: 'thousand', n: 1000, enabled: thousandsMode != null },\n            { key: 'hundred', n: 100, enabled: hundredsMode != null },\n            { key: 'ten', n: 10, enabled: tensMode != null },\n            { key: 'one', n: 1, enabled: onesMode != null },\n        ];\n        var enabledKeys_1 = allKeys.filter(function (x) { return x.enabled; });\n        var buttons_1 = {};\n        if (enabledKeys_1.length > 0) {\n            // Resolve symbolic position/align values to fractions in [0..1].\n            var xPosFrac = b_1.xPosition === 'left' ? 0\n                : b_1.xPosition === 'center' ? 0.5\n                    : b_1.xPosition === 'right' ? 1\n                        : b_1.xPosition;\n            var yPosFrac = b_1.yPosition === 'bottom' ? 0\n                : b_1.yPosition === 'middle' ? 0.5\n                    : b_1.yPosition === 'top' ? 1\n                        : b_1.yPosition;\n            var xAlignFrac = b_1.xAlign === 'left' ? 0\n                : b_1.xAlign === 'mid' ? 0.5\n                    : b_1.xAlign === 'right' ? 1\n                        : b_1.xAlign;\n            var yAlignFrac = b_1.yAlign === 'bottom' ? 0\n                : b_1.yAlign === 'middle' ? 0.5\n                    : b_1.yAlign === 'top' ? 1\n                        : b_1.yAlign;\n            // Strip bounds depend on layout. In 'row' the strip spans all buttons\n            // horizontally; in 'col' it spans them vertically.\n            var isCol = b_1.layout === 'col';\n            var stripW = isCol\n                ? b_1.width\n                : enabledKeys_1.length * b_1.width\n                    + (enabledKeys_1.length - 1) * b_1.spacing;\n            var stripH = isCol\n                ? enabledKeys_1.length * b_1.height\n                    + (enabledKeys_1.length - 1) * b_1.spacing\n                : b_1.height;\n            // Reference frame: the slot's border outer visible edge — i.e. the\n            // outermost rectangle a user sees. When `border` is disabled, both\n            // borderSpace and borderOffset (= line.width/2) are 0, so the frame\n            // collapses to the content rectangle. For multi-group (column-gap)\n            // layouts, the frame spans from the first group's outer-left to the\n            // last group's outer-right, including the inter-group gaps.\n            var frameLeft = -borderSpace;\n            var frameBottom = slotYBase - borderSpace - borderOffset;\n            var frameWidth = renderedWidth + 2 * (borderSpace + borderOffset);\n            var frameHeight = height + 2 * (borderSpace + borderOffset);\n            // Anchor point on the border rectangle (xPosition × yPosition), then\n            // the strip's align point (xAlign × yAlign) is placed at that anchor\n            // plus `offset`.\n            var anchorX = frameLeft + xPosFrac * frameWidth;\n            var anchorY = frameBottom + yPosFrac * frameHeight;\n            var stripLeft = anchorX - xAlignFrac * stripW + b_1.offset[0];\n            var stripBottom = anchorY - yAlignFrac * stripH + b_1.offset[1];\n            // Icon cell size: 10 cells fit vertically within ~70% of the button\n            // height, leaving padding above and below. All three icons use the\n            // same cell so the 1 and 10 blocks read as scale-true relative to\n            // the 100 — visually communicating \"one tenth of a 10, one hundredth\n            // of a 100\" even though it makes the 1 block tiny.\n            var cell = (b_1.height * 0.85) / 10;\n            var _loop_1 = function (i) {\n                var _a = enabledKeys_1[i], key = _a.key, n = _a.n;\n                // In 'col' layout the highest place sits at the top (highest by),\n                // ones at the bottom (lowest by). Index 0 = highest place → bottom +\n                // (N-1)·step.\n                var bx = isCol\n                    ? stripLeft\n                    : stripLeft + i * (b_1.width + b_1.spacing);\n                var by = isCol\n                    ? stripBottom + (enabledKeys_1.length - 1 - i) * (b_1.height + b_1.spacing)\n                    : stripBottom;\n                // The button is its own collection; child positions are relative\n                // to the button's bottom-left at [bx, by].\n                var btn = element.add({\n                    name: \"btn_\".concat(key),\n                    make: 'collection',\n                    position: [bx, by],\n                });\n                if (b_1.inSize === false) {\n                    btn.border = [[]];\n                }\n                // Touchable background. `bg` carries the click handler and is the\n                // only child whose color changes on enable/disable.\n                var bg = btn.add({\n                    name: 'bg',\n                    make: 'rectangle',\n                    width: b_1.width,\n                    height: b_1.height,\n                    xAlign: 'left',\n                    yAlign: 'bottom',\n                    color: b_1.backgroundColor,\n                    corner: { radius: b_1.radius, sides: 6 },\n                    position: [0, 0],\n                    touch: buttonsInteractive,\n                });\n                // Face color is assigned by refreshButtons (the single source of truth,\n                // run immediately after construction) via btn.custom.face /\n                // btn.custom.setFaceColor; the colors set here are placeholders.\n                var face;\n                // Text-label buttons have no separate icon border; refreshButtons\n                // guards on null before recoloring it.\n                var iconBorder = null;\n                var labelText = labelFor(n);\n                if (labelText != null) {\n                    // Render a text label (e.g. '+100') centered in the button instead\n                    // of the block icon. The text becomes `face`, so refreshButtons\n                    // recolors it through the same enabled/disabled face-color path.\n                    face = btn.add({\n                        name: 'face',\n                        make: 'text',\n                        text: labelText,\n                        font: Fig.joinObjects({\n                            size: b_1.height * 0.38,\n                            family: defaultFontFamilyMath,\n                            weight: '400',\n                        }, b_1.labelFont),\n                        color: b_1.color,\n                        xAlign: 'center',\n                        yAlign: 'middle',\n                        position: [b_1.width / 2, b_1.height / 2],\n                    });\n                }\n                else if (n === 1000) {\n                    // A thousand renders as an oblique 3D cube so it reads distinctly\n                    // from the flat 100 square. The cube is sized so its whole\n                    // silhouette — 10 cells plus the 2.5-cell oblique depth (10 deep ×\n                    // 0.25, mirroring baseTenBlocks) = 12.5 cells — fits the same\n                    // vertical budget the other icons give 10 cells.\n                    var depthCellsIcon = 2.5;\n                    var totalCells = 10 + depthCellsIcon;\n                    var cCell = (b_1.height * 0.85) / totalCells;\n                    var fSize = 10 * cCell; // front-face edge length\n                    var d_1 = depthCellsIcon * cCell; // oblique depth (up-and-right)\n                    var ox = (b_1.width - (fSize + d_1)) / 2;\n                    var oy = (b_1.height - (fSize + d_1)) / 2;\n                    var FR = [ox + fSize, oy];\n                    var TR = [ox + fSize, oy + fSize];\n                    var TL = [ox, oy + fSize];\n                    var back = function (p) {\n                        return [p[0] + d_1, p[1] + d_1];\n                    };\n                    // Visible top and right faces, drawn before the front face so the\n                    // front sits on top. Shaded by setFaceColor (top lighter, right\n                    // darker) for the 3D read.\n                    var topFace_1 = btn.add({\n                        name: 'faceTop',\n                        make: 'generic',\n                        points: [TL, TR, back(TR), back(TL)],\n                        drawType: 'FAN',\n                        color: b_1.color,\n                    });\n                    var rightFace_1 = btn.add({\n                        name: 'faceRight',\n                        make: 'generic',\n                        points: [FR, TR, back(TR), back(FR)],\n                        drawType: 'FAN',\n                        color: b_1.color,\n                    });\n                    // Subtle depth edges so the cube reads as 3D for any base color.\n                    var edgeColor = [0, 0, 0, 0.25];\n                    btn.add({\n                        name: 'cubeEdges',\n                        make: 'polyline',\n                        points: [TL, back(TL), back(TR), back(FR), FR],\n                        width: 0.004,\n                        color: edgeColor,\n                    });\n                    btn.add({\n                        name: 'cubeEdgeInterior',\n                        make: 'polyline',\n                        points: [TR, back(TR)],\n                        width: 0.004,\n                        color: edgeColor,\n                    });\n                    face = btn.add({\n                        name: 'face',\n                        make: 'rectangle',\n                        width: fSize,\n                        height: fSize,\n                        color: b_1.color,\n                        xAlign: 'left',\n                        yAlign: 'bottom',\n                        position: [ox, oy],\n                        corner: { radius: 0.005, sides: 4 },\n                    });\n                    btn.add({\n                        name: 'gridV',\n                        make: 'line',\n                        color: [1, 1, 1, 1],\n                        p1: [ox + cCell, oy],\n                        p2: [ox + cCell, oy + fSize],\n                        width: 0.002,\n                        copy: { along: 'x', step: cCell, num: 8 },\n                    });\n                    btn.add({\n                        name: 'gridH',\n                        make: 'line',\n                        color: [1, 1, 1, 1],\n                        p1: [ox, oy + cCell],\n                        p2: [ox + fSize, oy + cCell],\n                        width: 0.002,\n                        copy: { along: 'y', step: cCell, num: 8 },\n                    });\n                    iconBorder = btn.add({\n                        name: 'iconBorder',\n                        make: 'rectangle',\n                        width: fSize,\n                        height: fSize,\n                        color: b_1.lineColor,\n                        line: { width: 0.002 },\n                        xAlign: 'left',\n                        yAlign: 'bottom',\n                        position: [ox, oy],\n                        corner: { radius: 0.01, sides: 4 },\n                    });\n                    btn.custom.setFaceColor = function (c) {\n                        face.setColor(c);\n                        topFace_1.setColor(lighten(c, 0.14));\n                        rightFace_1.setColor(darken(c, 0.14));\n                    };\n                }\n                else {\n                    var cols = 1;\n                    var rows = 1;\n                    if (n === 100) {\n                        cols = 10;\n                        rows = 10;\n                    }\n                    else if (n === 10) {\n                        cols = 1;\n                        rows = 10;\n                    }\n                    var iconW = cols * cell;\n                    var iconH = rows * cell;\n                    var iconX = (b_1.width - iconW) / 2;\n                    var iconY = (b_1.height - iconH) / 2;\n                    face = btn.add({\n                        name: 'face',\n                        make: 'rectangle',\n                        width: iconW,\n                        height: iconH,\n                        color: b_1.color,\n                        xAlign: 'left',\n                        yAlign: 'bottom',\n                        position: [iconX, iconY],\n                        corner: { radius: 0.005, sides: 4 },\n                    });\n                    if (cols > 1) {\n                        btn.add({\n                            name: 'gridV',\n                            make: 'line',\n                            color: [1, 1, 1, 1],\n                            p1: [iconX + cell, iconY],\n                            p2: [iconX + cell, iconY + iconH],\n                            width: 0.002,\n                            copy: { along: 'x', step: cell, num: cols - 2 },\n                        });\n                    }\n                    if (rows > 1) {\n                        btn.add({\n                            name: 'gridH',\n                            make: 'line',\n                            color: [1, 1, 1, 1],\n                            p1: [iconX, iconY + cell],\n                            p2: [iconX + iconW, iconY + cell],\n                            width: 0.002,\n                            copy: { along: 'y', step: cell, num: rows - 2 },\n                        });\n                    }\n                    iconBorder = btn.add({\n                        name: 'iconBorder',\n                        make: 'rectangle',\n                        width: iconW,\n                        height: iconH,\n                        color: b_1.lineColor,\n                        line: { width: 0.002 },\n                        xAlign: 'left',\n                        yAlign: 'bottom',\n                        position: [iconX, iconY],\n                        corner: { radius: 0.01, sides: 4 },\n                    });\n                }\n                btn.custom.enabled = true;\n                btn.custom.n = n;\n                btn.custom.bg = bg;\n                btn.custom.face = face;\n                btn.custom.line = iconBorder;\n                buttons_1[n] = btn;\n            };\n            for (var i = 0; i < enabledKeys_1.length; i += 1) {\n                _loop_1(i);\n            }\n        }\n        // Mark a block as belonging to this slot's button pool: hide it and\n        // zero its opacity so it's invisible until a button press dissolves\n        // it into the slot.\n        var claimForPool_1 = function (block) {\n            block.custom.buttonSourced = true;\n            block.setOpacity(0);\n            block.hasTouchableElements = false;\n            block.hide();\n        };\n        var onButtonPress_1 = function (n) {\n            var btn = buttons_1[n];\n            if (btn == null || !btn.custom.enabled)\n                return;\n            var block = findAvailableBlockOfType(n);\n            if (block == null)\n                return;\n            var target = element.getTargetPositionFor(block);\n            if (target == null)\n                return;\n            // Bring the pool block into view at its target position, opacity 0,\n            // ready to dissolve in. Setting position before commitSnap means the\n            // block's own animateBlockTo is a no-op — only shifting blocks animate.\n            block.show();\n            block.setOpacity(0);\n            block.setPosition(target);\n            block.hasTouchableElements = true;\n            block.notificationHelper.cleanup('onClick');\n            // Tap-to-remove: dissolve out, then hide and unsnap. The fade runs on\n            // fig.elements.animations (not the block's queue) so a sibling reflow's\n            // animateBlockTo → block.stopAnimating() can't cancel it. The slot's\n            // unsnap removes the block from its container, runs layoutAll on the\n            // remaining blocks, and refreshes button enabled state.\n            // @ts-expect-error TS2339\n            block.notificationHelper.add(block._container._block, 'onClick', function () {\n                if (!block.custom.isSnapped)\n                    return;\n                block.hasTouchableElements = false;\n                block.stopAnimating();\n                // fnMap-named trigger (owner = fig.elements, keyed by block name) so the post-fade\n                // hide + unsnap + park survive speech pause/resume. See btBlockHide / btBlockRemove.\n                var removeKey = \"btBlockRemove:\".concat(block.name);\n                fig.elements.fnMap.add(removeKey, function () {\n                    block.hide();\n                    element.unsnap(block);\n                    block.setPosition(POOL_PARK_POSITION[0], POOL_PARK_POSITION[1]);\n                });\n                fig.elements.animations\n                    .new()\n                    .opacity({\n                    element: block,\n                    target: 0,\n                    duration: o.animationDuration,\n                })\n                    .trigger({ callback: removeKey })\n                    .start();\n            });\n            // @ts-expect-error TS2339\n            block._container._block.isMovable = false;\n            toAdd.toFront(block);\n            if (!element.commitSnap(block)) {\n                block.hasTouchableElements = false;\n                return;\n            }\n            // Dissolve in on the figure's animation manager so a later commitSnap\n            // shifting this block (via animateBlockTo → block.stopAnimating())\n            // can't cancel the fade. The matching dissolve-out lives in\n            // baseTenBlocks.ts tryTapSlotReturn.\n            fig.elements.animations\n                .new()\n                .opacity({\n                element: block,\n                target: 1,\n                duration: o.animationDuration,\n            })\n                .start();\n        };\n        // Wire click handlers. FigureOne's onClick notification fires on the\n        // touchable child (the bg rectangle), not the collection itself. Skipped\n        // entirely when buttons are non-interactive, so taps never reach a handler.\n        if (buttonsInteractive) {\n            var _loop_2 = function (i) {\n                var n = enabledKeys_1[i].n;\n                var btn = buttons_1[n];\n                btn.custom.bg.notifications.add('onClick', function () { return onButtonPress_1(n); });\n            };\n            for (var i = 0; i < enabledKeys_1.length; i += 1) {\n                _loop_2(i);\n            }\n        }\n        element.refreshButtons = function () {\n            // Claim any pool block we haven't seen yet (handles blocks that load\n            // after the slot is created). allBlocksOfType already excludes blocks\n            // that don't match this slot's nameRegex, so a name-filtered slot never\n            // claims another pool's blocks.\n            for (var i = 0; i < enabledKeys_1.length; i += 1) {\n                var n = enabledKeys_1[i].n;\n                var all = allBlocksOfType(n);\n                for (var j = 0; j < all.length; j += 1) {\n                    var bl = all[j];\n                    if (!bl.custom.buttonSourced)\n                        claimForPool_1(bl);\n                }\n                var btn = buttons_1[n];\n                if (btn == null)\n                    continue;\n                var available = findAvailableBlockOfType(n);\n                var enabled = available != null;\n                if (enabled && available != null) {\n                    enabled = element.getTargetPositionFor(available) != null;\n                }\n                btn.custom.enabled = enabled;\n                btn.custom.bg.setColor(enabled ? b_1.backgroundColor : b_1.disabledBackgroundColor);\n                // Text-label buttons have no icon border (line == null).\n                if (btn.custom.line != null) {\n                    btn.custom.line.setColor(enabled ? b_1.lineColor : b_1.disabledLineColor);\n                }\n                var perType = n === 1000 ? b_1.thousands\n                    : n === 100 ? b_1.hundreds\n                        : n === 10 ? b_1.tens\n                            : b_1.ones;\n                var faceColor = perType != null ? perType : b_1.color;\n                var fc = enabled ? faceColor : b_1.disabledColor;\n                // Cube buttons recolor their three faces with shading via\n                // setFaceColor; flat buttons recolor the single face rectangle.\n                if (typeof btn.custom.setFaceColor === 'function') {\n                    btn.custom.setFaceColor(fc);\n                }\n                else {\n                    btn.custom.face.setColor(fc);\n                }\n            }\n        };\n        // Initial pool claim. refreshButtons is also called from snap, unsnap,\n        // and commitSnap so the state stays current as blocks move in and out.\n        element.refreshButtons();\n        // Re-claim once the figure is fully built. Pool blocks that come into\n        // existence after this slot is constructed — e.g. blocks force-created\n        // via `create: true`, which are appended to the equation *after* the\n        // slot's own element — aren't in the tree for the initial claim above, so\n        // the buttons would otherwise stay disabled. The 'ready' notification\n        // (published in initQuestionFinalize after every element exists) gives us\n        // a single post-build pass to find them. teardownQuestion clears all\n        // non-persistent figure notifications between questions, so this\n        // subscription doesn't leak across SPA transitions.\n        if (fig.notifications != null) {\n            fig.notifications.add('ready', function () { return element.refreshButtons(); });\n        }\n    }\n    // Programmatically animate a block. With the default `to: 'slot'` the\n    // block is added at the end of its container — no positional control.\n    // Selection (default `to: 'slot'`):\n    //   - string nameOrN: lookup by element name\n    //   - number nameOrN (1000/100/10/1): first unsnapped block of that type\n    //   - undefined: first unsnapped block fitting any enabled container,\n    //     iterated thousands → hundreds → tens → ones\n    // For 'init'/[x,y] eviction modes, the default selection inverts: pick\n    // the LAST snapped block of the requested type (the rightmost / top-\n    // rightmost in container ordering), and unsnap it before animating to\n    // the requested destination.\n    // Animation style mirrors the slot's interaction model: button-configured\n    // slots dissolve the block in at its target position (with the same\n    // tap-to-remove handler as a button press); other slots animate from the\n    // block's current position to the target.\n    element.animateBlock = function (nameOrN, toOrDuration, duration) {\n        // Two positional shapes:\n        //   (nameOrN, duration)            // legacy — destination defaults to 'slot'\n        //   (nameOrN, to, duration)        // destination-aware\n        // A numeric second arg is always `duration` (destinations are\n        // 'slot' / 'init' / [x, y]); a string or array is always `to`.\n        var legacy = typeof toOrDuration === 'number';\n        var destination = legacy || toOrDuration == null\n            ? 'slot'\n            : toOrDuration;\n        var resolvedDuration = legacy\n            ? toOrDuration\n            : duration;\n        // Object form: explicit per-type counts, e.g. { 10: 12 } for 12 tens.\n        // Iterate keys in descending order so the decomposition matches the\n        // thousands → hundreds → tens → ones convention used elsewhere in this\n        // method. Unknown keys (anything other than 1000/100/10/1) are silently\n        // ignored.\n        if (nameOrN != null\n            && typeof nameOrN === 'object'\n            && !Array.isArray(nameOrN)) {\n            var counts = nameOrN;\n            var keys = Object.keys(counts)\n                .map(function (k) { return Number(k); })\n                .filter(function (k) { return k === 1 || k === 10 || k === 100 || k === 1000; })\n                .sort(function (a, b) { return b - a; });\n            for (var i = 0; i < keys.length; i += 1) {\n                var n = keys[i];\n                var c = counts[n];\n                if (c == null || c <= 0)\n                    continue;\n                for (var j = 0; j < c; j += 1) {\n                    element.animateBlock(n, destination, resolvedDuration);\n                }\n            }\n            return;\n        }\n        // A numeric input that isn't a single block-type (1/10/100/1000) is\n        // treated as a place-value decomposition: animate one block per place, in\n        // thousands → hundreds → tens → ones order. Each recursive call is\n        // synchronous on the state side (insertBlock / commitSnap / unsnap mutate\n        // first), so successive blocks see updated capacity / picks. Capped at 9\n        // per place by the modulo arithmetic; for counts ≥ 10 callers should use\n        // the object form above.\n        if (typeof nameOrN === 'number'\n            && nameOrN !== 1 && nameOrN !== 10 && nameOrN !== 100 && nameOrN !== 1000) {\n            if (nameOrN <= 0)\n                return;\n            var th = Math.floor(nameOrN / 1000);\n            var h = Math.floor(nameOrN / 100) % 10;\n            var t = Math.floor(nameOrN / 10) % 10;\n            var o_1 = nameOrN % 10;\n            for (var i = 0; i < th; i += 1) {\n                element.animateBlock(1000, destination, resolvedDuration);\n            }\n            for (var i = 0; i < h; i += 1) {\n                element.animateBlock(100, destination, resolvedDuration);\n            }\n            for (var i = 0; i < t; i += 1) {\n                element.animateBlock(10, destination, resolvedDuration);\n            }\n            for (var i = 0; i < o_1; i += 1) {\n                element.animateBlock(1, destination, resolvedDuration);\n            }\n            return;\n        }\n        var block = null;\n        if (typeof nameOrN === 'string') {\n            block = findBlockByName(nameOrN);\n        }\n        else if (typeof nameOrN === 'number') {\n            block = destination === 'slot'\n                ? findAvailableBlockOfType(nameOrN)\n                : findLastSnappedBlockOfType(nameOrN);\n        }\n        else {\n            block = destination === 'slot'\n                ? findNextAvailableBlock()\n                : findLastSnappedBlock();\n        }\n        if (block == null)\n            return;\n        // Eviction modes: resolve the destination point, unsnap if currently\n        // snapped (so the rest of the container reflows), then animate.\n        if (destination !== 'slot') {\n            var d_2 = resolvedDuration != null ? resolvedDuration : o.animationDuration;\n            // Button-pool blocks live hidden off-screen; their `initialPosition`\n            // isn't a meaningful on-screen location. Run a dissolve-out similar\n            // to the onButtonPress tap-to-remove flow, but unsnap synchronously\n            // (BEFORE the fade) so successive calls in the same tick — e.g. the\n            // object-form / decomposition loops above — see this block as no\n            // longer snapped and pick a different one. The fade then only owns\n            // the visual opacity + post-fade hide/park. The block keeps its\n            // on-slot world position during the fade because `snapPositionDelta`\n            // is cleared by unsnap and the slot itself doesn't move.\n            if (destination === 'init' && buttonsEnabled) {\n                if (!block.custom.isSnapped)\n                    return;\n                block.hasTouchableElements = false;\n                block.stopAnimating();\n                element.unsnap(block);\n                // fnMap-named trigger (owner = fig.elements, keyed by block name) so the\n                // post-fade hide + park survive speech pause/resume; an inline trigger would be\n                // dropped, leaving the block faded-to-invisible but still shown and un-parked.\n                var hideKey = \"btBlockHide:\".concat(block.name);\n                fig.elements.fnMap.add(hideKey, function () {\n                    block.hide();\n                    block.setPosition(POOL_PARK_POSITION[0], POOL_PARK_POSITION[1]);\n                });\n                fig.elements.animations\n                    .new()\n                    .opacity({\n                    element: block,\n                    target: 0,\n                    duration: d_2,\n                })\n                    .trigger({ callback: hideKey })\n                    .start();\n                return;\n            }\n            var target_1 = null;\n            if (destination === 'init') {\n                var ip = block.custom.initialPosition;\n                if (ip == null)\n                    return;\n                target_1 = Fig.parsePoint(ip);\n            }\n            else {\n                target_1 = Fig.parsePoint(destination);\n            }\n            if (block.custom.isSnapped)\n                element.unsnap(block);\n            // For 'init' eviction (non-buttons): after the block lands back on\n            // its initial-position pile, the slot's reflow during the outbound\n            // animation left it potentially below other unsnapped blocks\n            // overlapping the same pile. The block-side helper raises any block\n            // resting at its init position to the front so the pile stays\n            // pickable. The [x, y] destination doesn't get this treatment —\n            // there's no shared pile to reorder around an arbitrary point.\n            var onArrive = destination === 'init'\n                && typeof block.custom.bringUnsnappedBlocksToFront === 'function'\n                ? function () { return block.custom.bringUnsnappedBlocksToFront(); }\n                : undefined;\n            animateBlockTo(block, target_1, d_2, onArrive);\n            return;\n        }\n        var target = element.getTargetPositionFor(block);\n        if (target == null)\n            return;\n        var d = resolvedDuration != null ? resolvedDuration : o.animationDuration;\n        if (buttonsEnabled) {\n            block.show();\n            block.setOpacity(0);\n            block.setPosition(target);\n            // Tap-to-remove is only wired when buttons are interactive; a\n            // non-interactive slot's animated-in blocks stay inert.\n            if (buttonsInteractive) {\n                block.hasTouchableElements = true;\n                block.notificationHelper.cleanup('onClick');\n                // @ts-expect-error TS2339\n                block.notificationHelper.add(block._container._block, 'onClick', function () {\n                    if (!block.custom.isSnapped)\n                        return;\n                    block.hasTouchableElements = false;\n                    block.stopAnimating();\n                    // fnMap-named trigger (owner = fig.elements, keyed by block name) so the\n                    // post-fade hide + unsnap + park survive speech pause/resume. See btBlockHide.\n                    var removeKey = \"btBlockRemove:\".concat(block.name);\n                    fig.elements.fnMap.add(removeKey, function () {\n                        block.hide();\n                        element.unsnap(block);\n                        block.setPosition(POOL_PARK_POSITION[0], POOL_PARK_POSITION[1]);\n                    });\n                    fig.elements.animations\n                        .new()\n                        .opacity({\n                        element: block,\n                        target: 0,\n                        duration: o.animationDuration,\n                    })\n                        .trigger({ callback: removeKey })\n                        .start();\n                });\n            }\n            else {\n                block.hasTouchableElements = false;\n            }\n            // @ts-expect-error TS2339\n            block._container._block.isMovable = false;\n            toAdd.toFront(block);\n            if (!element.commitSnap(block)) {\n                block.hasTouchableElements = false;\n                return;\n            }\n            fig.elements.animations\n                .new()\n                .opacity({\n                element: block,\n                target: 1,\n                duration: d,\n            })\n                .start();\n            return;\n        }\n        if (!insertBlock(block))\n            return;\n        // layoutAll animates the new block to its target AND reflows every\n        // other snapped block — necessary because inserting a higher-place\n        // block (e.g. a ten before existing ones) shifts the trailing\n        // containers right. A bare animateBlockTo on just the new block would\n        // leave previously-placed blocks overlapping it.\n        layoutAll(d);\n        element.refreshButtons();\n    };\n    element.reset = function (duration) {\n        // animateBlock snapshots the object's counts before iterating, so the\n        // shrinking live container lengths during eviction don't affect it.\n        element.animateBlock({\n            1000: element.thousands.length,\n            100: element.hundreds.length,\n            10: element.tens.length,\n            1: element.ones.length,\n        }, 'init', duration);\n    };\n    element.showAnswer = function (show, showOptions) {\n        if (showOptions === void 0) { showOptions = {}; }\n        // Fold `show` into per-place target counts. Each entry is either an exact\n        // place value (1/10/100/1000), counted directly, or a composite number,\n        // decomposed canonically the same way animateBlock does — so an answer\n        // authored as a single number reveals instead of silently clearing.\n        var values = Array.isArray(show) ? show : [show];\n        var target = { 1000: 0, 100: 0, 10: 0, 1: 0 };\n        for (var i = 0; i < values.length; i += 1) {\n            var v = Number(values[i]);\n            if (!(v > 0))\n                continue;\n            if (v === 1 || v === 10 || v === 100 || v === 1000) {\n                target[v] += 1;\n            }\n            else {\n                target[1000] += Math.floor(v / 1000);\n                target[100] += Math.floor(v / 100) % 10;\n                target[10] += Math.floor(v / 10) % 10;\n                target[1] += v % 10;\n            }\n        }\n        // Diff against what the learner already built, per place, and only evict the\n        // surplus / add the shortfall. Evicting and re-adding the same place in the\n        // same tick collides: an eviction to 'init' leaves a pending btBlockHide\n        // trigger on the block, and animateBlock() re-grabs that very block (first\n        // unsnapped of its type) — so the stale trigger then hides part of the\n        // revealed answer. The demonstrate guides diff per place for this reason.\n        var current = {\n            1000: element.thousands.length,\n            100: element.hundreds.length,\n            10: element.tens.length,\n            1: element.ones.length,\n        };\n        var evict = {};\n        var add = {};\n        [1000, 100, 10, 1].forEach(function (p) {\n            var delta = target[p] - current[p];\n            if (delta < 0)\n                evict[p] = -delta;\n            else if (delta > 0)\n                add[p] = delta;\n        });\n        // In test mode animate instantly (duration 0) so snapshots are stable.\n        var duration = showOptions.test ? 0 : undefined;\n        element.animateBlock(evict, 'init', duration);\n        element.animateBlock(add, 'slot', duration);\n        // The reveal is not the learner's work: disable the slot (its buttons) and\n        // suppress touch on every revealed block so a buttons-interactive slot\n        // can't be tapped to remove the answer or pile more blocks on top.\n        element.disable();\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            suppressManipulativeTouch(element.snappedBlocks[i]);\n        }\n    };\n    element.custom.showCorrectness = function (result) {\n        var _a, _b;\n        if (!o.correctness)\n            return;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        var borderTarget = result === 1\n            ? (correctColor || (o.border && o.border.correct))\n            : (result === 2 || result === 6)\n                ? (incorrectColor || (o.border && o.border.incorrect))\n                : (o.border && o.border.color);\n        var fillTarget = result === 1\n            ? (correctColor || (o.fill && o.fill.correct))\n            : (result === 2 || result === 6)\n                ? (incorrectColor || (o.fill && o.fill.incorrect))\n                : (o.fill && o.fill.color);\n        if (o.border && borderTarget != null) {\n            for (var i = 0; i < borders.length; i += 1)\n                borders[i].setColor(borderTarget);\n        }\n        if (o.fill && fillTarget != null) {\n            for (var i = 0; i < fills.length; i += 1)\n                fills[i].setColor(fillTarget);\n        }\n        // Hide the to-snap highlight while a correctness color is showing\n        // (result 1/2/6); restore it when correctness clears.\n        element.custom.showingCorrectness = result === 1 || result === 2 || result === 6;\n        if (typeof element.custom.refreshToSnapHighlight === 'function') {\n            element.custom.refreshToSnapHighlight();\n        }\n    };\n    // Honor `toSnapSlot.select: true` — make this slot the initial to-snap\n    // target. We only update the shared ref here; the refresh-all-siblings\n    // pass below handles the actual visual update. This separation matters\n    // for the \"first slot constructed has select:true\" case: at this point\n    // no siblings exist yet, so a refresh would see multi=false and hide\n    // the highlight. The later-constructed sibling's own refresh pass picks\n    // it up once the count reaches 2+. Last select=true constructed wins.\n    if (toSnapOpt.select === true) {\n        if (toAdd.custom == null)\n            toAdd.custom = {};\n        toAdd.custom.toSnapBaseTenBlocksSlot = element;\n    }\n    // Refresh every slot now that this one has joined the equation. Handles\n    // both directions of the timing problem: an earlier sibling with\n    // select:true that's waiting for company, and this slot with select:true\n    // joining existing siblings.\n    var siblingsNow = getSiblingSlots();\n    for (var i = 0; i < siblingsNow.length; i += 1) {\n        var s = siblingsNow[i];\n        if (s.custom != null && typeof s.custom.refreshToSnapHighlight === 'function') {\n            s.custom.refreshToSnapHighlight();\n        }\n    }\n    return element;\n};\nexport { baseTenBlocksSlot, };\n","import { baseTenBlocks, createBaseTenBlocks, } from './baseTenBlocks';\nvar baseTenBlocksControl = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var controlOptions = Fig.joinObjects({\n        appear: 'right',\n        appearSpace: 0.05,\n        maxNum: {\n            10: 15,\n            1: 20,\n            100: 5,\n        },\n        createScale: 1,\n        orientation: 'v',\n        boundMove: true,\n        color: [0, 0.478, 0.823, 0.95],\n        toElement: toAdd,\n        snap: false,\n    }, options);\n    var blockOptions = Fig.joinObjects({}, controlOptions, {\n        name: \"__M_B10B\".concat(controlOptions.n),\n        label: false,\n    });\n    // Set after block options so control specific options don't overwrite block options\n    Fig.joinObjects(controlOptions, options.controlOnly);\n    var element = baseTenBlocks(eqn_name, controlOptions, fig);\n    element.custom.manipulativeType = null;\n    element.custom.manipulativeControlType = 'b10_blocks';\n    element.notificationHelper.cleanup();\n    element._container._block.isTouchable = false;\n    element._container._block.isMovable = false;\n    var appear = controlOptions.appear, maxNum = controlOptions.maxNum;\n    element.setTouchable();\n    element.custom.count = 0;\n    element.custom.create = function (name, customN) {\n        if (name === void 0) { name = null; }\n        if (customN === void 0) { customN = blockOptions.n; }\n        // name and createdFrom is needed for recreating the manipulatives in\n        // the snapshots\n        var o = Fig.joinObjects({}, blockOptions, {\n            createdFrom: element.getPath(),\n            n: customN,\n        });\n        if (name != null) {\n            o.name = name;\n        }\n        var new_element = createBaseTenBlocks(fig, eqn_name, controlOptions.toElement, o, blockOptions.boundMove);\n        toAdd.notifications.add('layoutForms', function () {\n            new_element.show();\n            new_element.setPosition(new_element.custom.state.p);\n            // This is needed after the show as when an element is hidden, getBoundingRect\n            // returns 0\n            new_element.setMoveBounds();\n        });\n        new_element.setPositionToElement(element);\n        new_element.custom.initialPosition = new_element.getPosition();\n        fig.beingMovedElement = new_element;\n        new_element.startBeingMoved();\n        new_element.custom.startMove = performance.now();\n        // const w = new_element.getBoundingRect().width;\n        new_element.notifications.add('stopBeingMoved', function () {\n            var new_element_p = new_element.getPosition();\n            if (performance.now() - new_element.custom.startMove < 200 ||\n                new_element_p.sub(new_element.custom.initialPosition).distance() <\n                    new_element.custom.s) {\n                var p = element.getPosition();\n                var r = element.getBoundingRect();\n                var newR = new_element.getBoundingRect();\n                var target = new Fig.Point(0, 0);\n                switch (appear) {\n                    case 'right':\n                        target = p.add(r.width, 0);\n                        break;\n                    case 'left':\n                        target = p.add(0, 0);\n                        break;\n                    case 'top':\n                        target = p.add(0, r.height);\n                        break;\n                    case 'bottom':\n                        target = p.add(0, 0);\n                        break;\n                }\n                var t1 = element.pointFromSpaceToSpace(target, 'local', 'figure');\n                var t2 = new_element.pointFromSpaceToSpace(t1, 'figure', 'local');\n                switch (appear) {\n                    case 'right':\n                        t2 = t2.add(controlOptions.appearSpace, 0);\n                        break;\n                    case 'left':\n                        t2 = t2.add(-newR.width - controlOptions.appearSpace, 0);\n                        break;\n                    case 'top':\n                        t2 = t2.add(0, controlOptions.appearSpace);\n                        break;\n                    case 'bottom':\n                        t2 = t2.add(0, -newR.height - controlOptions.appearSpace);\n                        break;\n                }\n                new_element.custom.state.p = t2;\n                element.animations\n                    .new()\n                    .trigger(function () {\n                    new_element.hasTouchableElements = false;\n                })\n                    .position({\n                    target: t2,\n                    duration: 0.5,\n                    progression: 'easeout',\n                    element: new_element,\n                })\n                    .trigger(function () {\n                    new_element.hasTouchableElements = true;\n                })\n                    .start();\n            }\n        }, 1);\n        return new_element;\n    };\n    element.custom.secondaryTouchBounds = 0.1;\n    element.notifications.add('onClick', function () {\n        window.clickHandled = true;\n        if (element.custom.count < maxNum[blockOptions.n]) {\n            element.custom.create();\n            element.custom.count += 1;\n            if (element.custom.count >= maxNum[blockOptions.n]) {\n                // element.hide();\n                element.hasTouchableElements = false;\n                element.dim();\n                element.custom.disabled = true;\n                // isTouchable needs to be false so secondary seondary touch border\n                // of nearby touchable elements does work\n                element.isTouchable = false;\n            }\n        }\n    });\n    return element;\n};\nexport { baseTenBlocksControl, };\n","import { baseTenBlocksControl } from './baseTenBlocksControl';\nimport { selectorManipulative } from './selector';\nimport { TRASH_MANIPULATIVES } from './tools';\nvar baseTenBlocksMenu = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        justify: 'right',\n        scale: 1,\n        upScale: 1,\n        size: 0.07,\n        position: [0, 0],\n        appear: null,\n        space: 0.05,\n        snap: true,\n        maxNum: {\n            1: 20,\n            10: 20,\n            100: 5,\n        },\n        boundMove: false,\n        controls: [],\n        control: {\n            width: 0.2,\n            height: 0.2,\n            space: 0.05,\n        },\n    }, options);\n    var name = o.name, scale = o.scale, upScale = o.upScale, position = o.position, justify = o.justify, size = o.size, space = o.space;\n    var xAlign = o.xAlign;\n    if (xAlign == null) {\n        switch (justify) {\n            case 'left':\n                xAlign = 'left';\n                break;\n            case 'right':\n                xAlign = 'right';\n                break;\n            case 'top':\n                xAlign = 'right';\n                break;\n            case 'bottom':\n                xAlign = 'left';\n                break;\n        }\n    }\n    var orientation = o.orientation;\n    if (orientation == null) {\n        orientation = justify === 'right' || justify === 'left' ? 'h' : 'v';\n    }\n    var appear = o.appear;\n    if (appear == null) {\n        appear = justify;\n    }\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n    });\n    element.setScale(scale);\n    var blocks = [];\n    // const blockX = [1, 1, 10]\n    // const blockY = [1, 10, 10]\n    for (var i = 0; i < 3; i += 1) {\n        var n = [1, 10, 100][i];\n        blocks.push(baseTenBlocksControl(element, {\n            name: \"__M_B10B\".concat(n),\n            n: n,\n            createScale: upScale,\n            toElement: toAdd,\n            xAlign: xAlign,\n            orientation: orientation,\n            appear: appear,\n            size: size,\n            maxNum: o.maxNum,\n            boundMove: o.boundMove,\n            snap: o.snap,\n        }, fig));\n    }\n    var x = -((11 + (orientation == 'v' ? 1 : 10)) * size + 2 * space) / 2;\n    var y = ((11 + (orientation == 'v' ? 10 : 1)) * size + 2 * space) / 2;\n    for (var i = 0; i < blocks.length; i += 1) {\n        var b = blocks[i];\n        var r = b.getBoundingRect();\n        switch (justify) {\n            case 'right':\n                b.setPosition(-r.right + size * 1.5, y - r.height);\n                y -= r.height + space;\n                break;\n            case 'left':\n                b.setPosition(-size * 1.5, y - r.height);\n                y -= r.height + space;\n                break;\n            case 'top':\n                b.setPosition(x, -r.height + size * 1.5);\n                x += r.width + space;\n                break;\n            case 'bottom':\n                b.setPosition(x, -size * 1.5);\n                x += r.width + space;\n                break;\n        }\n    }\n    var f = element.parent.getPosition('figure');\n    element.custom.controlElements = [];\n    for (var i = 0; i < o.controls.length; i += 1) {\n        var selector = selectorManipulative(element.parent, {\n            name: \"\".concat(element.name, \"_\").concat(o.controls[i]),\n            method: o.controls[i],\n            width: o.control.width,\n            height: o.control.height,\n            select: TRASH_MANIPULATIVES,\n        }, fig);\n        element.custom.controlElements.push(selector);\n        var scene = selector.getScene();\n        selector.setPosition(new Fig.Point(scene.left, scene.bottom)\n            .sub(f)\n            .add((o.control.width + o.control.space) * i, 0));\n        selector.custom.initialPosition = selector.getPosition();\n    }\n    element.preserveChildColor = true;\n};\nexport { baseTenBlocksMenu };\n","import { snapPointToPoint } from '../tools/snap';\nimport { setupManipulative, getAllLinearBlocksSlots, checkAnswerContainers, highlightAnswerContainer, removeFromContainer, incrementManipulativeIndex, getManipulativeIndex, suppressManipulativeTouch, releaseManipulativeTouch, } from './tools';\nimport { getRectPoints, rectangleBorderToTris } from '../tools/getRectPoints';\nimport { joinObjects } from '../tools/joinObjects';\nimport { NotificationHelper } from '../tools/notifications';\nimport { darken } from '../tools/color';\nimport { getSelectedSelector } from './manage';\nimport { setAtlasId } from '../tools/equation';\nfunction createLinearBlock(fig, eqn_name, toElement, o, xAlign, boundMove) {\n    var newO = Fig.joinObjects({}, o, {\n        name: \"\".concat(o.name, \"_\").concat(getManipulativeIndex('linearBlocks', o.n)),\n        scale: o.createScale,\n        xAlign: 'centerLeft',\n        fromPalette: true,\n        boundMove: boundMove,\n    });\n    if (xAlign === 'right') {\n        newO.xAlign = 'centerRight';\n    }\n    else if (xAlign === 'left') {\n        newO.xAlign = 'centerLeft';\n    }\n    // element.custom.count += 1;\n    var to = toElement;\n    if (to == null) {\n        to = eqn_name;\n    }\n    return linearBlocks(to, newO, fig);\n}\nvar BLOCK_COLORS = {\n    12: [0, 0.478, 0.823, 0.95],\n    11: [0, 0.478, 0.823, 0.95],\n    10: [0, 0.478, 0.823, 0.95],\n    9: [0.682, 0.831, 0.756, 0.95],\n    8: [0.274, 0.114, 0, 0.95],\n    7: [0.843, 0.764, 0.647, 0.95],\n    6: [0.662, 0.576, 0.792, 0.95],\n    5: [0.317, 0.611, 0.835, 0.95],\n    4: [0.843, 0.619, 0, 0.95],\n    3: [0.804, 0.525, 0.557, 0.95],\n    2: [0.847, 0.403, 0, 0.95],\n    1: [0, 0.454, 0, 0.95],\n};\nvar linearBlocks = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var OFFSET = {\n        10: [-0.48, 0],\n        9: [0, 0],\n        8: [-0.45, 0],\n        7: [0, 0],\n        6: [-0.45, 0],\n        5: [0, 0],\n        4: [-0.45, 0],\n        3: [0, 0],\n        2: [-0.45, 0],\n        1: [0, 0],\n    };\n    var o = Fig.joinObjects({\n        size: 0.15,\n        scale: 1,\n        color: BLOCK_COLORS[options.n] || BLOCK_COLORS[12],\n        // colorHighlight: [...BLOCK_COLORS[options.n].slice(0, 3), 0.8],\n        // colorDim: [...BLOCK_COLORS[options.n].slice(0, 3), 0.2],\n        // borderWidth: 0.01,\n        label: false,\n        createdFrom: null,\n        boundMove: true,\n        snapBorder: 0.05,\n        createScale: 1,\n        xAlign: 'centerLeft',\n        appear: 'left',\n        orientation: 'h',\n        border: false,\n        canRotate: true,\n        yAlign: 'bottom',\n        yOffset: 0,\n        groupSize: 10,\n        snap: false,\n        fromPalette: false,\n        preserveChildColor: true,\n        countColor: BLOCK_COLORS[options.n] || BLOCK_COLORS[12],\n        debug: false,\n        isSelectable: false,\n        isTouchable: true,\n        isCountable: false,\n        countDirection: 'any',\n        continueAt: null,\n        countUpColor: null,\n        countDownColor: null,\n        countElement: 'Q',\n        countElementValue: 'global',\n        selectLine: {\n            width: 0.02,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            space: 0.04,\n        },\n        showSnap: false,\n        radius: null,\n        sides: 10,\n        snapTo: [],\n    }, options);\n    if (o.isCountable) {\n        o.showSnap = 'count';\n        if (o.countUpColor == null) {\n            o.countUpColor = o.color.slice();\n        }\n        if (o.countDownColor == null) {\n            o.countDownColor = o.color.slice();\n        }\n    }\n    var name = o.name, color = o.color, n = o.n, size = o.size, scale = o.scale, position = o.position, xAlign = o.xAlign, orientation = o.orientation, canRotate = o.canRotate, yOffset = o.yOffset, yAlign = o.yAlign;\n    var borderDefaults = {\n        width: 0.01,\n        color: [0.8, 0.8, 0.8, 1],\n    };\n    if (o.border === true) {\n        o.border = borderDefaults;\n    }\n    else if (o.border) {\n        o.border = joinObjects(borderDefaults, o.border);\n    }\n    var borderWidth = borderDefaults.width;\n    if (o.border != null && o.border !== false) {\n        borderWidth = o.border.width;\n    }\n    if (o.color == null) {\n        o.color = BLOCK_COLORS[o.n] || BLOCK_COLORS[12];\n    }\n    if (o.colorHighlight == null) {\n        o.colorHighlight = darken(o.color);\n    }\n    if (o.colorDim == null) {\n        // o.colorDim = desaturate(o.color, 0.8);\n        o.colorDim = [0.8, 0.8, 0.8, 1];\n    }\n    var s = size * scale;\n    var line = (borderWidth / 2) * scale;\n    if (o.line === true || o.line == null) {\n        o.line = {\n            width: 0.005,\n            color: [1, 1, 1, 1],\n        };\n    }\n    if (o.line && o.line.color == null) {\n        o.line.color = [1, 1, 1, 1];\n    }\n    if (o.line && o.line.width == null) {\n        o.line.width = 0.005;\n    }\n    var lineWidth = o.line ? o.line.width : 0.005;\n    var lineColor = o.line ? o.line.color : [1, 1, 1, 1];\n    var length = s * n;\n    var yBorderDelta = 0;\n    if (yAlign === 'middle') {\n        yBorderDelta -= (s * n) / 2;\n    }\n    else if (yAlign === 'top') {\n        yBorderDelta -= s * n;\n    }\n    yBorderDelta += yOffset;\n    var hBorder = [\n        [\n            new Fig.Point(0, 0 + yBorderDelta),\n            new Fig.Point(length, 0 + yBorderDelta),\n            new Fig.Point(length, s + yBorderDelta),\n            new Fig.Point(0, s + yBorderDelta),\n        ],\n    ];\n    var vBorder = [\n        [\n            new Fig.Point(0, 0 + yBorderDelta),\n            new Fig.Point(s, 0 + yBorderDelta),\n            new Fig.Point(s, length + yBorderDelta),\n            new Fig.Point(0, length + yBorderDelta),\n        ],\n    ];\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n        border: orientation === 'h' ? hBorder : vBorder,\n    });\n    element.custom.s = s;\n    element.custom.n = n;\n    element.notificationHelper = new NotificationHelper();\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [s / 2, s / 2 + yBorderDelta],\n    });\n    if (orientation === 'v') {\n        container.setRotation(Math.PI / 2);\n    }\n    var block = container.add({\n        name: 'block',\n        make: 'collection',\n        position: [-s / 2, -s / 2 + line / 2],\n    });\n    element.snaps = [];\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    function getSnapPosition(index) {\n        if (element.custom.getBlockRotation() === 'h') {\n            if (index === 'center') {\n                return new Fig.Point((s * (n - 1)) / 2 + s / 2, s / 2);\n            }\n            return new Fig.Point(s * index + s / 2, s / 2);\n        }\n        if (index === 'center') {\n            return new Fig.Point(s / 2, (s * (n - 1)) / 2 + s / 2);\n        }\n        return new Fig.Point(s / 2, s * index + s / 2);\n    }\n    var _loop_1 = function (i) {\n        element.snaps[i] = {\n            // Snap position relative to block (draw space of block)\n            getPosition: function () { return getSnapPosition(i); },\n            // Snap position relative to block's local space\n            getLocalPosition: function () { return element.getPosition().add(getSnapPosition(i)); },\n            slot: null, // Slot the block snap is snapped to\n            slotSnapIndex: null, // Slot snap index the block snap is snapped to\n            isPrimarySnap: false, // True if block snap is primary snap of slot\n            // - all of a block's snaps must be the primary snap to be\n            //   a valid answer\n        };\n    };\n    for (var i = 0; i < n; i += 1) {\n        _loop_1(i);\n    }\n    var radius = o.radius;\n    var sides = o.sides;\n    if (o.radius == null) {\n        radius = s * 0.3;\n    }\n    var startPoints;\n    var endPoints;\n    var midPoints;\n    var unitPoints;\n    if (o.showSnap === 'block' || o.showSnap === 'count' || o.showSnap === 'color') {\n        startPoints = rectangleBorderToTris(getRectPoints(s - line / 2, s - line, sides, radius, 0, 0, new Fig.Point(0, 0), [true, false, false, true]));\n        endPoints = rectangleBorderToTris(getRectPoints(s - line / 2, s - line, sides, radius, 0, 0, new Fig.Point(0, 0), [false, true, true, false]));\n        midPoints = rectangleBorderToTris(getRectPoints(s, s - line, sides, 0, 0, 0));\n        unitPoints = rectangleBorderToTris(getRectPoints(s - line, s - line, sides, radius, 0, 0, new Fig.Point(0, 0), [true, true, true, true]));\n        if (o.isCountable) {\n            window.grokkoli.globalBlockCounter = 0;\n            if (window.grokkoli.blockCountElements == null) {\n                window.grokkoli.blockCountElements = [];\n            }\n            figure.elements._expression.custom.resetCount = function (startCount) {\n                if (startCount === void 0) { startCount = 0; }\n                window.grokkoli.globalBlockCounter = startCount;\n                for (var i = 0; i < window.grokkoli.blockCountElements.length; i += 1) {\n                    if (i < startCount) {\n                        window.grokkoli.blockCountElements[i].custom.countUp();\n                    }\n                    else {\n                        window.grokkoli.blockCountElements[i].custom.countDown();\n                    }\n                }\n                // figure.elements._expression.updateElementText(\n                //   { Q: `${window.grokkoli.globalBlockCounter}` },\n                //   'current',\n                // );\n                block.custom.count = 0;\n                for (var i = 0; i < block.custom.countElements.length; i += 1) {\n                    if (block.custom.countElements[i].custom.countState === 'up') {\n                        block.custom.count += 1;\n                    }\n                }\n            };\n        }\n    }\n    block.custom.count = 0;\n    block.custom.countElements = [];\n    block.custom.updateCount = function () {\n        // const updateText: {[name: string]: string} = {}\n        if (o.countElementValue === 'global' && o.countElement != null) {\n            // updateText[o.countElement] = `${window.grokkoli.globalBlockCounter}`;\n            figure.elements._expression.elements[o.countElement].setText(\"\".concat(window.grokkoli.globalBlockCounter));\n        }\n        if (o.countElementValue === 'block' && o.countElement != null) {\n            // updateText[o.countElement] = `${block.custom.count}`;\n            figure.elements._expression.elements[o.countElement].setText(\"\".concat(block.custom.count));\n        }\n    };\n    var snapIndex = 0;\n    for (var i = 0; i < Math.ceil(n / o.groupSize); i += 1) {\n        var m = (i + 1) * o.groupSize < n ? o.groupSize : n % o.groupSize;\n        if (m == 0) {\n            m = o.groupSize;\n        }\n        var leftSpace = line / 2;\n        var rightSpace = line / 2;\n        if (i > 0) {\n            leftSpace = 0;\n        }\n        if (i < Math.ceil(n / o.groupSize) - 1) {\n            rightSpace = 0;\n        }\n        var c = color == null ? (BLOCK_COLORS[m == 0 ? o.groupSize : m] || BLOCK_COLORS[12]) : color;\n        block.add({\n            name: \"block\".concat(i),\n            make: 'rectangle',\n            width: s * m - leftSpace - rightSpace,\n            height: s - line,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: radius,\n                sides: sides,\n            },\n            position: [i * o.groupSize * s + leftSpace, 0],\n            color: c,\n        });\n        if (o.showSnap === 'block' || o.showSnap === 'count' || o.showSnap === 'color') {\n            var _loop_2 = function (j) {\n                var points = void 0;\n                var leftSpc = 0;\n                if (n === 1) {\n                    points = unitPoints;\n                    leftSpc = leftSpace;\n                }\n                else if (j === 0 && i === 0) {\n                    points = startPoints;\n                    leftSpc = leftSpace;\n                }\n                else if (j === m - 1 && i === Math.ceil(n / o.groupSize) - 1) {\n                    points = endPoints;\n                    // leftSpc = leftSpace;\n                }\n                else {\n                    points = midPoints;\n                }\n                var c_1 = [0, 0, 0, 0.3];\n                if (o.isCountable) {\n                    if (o.countDirection === 'up' || o.countDirection === 'any') {\n                        c_1 = o.countDownColor;\n                    }\n                    else if (o.countDirection === 'down') {\n                        c_1 = o.countUpColor;\n                    }\n                }\n                var e = block.add({\n                    make: 'collection',\n                    name: \"showSnap\".concat(snapIndex),\n                    elements: [\n                        {\n                            make: 'generic',\n                            name: 'fill',\n                            points: points,\n                            color: c_1,\n                            drawType: 'TRIANGLES',\n                            transform: [['t', i * o.groupSize * s + leftSpc + j * s, 0]],\n                        },\n                        {\n                            make: 'polyline',\n                            name: 'cross',\n                            points: [\n                                [s * 0.3, s * 0.3],\n                                [s * 0.7, s * 0.7],\n                                [s * 0.5, s * 0.5],\n                                [s * 0.3, s * 0.7],\n                                [s * 0.7, s * 0.3],\n                            ],\n                            width: 0.02,\n                            color: [1, 1, 1, 1],\n                            drawType: 'TRIANGLES',\n                            transform: [['t', i * o.groupSize * s + leftSpc + j * s, 0]],\n                        },\n                    ],\n                });\n                e.hide();\n                if (o.showSnap === 'color') {\n                    e._cross.hide();\n                    e._cross.setColor([0, 0, 0, 0]);\n                    e.show();\n                    e._fill.setColor(o.color);\n                }\n                if (o.showSnap === 'count') {\n                    e._cross.hide();\n                    e.show();\n                    e.setOpacity(0);\n                    e._fill.setTouchable();\n                    e.custom.countState = 'down';\n                    window.grokkoli.blockCountElements.push(e);\n                    block.custom.countElements.push(e);\n                    e.custom.blockCounter = 0;\n                    e.custom.countUp = function () {\n                        e._fill.setColor(o.countUpColor);\n                        e.setOpacity(1);\n                        e.custom.countState = 'up';\n                        block.custom.updateCount();\n                    };\n                    e.custom.countDown = function () {\n                        // e.setOpacity(0);\n                        e.setOpacity(1);\n                        e._fill.setColor(o.countDownColor);\n                        e.custom.countState = 'down';\n                        block.custom.updateCount();\n                    };\n                    e._fill.notifications.add('onClick', function () {\n                        if (e.custom.countState === 'down') {\n                            if (o.countDirection === 'up' || o.countDirection === 'any') {\n                                window.grokkoli.globalBlockCounter += 1;\n                                block.custom.count += 1;\n                                e.custom.countUp();\n                            }\n                        }\n                        else {\n                            if (o.countDirection === 'down' || o.countDirection === 'any') {\n                                window.grokkoli.globalBlockCounter -= 1;\n                                block.custom.count -= 1;\n                                e.custom.countDown();\n                            }\n                        }\n                        // if (figure.elements._expression.elements[o.countElement] != null) {\n                        //   const updateText: {[name: string]: string} = {}\n                        //   if (o.countElementValue === 'global') {\n                        //     updateText[o.countElement] = window.grokkoli.globalBlockCounter\n                        //   }\n                        //   if (o.countElementValue === 'block') {\n                        //     updateText[o.countElement] = block.custom.count;\n                        //   }\n                        //   figure.elements._expression.updateElementText(\n                        //     updateText,\n                        //     'current',\n                        //   );\n                        // }\n                        if (figure.elements._continue_button != null &&\n                            figure.elements._continue_button.isTouchable === false &&\n                            window.grokkoli.globalBlockCounter === o.continueAt) {\n                            figure.elements._continue_button.setTouchable();\n                            figure.elements._continue_button.stop();\n                            figure.elements._continue_button.animations\n                                .new()\n                                .opacity({ start: 0, target: 1, duration: 1 })\n                                .start();\n                        }\n                        if (figure.elements._expression.custom.countCallback) {\n                            figure.elements._expression.custom.countCallback(window.grokkoli.globalBlockCounter);\n                        }\n                    });\n                }\n                snapIndex += 1;\n            };\n            for (var j = 0; j < m; j += 1) {\n                _loop_2(j);\n            }\n        }\n    }\n    if (o.border) {\n        container.add({\n            make: 'rectangle',\n            width: s * n - line,\n            height: s - line,\n            corner: {\n                radius: radius,\n                sides: 10,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: o.border.width },\n            position: [-s / 2 + line / 2, -s / 2 + line / 2],\n            color: o.border.color,\n        });\n    }\n    var selectBorder;\n    if (o.isSelectable) {\n        selectBorder = container.add({\n            name: 'selectBorder',\n            make: 'rectangle',\n            width: s * n + o.selectLine.space * 2,\n            height: s + o.selectLine.space * 2,\n            corner: {\n                radius: radius + o.selectLine.space,\n                sides: 10,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: o.selectLine.width },\n            position: [-s / 2 - o.selectLine.space, -s / 2 - o.selectLine.space],\n            // position: [, 0],\n            color: o.selectLine.color,\n        });\n        selectBorder.hide();\n    }\n    if (n > 1) {\n        container.add({\n            name: 'lines',\n            make: 'line',\n            p1: [s / 2, -s / 2 + line / 2],\n            p2: [s / 2, s / 2 - line / 2],\n            color: lineColor,\n            width: lineWidth * scale,\n            copy: {\n                along: 'x',\n                step: s,\n                num: n - 2,\n            },\n        });\n    }\n    // In debug mode, show dots at the center of each block\n    if (o.debug) {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            container.add({\n                make: 'polygon',\n                name: \"debugCenter\".concat(i),\n                sides: 10,\n                radius: 0.01,\n                position: [s * i, 0],\n            });\n        }\n        element.add({\n            make: 'polygon',\n            name: 'zerozero',\n            sides: 10,\n            radius: 0.02,\n            position: [0, 0],\n        });\n    }\n    var nMod = n % 10 == 0 ? 10 : n % 10;\n    var textP = [s / 2 + OFFSET[nMod][0] * s, s / 2 + OFFSET[nMod][1] * s];\n    if (xAlign === 'right') {\n        textP = [length - s / 2, s / 2 + OFFSET[nMod][1] * s];\n        textP[0] -= s / 2;\n        textP[1] += -s / 2 + line / 2;\n    }\n    else if (xAlign === 'left') {\n        textP = [s / 2, s / 2 + OFFSET[nMod][1] * s];\n        textP[0] -= s / 2;\n        textP[1] += -s / 2 + line / 2;\n    }\n    else if (xAlign === 'centerRight') {\n        textP = [\n            length / 2 - s / 2 - OFFSET[nMod][0] * s,\n            s / 2 + OFFSET[nMod][1] * s,\n        ];\n        textP[1] += -s / 2 + line / 2;\n    }\n    else {\n        // centerLeft (default)\n        textP[0] = length / 2 - s / 2 + OFFSET[nMod][0] * s;\n        textP[1] += -s / 2 + line / 2;\n    }\n    // textP[0] -= s/2;\n    // textP[1] +=-s / 2 + line / 2;\n    // -s / 2, -s / 2 + line / 2\n    var labelText = '';\n    var labelColor = [1, 1, 1, 1];\n    var labelSize = s * 0.7;\n    if (o.label != null && o.label !== false) {\n        if (typeof o.label === 'string') {\n            labelText = o.label;\n        }\n        else if (typeof o.label === 'object') {\n            labelText = o.label.text != null ? o.label.text : n.toString();\n            if (o.label.color != null)\n                labelColor = o.label.color;\n            if (o.label.size != null)\n                labelSize = o.label.size;\n        }\n        else {\n            labelText = n.toString();\n        }\n    }\n    var blockFont = { size: labelSize, family: defaultFontFamilyMath, render: 'gl' };\n    setAtlasId(blockFont);\n    var text = container.add({\n        make: 'text',\n        name: 'text',\n        text: labelText,\n        font: blockFont,\n        xAlign: 'center',\n        yAlign: 'middle',\n        position: textP,\n        color: labelColor,\n    });\n    element.custom.getState = function () {\n        var p = element.getPosition();\n        var orient = container.getRotation() === 0 ? 'h' : 'v';\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        var regex = new RegExp('^' + e_name);\n        var createdFrom = o.createdFrom\n            ? o.createdFrom.replace(regex, '').slice(1)\n            : null;\n        return {\n            c: createdFrom,\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            o: orient,\n            sel: element.custom.selected,\n            n: o.n,\n            sh: element.isShown,\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        // element.setScale(stats.s)\n        element.custom.setBlockRotation(stats.o, false);\n        element.custom.state = stats;\n        element.custom.moved = true;\n        if (o.isSelectable && stats.sel) {\n            element.custom.select();\n        }\n        if (stats.sh === false) {\n            element.hide();\n        }\n        else if (stats.sh === true) {\n            element.show();\n        }\n    };\n    setupManipulative(element, selectBorder, o);\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n            // element.custom.setState(element.custom.state)\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    element.getContainerBounds = function () {\n        return { rect: element.custom.getBoundingRect('local') };\n    };\n    element.custom.worksWith = {\n        trash: true,\n    };\n    if (o.n === 1) {\n        element.custom.worksWith['split'] = false;\n    }\n    else {\n        element.custom.worksWith['split'] = true;\n    }\n    element.getSnapPosition = function (snapIndex) {\n        return element.getPosition().add(getSnapPosition(snapIndex));\n        // return element.snaps[snapIndex].getLocalPosition();\n    };\n    // Splitting only works on workPad elements (not in equations likes expression\n    // as when the equations get a relayout - the original element is gone and the new\n    // elements will be hidden)\n    element.split = function (at) {\n        var blockRotation = element.custom.getBlockRotation();\n        var n1 = at;\n        var n2 = o.n - at;\n        var new_element = createLinearBlock(fig, eqn_name, options.toElement, Fig.joinObjects({}, o, {\n            n: n1,\n            color: BLOCK_COLORS[n1] || BLOCK_COLORS[12],\n            name: \"__M_LB\".concat(n1),\n        }), xAlign, o.boundMove);\n        new_element.setPositionToElement(element);\n        new_element.custom.setBlockRotation(blockRotation);\n        new_element.notificationHelper.add(toAdd, 'layoutForms', function () {\n            new_element.showAll();\n        });\n        var second_element = createLinearBlock(fig, eqn_name, options.toElement, Fig.joinObjects({}, o, {\n            n: n2,\n            color: BLOCK_COLORS[n2] || BLOCK_COLORS[12],\n            name: \"__M_LB\".concat(n2),\n        }), xAlign, o.boundMove);\n        second_element.notificationHelper.add(toAdd, 'layoutForms', function () {\n            second_element.showAll();\n        });\n        second_element.setPositionToElement(element);\n        second_element.custom.setBlockRotation(blockRotation);\n        if (blockRotation === 'h') {\n            second_element.setPosition(second_element.getPosition().add(at * s, 0));\n        }\n        else {\n            second_element.setPosition(second_element.getPosition().add(0, at * s));\n        }\n        element.trash();\n    };\n    incrementManipulativeIndex('linearBlocks', n);\n    if (o.isSelectable) {\n        block.setTouchable();\n    }\n    else if (o.isCountable === false) {\n        block.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    element.custom.manipulativeAid = {\n        style: 'linear_blocks',\n        n: n,\n    };\n    // block.notifications.add('onClick', () => {\n    // })\n    element.notificationHelper.add(element, 'startBeingMoved', function () {\n        element.custom.startMovePosition = element.getPosition();\n    });\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n        element.highlightContainer();\n    });\n    element._container._block.custom.secondaryTouchBounds = 0.1;\n    element.notificationHelper.add(element._container._block, 'onClick', function () {\n        var selector = getSelectedSelector(fig);\n        if (selector != null) {\n            element.custom.clickStart = null;\n            if (selector.custom.method === 'trash') {\n                element.trash();\n                selector.highlightWorksWith();\n                selector.checkDeselect();\n                return;\n            }\n        }\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        // figure.htmlCanvas.classList.add('figureone_shaddow');\n        window.clickHandled = true;\n        if (o.isSelectable) {\n            element.custom.toggleSelect();\n            return;\n        }\n        var workPad = fig.get('workPad');\n        if (workPad != null) {\n            if (workPad._controls != null &&\n                workPad._controls._delete != null &&\n                workPad._controls._delete.custom.selected) {\n                element.hideAll();\n                element.setPosition(10000, 10000);\n                element.stop();\n                element.isTouchable = false;\n                element.parent.remove(element.name);\n                // workPad.custom.clearControls([]);\n                return;\n            }\n        }\n        if (element.custom.isSnapped) {\n            element.custom.snappedAtMoveStart = true;\n        }\n        element.unsnap();\n        element.removeFromContainer();\n    });\n    element.afterSnapChange = function () {\n        if (o.debug) {\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                var snap = element.snaps[i];\n                if (element.custom.isSnapped === false) {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        0.5, 0.5, 0.5, 0.5,\n                    ]);\n                }\n                else if (snap.isPrimarySnap) {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        0, 0, 1, 0.5,\n                    ]);\n                }\n                else {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        1, 0, 0, 0.5,\n                    ]);\n                }\n            }\n        }\n        if (o.showSnap === 'block') {\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                var snap = element.snaps[i];\n                if (element.custom.isSnapped === false || snap.isPrimarySnap) {\n                    element._container._block.elements[\"showSnap\".concat(i)].hide();\n                }\n                else {\n                    // element._container._block.elements[`showSnap${i}`].setColor([1, 0, 0, 0.5]);\n                    element._container._block.elements[\"showSnap\".concat(i)].show();\n                }\n            }\n        }\n    };\n    element.answerContainers = [];\n    element.checkAnswerContainers = function () { return checkAnswerContainers(o, element); };\n    element.highlightContainer = function () { return highlightAnswerContainer(o, element); };\n    element.removeFromContainer = function () { return removeFromContainer(o, element); };\n    // element.unhighlight = () => {};\n    element.unhighlight = function () {\n        block.setColor(o.color);\n    };\n    element.highlight = function () {\n        block.setColor(o.colorHighlight);\n    };\n    element.dim = function () {\n        block.setColor(o.colorDim);\n    };\n    if (o.preserveChildColor === false) {\n        element.setColor = function (color) {\n            block.setColor(color);\n        };\n    }\n    // Animate the block to `target`. Skip the animation if the block is already\n    // there (so programmatic setPositionToSlot + checkSlotSnaps in static tests\n    // remains synchronous).\n    var animateToPosition = function (target, onArrive) {\n        if (element.getPosition().sub(target).distance() < 0.001) {\n            element.setPosition(target);\n            onArrive();\n            return;\n        }\n        element.stopAnimating();\n        suppressManipulativeTouch(element);\n        fig.elements.animations\n            .new()\n            .position({ element: element, target: target, duration: 0.3 })\n            .trigger(function () {\n            onArrive();\n            releaseManipulativeTouch(element);\n        })\n            .start();\n    };\n    var animateAndSnapToSlot = function (target, slot) {\n        animateToPosition(target, function () {\n            element.snap(slot);\n            element.afterSnapChange();\n            // Mark the block as moved so the `layoutForms` relayout handler re-pins\n            // it to state.p instead of resetting it to the equation-default (initial)\n            // position. Dragging sets this via the 'moved' notification; the tap-snap\n            // animation doesn't fire that, so set it explicitly here.\n            element.custom.moved = true;\n            element.custom.state.p = element.getPosition();\n            if (element.custom.isSnapped) {\n                element.custom.stopBeingMovedProcessing = true;\n                figure.answerChanged();\n                element.custom.stopBeingMovedProcessing = false;\n            }\n        });\n    };\n    var hasAnyAutoSnapSlot = function () {\n        var slots = getAllLinearBlocksSlots(toAdd);\n        for (var i = 0; i < slots.length; i += 1) {\n            if (slots[i].custom.autoSnap)\n                return true;\n        }\n        return false;\n    };\n    // Try to snap the block to the first available anchor of an autoSnap slot.\n    // Returns true if an animation was started (caller should not run other\n    // snap logic).\n    var tryTapSnap = function () {\n        if (o.snapTo == null || o.snapTo.indexOf('linear_blocks_slot') === -1) {\n            return false;\n        }\n        var linearBlocksSlots = getAllLinearBlocksSlots(toAdd);\n        for (var i = 0; i < linearBlocksSlots.length; i += 1) {\n            var slot = linearBlocksSlots[i];\n            if (!slot.custom.autoSnap)\n                continue;\n            var anchor = slot.findFirstAvailableAnchor(element);\n            if (anchor == null)\n                continue;\n            slot.reservePendingPlacement(element, anchor);\n            animateAndSnapToSlot(slot.getTargetForAnchor(element, anchor), slot);\n            return true;\n        }\n        return false;\n    };\n    element.custom.tryTapSnap = tryTapSnap;\n    // Tap on a snapped block: animate back to the position the block was\n    // created at. Only active when at least one autoSnap slot exists in the\n    // figure (paired feature with tap-snap-in). The real tap path unsnaps via\n    // onClick before this runs; the isSnapped check makes it safe to call\n    // standalone (e.g. from tests).\n    var tryTapReturn = function () {\n        if (element.custom.initialPosition == null)\n            return false;\n        if (!hasAnyAutoSnapSlot())\n            return false;\n        if (element.custom.isSnapped)\n            element.unsnap();\n        animateToPosition(element.custom.initialPosition, function () {\n            element.custom.state.p = element.getPosition();\n        });\n        return true;\n    };\n    element.custom.tryTapReturn = tryTapReturn;\n    element.checkSlotSnaps = function () {\n        if (o.snapTo == null || o.snapTo.indexOf('linear_blocks_slot') === -1) {\n            return;\n        }\n        var linearBlocksSlots = getAllLinearBlocksSlots(toAdd);\n        // Auto-snap path: slots with autoSnap=true are evaluated separately. A\n        // valid placement requires every block snap to land on an empty slot snap\n        // within bounds. If the block was dropped over an autoSnap slot but no\n        // valid placement exists, the block animates back to where the drag\n        // started.\n        var autoSnapWinnerSlot = null;\n        var autoSnapWinnerDelta = null;\n        var autoSnapAttempted = false;\n        for (var i = 0; i < linearBlocksSlots.length; i += 1) {\n            var slot = linearBlocksSlots[i];\n            if (!slot.custom.autoSnap) {\n                continue;\n            }\n            var result = slot.findAutoSnapPlacement(element);\n            if (result.inBounds) {\n                autoSnapAttempted = true;\n            }\n            if (result.delta != null) {\n                if (autoSnapWinnerDelta == null\n                    || autoSnapWinnerDelta.distance() > result.delta.distance()) {\n                    autoSnapWinnerSlot = slot;\n                    autoSnapWinnerDelta = result.delta;\n                }\n            }\n        }\n        if (autoSnapWinnerSlot != null) {\n            var target = element.getPosition().sub(autoSnapWinnerDelta);\n            animateAndSnapToSlot(target, autoSnapWinnerSlot);\n            return;\n        }\n        if (autoSnapAttempted && element.custom.startMovePosition != null) {\n            animateToPosition(element.custom.startMovePosition, function () {\n                element.custom.state.p = element.getPosition();\n            });\n            return;\n        }\n        var smallestDelta = null;\n        var slotIndex = null;\n        for (var i = 0; i < linearBlocksSlots.length; i += 1) {\n            if (linearBlocksSlots[i].custom.autoSnap) {\n                continue;\n            }\n            var delta = linearBlocksSlots[i].checkSnaps(element);\n            if (delta != null) {\n                if (smallestDelta == null) {\n                    smallestDelta = delta;\n                    slotIndex = i;\n                }\n                else if (smallestDelta.distance() > delta.distance()) {\n                    smallestDelta = delta;\n                    slotIndex = i;\n                }\n            }\n        }\n        if (smallestDelta != null) {\n            element.setPosition(element.getPosition().sub(smallestDelta));\n            element.snap(linearBlocksSlots[slotIndex]);\n            element.afterSnapChange();\n        }\n    };\n    element.unsnap = function () {\n        if (o.snapTo == null || o.snapTo.indexOf('linear_blocks_slot') === -1) {\n            return;\n        }\n        element.custom.isSnapped = false;\n        var linearBlocksSlots = getAllLinearBlocksSlots(toAdd);\n        for (var i = 0; i < linearBlocksSlots.length; i += 1) {\n            linearBlocksSlots[i].unsnap(element);\n        }\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            element.snaps[i].slot = null;\n            element.snaps[i].slotSnapIndex = null;\n            // element.snaps[i].isSnapped = false;\n            element.snaps[i].isPrimarySnap = false;\n        }\n        element.afterSnapChange();\n    };\n    element.snap = function (slot) {\n        if (o.snapTo == null || o.snapTo.indexOf('linear_blocks_slot') === -1) {\n            return;\n        }\n        element.custom.isSnapped = true;\n        slot.snap(element);\n    };\n    element.setPositionToSlot = function (slot, slotSnapIndex, offset) {\n        if (slotSnapIndex === void 0) { slotSnapIndex = 0; }\n        var oOffset = offset ? Fig.parsePoint(offset) : new Fig.Point(0, 0);\n        var slotSnapPos = slot.getSnapPosition(slotSnapIndex);\n        var blockSnapOffset = element.snaps[0].getLocalPosition().sub(element.getPosition());\n        element.setPosition(slotSnapPos.sub(blockSnapOffset).add(oOffset));\n    };\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        if (element.custom.stopBeingMovedProcessing) {\n            return;\n        }\n        // If the element was snapped at the start of the move, then we will\n        // consider the answer changed.\n        // The stopBeingMovedProcessing is\n        // used because answerChanged MAY call a figure.stop() which would send\n        // an additional stopBeingMoved notification.\n        if (element.custom.snappedAtMoveStart) {\n            element.custom.stopBeingMovedProcessing = true;\n            figure.answerChanged();\n            element.custom.stopBeingMovedProcessing = false;\n        }\n        var wasSnappedAtMoveStart = element.custom.snappedAtMoveStart === true;\n        element.custom.snappedAtMoveStart = false;\n        var answerContainerMoved = element.checkAnswerContainers();\n        // figure.htmlCanvas.classList.remove('figureone_shaddow');\n        // element.custom.hideBounds();\n        if (answerContainerMoved === 'notConfigured'\n            && element.custom.clickStart != null\n            && performance.now() - element.custom.clickStart < 200) {\n            var selector = getSelectedSelector(fig);\n            if (selector != null) {\n                element.custom.clickStart = null;\n                if (selector.custom.method === 'split') {\n                    element.split();\n                    selector.highlightWorksWith();\n                    selector.checkDeselect();\n                    return;\n                }\n            }\n        }\n        // Tap on a snapped block: return it to its initial position. The slot\n        // unsnap already happened in the click-down handler.\n        if (answerContainerMoved === 'notConfigured' &&\n            element.custom.clickStart != null &&\n            performance.now() - element.custom.clickStart < 200 &&\n            wasSnappedAtMoveStart &&\n            tryTapReturn()) {\n            element.custom.clickStart = null;\n            return;\n        }\n        // Tap-to-snap: a quick tap on an unsnapped block sends it to the first\n        // available anchor of an autoSnap slot. Concurrent rapid taps each land\n        // on a distinct anchor because the slot reserves snaps synchronously.\n        if (answerContainerMoved === 'notConfigured' &&\n            element.custom.clickStart != null &&\n            performance.now() - element.custom.clickStart < 200 &&\n            !wasSnappedAtMoveStart &&\n            tryTapSnap()) {\n            element.custom.clickStart = null;\n            return;\n        }\n        if (answerContainerMoved === 'notConfigured' &&\n            element.custom.clickStart != null &&\n            performance.now() - element.custom.clickStart < 200 &&\n            canRotate) {\n            var r = Fig.round(container.getRotation(), 8);\n            var target = Math.PI / 2;\n            var tTarget = -Math.PI / 2;\n            var border = vBorder;\n            if (r !== 0) {\n                target = 0;\n                tTarget = 0;\n                border = hBorder;\n            }\n            // element.border = border;\n            element.custom.clickStart = null;\n            element.stopAnimating();\n            fig.elements.animations\n                .new()\n                .trigger(function () {\n                element.unsnap();\n            })\n                .rotation({ target: target, duration: 0.3, element: container })\n                .trigger(function () {\n                element.checkSlotSnaps();\n                element.checkAnswerContainers();\n                if (element.isShown) {\n                    element.setMoveBounds();\n                }\n            })\n                .start();\n            fig.elements.animations\n                .new()\n                .rotation({ target: tTarget, duration: 0.3, element: text })\n                .start();\n            fig.elements.animations;\n            return;\n        }\n        if (element.custom.startMove != null &&\n            performance.now() - element.custom.startMove < 200) {\n            return;\n        }\n        if (o.snap) {\n            element.setPosition(snapPointToPoint(element.getPosition(), [0, 0], s / 2, s / 2));\n        }\n        element.checkSlotSnaps();\n        // element.checkAnswerContainers();\n        element.custom.state.p = element.getPosition();\n        // If the element is now snapped, then we consider the answer changed\n        if (element.custom.isSnapped) {\n            element.custom.stopBeingMovedProcessing = true;\n            figure.answerChanged();\n            element.custom.stopBeingMovedProcessing = false;\n        }\n    });\n    element.custom.manipulativeType = 'linear_blocks';\n    element.custom.setBlockRotation = function (orient, setBorder) {\n        if (setBorder === void 0) { setBorder = true; }\n        if (orient === 'v') {\n            container.setRotation(Math.PI / 2);\n            if (setBorder) {\n                element.border = vBorder;\n            }\n            if (container._text) {\n                container._text.setRotation(-Math.PI / 2);\n            }\n        }\n        else {\n            container.setRotation(0);\n            if (setBorder) {\n                element.border = hBorder;\n            }\n            if (container._text) {\n                container._text.setRotation(0);\n            }\n        }\n        element.setMoveBounds();\n    };\n    element.custom.getBlockRotation = function () {\n        return container.getRotation() === 0 ? 'h' : 'v';\n    };\n    element.custom.setBlockRotation(orientation);\n    if (o.isTouchable === false && o.isCountable === false) {\n        element.hasTouchableElements = false;\n    }\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    element.toColor = function (targetColor, duration, countOrIndexes, startColor) {\n        if (duration === void 0) { duration = 0.5; }\n        if (countOrIndexes === void 0) { countOrIndexes = []; }\n        if (startColor === void 0) { startColor = null; }\n        var indexes;\n        if (typeof countOrIndexes === 'number') {\n            indexes = [];\n            for (var i = 0; i < countOrIndexes; i += 1) {\n                indexes.push(i);\n            }\n        }\n        else {\n            indexes = countOrIndexes;\n        }\n        var steps = [];\n        for (var i = 0; i < indexes.length; i += 1) {\n            var e = element._container._block.elements[\"showSnap\".concat(indexes[i])]._fill;\n            var start = startColor == null ? e.color : startColor;\n            steps.push(element.animations.color({\n                element: e,\n                start: start,\n                target: targetColor,\n                duration: duration,\n            }));\n        }\n        element.animations.new()\n            .inParallel(steps)\n            .start();\n    };\n    element.resetColors = function (duration) {\n        if (duration === void 0) { duration = 0.5; }\n        var steps = [];\n        for (var i = 0; i < o.n; i += 1) {\n            var e = element._container._block.elements[\"showSnap\".concat(i)]._fill;\n            // const e.color;\n            steps.push(element.animations.color({\n                element: e,\n                // start: e.color,\n                target: o.color,\n                duration: duration,\n            }));\n        }\n        element.animations.new()\n            .inParallel(steps)\n            .start();\n    };\n    element.custom.getBoundingRect = function (space) {\n        var bounds = element.getBoundingRect(space);\n        var width = bounds.width > bounds.height ? bounds.width : bounds.height;\n        var height = bounds.width < bounds.height ? bounds.width : bounds.height;\n        if (element.custom.getBlockRotation() === 'h') {\n            return new Fig.Rect(bounds.left, bounds.bottom, width, height);\n        }\n        return new Fig.Rect(bounds.left, bounds.bottom, height, width);\n    };\n    return element;\n};\nexport { linearBlocks, createLinearBlock, BLOCK_COLORS, };\n","import { createLinearBlock, linearBlocks, } from './linearBlocks';\nvar linearBlocksControl = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var controlOptions = Fig.joinObjects({\n        appear: 'right',\n        appearSpace: 0.05,\n        xAlign: 'centerRight',\n        label: true,\n        maxNum: 10,\n        createScale: 1,\n        orientation: 'h',\n        boundMove: true,\n        toElement: toAdd,\n        snap: false,\n    }, options);\n    var blockOptions = Fig.joinObjects({}, controlOptions, {\n        name: \"__M_LB\".concat(controlOptions.n),\n        label: false,\n    });\n    Fig.joinObjects(controlOptions, options.controlOnly);\n    var element = linearBlocks(eqn_name, controlOptions, fig);\n    element.custom.manipulativeType = null;\n    element.custom.manipulativeControlType = 'linear_blocks';\n    element.notificationHelper.cleanup();\n    element._container._block.isTouchable = false;\n    element._container._block.isMovable = false;\n    var xAlign = controlOptions.xAlign, appear = controlOptions.appear, maxNum = controlOptions.maxNum;\n    ///////////////////////////////////\n    element.setTouchable();\n    element.custom.count = 0;\n    element.custom.create = function (name, customN) {\n        if (name === void 0) { name = null; }\n        if (customN === void 0) { customN = blockOptions.n; }\n        var o = Fig.joinObjects({}, blockOptions, {\n            createdFrom: element.getPath(),\n        });\n        if (name != null) {\n            o.name = name;\n        }\n        var new_element = createLinearBlock(fig, eqn_name, controlOptions.toElement, o, xAlign, blockOptions.boundMove);\n        toAdd.notifications.add('layoutForms', function () {\n            new_element.show();\n            new_element.setPosition(new_element.custom.state.p);\n            // This is needed after the show as when an element is hidden, getBoundingRect\n            // returns 0\n            new_element.setMoveBounds();\n        });\n        new_element.setPositionToElement(element);\n        new_element.custom.initialPosition = new_element.getPosition();\n        fig.beingMovedElement = new_element;\n        new_element.startBeingMoved();\n        new_element.custom.startMove = performance.now();\n        new_element.notifications.add('stopBeingMoved', function () {\n            var new_p = new_element.getPosition();\n            if (performance.now() - new_element.custom.startMove < 200 ||\n                new_p.sub(new_element.custom.initialPosition).distance() <\n                    new_element.custom.s) {\n                var p = element.getPosition();\n                var r = element.getBoundingRect();\n                var newR = new_element.getBoundingRect();\n                var target = new Fig.Point(0, 0);\n                switch (appear) {\n                    case 'right':\n                        target = p.add(r.width, 0);\n                        break;\n                    case 'left':\n                        target = p.add(0, 0);\n                        break;\n                    case 'top':\n                        target = p.add(0, r.height);\n                        break;\n                    case 'bottom':\n                        target = p.add(0, 0);\n                        break;\n                }\n                var t1 = element.pointFromSpaceToSpace(target, 'local', 'figure');\n                var t2 = new_element.pointFromSpaceToSpace(t1, 'figure', 'local');\n                switch (appear) {\n                    case 'right':\n                        t2 = t2.add(controlOptions.appearSpace, 0);\n                        break;\n                    case 'left':\n                        t2 = t2.add(-newR.width - controlOptions.appearSpace, 0);\n                        break;\n                    case 'top':\n                        t2 = t2.add(0, controlOptions.appearSpace);\n                        break;\n                    case 'bottom':\n                        t2 = t2.add(0, -newR.height - controlOptions.appearSpace);\n                        break;\n                }\n                new_element.custom.state.p = t2;\n                element.animations\n                    .new()\n                    .trigger(function () {\n                    new_element.hasTouchableElements = false;\n                })\n                    .position({\n                    target: t2,\n                    duration: 0.5,\n                    progression: 'easeout',\n                    element: new_element,\n                })\n                    .trigger(function () {\n                    new_element.hasTouchableElements = true;\n                })\n                    .start();\n            }\n        }, 1);\n        return new_element;\n    };\n    element.custom.secondaryTouchBounds = 0.1;\n    element.notifications.add('onClick', function () {\n        window.clickHandled = true;\n        if (element.custom.count < maxNum) {\n            element.custom.create();\n            element.custom.count += 1;\n            if (element.custom.count >= maxNum) {\n                element.hide();\n            }\n        }\n    });\n    return element;\n};\nexport { linearBlocksControl, };\n","// import {linearBlocks} from './linearBlocks';\nimport { linearBlocksControl } from './linearBlocksControl';\nimport { selectorManipulative } from './selector';\nimport { TRASH_MANIPULATIVES } from './tools';\nvar linearBlocksMenu = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        justify: 'right',\n        scale: 1,\n        upScale: 1,\n        size: 0.15 * 0.8,\n        lineWidth: 0.005 * 0.6,\n        borderWidth: 0.02 * 0.6,\n        position: [0, 0],\n        appear: null,\n        canRotate: true,\n        space: 0.025,\n        maxNum: 20,\n        snap: true,\n        boundMove: false,\n        controls: [],\n        control: {\n            width: 0.2,\n            height: 0.2,\n            space: 0.05,\n        },\n    }, options);\n    var name = o.name, scale = o.scale, upScale = o.upScale, position = o.position, justify = o.justify, size = o.size, space = o.space;\n    var xAlign = o.xAlign;\n    if (xAlign == null) {\n        switch (justify) {\n            case 'left':\n                xAlign = 'left';\n                break;\n            case 'right':\n                xAlign = 'right';\n                break;\n            case 'top':\n                xAlign = 'right';\n                break;\n            case 'bottom':\n                xAlign = 'left';\n                break;\n        }\n    }\n    var orientation = o.orientation;\n    if (orientation == null) {\n        orientation = justify === 'right' || justify === 'left' ? 'h' : 'v';\n    }\n    var appear = o.appear;\n    if (appear == null) {\n        appear = justify;\n    }\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n    });\n    element.setScale(scale);\n    var blocks = [];\n    for (var i = 1; i <= 10; i += 1) {\n        blocks.push(linearBlocksControl(element, {\n            name: \"__M_LB\".concat(i),\n            n: i,\n            createScale: upScale,\n            toElement: toAdd,\n            // control: true,\n            xAlign: xAlign,\n            orientation: orientation,\n            appear: appear,\n            size: size,\n            maxNum: o.maxNum,\n            boundMove: o.boundMove,\n            snap: o.snap,\n        }, fig));\n    }\n    var x = -(blocks.length * size + (blocks.length - 1) * space) / 2;\n    var y = (blocks.length * size + (blocks.length - 1) * space) / 2;\n    for (var i = 0; i < blocks.length; i += 1) {\n        var b = blocks[i];\n        var r = b.getBoundingRect();\n        switch (justify) {\n            case 'right':\n                b.setPosition(-r.right + size, y - size);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'left':\n                b.setPosition(0 / size / 2, y - size);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'top':\n                b.setPosition(x, -r.height / 2 + size);\n                x += b.getBoundingRect().width + space;\n                break;\n            case 'bottom':\n                b.setPosition(x, r.height / 2 - size);\n                x += b.getBoundingRect().width + space;\n                break;\n        }\n    }\n    var f = element.parent.getPosition('figure');\n    element.custom.controlElements = [];\n    for (var i = 0; i < o.controls.length; i += 1) {\n        var selector = selectorManipulative(element.parent, {\n            name: \"\".concat(element.name, \"_\").concat(o.controls[i]),\n            method: o.controls[i],\n            width: o.control.width,\n            height: o.control.height,\n            select: TRASH_MANIPULATIVES,\n        }, fig);\n        element.custom.controlElements.push(selector);\n        selector.drawNumber = -1;\n        var scene = selector.getScene();\n        selector.setPosition(new Fig.Point(scene.left, scene.bottom)\n            .sub(f)\n            .add((o.control.width + o.control.space) * i, 0));\n        selector.custom.initialPosition = selector.getPosition();\n    }\n    element.preserveChildColor = true;\n};\nexport { linearBlocksMenu };\n","import { joinObjects } from '../tools/joinObjects';\nimport { doRectsOverlap } from '../workpad_new/tools';\nimport { setAtlasId } from '../tools/equation';\nimport { suppressManipulativeTouch, releaseManipulativeTouch, } from './tools';\nvar linearBlocksSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        snap: 0.1,\n        numX: 1,\n        numY: 1,\n        fill: false,\n        yOffset: 0,\n        radius: 0.08,\n        sides: 10,\n        debug: false,\n        grid: true,\n        space: 0.01,\n        line: true,\n        label: '?',\n        xLabelOffset: 0,\n        yLabelOffset: 0,\n        font: {\n            size: 0.15,\n            color: [0.6, 0.6, 0.6, 1],\n            family: defaultFontFamilyMath,\n        },\n        snapBorder: 0,\n        borderInSize: false,\n        correctness: true,\n        showBlocks: false,\n        enforceOrder: false,\n        stateOrder: 'time',\n        autoSnap: false,\n        autoSnapFit: true,\n    }, options);\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var lineDefaults = {\n        color: [0.6, 0.6, 0.6, 1],\n        width: 0.02,\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n    };\n    var fillDefaults = {\n        color: [0, 0, 0, 0],\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n    };\n    var gridDefaults = {\n        show: true,\n        lineWidth: 0.01,\n        color: [0.8, 0.8, 0.8, 1],\n    };\n    if (o.line === true) {\n        o.line = lineDefaults;\n    }\n    else if (o.line) {\n        o.line = joinObjects(lineDefaults, o.line);\n    }\n    if (o.fill === true) {\n        o.fill = fillDefaults;\n    }\n    else if (o.fill) {\n        o.fill = joinObjects(fillDefaults, o.fill);\n    }\n    if (o.grid === true) {\n        o.grid = gridDefaults;\n    }\n    else if (o.grid) {\n        o.grid = joinObjects(gridDefaults, o.grid);\n    }\n    var showBlocksDefaults = {\n        lineWidth: 0.01,\n        color: [0.7, 0.7, 0.7, 1],\n        radius: o.radius,\n        sides: o.sides,\n    };\n    if (o.showBlocks === true) {\n        o.showBlocks = showBlocksDefaults;\n    }\n    else if (o.showBlocks) {\n        o.showBlocks = joinObjects(showBlocksDefaults, o.showBlocks);\n    }\n    var width = o.snap * o.numX;\n    var height = o.snap * o.numY;\n    var borderOffset = o.line.show ? o.line.width / 2 : 0;\n    var snapPositions = [];\n    for (var i = 0; i < o.numX; i += 1) {\n        for (var j = 0; j < o.numY; j += 1) {\n            var snapPosition = new Fig.Point(borderOffset + o.snap * i + o.snap / 2, o.snap * j + o.snap / 2);\n            snapPositions.push(snapPosition);\n        }\n    }\n    var fill;\n    if (o.fill) {\n        fill = element.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: width,\n            height: height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n            position: [borderOffset, o.yOffset],\n        });\n    }\n    if (o.showBlocks) {\n        for (var i = 0; i < snapPositions.length; i += 1) {\n            element.add({\n                make: 'rectangle',\n                name: \"showBlock\".concat(i),\n                width: o.snap - o.showBlocks.lineWidth,\n                height: o.snap - o.showBlocks.lineWidth,\n                corner: {\n                    radius: o.showBlocks.radius,\n                    sides: o.showBlocks.sides,\n                },\n                position: snapPositions[i],\n                color: o.showBlocks.color,\n            });\n        }\n    }\n    if (o.grid) {\n        if (o.numX > 1) {\n            element.add({\n                make: 'line',\n                color: o.grid.color,\n                p1: [borderOffset + o.snap, o.yOffset],\n                p2: [borderOffset + o.snap, height + o.yOffset],\n                width: o.grid.lineWidth,\n                copy: {\n                    along: 'x',\n                    step: o.snap,\n                    num: o.numX - 2,\n                },\n            });\n        }\n        if (o.numY > 1) {\n            element.add({\n                make: 'line',\n                color: o.grid.color,\n                p1: [0, o.snap + o.yOffset],\n                p2: [0 + width + o.space * 2, o.snap + o.yOffset],\n                width: o.grid.lineWidth,\n                copy: {\n                    along: 'y',\n                    step: o.snap,\n                    num: o.numY - 2,\n                },\n            });\n        }\n    }\n    var border;\n    if (o.line) {\n        border = element.add({\n            make: 'rectangle',\n            name: 'border',\n            width: width + o.space * 2,\n            height: height + o.space * 2,\n            color: o.line.color,\n            line: { width: o.line.width, dash: o.line.dash },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n            position: [borderOffset - o.space, -o.space + o.yOffset],\n        });\n        border.custom.initialColor = border.color.slice();\n        if (o.borderInSize === false) {\n            border.border = [\n                [\n                    new Fig.Point(0, 0),\n                    new Fig.Point(width + o.space * 2, 0),\n                    new Fig.Point(width + o.space * 2, height + o.space * 2),\n                    new Fig.Point(0, height + o.space * 2),\n                ],\n            ];\n        }\n    }\n    if (o.label) {\n        var label = void 0;\n        if (typeof o.label === 'number') {\n            label = o.label.toString();\n        }\n        else {\n            label = o.label;\n        }\n        var slotFont = { size: o.font.size, family: o.font.family, render: 'gl', color: o.font.color };\n        setAtlasId(slotFont);\n        element.add({\n            make: 'equation',\n            forms: {\n                '0': label,\n            },\n            formDefaults: {\n                alignment: {\n                    xAlign: 'center',\n                    yAlign: 'middle',\n                },\n            },\n            font: slotFont,\n            xAlign: 'center',\n            yAlign: 'middle',\n            position: [\n                borderOffset + width / 2 + o.xLabelOffset,\n                height / 2 + o.yLabelOffset + o.yOffset,\n            ],\n            scale: 1,\n        });\n    }\n    element.preserveChildColor = true;\n    if (o.debug) {\n        for (var i = 0; i < snapPositions.length; i += 1) {\n            element.add({\n                make: 'polygon',\n                sides: 10,\n                radius: 0.005,\n                color: [0, 0, 0, 1],\n                position: snapPositions[i],\n            });\n            element.add({\n                make: 'rectangle',\n                sides: 4,\n                radius: 0.01,\n                color: [0, 0, 0, 0.5],\n                width: o.snap,\n                height: o.snap,\n                line: { width: 0.001 },\n                position: snapPositions[i],\n            });\n        }\n        element.add({\n            make: 'rectangle',\n            name: 'snapBorder',\n            width: width + o.snapBorder * 2,\n            height: height + o.snapBorder * 2,\n            color: o.line.color,\n            line: { width: 0.005, dash: [0.02, 0.02] },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            position: [borderOffset - o.snapBorder, -o.snapBorder + o.yOffset],\n        });\n    }\n    element.getManipulativeBaseSnap = function () { return 0; };\n    element.custom.getState = function () {\n        // Get a list of blocks that are fully valid within the slot\n        var fullBlocks = [];\n        var partialBlocks = [];\n        var snappedBlocks = element.snappedBlocks;\n        if (o.stateOrder === 'position') {\n            snappedBlocks = [];\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                var snap = element.snaps[i];\n                for (var j = 0; j < snap.blocks.length; j += 1) {\n                    if (snappedBlocks.indexOf(snap.blocks[j]) === -1) {\n                        snappedBlocks.push(snap.blocks[j]);\n                    }\n                }\n            }\n        }\n        for (var i = 0; i < snappedBlocks.length; i += 1) {\n            var block = snappedBlocks[i];\n            var full = true;\n            for (var j = 0; j < block.snaps.length; j += 1) {\n                var blockSnap = block.snaps[j];\n                if (blockSnap.slot !== element || blockSnap.isPrimarySnap === false) {\n                    full = false;\n                    break;\n                }\n            }\n            if (full) {\n                fullBlocks.push(block.name);\n            }\n            else {\n                partialBlocks.push(block.name);\n            }\n        }\n        return {\n            full: fullBlocks,\n            partial: partialBlocks,\n            order: snappedBlocks.map(function (b) { return b.name; }),\n        };\n    };\n    element.custom.showCorrectness = function (result) {\n        var _a, _b;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        if (border != null && o.correctness) {\n            if (result === 1) {\n                border.setColor(correctColor || o.line.correct);\n            }\n            else if (result === 2 || result === 6) {\n                border.setColor(incorrectColor || o.line.incorrect);\n            }\n            else {\n                border.setColor(o.line.color);\n            }\n        }\n        if (fill != null && o.correctness) {\n            if (result === 1) {\n                fill.setColor(correctColor || o.fill.correct);\n            }\n            else if (result === 2 || result === 6) {\n                fill.setColor(incorrectColor || o.fill.incorrect);\n            }\n            else {\n                fill.setColor(o.fill.color);\n            }\n        }\n    };\n    element.unhighlight = function () { };\n    element.custom.manipulativeType = 'linearBlocksSlot';\n    element.snaps = [];\n    // List of blocks current snapped to this slot\n    element.snappedBlocks = [];\n    for (var i = 0; i < snapPositions.length; i += 1) {\n        element.snaps.push({\n            position: snapPositions[i], // snap position relative to slot (draw space of slot)\n            blocks: [], // All blocks with a snap that aligns with this snap\n            blockIndexes: [], // Block indexes of all blocks above that align with\n            // this snap\n            primaryBlock: null, // primary block snapped to this snap\n            primaryBlockSnapIndex: null, // snapIndex of primary block snap snapped to\n            // this snap\n            // Block whose tap/auto-snap animation has reserved this snap but hasn't\n            // yet physically arrived. Treated as occupied for placement search.\n            pendingBlock: null,\n        });\n    }\n    element.getSnapPosition = function (snapIndex) {\n        return element.getPosition().add(element.snaps[snapIndex].position);\n    };\n    // block:\n    //  block.snaps: [\n    //      {\n    //        index: int,\n    //        position: Point,\n    //        snap: element,\n    //        snapIndex: int,\n    //        isSnapped: boolean,\n    //      }, ...\n    //  ]\n    //  block.custom.snapPositions: positions in block that are snappable\n    element.refreshSnaps = function () {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            var slotSnap = element.snaps[i];\n            if (slotSnap.block != null || slotSnap.blocks.length == 0) {\n                continue;\n            }\n            slotSnap.primaryBlock = slotSnap.blocks[0];\n            slotSnap.primaryBlockSnapIndex = slotSnap.blockIndexes[0];\n            slotSnap.primaryBlock.snaps[slotSnap.primaryBlockSnapIndex].isPrimarySnap = true;\n        }\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            element.snappedBlocks[i].afterSnapChange();\n        }\n        if (border != null) {\n            border.setColor(border.custom.initialColor);\n        }\n    };\n    /**\n     * Get slot's snap index from a position.\n     * Snap must be within o.snap/10 for a snap index to return\n     * @param position\n     * @returns index (number) or null\n     */\n    element.getSnapFromPosition = function (position) {\n        var p = element.getPosition();\n        for (var i = 0; i < snapPositions.length; i += 1) {\n            var snapPosition = p.add(snapPositions[i]);\n            if (position.sub(snapPosition).distance() < o.snap / 10) {\n                return i;\n            }\n        }\n        return null;\n    };\n    /**\n     * Snap a block to the slot.\n     * - Add block to slot's list of snapped blocks\n     * - Match up each slot's and block's snaps\n     * @param block\n     */\n    element.snap = function (block) {\n        // fig.answerChanged();\n        if (element.snappedBlocks.indexOf(block) == -1) {\n            element.snappedBlocks.push(block);\n        }\n        for (var i = 0; i < block.snaps.length; i += 1) {\n            var blockSnap = block.snaps[i];\n            var snapIndex = element.getSnapFromPosition(blockSnap.getLocalPosition());\n            if (snapIndex == null) {\n                continue;\n            }\n            blockSnap.slot = element;\n            blockSnap.slotSnapIndex = snapIndex;\n            var slotSnap = element.snaps[snapIndex];\n            if (slotSnap.blocks.indexOf(block) == -1) {\n                slotSnap.blocks.push(block);\n                slotSnap.blockIndexes.push(i);\n            }\n            // If the slot snap is empty, then can properly snap the block to it\n            if (slotSnap.primaryBlock == null) {\n                slotSnap.primaryBlock = block;\n                slotSnap.primaryBlockSnapIndex = i;\n                blockSnap.isPrimarySnap = true;\n            }\n        }\n        element.clearPendingPlacement(block);\n        block.snapPositionDelta = element.getPosition().sub(block.getPosition());\n        element.refreshSnaps();\n    };\n    element.unsnap = function (block) {\n        // fig.answerChanged();\n        element.clearPendingPlacement(block);\n        var index = element.snappedBlocks.indexOf(block);\n        block.snapPositionDelta = null;\n        if (index == -1) {\n            return;\n        }\n        element.snappedBlocks.splice(index, 1);\n        var slotSnaps = element.snaps;\n        for (var i = 0; i < slotSnaps.length; i += 1) {\n            var slotSnap = slotSnaps[i];\n            var index_1 = slotSnap.blocks.indexOf(block);\n            if (index_1 !== -1) {\n                slotSnap.blocks.splice(index_1, 1);\n                slotSnap.blockIndexes.splice(index_1, 1);\n            }\n            if (slotSnap.primaryBlock == block) {\n                slotSnap.primaryBlock = null;\n                slotSnap.primaryBlockSnapIndex = null;\n            }\n        }\n        element.refreshSnaps();\n    };\n    element.disable = function () {\n    };\n    element.notifications.add('setTransform', function () {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            if (block.snapPositionDelta != null) {\n                block.setPosition(element.getPosition().sub(block.snapPositionDelta));\n                block.custom.slotPosition = block.getPosition();\n                block.custom.state.p = block.getPosition();\n            }\n        }\n    });\n    element.custom.autoSnap = o.autoSnap;\n    var getSlotBorderBounds = function () {\n        var slotBounds = element.getBoundingRect('local');\n        return new Fig.Rect(slotBounds.left - (o.debug ? 0 : o.snapBorder), slotBounds.bottom - (o.debug ? 0 : o.snapBorder), width + o.snapBorder * 2, height + o.snapBorder * 2);\n    };\n    // For a block anchored such that block.snaps[0] sits on slot snap\n    // `anchorIndex`, return the slot snap indices each block snap would land on.\n    // Returns null if the placement overhangs the slot (unless autoSnapFit is\n    // false, in which case overhanging snaps are ignored) or any required slot\n    // snap is already occupied/reserved by a block other than `block`.\n    var getOccupiedSnapsForAnchor = function (block, anchorIndex) {\n        var p = element.getPosition();\n        var blockSnap0Pos = block.snaps[0].getLocalPosition();\n        var anchorPos = p.add(snapPositions[anchorIndex]);\n        var occupied = [];\n        for (var i = 0; i < block.snaps.length; i += 1) {\n            var targetPos = anchorPos.add(block.snaps[i].getLocalPosition().sub(blockSnap0Pos));\n            var matched = -1;\n            for (var k = 0; k < snapPositions.length; k += 1) {\n                if (targetPos.sub(p.add(snapPositions[k])).distance() < o.snap / 10) {\n                    matched = k;\n                    break;\n                }\n            }\n            if (matched === -1) {\n                if (!o.autoSnapFit)\n                    continue;\n                return null;\n            }\n            var slotSnap = element.snaps[matched];\n            var blockedBy = slotSnap.primaryBlock || slotSnap.pendingBlock;\n            if (blockedBy != null && blockedBy !== block)\n                return null;\n            occupied.push(matched);\n        }\n        return occupied;\n    };\n    // For autoSnap: find the first slot snap index (iterated bottom-to-top,\n    // left-to-right) where all of the block's snaps can land on empty slot\n    // snaps that are fully within the slot bounds.\n    //\n    // Returns:\n    //   { delta, inBounds: true }       valid placement found, delta to apply\n    //   { delta: null, inBounds: true } block is over the slot but no fit\n    //   { delta: null, inBounds: false } block is not over the slot\n    element.findAutoSnapPlacement = function (block) {\n        var blockBounds = block.custom.getBoundingRect('local');\n        if (!doRectsOverlap(getSlotBorderBounds(), blockBounds)) {\n            return { delta: null, inBounds: false };\n        }\n        var p = element.getPosition();\n        var blockSnap0Pos = block.snaps[0].getLocalPosition();\n        for (var j = 0; j < snapPositions.length; j += 1) {\n            if (getOccupiedSnapsForAnchor(block, j) != null) {\n                return {\n                    delta: blockSnap0Pos.sub(p.add(snapPositions[j])),\n                    inBounds: true,\n                };\n            }\n        }\n        return { delta: null, inBounds: true };\n    };\n    // Tap-snap entry point: find the first anchor (bottom-to-top, left-to-right)\n    // that produces a fully-in-bounds, fully-unoccupied placement. Ignores\n    // whether the block is currently over the slot, since the block is being\n    // teleported in.\n    element.findFirstAvailableAnchor = function (block) {\n        for (var j = 0; j < snapPositions.length; j += 1) {\n            if (getOccupiedSnapsForAnchor(block, j) != null)\n                return j;\n        }\n        return null;\n    };\n    // World-space position the block must be moved to so that block.snaps[0]\n    // sits exactly on slot snap `anchorIndex`.\n    element.getTargetForAnchor = function (block, anchorIndex) {\n        var blockSnap0Pos = block.snaps[0].getLocalPosition();\n        var anchorPos = element.getPosition().add(snapPositions[anchorIndex]);\n        return block.getPosition().sub(blockSnap0Pos.sub(anchorPos));\n    };\n    // Synchronously reserve the slot snaps a block would occupy if anchored at\n    // `anchorIndex`, so concurrent tap-snaps see them as taken.\n    element.reservePendingPlacement = function (block, anchorIndex) {\n        var occupied = getOccupiedSnapsForAnchor(block, anchorIndex);\n        if (occupied == null)\n            return;\n        for (var i = 0; i < occupied.length; i += 1) {\n            element.snaps[occupied[i]].pendingBlock = block;\n        }\n    };\n    element.clearPendingPlacement = function (block) {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            if (element.snaps[i].pendingBlock === block) {\n                element.snaps[i].pendingBlock = null;\n            }\n        }\n    };\n    // Look up a linear block.\n    //  - By name: first element matching that name, regardless of state.\n    //  - By n + outbound=false (filling the slot): first unsnapped block with\n    //    that n.\n    //  - By n + outbound=true (emptying the slot): the block of that n snapped\n    //    to this slot at the highest anchor index (i.e. the one furthest along\n    //    the slot, so repeated outbound calls peel blocks off in reverse order).\n    var findLinearBlock = function (nameOrN, outbound) {\n        if (typeof nameOrN === 'string') {\n            var elementNames_1 = Object.keys(toAdd.elements);\n            for (var i = 0; i < elementNames_1.length; i += 1) {\n                var e = toAdd.elements[elementNames_1[i]];\n                if (e.custom != null\n                    && e.custom.manipulativeType === 'linear_blocks'\n                    && e.name === nameOrN) {\n                    return e;\n                }\n            }\n            return null;\n        }\n        if (outbound) {\n            var best = null;\n            var bestAnchor = -1;\n            for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n                var b = element.snappedBlocks[i];\n                if (b.custom.n !== nameOrN)\n                    continue;\n                var anchor = b.snaps[0] != null ? b.snaps[0].slotSnapIndex : null;\n                if (anchor == null)\n                    continue;\n                if (anchor > bestAnchor) {\n                    bestAnchor = anchor;\n                    best = b;\n                }\n            }\n            return best;\n        }\n        var isPendingInSlot = function (b) {\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                if (element.snaps[i].pendingBlock === b)\n                    return true;\n            }\n            return false;\n        };\n        var elementNames = Object.keys(toAdd.elements);\n        for (var i = 0; i < elementNames.length; i += 1) {\n            var e = toAdd.elements[elementNames[i]];\n            if (e.custom != null\n                && e.custom.manipulativeType === 'linear_blocks'\n                && e.custom.n === nameOrN\n                && !e.custom.isSnapped\n                && !isPendingInSlot(e)) {\n                return e;\n            }\n        }\n        return null;\n    };\n    // Programmatically animate a block to:\n    //   - a numeric slot snap anchor index (registers a snap on arrival)\n    //   - null (first available anchor; snap on arrival)\n    //   - 'init' (the block's initialPosition; no snap)\n    //   - [x, y] or any FigureOne-parsable point (no snap)\n    // Returns a Promise that resolves when the animation completes (or\n    // immediately if there is no block to animate / no space available).\n    element.animateLinearBlock = function (nameOrN, snapIndex, duration) {\n        var block = findLinearBlock(nameOrN, snapIndex === 'init');\n        if (block == null)\n            return;\n        var target;\n        var anchorToReserve = null;\n        if (snapIndex === 'init') {\n            if (block.custom.initialPosition == null)\n                return;\n            target = block.custom.initialPosition;\n        }\n        else if (typeof snapIndex === 'number') {\n            if (snapIndex < 0 || snapIndex >= snapPositions.length)\n                return;\n            target = element.getTargetForAnchor(block, snapIndex);\n            anchorToReserve = snapIndex;\n        }\n        else if (snapIndex == null || snapIndex == 'next') {\n            var anchor = element.findFirstAvailableAnchor(block);\n            if (anchor == null)\n                return;\n            target = element.getTargetForAnchor(block, anchor);\n            anchorToReserve = anchor;\n        }\n        else {\n            target = Fig.parsePoint(snapIndex);\n        }\n        // Clear any existing snap state before reserving / animating, so cross-\n        // slot moves don't leave stale relationships and a self-move (e.g. snap\n        // 0 → snap 2 on the same slot) doesn't immediately wipe its reservation.\n        if (block.custom.isSnapped) {\n            block.unsnap();\n        }\n        if (anchorToReserve != null) {\n            element.reservePendingPlacement(block, anchorToReserve);\n        }\n        var d = duration != null ? duration : 0.3;\n        var onArrive = function () {\n            if (anchorToReserve != null) {\n                block.snap(element);\n                block.afterSnapChange();\n            }\n            block.custom.state.p = block.getPosition();\n        };\n        if (block.getPosition().sub(target).distance() < 0.001 || d === 0) {\n            block.setPosition(target);\n            onArrive();\n            return;\n        }\n        block.stopAnimating();\n        suppressManipulativeTouch(block);\n        // Name the completion trigger via fnMap (owner = fig.elements, keyed by block name)\n        // so the snap commit + touch-release survive speech pause/resume: an inline .trigger\n        // is dropped from figure.getState(), so a pause mid-move would land the block but\n        // never register it as snapped and leave touch suppressed. Per-block key so reset()\n        // (which animates every snapped block at once) never clobbers another's callback.\n        var arriveKey = \"linBlockArrive:\".concat(block.name);\n        fig.elements.fnMap.add(arriveKey, function () {\n            onArrive();\n            releaseManipulativeTouch(block);\n        });\n        fig.elements.animations\n            .new()\n            .position({ element: block, target: target, duration: d })\n            .trigger({ callback: arriveKey })\n            .start();\n    };\n    // Animate every snapped block back to its initialPosition. Snapshots the\n    // list first because animateLinearBlock('init') triggers block.unsnap(),\n    // which mutates element.snappedBlocks mid-iteration.\n    element.reset = function (duration) {\n        var blocks = element.snappedBlocks.slice();\n        for (var i = 0; i < blocks.length; i += 1) {\n            element.animateLinearBlock(blocks[i].name, 'init', duration);\n        }\n    };\n    element.checkSnaps = function (block) {\n        // Return the offset required to snap - null if no snap\n        // First check if the block bounds overlap with the slotBorderBounds\n        var blockBounds = block.custom.getBoundingRect('local');\n        if (!doRectsOverlap(getSlotBorderBounds(), blockBounds)) {\n            return null;\n        }\n        // Snap algorithm:\n        // Go through all snapPositions in manipulative to calc distance to all\n        // snap positions in Snap. Whichever snapPosition has the smallest distance to a\n        // snap gets snapped\n        var delta = null;\n        var distance = null;\n        var p = element.getPosition();\n        var found = false;\n        for (var i = 0; i < block.snaps.length; i += 1) {\n            if (found) {\n                break;\n            }\n            for (var j = 0; j < snapPositions.length; j += 1) {\n                if (found) {\n                    break;\n                }\n                var slotSnapPosition = p.add(snapPositions[j]);\n                var blockSnapPosition = block.snaps[i].getLocalPosition();\n                var del = blockSnapPosition.sub(slotSnapPosition);\n                var d = del.distance();\n                if (distance == null || distance > d) {\n                    distance = d;\n                    delta = del;\n                }\n                // If the distance is\n                if (Math.abs(delta.x) < o.snap / 2 && Math.abs(delta.y) < o.snap / 2) {\n                    found = true;\n                }\n            }\n        }\n        return delta;\n    };\n    return element;\n};\nexport { linearBlocksSlot, };\n","import { snapPointToPoint } from '../tools/snap';\nimport { NotificationHelper } from '../tools/notifications';\nimport { setupManipulative, checkAnswerContainers, highlightAnswerContainer, removeFromContainer, getAllManipulativeTileSlots, getAllAnswerContainers, suppressManipulativeTouch, releaseManipulativeTouch, } from './tools';\nimport { createEquation, setFontFamily } from '../tools/equation';\nvar manipulativeTile = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        scale: 1,\n        width: null,\n        height: null,\n        line: true,\n        fill: true,\n        yOffset: 0,\n        snap: false,\n        debug: false,\n        isTouchable: true,\n        isSelectable: false,\n        selectLine: {\n            width: 0.02,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            space: 0.04,\n        },\n        radius: 0.1,\n        sides: 20,\n        snapTo: [],\n        onClick: 'snap_last',\n        space: 0.05,\n        font: {\n            size: 0.2,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        textFont: {\n            family: defaultFontFamily,\n            style: 'normal',\n            weight: '300',\n            render: 'gl',\n            color: colors.COLOR_GROKKOLI_BLUE,\n        },\n        labelColors: true,\n        boundMove: true,\n        isShowable: true,\n    }, options);\n    if (o.line !== false) {\n        o.line = Fig.joinObjects({\n            width: 0.003,\n            color: [0.5, 0.5, 0.5, 1],\n            incorrect: true,\n            correct: true,\n            highlight: false,\n            dash: [],\n        }, o.line === true ? {} : o.line);\n    }\n    if (o.fill !== false) {\n        o.fill = Fig.joinObjects({\n            color: colors.COLOR_GROKKOLI_LIGHT_GREY,\n            incorrect: false,\n            correct: true,\n            highlight: false,\n        }, o.fill === true ? {} : o.fill);\n    }\n    if (o.labelColors !== false) {\n        o.labelColors = Fig.joinObjects({\n            color: o.font.color,\n            incorrect: false,\n            correct: [1, 1, 1, 1],\n            highlight: false,\n        }, o.labelColors === true ? {} : o.labelColors);\n    }\n    if (typeof o.space === 'number') {\n        o.space = [o.space, o.space];\n    }\n    var tile = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = tile.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    tile.snappedSlot = null;\n    if (o.n) {\n        tile.custom.n = o.n;\n    }\n    var label;\n    if (o.label) {\n        if (typeof o.label === 'string') {\n            setFontFamily(o.font, o.label);\n            label = container.add({\n                make: 'text',\n                name: 'label',\n                text: o.label,\n                font: o.font,\n                xAlign: 'center',\n                yAlign: 'middle',\n            });\n            if (tile.custom.n == null) {\n                var notInt = /[^1234567890]/;\n                var notFloat = /[^1234567890.]/;\n                if (!notInt.test(o.label)) {\n                    tile.custom.n = parseInt(o.label, 10);\n                }\n                else if (!notFloat.test(o.label)) {\n                    tile.custom.n = parseFloat(o.label);\n                }\n            }\n        }\n        else {\n            label = createEquation(container, o);\n        }\n    }\n    var line;\n    if (o.line) {\n        line = container.add({\n            name: 'border',\n            make: 'rectangle',\n            width: 1,\n            height: 1,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.line.color,\n            line: {\n                width: o.line.width,\n                dash: o.line.dash,\n            },\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    var fill;\n    if (o.fill) {\n        fill = container.add({\n            name: 'fill',\n            make: 'rectangle',\n            width: 1,\n            height: 1,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    tile.notificationHelper = new NotificationHelper();\n    // True if block is snapped in position to a slot\n    tile.custom.isSnapped = false;\n    var selectBorder;\n    if (o.isSelectable) {\n        selectBorder = tile.add({\n            name: 'selectBorder',\n            make: 'rectangle',\n            width: 1,\n            height: 1,\n            corner: {\n                radius: o.radius + o.selectLine.space,\n                sides: o.sides,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: o.selectLine.width },\n            position: [0, 0],\n            color: o.selectLine.color,\n        });\n        selectBorder.hide();\n        tile._container.setPosition(o.selectLine.space, o.selectLine.space + o.yOffset);\n    }\n    setupManipulative(tile, selectBorder, o);\n    // Resize lines, fills and borders to accomodate text, equation or child element\n    if (o.label) {\n        var b = label.getBoundingRect('local');\n        var width = o.width == null ? b.width + o.space[0] * 2 : o.width;\n        var height = o.height == null ? b.height + o.space[1] * 2 : o.height;\n        label.setPosition(width / 2, height / 2);\n        container.toFront(label.name);\n        if (selectBorder) {\n            selectBorder.custom.updatePoints({\n                width: width + o.selectLine.space * 2,\n                height: height + o.selectLine.space * 2,\n            });\n        }\n        if (line) {\n            line.custom.updatePoints({ width: width, height: height });\n        }\n        if (fill) {\n            fill.custom.updatePoints({ width: width, height: height });\n        }\n    }\n    if (o.child) {\n        tile.notifications.add('childAdded', function () {\n            var child = tile._CHILD;\n            var b = child.getBoundingRect('local');\n            var width = o.width == null ? b.width + o.space[0] * 2 : o.width;\n            var height = o.height == null ? b.height + o.space[1] * 2 : o.height;\n            var p = child.getPosition();\n            child.setPosition(width / 2 - b.width / 2 + p.x - b.left, height / 2 - b.height / 2 + p.y - b.bottom);\n            if (line) {\n                line.custom.updatePoints({ width: width, height: height });\n            }\n            if (selectBorder) {\n                selectBorder.custom.updatePoints({\n                    width: width + o.selectLine.space * 2,\n                    height: height + o.selectLine.space * 2,\n                });\n                child.setPosition(child.getPosition().add(container.getPosition()));\n            }\n            if (fill) {\n                fill.custom.updatePoints({ width: width, height: height });\n            }\n        });\n    }\n    tile.custom.getBoundingRect = function (space) {\n        return tile.getBoundingRect(space);\n    };\n    tile.disable = function () {\n        tile.hasTouchableElements = false;\n    };\n    tile.custom.getState = function () {\n        var p = tile.getPosition();\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        return {\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            sel: tile.custom.selected,\n        };\n    };\n    tile.custom.setState = function (stats) {\n        tile.setPosition(Fig.parsePoint(stats.p));\n        tile.custom.moved = true;\n        if (o.isSelectable && stats.sel) {\n            tile.custom.select();\n        }\n        tile.custom.initialPosition = tile.getPosition();\n    };\n    tile.custom.state = tile.custom.getState();\n    tile.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (tile.custom.moved) {\n            tile.setPosition(Fig.parsePoint(tile.custom.state.p));\n        }\n        tile.setMoveBounds();\n    });\n    tile.notificationHelper.add(figure, 'ready', function () {\n        tile.custom.initialPosition = tile.getPosition();\n        tile.custom.readyPosition = tile.getPosition();\n        tile.setMoveBounds();\n    });\n    tile.getContainerBounds = function () {\n        return { rect: tile.getBoundingRect('local') };\n    };\n    tile.getSnapPosition = function (snapIndex) {\n        return tile.getBoundingRect('local').center();\n    };\n    if (o.isSelectable) {\n        container.setTouchable();\n    }\n    else {\n        container.setMove({ freely: false, element: tile });\n        tile.move.freely = false;\n    }\n    tile.notifications.add('moved', function () {\n        tile.custom.moved = true;\n        tile.custom.state.p = tile.getPosition();\n        tile.highlightContainer();\n    });\n    tile._container.custom.secondaryTouchBounds = 0.1;\n    tile._container.notifications.add('onClick', function () {\n        tile.custom.slotOnClick = tile.snappedSlot;\n        tile.custom.clickStart = performance.now();\n        tile.startBeingMoved();\n        tile.custom.startPosition = tile.getPosition();\n        tile.custom.startMove = performance.now();\n        tile.parent.toFront(tile);\n        window.clickHandled = true;\n        if (o.isSelectable) {\n            tile.custom.toggleSelect();\n            return;\n        }\n        tile.custom.wasInContainer = tile.answerContainers.length > 0;\n        tile.custom.wasSnapped = tile.snappedSlot != null;\n        tile.unsnap();\n        tile.removeFromContainer();\n    });\n    tile.afterSnapChange = function () { };\n    tile.answerContainers = [];\n    tile.checkAnswerContainers = function () { return checkAnswerContainers(o, tile); };\n    tile.highlightContainer = function () { return highlightAnswerContainer(o, tile); };\n    tile.removeFromContainer = function () { return removeFromContainer(o, tile); };\n    tile.unhighlight = function () { };\n    tile.checkSlotSnaps = function () {\n        if (o.snapTo == null ||\n            o.snapTo === false ||\n            (Array.isArray(o.snapTo) &&\n                o.snapTo.indexOf('manipulative_tile_slot') === -1) ||\n            (typeof o.snapTo === 'string' && o.snapTo != 'manipulative_tile_slot')) {\n            return;\n        }\n        var tileSlots = getAllManipulativeTileSlots(toAdd);\n        var smallestDelta = null;\n        var slotIndex = null;\n        for (var i = 0; i < tileSlots.length; i += 1) {\n            var delta = tileSlots[i].checkSnaps(tile);\n            if (delta != null) {\n                if (smallestDelta == null) {\n                    smallestDelta = delta;\n                    slotIndex = i;\n                }\n                else if (smallestDelta.distance() > delta.distance()) {\n                    smallestDelta = delta;\n                    slotIndex = i;\n                }\n            }\n        }\n        if (smallestDelta != null) {\n            tile.setPosition(tile.getPosition().sub(smallestDelta));\n            var slot = tileSlots[slotIndex];\n            if (slot.snappedTile != null) {\n                var slotSnappedTile = slot.snappedTile;\n                slot.unsnap(slotSnappedTile);\n                if (tile.custom.slotOnClick != null) {\n                    var delta = slotSnappedTile\n                        .getSnapPosition(0)\n                        .sub(tile.custom.slotOnClick.getSnapPosition());\n                    slotSnappedTile.moveTo(slotSnappedTile.getPosition().sub(delta));\n                }\n                else {\n                    slotSnappedTile.moveTo(slotSnappedTile.custom.initialPosition);\n                }\n            }\n            tile.snap(tileSlots[slotIndex]);\n            tile.afterSnapChange();\n        }\n    };\n    tile.unsnap = function () {\n        if (o.snapTo == null ||\n            o.snapTo === false ||\n            (Array.isArray(o.snapTo) &&\n                o.snapTo.indexOf('manipulative_tile_slot') === -1) ||\n            (typeof o.snapTo === 'string' && o.snapTo != 'manipulative_tile_slot')) {\n            return;\n        }\n        tile.custom.isSnapped = false;\n        var tileSlots = getAllManipulativeTileSlots(toAdd);\n        for (var i = 0; i < tileSlots.length; i += 1) {\n            if (tileSlots[i].snappedTile === tile) {\n                tileSlots[i].unsnap(tile);\n                break;\n            }\n        }\n        tile.afterSnapChange();\n    };\n    tile.snap = function (slot, refresh) {\n        if (refresh === void 0) { refresh = true; }\n        if (o.snapTo == null ||\n            o.snapTo === false ||\n            (Array.isArray(o.snapTo) &&\n                o.snapTo.indexOf('manipulative_tile_slot') === -1) ||\n            (typeof o.snapTo === 'string' && o.snapTo != 'manipulative_tile_slot')) {\n            return;\n        }\n        tile.custom.isSnapped = true;\n        slot.snap(tile, refresh);\n    };\n    tile.moveTo = function (position) {\n        // Disable touch during the animation so a rapid follow-up click (e.g.\n        // double-click on a container tile) doesn't hit this tile while it's\n        // still visually over the container — which would cause\n        // checkAnswerContainers to re-add it to the snap it just left.\n        suppressManipulativeTouch(tile);\n        toAdd.animations\n            .new()\n            .position({\n            element: tile,\n            target: position,\n            duration: 0.5,\n            beforeFrame: function () {\n                tile.custom.state.p = tile.getPosition().toArray(2);\n            },\n        })\n            .trigger(function () {\n            releaseManipulativeTouch(tile);\n            tile.checkSlotSnaps();\n            tile.checkAnswerContainers();\n            tile.custom.state.p = tile.getPosition();\n        })\n            .start();\n    };\n    // Directed placement into an answer container by element OR name (so speech\n    // can drive it: {exec: 'Tile1', method: 'moveToContainer', params: ['ContA']}).\n    // Detaches the tile from any other container first, then hands off to the\n    // container's moveTile, which homes it to the next free snap — or, for adaptive\n    // regions, into the layout for the new tile count, animating the incoming tile\n    // and the re-flow of the existing tiles concurrently.\n    tile.moveToContainer = function (container) {\n        var containers = getAllAnswerContainers(toAdd);\n        var cont = null;\n        if (typeof container === 'string') {\n            for (var i = 0; i < containers.length; i += 1) {\n                if (containers[i].name === container) {\n                    cont = containers[i];\n                    break;\n                }\n            }\n        }\n        else {\n            cont = container;\n        }\n        if (cont == null || cont.moveTile == null) {\n            return;\n        }\n        // Detach from any OTHER container currently holding this tile: frees that\n        // snap and (adaptive) re-flows the source. Checked via each container's\n        // `contained` rather than tile.answerContainers, which some placement paths\n        // don't keep in sync.\n        for (var i = 0; i < containers.length; i += 1) {\n            if (containers[i] !== cont && containers[i].contained.indexOf(tile) !== -1) {\n                containers[i].removeFromContainer(tile);\n            }\n        }\n        tile.answerContainers = [];\n        cont.moveTile(tile);\n    };\n    // Directed placement into a NAMED region of a container (so speech can drive it:\n    // {exec: 'Tile1', method: 'moveToRegion', params: ['Sort', 'rhombus']}). Unlike\n    // moveToContainer, this targets a region by name rather than by the tile's\n    // position, and detaches from EVERY container currently holding the tile —\n    // including other regions of the SAME container — so a region-to-region move\n    // frees and re-flows the source. The container then homes the tile into the\n    // named pool (adaptive reflow / nearest free snap); no pre-positioning needed.\n    tile.moveToRegion = function (container, regionName) {\n        var containers = getAllAnswerContainers(toAdd);\n        var cont = null;\n        if (typeof container === 'string') {\n            for (var i = 0; i < containers.length; i += 1) {\n                if (containers[i].name === container) {\n                    cont = containers[i];\n                    break;\n                }\n            }\n        }\n        else {\n            cont = container;\n        }\n        if (cont == null || cont.moveTileToRegion == null) {\n            return;\n        }\n        for (var i = 0; i < containers.length; i += 1) {\n            if (containers[i].contained.indexOf(tile) !== -1) {\n                containers[i].removeFromContainer(tile);\n            }\n        }\n        tile.answerContainers = [];\n        cont.moveTileToRegion(tile, regionName);\n    };\n    // Send the tile back to where it started, out of any container or tile slot\n    // (so speech can drive it: {exec: 'Tile1', method: 'moveHome'}).\n    tile.moveHome = function () {\n        var containers = getAllAnswerContainers(toAdd);\n        for (var i = 0; i < containers.length; i += 1) {\n            if (containers[i].contained.indexOf(tile) !== -1) {\n                containers[i].removeFromContainer(tile);\n            }\n        }\n        tile.answerContainers = [];\n        tile.unsnap();\n        tile.resetColors();\n        tile.moveTo(tile.custom.initialPosition);\n    };\n    tile.notifications.add('stopBeingMoved', function () {\n        var isQuickClick = (tile.custom.startMove != null\n            && performance.now() - tile.custom.startMove < 200\n            && (tile.custom.startPosition == null\n                || tile.custom.startPosition.sub(tile.getPosition()).distance() < 0.02));\n        // Click on a tile that was inside a container or snapped to a tile slot:\n        // return to its initial position. Checked before checkAnswerContainers so\n        // the tile isn't immediately re-added to the container/slot it sits on.\n        if (isQuickClick && (tile.custom.wasInContainer || tile.custom.wasSnapped)) {\n            tile.moveTo(tile.custom.initialPosition);\n            tile.custom.wasInContainer = false;\n            tile.custom.wasSnapped = false;\n            return;\n        }\n        var answerContainerMoved = tile.checkAnswerContainers();\n        // Dropped over a container that's full — animate back. If the tile came\n        // from a container, animate to its initial (home) position rather than\n        // its drag-start position, since the prior container already removed it\n        // in onClick and animating to startPosition would visually park the tile\n        // inside a container it no longer belongs to.\n        if (answerContainerMoved === 'full') {\n            if (tile.custom.wasInContainer) {\n                tile.moveTo(tile.custom.initialPosition);\n            }\n            else if (tile.custom.startPosition != null) {\n                tile.moveTo(tile.custom.startPosition);\n            }\n            tile.custom.wasInContainer = false;\n            return;\n        }\n        // Click-to-place: tapped (not dragged), configured for answer_container,\n        // didn't land in one.\n        if (isQuickClick && answerContainerMoved === 'noTarget') {\n            if (o.onClick === false) {\n                // Tap-to-place disabled — leave the tile in the tray; it must be\n                // dragged into an area.\n                tile.custom.wasInContainer = false;\n                return;\n            }\n            // 'snap_last': prefer the container a tile was most recently snapped into\n            // (by drag or tap), then fall back to the first container (in element\n            // order) with a free snap.\n            var containers = getAllAnswerContainers(toAdd);\n            var last = toAdd.custom.lastSnapContainer;\n            var ordered = [];\n            if (last != null && containers.indexOf(last) !== -1) {\n                ordered.push(last);\n            }\n            for (var i = 0; i < containers.length; i += 1) {\n                if (containers[i] !== last) {\n                    ordered.push(containers[i]);\n                }\n            }\n            for (var i = 0; i < ordered.length; i += 1) {\n                var c = ordered[i];\n                if (o.slots != null && !o.slots.includes(c.name)) {\n                    continue;\n                }\n                if (c.snaps.length > 0 && c.contained.length < c.snaps.length) {\n                    tile.answerContainers.push(c);\n                    c.addToContainer(tile);\n                    c.placeTapped(tile);\n                    toAdd.custom.lastSnapContainer = c;\n                    break;\n                }\n            }\n            tile.custom.wasInContainer = false;\n            return;\n        }\n        if (answerContainerMoved === 'notConfigured'\n            && isQuickClick) {\n            // Go to first unpopulated slot\n            var tileSlots = getAllManipulativeTileSlots(toAdd);\n            var _loop_1 = function (i) {\n                var slot = tileSlots[i];\n                if (o.slots != null && !o.slots.includes(slot.name)) {\n                    return \"continue\";\n                }\n                if (slot.snappedTile == null\n                    || (slot.snappedTile && slot.custom.correctness === 0)) {\n                    if (slot.snappedTile && slot.custom.correctness === 0) {\n                        var snappedTile = slot.snappedTile;\n                        slot.unsnap(snappedTile);\n                        snappedTile.moveTo(snappedTile.custom.initialPosition);\n                    }\n                    var p = tile.getPosition();\n                    var delta = tile.getSnapPosition(0).sub(slot.getSnapPosition());\n                    tile.custom.moved = true;\n                    var duration = 0.5;\n                    if (delta.distance() < 0.1) {\n                        duration = 0;\n                    }\n                    tile.snap(slot);\n                    toAdd.animations\n                        .new()\n                        .position({\n                        element: tile,\n                        target: p.sub(delta),\n                        duration: duration,\n                        beforeFrame: function () {\n                            tile.custom.state.p = tile.getPosition().toArray(2);\n                        },\n                    })\n                        .trigger(function () {\n                        tile.snap(slot);\n                        tile.custom.state.p = tile.getPosition();\n                    })\n                        .start();\n                    return \"break\";\n                }\n            };\n            for (var i = 0; i < tileSlots.length; i += 1) {\n                var state_1 = _loop_1(i);\n                if (state_1 === \"break\")\n                    break;\n            }\n            tile.custom.wasInContainer = false;\n            return;\n        }\n        if (o.snap) {\n            tile.setPosition(snapPointToPoint(tile.getPosition(), [0, 0], o.snap[0], o.snap[1]));\n        }\n        tile.checkSlotSnaps();\n        tile.custom.state.p = tile.getPosition();\n        // Defensive: ensure the next stopBeingMoved doesn't see a stale flag if\n        // it somehow fires without a preceding onClick (e.g. programmatic stop).\n        tile.custom.wasInContainer = false;\n        tile.custom.wasSnapped = false;\n    });\n    tile.resetColors = function () {\n        if (line != null && o.line) {\n            line.setColor(o.line.color);\n        }\n        if (fill != null && o.fill) {\n            fill.setColor(o.fill.color);\n        }\n        if (label != null && o.labelColors) {\n            if (typeof o.label === 'string') {\n                label.setColor(o.labelColors.color);\n            }\n            else {\n                // @ts-expect-error TS2339\n                var labelElements = label.getAllElements();\n                for (var i = 0; i < labelElements.length; i += 1) {\n                    labelElements[i].setColor(o.labelColors.color);\n                }\n            }\n        }\n    };\n    // Speakable form of custom.showCorrectness:\n    // {exec: ['Tile1', 'Tile4'], method: 'showCorrectness', params: [1]}.\n    tile.showCorrectness = function (result) { return tile.custom.showCorrectness(result); };\n    tile.custom.showCorrectness = function (result) {\n        var _a, _b, _c, _d;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        var correctLabelColor = (_c = fig.custom) === null || _c === void 0 ? void 0 : _c.colorCorrectLabel;\n        var incorrectLabelColor = (_d = fig.custom) === null || _d === void 0 ? void 0 : _d.colorIncorrectLabel;\n        if (line != null) {\n            if (result === 1) {\n                if (o.line.correct === true) {\n                    line.setColor(correctColor || colors.COLOR_GROKKOLI_GREEN);\n                }\n                else if (o.line.correct) {\n                    line.setColor(o.line.correct);\n                }\n            }\n            else {\n                if (o.line.incorrect === true) {\n                    line.setColor(incorrectColor || colors.COLOR_GROKKOLI_ORANGE);\n                }\n                else if (o.line.incorrect) {\n                    line.setColor(o.line.incorrect);\n                }\n            }\n        }\n        if (fill != null) {\n            if (result === 1) {\n                if (o.fill.correct === true) {\n                    fill.setColor(correctColor || colors.COLOR_GROKKOLI_GREEN);\n                }\n                else if (o.fill.correct) {\n                    fill.setColor(o.fill.correct);\n                }\n            }\n            else {\n                if (o.fill.incorrect === true) {\n                    fill.setColor(incorrectColor || colors.COLOR_GROKKOLI_ORANGE);\n                }\n                else if (o.fill.incorrect) {\n                    fill.setColor(o.fill.incorrect);\n                }\n            }\n        }\n        if (label != null) {\n            if (result === 1) {\n                if (typeof o.label === 'string') {\n                    if (correctLabelColor || o.labelColors.correct) {\n                        label.setColor(correctLabelColor || o.labelColors.correct);\n                    }\n                    else {\n                        if (o.labelColors.incorrect) {\n                            label.setColor(o.labelColors.incorrect);\n                        }\n                    }\n                }\n                else {\n                    // @ts-expect-error TS2339\n                    var labelElements = label.getAllElements();\n                    for (var i = 0; i < labelElements.length; i += 1) {\n                        if (correctLabelColor || o.labelColors.correct) {\n                            labelElements[i].setColor(correctLabelColor || o.labelColors.correct);\n                        }\n                    }\n                }\n            }\n            else {\n                if (typeof o.label === 'string') {\n                    if (incorrectLabelColor || o.labelColors.incorrect) {\n                        label.setColor(incorrectLabelColor || o.labelColors.incorrect);\n                    }\n                }\n                else {\n                    // @ts-expect-error TS2339\n                    var labelElements = label.getAllElements();\n                    for (var i = 0; i < labelElements.length; i += 1) {\n                        if (incorrectLabelColor || o.labelColors.incorrect) {\n                            labelElements[i].setColor(incorrectLabelColor || o.labelColors.incorrect);\n                        }\n                    }\n                }\n            }\n        }\n    };\n    if (o.isTouchable === false) {\n        tile.hasTouchableElements = false;\n    }\n    tile.custom.manipulativeType = 'manipulative_tile';\n    return tile;\n};\nexport { manipulativeTile, };\n","import { createEquation, setFontFamily } from '../tools/equation';\nimport { joinObjects } from '../tools/joinObjects';\nimport { doRectsOverlap } from '../workpad_new/tools';\nvar manipulativeTileSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        width: 0.5,\n        height: 0.5,\n        fill: {\n            color: [0.9, 0.9, 0.9, 1],\n            colorCorrect: colors.COLOR_GROKKOLI_GREEN,\n            colorIncorrect: colors.COLOR_GROKKOLI_ORANGE,\n            colorSnapped: [0.6, 0.6, 0.6, 1],\n            show: false,\n        },\n        yOffset: 0,\n        radius: 0.1,\n        sides: 20,\n        debug: false,\n        line: {\n            // dash: [0.1, 0.01],\n            color: colors.COLOR_GROKKOLI_MEDIUM_GREY,\n            width: 0.04,\n            show: true,\n            colorCorrect: colors.COLOR_GROKKOLI_GREEN,\n            colorIncorrect: colors.COLOR_GROKKOLI_ORANGE,\n            colorSnapped: [0.4, 0.4, 0.4, 1],\n        },\n        label: null,\n        font: {\n            size: 0.2,\n            color: [0.6, 0.6, 0.6, 1],\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        textFont: {\n            family: defaultFontFamily,\n            style: 'normal',\n            weight: '300',\n            render: 'gl',\n            color: [0.6, 0.6, 0.6, 1],\n        },\n        correctness: true,\n        snapBorder: 0,\n    }, options);\n    var slot = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var borderOffset = o.line.show ? o.line.width / 2 : 0;\n    var snapPosition = [borderOffset + o.width / 2, o.yOffset + o.height / 2];\n    var fill;\n    if (o.fill.show) {\n        fill = slot.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n            position: [borderOffset, o.yOffset],\n        });\n        fill.custom.initialColor = fill.color.slice();\n    }\n    var border;\n    if (o.line.show) {\n        border = slot.add({\n            make: 'rectangle',\n            name: 'border',\n            width: o.width,\n            height: o.height,\n            color: o.line.color,\n            line: { width: o.line.width, dash: o.line.dash },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n            position: [borderOffset, o.yOffset],\n        });\n        border.custom.initialColor = border.color.slice();\n    }\n    if (o.label) {\n        if (typeof o.label === 'string') {\n            setFontFamily(o.font, o.label);\n            slot.add({\n                make: 'text',\n                name: 'label',\n                text: o.label,\n                font: o.font,\n                xAlign: 'center',\n                yAlign: 'middle',\n                position: [borderOffset + o.width / 2, o.height / 2 + o.yOffset],\n            });\n        }\n        else {\n            createEquation(slot, joinObjects({}, o, {\n                position: [borderOffset + o.width / 2, o.height / 2 + o.yOffset],\n            }));\n        }\n    }\n    slot.preserveChildColor = true;\n    if (o.debug) {\n        slot.add({\n            make: 'rectangle',\n            name: 'snapBorder',\n            width: o.width + o.snapBorder * 2,\n            height: o.height + o.snapBorder * 2,\n            color: [1, 0, 0, 1],\n            line: { width: 0.005, dash: [0.02, 0.04] },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            position: [borderOffset - o.snapBorder, -o.snapBorder + o.yOffset],\n        });\n    }\n    slot.snappedTile = null;\n    slot.getManipulativeBaseSnap = function () { return 0; };\n    slot.custom.getState = function () {\n        var fullBlocks = [];\n        if (slot.snappedTile) {\n            fullBlocks.push(slot.snappedTile.name);\n        }\n        return {\n            full: fullBlocks,\n            partial: [],\n        };\n    };\n    slot.custom.showCorrectness = function (result) {\n        var _a, _b, _c;\n        slot.custom.correctness = result === 1 ? 1 : 0;\n        (_a = slot.snappedTile) === null || _a === void 0 ? void 0 : _a.custom.showCorrectness(result);\n        var correctColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorCorrect;\n        var incorrectColor = (_c = fig.custom) === null || _c === void 0 ? void 0 : _c.colorIncorrect;\n        if (border != null && o.correctness) {\n            if (result === 1) {\n                border.setColor(correctColor || o.line.colorCorrect);\n            }\n            else {\n                border.setColor(incorrectColor || o.line.colorIncorrect);\n            }\n        }\n        if (fill != null && o.correctness) {\n            if (result === 1) {\n                fill.setColor(correctColor || o.fill.colorCorrect);\n            }\n            else {\n                fill.setColor(o.fill.colorIncorrect);\n            }\n        }\n    };\n    slot.notifications.add('setTransform', function () {\n        if (slot.snappedTile != null) {\n            var tile = slot.snappedTile;\n            var p = tile.getSnapPosition(0).sub(slot.getSnapPosition());\n            tile.setPosition(tile.getPosition().sub(p));\n            var tp = tile.getPosition();\n            tile.snap(slot, false);\n            tile.custom.state.p = tp;\n            tile.custom.slotPosition = tp._dup();\n        }\n    });\n    slot.unhighlight = function () { };\n    slot.custom.manipulativeType = 'manipulativeTileSlot';\n    slot.snaps = [new Fig.parsePoint(snapPosition)];\n    slot.getSnapPosition = function () {\n        return slot.getPosition().add(slot.snaps[0]);\n    };\n    slot.refreshSnaps = function () {\n        slot.custom.correctness = null;\n        if (slot.snappedTile) {\n            slot.snappedTile.afterSnapChange();\n            if (border != null) {\n                border.setColor(o.line.colorSnapped);\n            }\n            if (fill != null) {\n                fill.setColor(o.fill.colorSnapped);\n            }\n        }\n        else {\n            if (border != null) {\n                border.setColor(o.line.color);\n            }\n            if (fill != null) {\n                fill.setColor(o.fill.color);\n            }\n        }\n    };\n    slot.snap = function (tile, refresh) {\n        if (refresh === void 0) { refresh = true; }\n        fig.answerChanged();\n        slot.snappedTile = tile;\n        tile.snappedSlot = slot;\n        if (refresh) {\n            slot.refreshSnaps();\n        }\n    };\n    slot.unsnap = function (tile) {\n        fig.answerChanged();\n        if (slot.snappedTile != tile) {\n            return;\n        }\n        slot.snappedTile.resetColors();\n        slot.snappedTile.snappedSlot = null;\n        slot.snappedTile = null;\n        slot.refreshSnaps();\n    };\n    slot.custom.toPulse = function (pulseOptions) {\n        if (slot.snappedTile) {\n            slot.snappedTile.animations.new().pulse(pulseOptions).start();\n        }\n    };\n    slot.checkSnaps = function (tile) {\n        // Return the offset required to snap - null if no snap\n        // First check if the tile bounds overlap with the slotBorderBounds\n        var tileBounds = tile.custom.getBoundingRect('local');\n        var slotBounds = slot.getBoundingRect('local');\n        var slotBorderBounds = new Fig.Rect(slotBounds.left - (o.debug ? 0 : o.snapBorder), slotBounds.bottom - (o.debug ? 0 : o.snapBorder), o.width + o.snapBorder * 2, o.height + o.snapBorder * 2);\n        if (!doRectsOverlap(slotBorderBounds, tileBounds)) {\n            return null;\n        }\n        return tile.getSnapPosition(0).sub(slot.getSnapPosition());\n        // return delta\n    };\n    return slot;\n};\nexport { manipulativeTileSlot, };\n","import { snapPointToPoint } from '../tools/snap';\nimport { NotificationHelper } from '../tools/notifications';\nimport { setupManipulative, checkAnswerContainers, highlightAnswerContainer, removeFromContainer, getAllSimpleBlockSlots, } from './tools';\nimport { getRectPoints, rectangleBorderToTris } from '../tools/getRectPoints';\nimport { createEquation, setFontFamily } from '../tools/equation';\nvar simpleBlock = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        static: {\n            isTouchable: false,\n            fill: false,\n            static: true,\n            font: { color: [0.3, 0.3, 0.3, 1] },\n            boundMove: false,\n        },\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        width: 0.5,\n        height: 0.4,\n        scale: 1,\n        fill: true,\n        line: true,\n        yOffset: 0,\n        isSelectable: false,\n        isTouchable: true,\n        debug: false,\n        boundMove: true,\n        static: false,\n        selectLine: {\n            width: 0.02,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            space: 0.04,\n        },\n        radius: 0.02,\n        sides: 5,\n        snapTo: [],\n        font: {\n            size: 0.2,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n            dim: false,\n            glyphs: ['latin'],\n        },\n        textFont: {\n            family: defaultFontFamily,\n            style: 'normal',\n            weight: '300',\n            render: 'gl',\n            glyphs: ['latin'],\n            color: colors.COLOR_GROKKOLI_BLUE,\n        },\n        snapStyle: 'block',\n        labelOffset: [0, 0],\n    }, styleDefaults, options);\n    if (o.line !== false) {\n        o.line = Fig.joinObjects({\n            width: 0.01,\n            color: [0.5, 0.5, 0.5, 1],\n            snapped: [0.5, 0.5, 0.5, 1],\n            snapFail: [0.5, 0.5, 0.5, 1],\n            incorrect: false,\n            correct: false,\n            highlight: false,\n            dim: [0.7, 0.7, 0.7, 1],\n            dash: [],\n        }, o.line === true ? {} : o.line);\n    }\n    if (o.fill !== false) {\n        o.fill = Fig.joinObjects({\n            color: colors.COLOR_GROKKOLI_LIGHT_GREY,\n            // color: [1, 0, 0, 0.2],\n            snapped: colors.COLOR_GROKKOLI_LIGHT_GREY,\n            // snapped: [1, 0, 0, 0.2],\n            incorrect: false,\n            correct: false,\n            highlight: false,\n            dim: [0.9, 0.9, 0.9, 1],\n            snapFail: colors.COLOR_GROKKOLI_ORANGE,\n        }, o.fill === true ? {} : o.fill);\n    }\n    if (typeof o.snapTo === 'string') {\n        o.snapTo = [o.snapTo];\n    }\n    o.width = Fig.round(o.width, 7);\n    o.snap = Fig.round(o.snap, 7);\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n        border: [\n            [\n                new Fig.Point(0, o.yOffset),\n                new Fig.Point(0, o.height + o.yOffset),\n                new Fig.Point(o.width, o.height + o.yOffset),\n                new Fig.Point(o.width, o.yOffset),\n            ],\n        ],\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    element.notificationHelper = new NotificationHelper();\n    if (o.n) {\n        element.custom.n = o.n;\n    }\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    var numSnaps = Fig.round((o.width - o.snap) / o.snap, 2) + 1;\n    function getSnapPosition(index) {\n        if (index === 'center') {\n            return new Fig.Point(o.width / 2, o.height / 2);\n        }\n        return new Fig.Point(o.snap / 2 + index * o.snap, o.height / 2);\n    }\n    element.snaps = [];\n    if (o.fill !== false && o.snapStyle === 'block') {\n        var startPoints = rectangleBorderToTris(getRectPoints(o.snap, o.height, o.sides, o.radius, 0, 0, new Fig.Point(0, 0), [true, false, false, true]));\n        var endPoints = rectangleBorderToTris(getRectPoints(o.snap, o.height, o.sides, o.radius, 0, 0, new Fig.Point(0, 0), [false, true, true, false]));\n        var midPoints = rectangleBorderToTris(getRectPoints(o.snap, o.height, 10, 0, 0, 0));\n        var unitPoints = rectangleBorderToTris(getRectPoints(o.width, o.height, o.sides, o.radius, 0, 0, new Fig.Point(0, 0), [true, true, true, true]));\n        var _loop_1 = function (i) {\n            element.snaps.push({\n                // Snap position relative to block (draw space of block)\n                getPosition: function () { return getSnapPosition(i); },\n                // Snap position relative to block's local space\n                getLocalPosition: function () { return element.getPosition().add(getSnapPosition(i)); },\n                slot: null, // Slot the block snap is snapped to\n                slotSnapIndex: null, // Slot snap index the block snap is snapped to\n                isPrimarySnap: false, // True if block snap is primary snap of slot\n                // - all of a block's snaps must be the primary snap to be\n                //   a valid answer\n            });\n            var points = void 0;\n            if (numSnaps === 1) {\n                points = unitPoints;\n            }\n            else if (i === 0) {\n                points = startPoints;\n            }\n            else if (i === numSnaps - 1) {\n                points = endPoints;\n            }\n            else {\n                points = midPoints;\n            }\n            container.add({\n                make: 'generic',\n                name: \"block\".concat(i),\n                points: points,\n                color: o.fill.color,\n                drawType: 'TRIANGLES',\n                transform: [['t', i * o.snap, 0]],\n            });\n        };\n        for (var i = 0; i < numSnaps; i += 1) {\n            _loop_1(i);\n        }\n    }\n    if (o.fill !== false && o.snapStyle === 'fill') {\n        container.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    var line;\n    if (o.line) {\n        line = container.add({\n            name: 'border',\n            make: 'rectangle',\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.line.color,\n            line: {\n                width: o.line.width,\n                dash: o.line.dash,\n            },\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n        line.border = [\n            [\n                new Fig.Point(0, 0),\n                new Fig.Point(o.width, 0),\n                new Fig.Point(o.width, o.height),\n                new Fig.Point(0, o.height),\n            ],\n        ];\n    }\n    // let fill: FigureOneElement;\n    // if (o.fill) {\n    //   fill = container.add({\n    //     name: 'fill',\n    //     make: 'rectangle',\n    //     width: o.width,\n    //     height: o.height,\n    //     xAlign: 'left',\n    //     yAlign: 'bottom',\n    //     color: o.fill.color,\n    //     corner: {\n    //       radius: o.radius,\n    //       sides: o.sides,\n    //     },\n    //   });\n    // }\n    var selectBorder;\n    if (o.isSelectable) {\n        selectBorder = container.add({\n            name: 'selectBorder',\n            make: 'rectangle',\n            width: o.width + o.selectLine.space * 2,\n            height: o.height + o.selectLine.space * 2,\n            corner: {\n                radius: o.radius + o.selectLine.space,\n                sides: o.sides,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            line: { width: o.selectLine.width },\n            position: [-o.selectLine.space, -o.selectLine.space],\n            color: o.selectLine.color,\n        });\n        selectBorder.hide();\n    }\n    if (o.debug) {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            container.add({\n                make: 'polygon',\n                name: \"debugCenter\".concat(i),\n                sides: 10,\n                radius: 0.01,\n                position: [o.snap * i + o.snap / 2, o.height / 2],\n            });\n        }\n    }\n    var label;\n    if (o.label) {\n        if (typeof o.label === 'string') {\n            setFontFamily(o.font, o.label);\n            label = container.add({\n                make: 'text',\n                name: 'label',\n                text: o.label,\n                font: o.font,\n                xAlign: 'center',\n                yAlign: 'middle',\n            });\n            if (element.custom.n == null) {\n                var notInt = /[^1234567890]/;\n                var notFloat = /[^1234567890.]/;\n                if (!notInt.test(o.label)) {\n                    element.custom.n = parseInt(o.label, 10);\n                }\n                else if (!notFloat.test(o.label)) {\n                    element.custom.n = parseFloat(o.label);\n                }\n            }\n        }\n        else {\n            label = createEquation(container, Fig.joinObjects({}, o, { name: 'label' }));\n        }\n        var labelOffset = Fig.parsePoint(o.labelOffset);\n        label.setPosition(o.width / 2 + labelOffset.x, o.height / 2 + labelOffset.y);\n    }\n    element.custom.getState = function () {\n        var p = element.getPosition();\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        return {\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            sel: element.custom.selected,\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        element.custom.moved = true;\n        if (o.isSelectable && stats.sel) {\n            element.custom.select();\n        }\n    };\n    setupManipulative(element, selectBorder, o);\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(figure, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    element.getContainerBounds = function () {\n        var p = element.getPosition();\n        return { rect: new Fig.Rect(p.x, p.y, o.width, o.height) };\n    };\n    element.getSnapPosition = function (snapIndex) {\n        // -1 is called by a simpleBlockFillSlot\n        if (snapIndex === -1) {\n            return element.getPosition().add(0, o.height / 2);\n        }\n        // Otherwise it is a singleBlockSlot\n        return element.getPosition().add(getSnapPosition(snapIndex));\n        // return element.snaps[snapIndex].getLocalPosition();\n    };\n    element.setPositionToSlot = function (slot, slotIndex, offset) {\n        if (slotIndex === void 0) { slotIndex = 0; }\n        var o_offset = offset ? Fig.parsePoint(offset) : new Fig.Point(0, 0);\n        if (slot.custom.manipulativeType === 'simpleBlockFillSlot') {\n            var fillSlot = slot;\n            var _a = fillSlot.getFirstSpace(element), position = _a[1];\n            if (position != null) {\n                element.setPosition(position.add(o_offset));\n                // element.snap(fillSlot);\n                // element.afterSnapChange();\n            }\n            return;\n        }\n        var slotSnap = slot.getSnapPosition(slotIndex);\n        var blockSnapOffset = element.snaps[0].getPosition();\n        element.setPosition(slotSnap.sub(blockSnapOffset).add(o_offset));\n    };\n    if (o.isSelectable) {\n        container.setTouchable();\n    }\n    else if (o.isTouchable !== false) {\n        container.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    element.notifications.add('moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n        element.highlightContainer();\n    });\n    element._container.notifications.add('onClick', function () {\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n        if (o.isSelectable) {\n            element.custom.toggleSelect();\n            return;\n        }\n        if (element.custom.isSnapped) {\n            element.custom.snappedAtMoveStart = true;\n        }\n        element.unsnap();\n        element.removeFromContainer();\n    });\n    element.afterSnapChange = function () {\n        var _a, _b, _c, _d;\n        if (o.debug) {\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                var snap = element.snaps[i];\n                if (element.custom.isSnapped === false) {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        0.5, 0.5, 0.5, 0.5,\n                    ]);\n                }\n                else if (snap.isPrimarySnap) {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        0, 0, 1, 0.5,\n                    ]);\n                }\n                else {\n                    element._container.elements[\"debugCenter\".concat(i)].setColor([\n                        1, 0, 0, 0.5,\n                    ]);\n                }\n            }\n        }\n        if (o.snapStyle === 'block') {\n            var allSnapped = true;\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                var snap = element.snaps[i];\n                if (element.custom.isSnapped === false) {\n                    allSnapped = false;\n                    element._container.elements[\"block\".concat(i)].setColor(o.fill.color);\n                }\n                else if (snap.isPrimarySnap) {\n                    element._container.elements[\"block\".concat(i)].setColor(o.fill.snapped);\n                }\n                else {\n                    allSnapped = false;\n                    element._container.elements[\"block\".concat(i)].setColor(((_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorIncorrect) || o.fill.snapFail);\n                }\n            }\n            if (line != null) {\n                if (allSnapped) {\n                    line.setColor(o.line.snapped);\n                }\n                else if (element.custom.isSnapped === false) {\n                    line.setColor(o.line.color);\n                }\n                else {\n                    line.setColor(((_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect) || o.line.snapFail);\n                }\n            }\n        }\n        if (o.snapStyle === 'fill' && o.fill) {\n            if (element.custom.isSnapped === false) {\n                element._container._fill.setColor(o.fill.color);\n            }\n            else if (element.snapFail) {\n                element._container._fill.setColor(((_c = fig.custom) === null || _c === void 0 ? void 0 : _c.colorIncorrect) || o.fill.snapFail);\n            }\n            else {\n                element._container._fill.setColor(o.fill.snapped);\n            }\n        }\n        if (line != null) {\n            if (element.custom.isSnapped === false) {\n                line.setColor(o.line.color);\n            }\n            else if (element.snapFail) {\n                line.setColor(((_d = fig.custom) === null || _d === void 0 ? void 0 : _d.colorIncorrect) || o.line.snapFail);\n            }\n            else {\n                line.setColor(o.line.snapped);\n            }\n        }\n    };\n    // element.is = null;\n    // element.snappedFull = null;\n    element.answerContainers = [];\n    element.snappedFillSlot = null;\n    element.snapFail = null;\n    element.checkAnswerContainers = function () { return checkAnswerContainers(o, element); };\n    element.highlightContainer = function () { return highlightAnswerContainer(o, element); };\n    element.removeFromContainer = function () { return removeFromContainer(o, element); };\n    element.unhighlight = function () { };\n    element.checkSlotSnaps = function () {\n        if (o.snapTo == null) {\n            return;\n        }\n        if (o.snapTo.indexOf('simple_block_slot') > -1 ||\n            o.snapTo.indexOf('simple_block_fill_slot') > -1) {\n            var simpleBlockSlots = getAllSimpleBlockSlots(toAdd);\n            var smallestDelta = null;\n            var slotIndex = null;\n            for (var i = 0; i < simpleBlockSlots.length; i += 1) {\n                var delta = simpleBlockSlots[i].checkSnaps(element);\n                if (delta != null) {\n                    if (smallestDelta == null) {\n                        smallestDelta = delta;\n                        slotIndex = i;\n                    }\n                    else if (smallestDelta.distance() > delta.distance()) {\n                        smallestDelta = delta;\n                        slotIndex = i;\n                    }\n                }\n            }\n            if (smallestDelta != null) {\n                element.setPosition(element.getPosition().sub(smallestDelta));\n                element.snap(simpleBlockSlots[slotIndex]);\n                element.afterSnapChange();\n            }\n        }\n    };\n    element.unsnap = function () {\n        if (o.snapTo == null) {\n            return;\n        }\n        if (o.snapTo.indexOf('simple_block_slot') > -1 ||\n            o.snapTo.indexOf('simple_block_fill_slot') > -1) {\n            element.custom.isSnapped = false;\n            element.snapFail = null;\n            element.snappedFillSlot = null;\n            var simpleBlockSlots = getAllSimpleBlockSlots(toAdd);\n            for (var i = 0; i < simpleBlockSlots.length; i += 1) {\n                simpleBlockSlots[i].unsnap(element);\n            }\n            for (var i = 0; i < element.snaps.length; i += 1) {\n                element.snaps[i].slot = null;\n                element.snaps[i].slotSnapIndex = null;\n                // element.snaps[i].isSnapped = false;\n                element.snaps[i].isPrimarySnap = false;\n            }\n            element.afterSnapChange();\n        }\n    };\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    element.snap = function (slot) {\n        if (o.snapTo == null ||\n            (o.snapTo.indexOf('simple_block_slot') === -1 &&\n                o.snapTo.indexOf('simple_block_fill_slot') === -1)) {\n            return;\n        }\n        element.custom.isSnapped = true;\n        element.snapFail = false;\n        slot.snap(element);\n    };\n    element.notifications.add('stopBeingMoved', function () {\n        if (element.custom.stopBeingMovedProcessing) {\n            return;\n        }\n        // If the element was snapped at the start of the move, then we will\n        // consider the answer changed.\n        // The stopBeingMovedProcessing is\n        // used because answerChanged MAY call a figure.stop() which would send\n        // an additional stopBeingMoved notification.\n        if (element.custom.snappedAtMoveStart) {\n            element.custom.stopBeingMovedProcessing = true;\n            figure.answerChanged();\n            element.custom.stopBeingMovedProcessing = false;\n        }\n        element.custom.snappedAtMoveStart = false;\n        if (o.snapToGrid) {\n            element.setPosition(snapPointToPoint(element.getPosition(), [0, 0], o.snap, o.snap));\n        }\n        element.checkSlotSnaps();\n        element.checkAnswerContainers();\n        element.custom.state.p = element.getPosition();\n        // If the element is now snapped, then we consider the answer changed\n        if (element.custom.isSnapped) {\n            element.custom.stopBeingMovedProcessing = true;\n            figure.answerChanged();\n            element.custom.stopBeingMovedProcessing = false;\n        }\n    });\n    if (!o.static) {\n        element.custom.manipulativeType = 'simple_block';\n    }\n    element.custom.getBoundingRect = function (space) {\n        // const p = element.getBoundingRect(space);\n        // return new Fig.Rect(p.x, p.y, o.width, o.height);\n        return element.getBoundingRect(space);\n    };\n    element.setColors = function (color, duration, except) {\n        if (duration === void 0) { duration = 0; }\n        if (except === void 0) { except = []; }\n        if (color == 'reset') {\n            color = 'color';\n        }\n        if (element._container._fill && except.indexOf('fill') === -1) {\n            if (o.fill[color]) {\n                if (duration == 0) {\n                    element._container._fill.setColor(o.fill[color]);\n                }\n                else {\n                    element._container._fill.animations.new()\n                        .color({ target: o.fill[color], duration: duration })\n                        .start();\n                }\n            }\n        }\n        if (element._container._border && except.indexOf('border') === -1) {\n            if (o.line[color]) {\n                if (duration == 0) {\n                    element._container._border.setColor(o.line[color]);\n                }\n                else {\n                    element._container._border.animations.new()\n                        .color({ target: o.line[color], duration: duration })\n                        .start();\n                }\n            }\n        }\n        if (element._container._label && except.indexOf('label') === -1) {\n            if (o.font[color]) {\n                if (duration == 0) {\n                    element._container._label.setColor(o.font[color]);\n                }\n                else {\n                    element._container._label.animations.new()\n                        .color({ target: o.font[color], duration: duration })\n                        .start();\n                }\n            }\n        }\n    };\n    element._container.custom.secondaryTouchBounds = 0.1;\n    return element;\n};\nexport { simpleBlock, };\n","import { createEquation, setFontFamily } from '../tools/equation';\nimport { joinObjects } from '../tools/joinObjects';\nimport { doRectsOverlap } from '../workpad_new/tools';\nfunction setupLabel(element, o, width, height) {\n    var label;\n    if (o.label) {\n        if (typeof o.label === 'number') {\n            o.label = o.label.toString();\n        }\n        if (o.labelOptions.position === 'middle') {\n            if (typeof o.label === 'string') {\n                setFontFamily(o.font, o.label);\n                label = element.add({\n                    make: 'text',\n                    name: 'label',\n                    text: o.label,\n                    font: o.font,\n                    xAlign: 'center',\n                    yAlign: 'middle',\n                });\n                if (element.custom.n == null) {\n                    var notInt = /[^1234567890]/;\n                    var notFloat = /[^1234567890.]/;\n                    if (!notInt.test(o.label)) {\n                        element.custom.n = parseInt(o.label, 10);\n                    }\n                    else if (!notFloat.test(o.label)) {\n                        element.custom.n = parseFloat(o.label);\n                    }\n                }\n            }\n            else {\n                label = createEquation(element, o);\n            }\n            label.setPosition(width / 2, height / 2);\n        }\n        else {\n            var symbol = null;\n            if (o.labelOptions.symbol !== false) {\n                symbol = {\n                    __symbol__: {\n                        symbol: o.labelOptions.symbol,\n                        side: o.labelOptions.position,\n                        lineWidth: o.labelOptions.lineWidth,\n                        color: o.labelOptions.color,\n                        width: o.labelOptions.symbolHeight,\n                    },\n                };\n            }\n            var w = width;\n            if (o.space) {\n                w += o.space * 2;\n                if (o.line && typeof o.line === 'object') {\n                    w += o.line.width;\n                }\n            }\n            // if (o.borderInSize === true && o.correctnessBorder && o.space === false) {\n            //   x += o.correctnessBorder.space + o.correctnessBorder.width;\n            // }\n            var labelYOffset = 0;\n            if (o.space) {\n                labelYOffset += o.space;\n                if (o.line && typeof o.line === 'object') {\n                    labelYOffset += o.line.width / 2;\n                }\n            }\n            if (o.labelOptions.position === 'top') {\n                var content = {\n                    topComment: {\n                        content: { container: { width: w, ascent: 0, content: '_ ' } },\n                        comment: [o.label],\n                        symbol: symbol,\n                        commentSpace: o.labelOptions.commentSpace / 2,\n                        contentSpace: o.labelOptions.contentSpace / 2,\n                        scale: o.labelOptions.scale,\n                        inSize: o.labelOptions.inSize,\n                    },\n                };\n                label = createEquation(element, joinObjects({}, o, { label: content }), 'baseline');\n                label.setPosition(width / 2, height + labelYOffset);\n            }\n            else if (o.labelOptions.position === 'bottom') {\n                var content = {\n                    bottomComment: {\n                        content: { container: { width: w, descent: 0, content: '_ ' } },\n                        comment: [o.label],\n                        symbol: symbol,\n                        commentSpace: o.labelOptions.commentSpace / 2,\n                        contentSpace: o.labelOptions.contentSpace / 2,\n                        scale: o.labelOptions.scale,\n                        inSize: o.labelOptions.inSize,\n                    },\n                };\n                label = createEquation(element, joinObjects({}, o, { label: content }), 'baseline');\n                label.setPosition(width / 2, -labelYOffset);\n            }\n        }\n    }\n    return label;\n}\nvar simpleBlockSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        snap: 0.1,\n        numX: 1,\n        height: 0.4,\n        fill: false,\n        yOffset: 0,\n        radius: 0.02,\n        sides: 10,\n        debug: false,\n        space: false,\n        line: true,\n        label: false,\n        font: {\n            size: 0.15,\n            color: [0.3, 0.3, 0.3, 1],\n            family: defaultFontFamilyMath,\n        },\n        snapBorder: 0,\n        borderInSize: true,\n        correctness: true,\n        labelOptions: {\n            position: 'top',\n            symbol: 'brace',\n            lineWidth: 0.01,\n            symbolHeight: 0.1,\n            color: [0.3, 0.3, 0.3, 1],\n            commentSpace: 0.08,\n            contentSpace: 0.08,\n            scale: 1,\n            inSize: true,\n        },\n        tileLineWidth: 0.01,\n        correctnessBorder: true,\n    }, styleDefaults, options);\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    var fillDefaults = {\n        color: [0.8, 0.8, 0.8, 1],\n        correct: [0.8, 0.8, 0.8, 1],\n        incorrect: [0.8, 0.8, 0.8, 1],\n        technicallyCorrect: [0.8, 0.8, 0.8, 1],\n        invalid: [0.8, 0.8, 0.8, 1],\n        lineWidth: 0.01,\n    };\n    var lineDefaults = {\n        dash: false,\n        color: [0.6, 0.6, 0.6, 1],\n        width: 0.02,\n        correct: [0.6, 0.6, 0.6, 1],\n        incorrect: [0.6, 0.6, 0.6, 1],\n        technicallyCorrect: [0.6, 0.6, 0.6, 1],\n        invalid: [0.6, 0.6, 0.6, 1],\n    };\n    var correctnessBorderDefaults = {\n        color: [0, 0, 0, 0],\n        width: 0.05,\n        space: 0.025,\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n        technicallyCorrect: colors.COLOR_GROKKOLI_GOLD,\n        invalid: colors.COLOR_GROKKOLI_GREY,\n    };\n    if (o.line === true) {\n        o.line = lineDefaults;\n    }\n    else if (o.line) {\n        o.line = joinObjects(lineDefaults, o.line);\n    }\n    if (o.fill === true) {\n        o.fill = fillDefaults;\n    }\n    else if (o.fill) {\n        o.fill = joinObjects(fillDefaults, o.fill);\n    }\n    if (o.correctnessBorder === true) {\n        o.correctnessBorder = correctnessBorderDefaults;\n    }\n    else if (o.correctnessBorder) {\n        o.correctnessBorder = joinObjects(correctnessBorderDefaults, o.correctnessBorder);\n    }\n    var space = o.space ? o.space : 0;\n    var lineWidth = 0;\n    if (o.line !== false) {\n        lineWidth = o.line.width;\n    }\n    var width = o.snap * o.numX;\n    var height = o.height;\n    // let borderOffset = o.line ? o.line.width / 2 : 0;\n    var snapPositions = [];\n    element.custom.o = o;\n    element.custom.width = width;\n    for (var i = 0; i < o.numX; i += 1) {\n        var snapPosition = new Fig.Point(o.snap * i + o.snap / 2, height / 2);\n        snapPositions.push(snapPosition);\n    }\n    var cBorder;\n    if (o.correctnessBorder) {\n        var cSpace = o.correctnessBorder.space ? o.correctnessBorder.space : 0;\n        var cRadius = o.radius + cSpace;\n        if (o.space === false) {\n            if (o.fill && o.line === false) {\n                cRadius =\n                    o.radius + o.tileLineWidth / 2 + space + cSpace - o.tileLineWidth / 2;\n            }\n            else if (o.line) {\n                cRadius = o.radius - o.line.width / 2 + cSpace;\n            }\n        }\n        cBorder = container.add({\n            make: 'rectangle',\n            name: 'correctnessBorder',\n            width: width + cSpace * 2,\n            height: height + cSpace * 2,\n            color: o.correctnessBorder.color,\n            line: {\n                width: o.correctnessBorder.width,\n                dash: o.correctnessBorder.dash,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: cRadius,\n                sides: o.sides,\n            },\n            position: [-cSpace, -cSpace + o.yOffset],\n        });\n        cBorder.custom.initialColor = cBorder.color.slice();\n    }\n    var fill;\n    if (o.fill) {\n        fill = container.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: width + o.tileLineWidth + space * 2,\n            height: height + o.tileLineWidth + space * 2,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius + o.tileLineWidth / 2 + space,\n                sides: o.sides,\n            },\n            position: [\n                -o.tileLineWidth / 2 - space,\n                o.yOffset - o.tileLineWidth / 2 - space,\n            ],\n        });\n    }\n    var border;\n    var borderSpace = o.space === false ? -lineWidth / 2 + o.tileLineWidth / 2 : o.space;\n    if (o.line) {\n        var lineRadius = o.radius + space + o.tileLineWidth / 2;\n        if (o.space === false) {\n            lineRadius = o.radius - o.line.width / 2;\n        }\n        border = container.add({\n            make: 'rectangle',\n            name: 'border',\n            width: width + borderSpace * 2,\n            height: height + borderSpace * 2,\n            color: o.line.color,\n            line: { width: lineWidth, dash: o.line.dash },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: lineRadius,\n                sides: o.sides,\n            },\n            position: [-borderSpace, -borderSpace + o.yOffset],\n        });\n        border.custom.initialColor = border.color.slice();\n    }\n    setupLabel(container, Fig.joinObjects({}, o, { name: 'label' }), width, height);\n    // Compute the extent of visual elements beyond the snap area (in container\n    // coords, where snap area is 0..width x 0..height).\n    // All borders are symmetric, so leftExtent magnitude = rightExtent overshoot.\n    var sideExtent = 0;\n    if (o.borderInSize) {\n        // Line border outer edge\n        if (o.line !== false) {\n            var borderOuter = Math.abs(borderSpace) + lineWidth / 2;\n            sideExtent = Math.max(sideExtent, borderOuter);\n        }\n        // Correctness border outer edge\n        if (o.correctnessBorder !== false) {\n            var cSpace = o.correctnessBorder.space || 0;\n            var cOuter = cSpace + o.correctnessBorder.width / 2;\n            sideExtent = Math.max(sideExtent, cOuter);\n        }\n        // Fill extends by tileLineWidth/2 + space\n        if (o.fill) {\n            sideExtent = Math.max(sideExtent, o.tileLineWidth / 2 + space);\n        }\n    }\n    else {\n        // borderInSize false: only the fill area determines the bounds\n        if (o.fill) {\n            sideExtent = o.tileLineWidth / 2 + space;\n        }\n    }\n    // Position container so all in-size content starts at x=0\n    container.setPosition(sideExtent, o.yOffset);\n    var totalW = width + 2 * sideExtent;\n    var totalH = height + 2 * sideExtent;\n    // Label inSize adjustments\n    if (o.label && o.labelOptions.inSize) {\n        var labelRect = container._label.getBoundingRect();\n        // Label left/right in element coords\n        var labelLeft = sideExtent + labelRect.left;\n        var labelShift = 0;\n        if (labelLeft < 0) {\n            labelShift = -labelLeft;\n            container.setPosition(sideExtent + labelShift, o.yOffset);\n            totalW += labelShift;\n        }\n        var labelRight = sideExtent + labelShift + labelRect.right;\n        if (labelRight > totalW) {\n            totalW = labelRight;\n        }\n        totalH = Math.max(totalH, o.yOffset + labelRect.top);\n    }\n    // Set explicit border when label exists (to include or exclude it from\n    // bounds) or when borderInSize is false (to exclude borders from bounds).\n    if (o.label || !o.borderInSize) {\n        element.border = [\n            [\n                new Fig.Point(0, 0),\n                new Fig.Point(totalW, 0),\n                new Fig.Point(totalW, totalH),\n                new Fig.Point(0, totalH),\n            ],\n        ];\n    }\n    element.preserveChildColor = true;\n    var snapBorder = {\n        left: 0,\n        top: 0,\n        right: 0,\n        bottom: 0,\n    };\n    if (typeof o.snapBorder === 'number') {\n        snapBorder.left = o.snapBorder;\n        snapBorder.right = o.snapBorder;\n        snapBorder.top = o.snapBorder;\n        snapBorder.bottom = o.snapBorder;\n    }\n    else if (o.snapBorder) {\n        snapBorder = joinObjects({}, snapBorder, o.snapBorder);\n    }\n    if (o.debug) {\n        for (var i = 0; i < snapPositions.length; i += 1) {\n            container.add({\n                make: 'polygon',\n                sides: 10,\n                radius: 0.005,\n                color: [0, 0, 0, 1],\n                position: snapPositions[i],\n            });\n            container.add({\n                make: 'rectangle',\n                sides: 4,\n                radius: 0.01,\n                color: [0, 0, 0, 0.5],\n                width: o.snap,\n                height: o.height,\n                line: { width: 0.001 },\n                position: snapPositions[i],\n            });\n        }\n        container.add({\n            make: 'rectangle',\n            name: 'snapBorder',\n            width: width + snapBorder.left + snapBorder.right,\n            height: height + snapBorder.bottom + snapBorder.top,\n            color: o.line.color,\n            line: { width: 0.005, dash: [0.02, 0.02] },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            position: [-snapBorder.left, -snapBorder.bottom + o.yOffset],\n        });\n    }\n    element.getManipulativeBaseSnap = function () { return 0; };\n    element.custom.getState = function () {\n        // Get a list of blocks that are fully valid within the slot\n        var fullBlocks = [];\n        var partialBlocks = [];\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            var full = true;\n            for (var j = 0; j < block.snaps.length; j += 1) {\n                var blockSnap = block.snaps[j];\n                if (blockSnap.slot !== element || blockSnap.isPrimarySnap === false) {\n                    full = false;\n                    break;\n                }\n            }\n            if (full) {\n                fullBlocks.push(block.name);\n            }\n            else {\n                partialBlocks.push(block.name);\n            }\n        }\n        return {\n            full: fullBlocks,\n            partial: partialBlocks,\n        };\n    };\n    element.custom.showCorrectness = function (result) {\n        var _a, _b;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        if (o.correctness) {\n            if (cBorder != null) {\n                if (result === 1) {\n                    cBorder.setColor(correctColor || o.correctnessBorder.correct);\n                }\n                else if (result === 3) {\n                    cBorder.setColor(o.correctnessBorder.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    cBorder.setColor(incorrectColor || o.correctnessBorder.incorrect);\n                }\n                else if (result === 4) {\n                    cBorder.setColor(o.correctnessBorder.invalid);\n                }\n                else {\n                    cBorder.setColor(o.correctnessBorder.color);\n                }\n            }\n            if (border != null) {\n                if (result === 1) {\n                    border.setColor(correctColor || o.line.correct);\n                }\n                else if (result === 3) {\n                    border.setColor(o.line.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    border.setColor(incorrectColor || o.line.incorrect);\n                }\n                else if (result === 4) {\n                    border.setColor(o.line.invalid);\n                }\n                else {\n                    border.setColor(o.line.color);\n                }\n            }\n            if (fill != null) {\n                if (result === 1) {\n                    fill.setColor(correctColor || o.fill.correct);\n                }\n                else if (result === 3) {\n                    fill.setColor(o.fill.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    fill.setColor(incorrectColor || o.fill.incorrect);\n                }\n                else if (result === 4) {\n                    fill.setColor(o.fill.invalid);\n                }\n                else {\n                    fill.setColor(o.fill.color);\n                }\n            }\n        }\n    };\n    element.unhighlight = function () { };\n    element.custom.manipulativeType = 'simpleBlockSlot';\n    element.snaps = [];\n    // List of blocks current snapped to this slot\n    element.snappedBlocks = [];\n    for (var i = 0; i < snapPositions.length; i += 1) {\n        element.snaps.push({\n            position: snapPositions[i], // snap position relative to slot (draw space of slot)\n            blocks: [], // All blocks with a snap that aligns with this snap\n            blockIndexes: [], // Block indexes of all blocks above that align with\n            // this snap\n            primaryBlock: null, // primary block snapped to this snap\n            primaryBlockSnapIndex: null, // snapIndex of primary block snap snapped to\n            // this snap\n        });\n    }\n    element.getSnapPosition = function (snapIndex) {\n        return element\n            .getPosition()\n            .add(element._container.getPosition())\n            .add(element.snaps[snapIndex].position);\n    };\n    // block:\n    //  block.snaps: [\n    //      {\n    //        index: int,\n    //        position: Point,\n    //        snap: element,\n    //        snapIndex: int,\n    //        isSnapped: boolean,\n    //      }, ...\n    //  ]\n    //  block.custom.snapPositions: positions in block that are snappable\n    element.refreshSnaps = function () {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            var slotSnap = element.snaps[i];\n            if (slotSnap.block != null || slotSnap.blocks.length == 0) {\n                continue;\n            }\n            slotSnap.primaryBlock = slotSnap.blocks[0];\n            slotSnap.primaryBlockSnapIndex = slotSnap.blockIndexes[0];\n            slotSnap.primaryBlock.snaps[slotSnap.primaryBlockSnapIndex].isPrimarySnap = true;\n        }\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            element.snappedBlocks[i].afterSnapChange();\n        }\n        if (border != null) {\n            border.setColor(border.custom.initialColor);\n        }\n    };\n    /**\n     * Get slot's snap index from a position.\n     * Snap must be within o.snap/10 for a snap index to return\n     * @param position\n     * @returns index (number) or null\n     */\n    element.getSnapFromPosition = function (position) {\n        var p = element.getPosition().add(element._container.getPosition());\n        for (var i = 0; i < snapPositions.length; i += 1) {\n            var snapPosition = p.add(snapPositions[i]);\n            if (position.sub(snapPosition).distance() < o.snap / 10) {\n                return i;\n            }\n        }\n        return null;\n    };\n    /**\n     * Snap a block to the slot.\n     * - Add block to slot's list of snapped blocks\n     * - Match up each slot's and block's snaps\n     * @param block\n     */\n    element.snap = function (block) {\n        // fig.answerChanged();\n        if (element.snappedBlocks.indexOf(block) == -1) {\n            element.snappedBlocks.push(block);\n        }\n        for (var i = 0; i < block.snaps.length; i += 1) {\n            var blockSnap = block.snaps[i];\n            var snapIndex = element.getSnapFromPosition(blockSnap.getLocalPosition());\n            if (snapIndex == null) {\n                continue;\n            }\n            blockSnap.slot = element;\n            blockSnap.slotSnapIndex = snapIndex;\n            var slotSnap = element.snaps[snapIndex];\n            if (slotSnap.blocks.indexOf(block) == -1) {\n                slotSnap.blocks.push(block);\n                slotSnap.blockIndexes.push(i);\n            }\n            // If the slot snap is empty, then can properly snap the block to it\n            if (slotSnap.primaryBlock == null) {\n                slotSnap.primaryBlock = block;\n                slotSnap.primaryBlockSnapIndex = i;\n                blockSnap.isPrimarySnap = true;\n            }\n        }\n        block.snapPositionDelta = element.getPosition().sub(block.getPosition());\n        element.refreshSnaps();\n    };\n    element.unsnap = function (block) {\n        // fig.answerChanged();\n        var index = element.snappedBlocks.indexOf(block);\n        block.snapPositionDelta = null;\n        if (index == -1) {\n            return;\n        }\n        element.snappedBlocks.splice(index, 1);\n        var slotSnaps = element.snaps;\n        for (var i = 0; i < slotSnaps.length; i += 1) {\n            var slotSnap = slotSnaps[i];\n            var index_1 = slotSnap.blocks.indexOf(block);\n            if (index_1 !== -1) {\n                slotSnap.blocks.splice(index_1, 1);\n                slotSnap.blockIndexes.splice(index_1, 1);\n            }\n            if (slotSnap.primaryBlock == block) {\n                slotSnap.primaryBlock = null;\n                slotSnap.primaryBlockSnapIndex = null;\n            }\n        }\n        element.refreshSnaps();\n    };\n    element.custom.toPulse = function (pulseOptions) {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            block.animations.new().pulse(pulseOptions).start();\n        }\n    };\n    element.notifications.add('setTransform', function () {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            if (block.snapPositionDelta != null) {\n                block.setPosition(element.getPosition().sub(block.snapPositionDelta));\n                block.custom.slotPosition = block.getPosition();\n                block.custom.state.p = block.getPosition();\n            }\n            // const p = tile.getSnapPosition(0).sub(slot.getSnapPosition())\n            // tile.setPosition(tile.getPosition().sub(p))\n            // const tp = tile.getPosition();\n            // tile.snap(slot)\n            // tile.custom.state.p = tp;\n            // tile.custom.slotPosition = tp._dup();\n        }\n    });\n    element.checkSnaps = function (block) {\n        // Return the offset required to snap - null if no snap\n        // First check if the block bounds overlap with the slotBorderBounds\n        var blockBounds = block.custom.getBoundingRect('local');\n        // const slotBounds = element.getBoundingRect('local');\n        var e = element.getPosition().add(element._container.getPosition());\n        // const slotPosition = element.getPosition('local');\n        // const slotBounds = new Fig.Rect(slotPosition.x, slotPosition.y, width, height)\n        var slotBorderBounds = new Fig.Rect(e.x - (o.debug ? 0 : snapBorder.left), e.y - (o.debug ? 0 : snapBorder.bottom), width + snapBorder.left + snapBorder.right, height + snapBorder.left + snapBorder.right);\n        if (!doRectsOverlap(slotBorderBounds, blockBounds)) {\n            return null;\n        }\n        // Snap algorithm:\n        // Go through all snapPositions in manipulative to calc distance to all\n        // snap positions in Snap. Whichever snapPosition has the smallest distance to a\n        // snap gets snapped\n        var delta = null;\n        var distance = null;\n        var p = element.getPosition().add(element._container.getPosition());\n        var found = false;\n        for (var i = 0; i < block.snaps.length; i += 1) {\n            if (found) {\n                break;\n            }\n            for (var j = 0; j < snapPositions.length; j += 1) {\n                if (found) {\n                    break;\n                }\n                var slotSnapPosition = p.add(snapPositions[j]);\n                var blockSnapPosition = block.snaps[i].getLocalPosition();\n                var del = blockSnapPosition.sub(slotSnapPosition);\n                var d = del.distance();\n                if (distance == null || distance > d) {\n                    distance = d;\n                    delta = del;\n                }\n                // If the distance is\n                if (Math.abs(delta.x) < o.snap / 2 &&\n                    Math.abs(delta.y) < o.height / 2) {\n                    found = true;\n                }\n            }\n        }\n        return delta;\n    };\n    return element;\n};\nexport { simpleBlockSlot, setupLabel, };\n","import { joinObjects } from '../tools/joinObjects';\nimport { doRectsOverlap } from '../workpad_new/tools';\nimport { setupLabel } from './simpleBlockSlot';\nvar simpleBlockFillSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        // Add styles here with overrides of default\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        width: 0.6,\n        height: 0.4,\n        fill: false,\n        yOffset: 0,\n        radius: 0.02,\n        sides: 10,\n        debug: false,\n        space: false,\n        line: true,\n        label: '?',\n        font: {\n            size: 0.15,\n            color: [0.3, 0.3, 0.3, 1],\n            family: defaultFontFamilyMath,\n        },\n        snapBorder: 0,\n        borderInSize: true,\n        correctness: true,\n        disabled: false,\n        labelOptions: {\n            position: 'top',\n            symbol: 'brace',\n            lineWidth: 0.015,\n            symbolHeight: 0.1,\n            color: [0.3, 0.3, 0.3, 1],\n            commentSpace: 0.1,\n            contentSpace: 0.3,\n            scale: 1,\n            inSize: true,\n        },\n        tileLineWidth: 0.01,\n        correctnessBorder: true,\n    }, styleDefaults, options);\n    var fillDefaults = {\n        color: [0.8, 0.8, 0.8, 1],\n        correct: [0.8, 0.8, 0.8, 1],\n        incorrect: [0.8, 0.8, 0.8, 1],\n        technicallyCorrect: [0.8, 0.8, 0.8, 1],\n        invalid: [0.8, 0.8, 0.8, 1],\n        // lineWidth: 0.01,\n    };\n    var lineDefaults = {\n        dash: [0.07, 0.02],\n        color: [0.6, 0.6, 0.6, 1],\n        width: 0.02,\n        correct: [0.6, 0.6, 0.6, 1],\n        incorrect: [0.6, 0.6, 0.6, 1],\n        technicallyCorrect: [0.6, 0.6, 0.6, 1],\n        invalid: [0.6, 0.6, 0.6, 1],\n    };\n    var correctnessBorderDefaults = {\n        color: [0, 0, 0, 0],\n        width: 0.05,\n        space: 0.025,\n        // fill: true,\n        correct: colors.COLOR_GROKKOLI_GREEN,\n        incorrect: colors.COLOR_GROKKOLI_ORANGE,\n        technicallyCorrect: colors.COLOR_GROKKOLI_GOLD,\n        invalid: colors.COLOR_GROKKOLI_GREY,\n    };\n    if (o.line === true) {\n        o.line = lineDefaults;\n    }\n    else if (o.line) {\n        o.line = joinObjects(lineDefaults, o.line);\n    }\n    if (o.fill === true) {\n        o.fill = fillDefaults;\n    }\n    else if (o.fill) {\n        o.fill = joinObjects(fillDefaults, o.fill);\n    }\n    if (o.correctnessBorder === true) {\n        o.correctnessBorder = correctnessBorderDefaults;\n    }\n    else if (o.correctnessBorder) {\n        o.correctnessBorder = joinObjects(correctnessBorderDefaults, o.correctnessBorder);\n    }\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    var space = o.space ? o.space : 0;\n    var lineWidth = 0;\n    if (o.line !== false) {\n        lineWidth = o.line.width;\n    }\n    var width = Fig.round(o.width, 7);\n    var height = o.height;\n    element.custom.o = o;\n    var cBorder;\n    if (o.correctnessBorder) {\n        var cSpace = o.correctnessBorder.space ? o.correctnessBorder.space : 0;\n        // const lineWidth1 = o.space !== false ? lineWidth / 2 : 0;\n        var cRadius = o.radius + cSpace;\n        if (o.space === false) {\n            if (o.fill && o.line === false) {\n                cRadius =\n                    o.radius + o.tileLineWidth / 2 + space + cSpace - o.tileLineWidth / 2;\n            }\n            else if (o.line) {\n                cRadius = o.radius - o.line.width / 2 + cSpace;\n            }\n        }\n        cBorder = container.add({\n            make: 'rectangle',\n            name: 'correctnessBorder',\n            width: width + cSpace * 2,\n            height: height + cSpace * 2,\n            color: o.correctnessBorder.color,\n            line: {\n                width: o.correctnessBorder.width,\n                dash: o.correctnessBorder.dash,\n            },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: cRadius,\n                sides: o.sides,\n            },\n            position: [-cSpace, -cSpace + o.yOffset],\n        });\n        cBorder.custom.initialColor = cBorder.color.slice();\n    }\n    var fill;\n    if (o.fill) {\n        fill = container.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: width + o.tileLineWidth + space * 2,\n            height: height + o.tileLineWidth + space * 2,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius + o.tileLineWidth / 2 + space,\n                sides: o.sides,\n            },\n            position: [\n                -o.tileLineWidth / 2 - space,\n                o.yOffset - o.tileLineWidth / 2 - space,\n            ],\n        });\n        fill.custom.initialColor = o.fill.color;\n    }\n    var border;\n    var borderSpace = o.space === false ? -lineWidth / 2 + o.tileLineWidth / 2 : o.space;\n    if (o.line) {\n        var lineRadius = o.radius + space + o.tileLineWidth / 2;\n        if (o.space === false) {\n            lineRadius = o.radius - o.line.width / 2;\n        }\n        border = container.add({\n            make: 'rectangle',\n            name: 'border',\n            width: width + borderSpace * 2,\n            height: height + borderSpace * 2,\n            color: o.line.color,\n            line: { width: lineWidth, dash: o.line.dash },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            corner: {\n                radius: lineRadius,\n                sides: o.sides,\n            },\n            position: [-borderSpace, -borderSpace + o.yOffset],\n        });\n        border.custom.initialColor = border.color.slice();\n    }\n    // createNumberLine(element, {})\n    setupLabel(container, Fig.joinObjects({}, o, { name: 'label' }), width, height);\n    if (o.borderInSize) {\n        var s = space;\n        if (o.line !== false && o.space !== false) {\n            s += o.line.width / 2;\n        }\n        if (o.correctnessBorder !== false && o.correctnessBorder.space > s) {\n            var s1 = o.correctnessBorder.space + o.correctnessBorder.width / 2;\n            if (s1 > s) {\n                s = s1;\n            }\n        }\n        container.setPosition(s, o.yOffset);\n    }\n    else {\n        var maxY = o.height + space * 2;\n        if (o.label && o.labelOptions.inSize) {\n            var rect = container._label.getBoundingRect();\n            maxY = rect.top + space;\n        }\n        element.border = [\n            [\n                new Fig.Point(0),\n                new Fig.Point(o.width + space * 2, 0),\n                new Fig.Point(o.width + space * 2, maxY),\n                new Fig.Point(0, maxY),\n            ],\n        ];\n    }\n    element.preserveChildColor = true;\n    var snapBorder = {\n        left: 0,\n        top: 0,\n        right: 0,\n        bottom: 0,\n    };\n    if (typeof o.snapBorder === 'number') {\n        snapBorder.left = o.snapBorder;\n        snapBorder.right = o.snapBorder;\n        snapBorder.top = o.snapBorder;\n        snapBorder.bottom = o.snapBorder;\n    }\n    else if (o.snapBorder) {\n        snapBorder = joinObjects({}, snapBorder, o.snapBorder);\n    }\n    if (o.debug) {\n        container.add({\n            make: 'rectangle',\n            name: 'snapBorder',\n            width: width + snapBorder.left + snapBorder.right,\n            height: height + snapBorder.bottom + snapBorder.top,\n            color: o.line.color,\n            line: { width: 0.005, dash: [0.02, 0.02] },\n            xAlign: 'left',\n            yAlign: 'bottom',\n            position: [snapBorder.left, -snapBorder.bottom + o.yOffset],\n        });\n    }\n    element.snappedBlocks = [];\n    element.getManipulativeBaseSnap = function () { return -1; };\n    element.custom.getState = function () {\n        var fullBlocks = [];\n        var partialBlocks = [];\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            if (block.snapFail) {\n                partialBlocks.push(block.name);\n            }\n            else {\n                fullBlocks.push(block.name);\n            }\n        }\n        return {\n            full: fullBlocks,\n            partial: partialBlocks,\n        };\n    };\n    element.custom.showCorrectness = function (result) {\n        var _a, _b;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        if (o.correctness) {\n            if (cBorder != null) {\n                if (result === 1) {\n                    cBorder.setColor(correctColor || o.correctnessBorder.correct);\n                }\n                else if (result === 3) {\n                    cBorder.setColor(o.correctnessBorder.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    cBorder.setColor(incorrectColor || o.correctnessBorder.incorrect);\n                }\n                else if (result === 4) {\n                    cBorder.setColor(o.correctnessBorder.invalid);\n                }\n                else {\n                    cBorder.setColor(o.correctnessBorder.color);\n                }\n            }\n            if (border != null) {\n                if (result === 1) {\n                    border.setColor(correctColor || o.line.correct);\n                }\n                else if (result === 3) {\n                    border.setColor(o.line.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    border.setColor(incorrectColor || o.line.incorrect);\n                }\n                else if (result === 4) {\n                    border.setColor(o.line.invalid);\n                }\n                else {\n                    border.setColor(o.line.color);\n                }\n            }\n            if (fill != null) {\n                if (result === 1) {\n                    fill.setColor(correctColor || o.fill.correct);\n                }\n                else if (result === 3) {\n                    fill.setColor(o.fill.technicallyCorrect);\n                }\n                else if (result === 2 || result === 6) {\n                    fill.setColor(incorrectColor || o.fill.incorrect);\n                }\n                else if (result === 4) {\n                    fill.setColor(o.fill.invalid);\n                }\n                else {\n                    fill.setColor(o.fill.color);\n                }\n            }\n        }\n    };\n    element.unhighlight = function () { };\n    element.custom.manipulativeType = 'simpleBlockFillSlot';\n    element.getSnapPosition = function (snapIndex) {\n        var p = element.getPosition().add(element._container.getPosition());\n        if (element.snappedBlocks.length === 0) {\n            return p.add(0, height / 2);\n        }\n        var lastBlock = element.snappedBlocks.slice(-1)[0];\n        return new Fig.Point(lastBlock.custom.getBoundingRect().right, p.y + height / 2);\n    };\n    element.refreshSnaps = function () {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            element.snappedBlocks[i].afterSnapChange();\n        }\n        if (border != null) {\n            border.setColor(border.custom.initialColor);\n        }\n        if (fill != null) {\n            fill.setColor(fill.custom.initialColor);\n        }\n        if (cBorder != null) {\n            cBorder.setColor(cBorder.custom.initialColor);\n        }\n    };\n    // /**\n    //  * Get slot's snap index from a position.\n    //  * Snap must be within o.snap/10 for a snap index to return\n    //  * @param position\n    //  * @returns index (number) or null\n    //  */\n    // element.getSnapFromPosition = (position: FigureOnePoint) => {\n    //   const p = element.getPosition()\n    //   for (let i = 0; i < snapPositions.length; i += 1) {\n    //     const snapPosition = p.add(snapPositions[i]);\n    //     if (position.sub(snapPosition).distance() < o.snap / 10) {\n    //       return i;\n    //     }\n    //   }\n    //   return null;\n    // }\n    // // Ordered (in x) blocks snapped to slot\n    // element.snappedBlocks = []\n    element.getFirstSpace = function (block) {\n        var r = 6;\n        var p = element.getPosition().add(element._container.getPosition());\n        var elementRectWidth = Fig.round(o.width, r);\n        var elementRectRight = Fig.round(p.x + o.width, r);\n        var blockRect = block.custom.getBoundingRect();\n        var blockWidth = Fig.round(blockRect.width, r);\n        if (element.snappedBlocks.length === 0) {\n            if (elementRectWidth >= blockWidth) {\n                return [0, p, true];\n            }\n            else {\n                return [null, null, null];\n            }\n        }\n        var lastX = Fig.round(p.x, r);\n        var space = null;\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var snappedBlockRect = element.snappedBlocks[i].custom.getBoundingRect();\n            if (Fig.round(snappedBlockRect.left, r) > lastX) {\n                space = Fig.round(snappedBlockRect.left - lastX, r);\n                if (space >= blockWidth) {\n                    return [i, new Fig.Point(lastX, p.y), true];\n                }\n            }\n            lastX = Fig.round(snappedBlockRect.right, r);\n        }\n        if (lastX < elementRectRight) {\n            return [\n                -1,\n                new Fig.Point(lastX, p.y),\n                Fig.round(lastX + blockWidth, r) <= elementRectRight + 0.00001,\n            ];\n        }\n        return [null, null, null];\n    };\n    /**\n     * Snap a block to the slot.\n     * - Add block to slot's list of snapped blocks\n     * - Match up each slot's and block's snaps\n     * @param block\n     */\n    element.snap = function (block) {\n        // fig.answerChanged();\n        // block.\n        var _a = element.getFirstSpace(block), index = _a[0], _ = _a[1], fullSnap = _a[2];\n        if (index == null) {\n            return;\n        }\n        if (index === -1) {\n            element.snappedBlocks.push(block);\n        }\n        else {\n            element.snappedBlocks.splice(index, 0, block);\n        }\n        block.snappedFillSlot = element;\n        block.snapFail = !fullSnap;\n        block.snapPositionDelta = element.getPosition().sub(block.getPosition());\n        element.refreshSnaps();\n    };\n    // Add styles here with overrides of default\n    element.unsnap = function (block) {\n        // fig.answerChanged();\n        var index = element.snappedBlocks.indexOf(block);\n        block.snapPositionDelta = null;\n        if (index == -1) {\n            return;\n        }\n        element.snappedBlocks.splice(index, 1);\n        element.refreshSnaps();\n    };\n    element.custom.toPulse = function (pulseOptions) {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            block.animations.new().pulse(pulseOptions).start();\n        }\n    };\n    element.notifications.add('setTransform', function () {\n        for (var i = 0; i < element.snappedBlocks.length; i += 1) {\n            var block = element.snappedBlocks[i];\n            if (block.snapPositionDelta != null) {\n                block.setPosition(element.getPosition().sub(block.snapPositionDelta));\n                block.custom.slotPosition = block.getPosition();\n                block.custom.state.p = block.getPosition();\n            }\n            // const p = tile.getSnapPosition(0).sub(slot.getSnapPosition())\n            // tile.setPosition(tile.getPosition().sub(p))\n            // const tp = tile.getPosition();\n            // tile.snap(slot)\n            // tile.custom.state.p = tp;\n            // tile.custom.slotPosition = tp._dup();\n        }\n    });\n    element.custom.disabled = o.disabled;\n    element.disable = function () { element.custom.disabled = true; };\n    element.enable = function () { element.custom.disabled = false; };\n    element.checkSnaps = function (block) {\n        if (element.custom.disabled) {\n            return null;\n        }\n        // Return the offset required to snap - null if no snap\n        // First check if the block bounds overlap with the slotBorderBounds\n        var blockBounds = block.custom.getBoundingRect('local');\n        var e = element.getPosition().add(element._container.getPosition());\n        var slotBorderBounds = new Fig.Rect(e.x - (o.debug ? 0 : snapBorder.left), e.y - (o.debug ? 0 : snapBorder.bottom), width + snapBorder.left + snapBorder.right, o.height + snapBorder.left + snapBorder.right);\n        if (!doRectsOverlap(slotBorderBounds, blockBounds)) {\n            return null;\n        }\n        // Snap algorithm:\n        // Snap the block into the first space between snapped blocks big enough\n        // for the block\n        var firstSpace = element.getFirstSpace(block)[1];\n        if (firstSpace == null) {\n            return null;\n        }\n        return block.getPosition().sub(firstSpace);\n    };\n    return element;\n};\nexport { simpleBlockFillSlot, };\n","import { createNumberLine } from '../tools/numberline';\nvar numberlineManipulative = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({}, options);\n    var numberline = createNumberLine(toAdd, o);\n    return numberline;\n};\nexport { numberlineManipulative, };\n","import { simpleBlock } from './simpleBlock';\nimport { getEllipsePoints } from '../tools/geometry';\nimport { setAtlasId } from '../tools/equation';\nvar hopManipulative = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({\n        width: 0.5,\n        height: 0.4,\n        scale: 1,\n        line: true,\n        yOffset: 0,\n        isSelectable: false,\n        isTouchable: true,\n        debug: false,\n        boundMove: true,\n        sides: 500,\n        snapTo: [],\n        font: {\n            size: 0.2,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        textFont: {\n            family: defaultFontFamily,\n            style: 'normal',\n            weight: '300',\n            render: 'gl',\n            color: colors.COLOR_GROKKOLI_BLUE,\n        },\n        arrow: true,\n        snapStyle: 'block',\n        xOffset: -0.005,\n    }, options);\n    setAtlasId(o.font);\n    setAtlasId(o.textFont);\n    if (o.line !== false) {\n        o.line = Fig.joinObjects({\n            width: 0.05,\n            color: [0.5, 0.5, 0.5, 1],\n            snapped: [0.5, 0.5, 0.5, 1],\n            snapFail: [0.5, 0.5, 0.5, 1],\n            incorrect: false,\n            correct: false,\n            highlight: false,\n            dash: [],\n        }, o.line === true ? {} : o.line);\n    }\n    if (o.arrow != false) {\n        var defaultArrowOptions = {\n            head: 'triangle',\n            width: o.line.width * 2,\n            length: o.line.width * 1.5,\n            tailLength: 0,\n        };\n        if (o.arrow === true) {\n            o.arrow = defaultArrowOptions;\n        }\n        else {\n            o.arrow = Fig.joinObjects(defaultArrowOptions, o.arrow);\n        }\n    }\n    var hopElement = simpleBlock(eqn_name, Fig.joinObjects({}, o, {\n        line: false,\n        fill: {\n            color: [0, 0, 0, 0],\n            snapped: [0, 0, 0, 0],\n            snapFail: [0, 0, 0, 0],\n            incorrect: [0, 0, 0, 0],\n            correct: [0, 0, 0, 0],\n        },\n        // label: false,\n    }), fig);\n    var container = hopElement._container;\n    var points = getEllipsePoints(o.width, o.height * 2 - o.line.width, o.sides, o.width / 2, 0, Math.PI);\n    container.add({\n        name: 'polygon',\n        make: 'polyline',\n        points: points,\n        color: o.color,\n        arrow: {\n            start: o.arrow,\n        },\n        width: o.line.width,\n        position: [o.xOffset, 0],\n    });\n    if (container._label != null) {\n        container.toFront(container._label);\n    }\n    hopElement.custom.getBoundingRect = function (space) {\n        // const p = element.getBoundingRect(space);\n        // return new Fig.Rect(p.x, p.y, o.width, o.height);\n        return hopElement.getBoundingRect(space);\n    };\n    return hopElement;\n};\nexport { hopManipulative, };\n","import { selectorManipulative } from './selector';\nvar selectorControlManipulative = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var selector = selectorManipulative(eqn_name, options, fig);\n    selector.custom.manipulativeType = null;\n    selector.notificationHelper.cleanup();\n    selector._container.isMovable = false;\n    selector.setTouchable();\n    selector.notifications.add('onClick', function () {\n        var newSelector = selectorManipulative(eqn_name, Fig.joinObjects({}, options, { name: \"\".concat(options.name, \"_temp\") }), fig);\n        newSelector.setPositionToElement(selector);\n        fig.beingMovedElement = newSelector._container;\n        newSelector.startBeingMoved();\n        toAdd.notifications.add('layoutForms', function () {\n            newSelector.show();\n            newSelector.setPosition(newSelector.custom.state.p);\n        });\n    });\n    return selector;\n};\nexport { selectorControlManipulative, };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\nvar trashManipulative = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        width: 0.4,\n        height: 0.4,\n        icon: 'break',\n        method: 'split',\n        yOffset: 0,\n        debug: false,\n        select: 'b10_blocks',\n    }, options);\n    if (o.selectPosition == null) {\n        o.selectPosition = [o.width * 0.15, o.height * 0.85];\n    }\n    var selector = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = selector.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    container.add({\n        name: 'icon',\n        make: 'rectangle',\n        width: o.width,\n        height: o.height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        texture: {\n            src: window.location.origin + '/static/img/control_atlas.png',\n            mapFrom: new Fig.Rect(0.2, 0, 0.2, 0.2),\n            mapTo: new Fig.Rect(0, 0, o.width, o.height),\n            loadColor: [0, 0, 0, 0],\n        },\n    });\n    if (o.debug) {\n        container.add({\n            make: 'rectangle',\n            line: { width: 0.01 },\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n        });\n        container.add({\n            make: 'polygon',\n            position: o.selectPosition,\n            radius: 0.01,\n            color: [0, 0, 0, 1],\n            sides: 10,\n        });\n    }\n    var s = 0.12;\n    var target = container.add({\n        make: 'collection',\n        elements: [\n            {\n                make: 'rectangle',\n                name: 'line1',\n                corner: {\n                    radius: 0.01,\n                    sides: 5,\n                },\n                color: [1, 1, 1, 0],\n                position: o.selectPosition,\n                width: s * 2 + 0.02,\n                height: 0.02,\n            },\n            {\n                make: 'rectangle',\n                name: 'line2',\n                // dash: [0.04, 0.01],\n                corner: {\n                    radius: 0.01,\n                    sides: 5,\n                },\n                color: [1, 1, 1, 0],\n                height: s * 2 + 0.02,\n                width: 0.02,\n                position: o.selectPosition,\n            },\n            {\n                make: 'line',\n                name: 'line3',\n                dash: [0.04, 0.01],\n                width: 0.005,\n                color: [0.5, 0.5, 0.5, 0],\n                p1: [o.selectPosition[0] - s, o.selectPosition[1]],\n                p2: [o.selectPosition[0] + s, o.selectPosition[1]],\n            },\n            {\n                make: 'line',\n                name: 'line4',\n                dash: [0.04, 0.01],\n                width: 0.005,\n                color: [0.5, 0.5, 0.5, 0],\n                p1: [o.selectPosition[0], o.selectPosition[1] - s],\n                p2: [o.selectPosition[0], o.selectPosition[1] + s],\n            },\n        ],\n    });\n    // const t1 = container.add()\n    // const t2 = container.add()\n    // t1.hide();\n    // t2.hide();\n    selector.notificationHelper = new NotificationHelper();\n    setupManipulative(selector, null, o);\n    selector.custom.getBoundingRect = function (space) {\n        return selector.getBoundingRect(space);\n    };\n    selector.custom.getState = function () {\n        var p = selector.getPosition();\n        return {\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n        };\n    };\n    selector.custom.setState = function (stats) {\n        selector.setPosition(Fig.parsePoint(stats.p));\n        selector.custom.moved = true;\n    };\n    selector.custom.state = selector.custom.getState();\n    selector.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (selector.custom.moved) {\n            selector.setPosition(Fig.parsePoint(selector.custom.state.p));\n        }\n    });\n    selector.notificationHelper.add(fig, 'ready', function () {\n        selector.custom.initialPosition = selector.getPosition();\n    });\n    selector.custom.lastPosition = selector.getPosition();\n    selector.custom.highlighted = null;\n    selector.notificationHelper.add(selector, 'moved', function () {\n        selector.custom.moved = true;\n        selector.custom.state.p = selector.getPosition();\n        // If there hasn't been enough movement, then do nothing.\n        if (selector.custom.lastPosition.sub(selector.custom.state.p).distance() <\n            0.01) {\n            return;\n        }\n        var selectPosition = selector.custom.state.p.add(new Fig.parsePoint(o.selectPosition));\n        selector.custom.lastPosition = selector.custom.state.p;\n        for (var i = selector.parent.drawOrder.length - 1; i >= 0; i -= 1) {\n            var element = selector.parent.elements[selector.parent.drawOrder[i]];\n            if (element.custom.manipulativeType == null\n            // || element.custom.manipulativeType !== o.select\n            ) {\n                continue;\n            }\n            if (!element.custom.worksWithTrash) {\n                continue;\n            }\n            var bounds = element.custom.getBoundingRect();\n            if (bounds.isPointInside(selectPosition)) {\n                if (selector.custom.highlighted) {\n                    selector.custom.highlighted.unhighlight();\n                }\n                element.highlight();\n                selector.custom.highlighted = element;\n                return;\n            }\n        }\n        if (selector.custom.highlighted) {\n            selector.custom.highlighted.unhighlight();\n            selector.custom.highlighted = null;\n        }\n    });\n    selector.custom.secondaryTouchBounds = 0.1;\n    selector.notificationHelper.add(selector._container, 'onClick', function () {\n        selector.custom.clickStart = performance.now();\n        selector.startBeingMoved();\n        selector.custom.startMove = performance.now();\n        selector.parent.toFront(selector);\n        window.clickHandled = true;\n        // t1.show();\n        // t2.show();\n        target._line1.setColor([1, 1, 1, 1]);\n        target._line2.setColor([1, 1, 1, 1]);\n        target._line3.setColor([0.5, 0.5, 0.5, 1]);\n        target._line4.setColor([0.5, 0.5, 0.5, 1]);\n        target.pulse({ scale: 1.4, duration: 0.4 });\n    });\n    selector.notificationHelper.add(selector, 'stopBeingMoved', function () {\n        if (selector.custom.highlighted) {\n            selector.custom.highlighted[o.method]();\n            selector.custom.highlighted.unhighlight;\n            selector.custom.highlighted = null;\n        }\n        selector.custom.state.p = selector.getPosition();\n        // t1.hide();\n        // t2.hide();\n        target._line1.setColor([1, 1, 1, 0]);\n        target._line2.setColor([1, 1, 1, 0]);\n        target._line3.setColor([0.5, 0.5, 0.5, 0]);\n        target._line4.setColor([0.5, 0.5, 0.5, 0]);\n        toAdd.animations\n            .new()\n            .dissolveOut({ element: selector, duration: 0.01 })\n            .delay(0.4)\n            .trigger(function () {\n            selector.setPosition(selector.custom.initialPosition);\n            selector.custom.state.p = selector.custom.initialPosition;\n        })\n            .dissolveIn({ element: selector, duration: 0.5 })\n            .start();\n        // selector.hide();\n        // setTimeout(() => {\n        //   selector.parent.remove(selector);\n        // }, 5);\n    });\n    if (o.isTouchable === false) {\n        selector.hasTouchableElements = false;\n    }\n    // selector.custom.manipulativeType = 'manipulative_selector';\n    container.setMove({ freely: false, element: selector });\n    selector.move.freely = false;\n    return selector;\n};\nexport { trashManipulative, };\n","import { NotificationHelper } from '../tools/notifications';\nimport { getSelectedSelector } from './manage';\nimport { setupManipulative } from './tools';\nimport { setAtlasId } from '../tools/equation';\nvar RATIO = 550 / 235;\nfunction createTimesTable(fig, eqn_name, toElement, o, boundMove) {\n    var newO = Fig.joinObjects({}, o, {\n        name: \"\".concat(o.name).concat(o.n),\n        // scale: o.createScale,\n        fromPalette: true,\n        boundMove: boundMove,\n    });\n    // element.custom.count += 1;\n    var to = toElement;\n    if (to == null) {\n        to = eqn_name;\n    }\n    return timesTable(to, newO, fig);\n}\nvar timesTable = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        static: {\n            isTouchable: false,\n            boundMove: false,\n        },\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        space: [0.03, 0.05],\n        scale: 1,\n        width: 0.6,\n        fill: true,\n        line: true,\n        yOffset: 0,\n        isTouchable: true,\n        debug: false,\n        boundMove: true,\n        radius: 0.02,\n        ratio: RATIO,\n        sides: 5,\n        font: {\n            size: 0.2,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        arrow: {\n            space: 0,\n            head: 'triangle',\n            side: 'left',\n            color: [0.2, 0.2, 1, 1],\n            width: 0.1,\n            length: 0.15,\n            tailWidth: 0.05,\n            tail: 0.05,\n            inSize: false,\n        }\n    }, styleDefaults, options);\n    setAtlasId(o.font);\n    if (o.line !== false) {\n        o.line = Fig.joinObjects({\n            width: 0.003,\n            // color: BLOCK_COLORS[o.n],\n            color: [0.6, 0.6, 0.6, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.6, 0.6, 1, 1],\n            dash: [],\n        }, o.line === true ? {} : o.line);\n    }\n    if (o.fill !== false) {\n        o.fill = Fig.joinObjects({\n            color: [1, 1, 1, 1],\n            dim: [1, 1, 1, 1],\n            highlight: [0.9, 0.9, 1, 1],\n            // color: colors.COLOR_GROKKOLI_LIGHT_GREY,\n            // color: desaturate(lighten(BLOCK_COLORS[o.n], 0.2), 0.2)\n        }, o.fill === true ? {} : o.fill);\n    }\n    if (typeof o.space === 'number') {\n        o.space = [o.space, o.space];\n    }\n    var width = o.width * o.scale;\n    var height = o.width * o.scale * o.ratio;\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    element.notificationHelper = new NotificationHelper();\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    if (o.n) {\n        element.custom.n = o.n;\n    }\n    if (o.fill !== false) {\n        container.add({\n            make: 'rectangle',\n            name: 'fill',\n            width: width + o.space[0] * 2,\n            height: height + o.space[1] * 2,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    if (o.line) {\n        container.add({\n            name: 'line',\n            make: 'rectangle',\n            width: width + o.space[0] * 2,\n            height: height + o.space[1] * 2,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.line.color,\n            line: {\n                width: o.line.width,\n                dash: o.line.dash,\n            },\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n        container.setPosition(o.line.width / 2, o.line.width / 2 + o.yOffset);\n    }\n    var text = container.add({\n        name: 'text',\n        make: 'rectangle',\n        width: width,\n        height: height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        texture: {\n            src: window.location.origin + \"/static/img/times_table_\".concat(o.n, \"_big.png\"),\n            mapFrom: new Fig.Rect(0, 0, 1, 1),\n            mapTo: new Fig.Rect(0, 0, width, height),\n            loadColor: [0, 0, 0, 0],\n        },\n        position: [o.space[0], o.space[1]],\n    });\n    var dimRect = container.add({\n        name: 'dim',\n        make: 'rectangle',\n        width: width,\n        height: height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        color: [1, 1, 1, 0.5],\n        position: [o.space[0], o.space[1]],\n    });\n    dimRect.color[3] = 0;\n    dimRect.hide();\n    var arrow = container.add({\n        name: 'arrow',\n        make: 'arrow',\n        color: o.arrow.color,\n        head: o.arrow.head * o.scale,\n        angle: o.arrow.side === 'left' ? 0 : Math.PI,\n        width: o.arrow.width * o.scale,\n        length: o.arrow.length * o.scale,\n        tailWidth: o.arrow.tailWidth * o.scale,\n        tail: o.arrow.tail * o.scale,\n        border: [[]]\n    });\n    arrow.color[3] = 0;\n    // if (o.arrow.inSize === false) {\n    //   o.arrow.border = [[]];\n    // }\n    arrow.hide();\n    // let fill: FigureOneElement;\n    // if (o.fill) {\n    //   fill = container.add({\n    //     name: 'fill',\n    //     make: 'rectangle',\n    //     width: o.width,\n    //     height: o.height,\n    //     xAlign: 'left',\n    //     yAlign: 'bottom',\n    //     color: o.fill.color,\n    //     corner: {\n    //       radius: o.radius,\n    //       sides: o.sides,\n    //     },\n    //   });\n    // }\n    if (o.debug) {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            container.add({\n                make: 'polygon',\n                name: \"debugCenter\".concat(i),\n                sides: 10,\n                radius: 0.01,\n                position: [0, 0],\n            });\n        }\n    }\n    element.custom.worksWith = {\n        trash: true,\n    };\n    element.custom.getState = function () {\n        var p = element.getPosition();\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        var regex = new RegExp('^' + e_name);\n        var createdFrom = o.createdFrom\n            ? o.createdFrom.replace(regex, '').slice(1)\n            : null;\n        return {\n            c: createdFrom,\n            e: e_name,\n            h: !element.isShown,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        element.custom.moved = true;\n        // if (stats.h) {\n        var controlElement = fig.getElement(stats.e + '.' + stats.c);\n        if (controlElement != null) {\n            controlElement.snapshot();\n        }\n        if (stats.h) {\n            element.setOpacity(0.15);\n        }\n        // }\n    };\n    setupManipulative(element, null, o);\n    element.trash = function () {\n        element.hide();\n        element.custom.state.h = true;\n        element.notifications.publish('hidden');\n    };\n    if (o.isTouchable) {\n        element.setMove({ freely: false });\n    }\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n        if (element.custom.state.h) {\n            element.hide();\n        }\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n        // element.highlightContainer();\n    });\n    element.notificationHelper.add(element, 'onClick', function () {\n        var selector = getSelectedSelector(fig);\n        if (selector != null) {\n            element.custom.clickStart = null;\n            if (selector.custom.method === 'trash') {\n                element.trash();\n                selector.highlightWorksWith();\n                selector.checkDeselect();\n                return;\n            }\n        }\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element.name);\n        window.clickHandled = true;\n    });\n    element.unhighlight = function () { };\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition();\n    });\n    if (!o.static) {\n        element.custom.manipulativeType = 'times_table';\n    }\n    element.showArrow = function (operand, duration) {\n        if (duration === void 0) { duration = 0.3; }\n        var rect = text.getBoundingRect('local');\n        var row = 12 - operand;\n        arrow.color[3] = 1;\n        if (o.arrow.side === 'left') {\n            arrow.setPosition(rect.left - o.arrow.space - 0.1 * o.scale * rect.width, rect.bottom + rect.height * 0.04 + row * (rect.height) / 12);\n        }\n        else {\n            arrow.setPosition(rect.right + o.arrow.space + 0.1 * o.scale * rect.width, rect.bottom + rect.height * 0.04 + row * (rect.height) / 12);\n        }\n        arrow.animations.new().dissolveIn(duration).start();\n    };\n    element.moveArrow = function (operand, duration) {\n        var rect = text.getBoundingRect('local');\n        var row = 12 - operand;\n        var p;\n        if (o.arrow.side === 'left') {\n            p = [\n                rect.left - o.arrow.space - 0.1 * o.scale * rect.width,\n                rect.bottom + rect.height * 0.04 + row * (rect.height) / 12,\n            ];\n        }\n        else {\n            p = [\n                rect.right + o.arrow.space + 0.1 * o.scale * rect.width,\n                rect.bottom + rect.height * 0.04 + row * (rect.height) / 12,\n            ];\n        }\n        arrow.animations.new().position({ target: p, duration: duration }).start();\n    };\n    element.hideArrow = function (duration) {\n        if (duration === void 0) { duration = 0.3; }\n        // fnMap-named trigger (owner = arrow) so the alpha reset survives speech\n        // pause/resume; an inline trigger is dropped from figure.getState().\n        arrow.fnMap.add('ttHideArrow', function () {\n            arrow.color[3] = 0;\n        });\n        arrow.animations.new()\n            .dissolveOut(duration)\n            .trigger({ callback: 'ttHideArrow' })\n            .start();\n    };\n    element.custom.getBoundingRect = function (space) {\n        // const p = element.getBoundingRect(space);\n        // return new Fig.Rect(p.x, p.y, o.width, o.height);\n        return element.getBoundingRect(space);\n    };\n    element._container.custom.secondaryTouchBounds = 0.1;\n    element.dim = function () {\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.dim);\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.dim);\n        }\n        dimRect.color[3] = 1;\n        dimRect.show();\n    };\n    element.unhighlight = function () {\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.color);\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.color);\n        }\n        dimRect.color[3] = 0;\n        dimRect.hide();\n    };\n    element.highlight = function () {\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.highlight);\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.highlight);\n        }\n        dimRect.color[3] = 0;\n        dimRect.hide();\n    };\n    return element;\n};\nexport { timesTable, createTimesTable, RATIO, };\n","import { NotificationHelper } from '../tools/notifications';\nimport { getSelectedSelector } from './manage';\nimport { setupManipulative } from './tools';\nimport { setAtlasId } from '../tools/equation';\nvar RATIO = 550 / 235;\nfunction createRekenrek(fig, eqn_name, toElement, o, boundMove) {\n    var newO = Fig.joinObjects({}, o, {\n        name: o.name,\n        // scale: o.createScale,\n        fromPalette: true,\n        boundMove: boundMove,\n    });\n    // element.custom.count += 1;\n    var to = toElement;\n    if (to == null) {\n        to = eqn_name;\n    }\n    return rekenrek(to, newO, fig);\n}\nvar rekenrek = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        static: {\n            isTouchable: false,\n            boundMove: false,\n        },\n        single10: {\n            rows: 1,\n            beads: 10,\n            barOverhang: 0.2,\n        },\n        double10: {\n            rows: 2,\n            beads: 10,\n            barOverhang: 0.1,\n        },\n        triple10: {\n            rows: 3,\n            beads: 10,\n            barOverhang: 0.05,\n            space: 0.6\n        },\n        quadruple10: {\n            rows: 4,\n            beads: 10,\n            barOverhang: 0.01,\n            space: 0.6\n        },\n        double20: {\n            rows: 2,\n            beads: 20,\n            size: 0.15,\n            barOverhang: 0.1,\n        },\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        rows: 2,\n        beads: 10,\n        fill1: true,\n        fill2: true,\n        line1: true,\n        line2: true,\n        // bar: true,\n        // color1: [1, 0, 0, 1],\n        // color2: [1, 1, 1, 1],\n        barColor: {\n            color: [0.5, 0.5, 0.5, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.4, 0.4, 0.4, 1],\n            disabled: [0.6, 0.6, 0.6, 1],\n        },\n        rightFill1: false,\n        rightFill2: false,\n        size: 0.22,\n        rod: 0.02,\n        length: 4.6,\n        space: 0.7,\n        height: null,\n        radius: null,\n        muted: null,\n        barWidth: null,\n        neverShowBounds: false,\n        barOverhang: null,\n        slot: false,\n        move: 'group',\n        yOffset: 0,\n        isTouchable: false,\n        debug: false,\n        boundMove: true,\n        sides: 40,\n        secondaryTouchBounds: 0.3,\n        lineWidth: 0.005,\n        start: null,\n        colorRight: false,\n        count: false,\n        reset: false,\n    }, styleDefaults, options);\n    if (o.line1 !== false) {\n        o.line1 = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            right: [0.5, 0.5, 0.5, 1],\n            muted: [0.5, 0.5, 0.5, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            disabled: [0.3, 0.3, 0.3, 1],\n        }, o.line1 === true ? {} : o.line1);\n    }\n    if (o.fill1 !== false) {\n        o.fill1 = Fig.joinObjects({\n            color: [1, 0, 0, 1],\n            dim: [1, 0.8, 0.8, 1],\n            right: [1, 0.8, 0.8, 1],\n            muted: [1, 0.8, 0.8, 1],\n            highlight: [0.8, 0, 0, 1],\n            disabled: [1, 0.2, 0.2, 1],\n        }, o.fill1 === true ? {} : o.fill1);\n    }\n    if (o.line2 !== false) {\n        o.line2 = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            right: [0.5, 0.5, 0.5, 1],\n            muted: [0.5, 0.5, 0.5, 1],\n            disabled: [0.3, 0.3, 0.3, 1],\n        }, o.line2 === true ? {} : o.line2);\n    }\n    if (o.fill2 !== false) {\n        o.fill2 = Fig.joinObjects({\n            color: [1, 1, 1, 1],\n            dim: [1, 1, 1, 1],\n            right: [0.9, 0.9, 0.9, 1],\n            muted: [0.9, 0.9, 0.9, 1],\n            highlight: [0.9, 0.9, 0.9, 1],\n            disabled: [0.95, 0.95, 0.95, 1],\n        }, o.fill2 === true ? {} : o.fill2);\n    }\n    if (o.barWidth == null) {\n        o.barWidth = o.rod * 5;\n        o.barWidth = o.size;\n    }\n    if (o.barOverhang == null) {\n        o.barOverhang = o.size * 1.2;\n    }\n    if (o.radius == null) {\n        o.radius = o.size / 2;\n    }\n    if (o.height == null) {\n        o.height = o.size * 2;\n    }\n    if (o.count) {\n        o.count = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            size: 0.2,\n            xAlign: 'center',\n            yAlign: 'bottom',\n            offset: [0, 0],\n            style: 'moves',\n            prefix: 'Moves: ',\n        }, o.count === true ? {} : o.count);\n        var x = 0;\n        var y = 0;\n        if (o.count.xAlign === 'left') {\n            x = -o.barWidth / 2 + 0.02;\n        }\n        else if (o.count.xAlign === 'right') {\n            x = o.length + o.barWidth / 2 + 0.02;\n        }\n        else if (o.count.xAlign === 'center') {\n            x = o.length / 2;\n        }\n        if (o.count.yAlign === 'top') {\n            y =\n                (o.rows - 1) * o.space +\n                    o.height / 2 +\n                    o.barOverhang +\n                    o.count.size / 2 +\n                    0.05;\n        }\n        else if (o.count.yAlign === 'bottom') {\n            y = -o.barOverhang - o.height / 2 - 0.2;\n        }\n        else if (o.count.yAlign === 'middle') {\n            y = ((o.rows - 1) * o.space) / 2;\n        }\n        o.count.position = [x, y];\n    }\n    if (o.reset) {\n        o.reset = Fig.joinObjects({\n            color: {\n                fill: {\n                    color: [0.8, 0.8, 0.8, 1],\n                    highlight: [0.8, 0.8, 0.8, 1],\n                    dim: [0.8, 0.8, 0.8, 1],\n                    disabled: [0.7, 0.7, 0.7, 1],\n                },\n                label: {\n                    color: [0.2, 0.2, 0.2, 1],\n                    highlight: [0.2, 0.2, 0.2, 1],\n                    dim: [0.2, 0.2, 0.2, 1],\n                    disabled: [0.4, 0.4, 0.4, 1],\n                },\n            },\n            width: 0.8,\n            label: 'Reset',\n            xAlign: 'right',\n            yAlign: 'bottom',\n            height: 0.3,\n            offset: [0, 0],\n            font: {\n                family: defaultFontFamily,\n                size: 0.18,\n            },\n        }, o.reset === true ? {} : o.reset);\n        var x = 0;\n        var y = 0;\n        if (o.reset.xAlign === 'left') {\n            x = -o.barWidth / 2 + 0.02;\n        }\n        else if (o.reset.xAlign === 'right') {\n            x = o.length + o.barWidth / 2 + 0.02;\n        }\n        else if (o.reset.xAlign === 'center') {\n            x = o.length / 2;\n        }\n        if (o.reset.yAlign === 'top') {\n            y =\n                (o.rows - 1) * o.space +\n                    o.height / 2 +\n                    o.barOverhang +\n                    o.reset.height / 2 +\n                    0.05;\n        }\n        else if (o.reset.yAlign === 'bottom') {\n            y = -o.barOverhang - o.height / 2 - 0.2;\n        }\n        else if (o.reset.yAlign === 'middle') {\n            y = ((o.rows - 1) * o.space) / 2;\n        }\n        o.reset.x = x;\n        o.reset.y = y;\n    }\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    element.notificationHelper = new NotificationHelper();\n    // Tracks the settled \"should beads be touchable\" intent, independent of the\n    // transient isTouchable=false that showAnswer sets during its animation.\n    // disableInteraction snapshots isTouchable at the moment of call; without\n    // this flag, a submit mid-showAnswer would capture the transient false and\n    // leave beads stuck untouchable after enableInteraction restores.\n    element.custom.intendedTouchable = true;\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [o.barWidth, o.yOffset + o.barOverhang + o.height / 2],\n    });\n    if (o.n) {\n        element.custom.n = o.n;\n    }\n    var rows = [];\n    var barWidth = o.barWidth;\n    var barOverhang = o.barOverhang;\n    if (o.neverShowBounds) {\n        element.custom.neverShowBounds = true;\n    }\n    if (o.isTouchable) {\n        var touchLeft = container.add({\n            make: 'rectangle',\n            name: 'touchLeft',\n            width: 0.001,\n            height: (o.rows - 1) * o.space + o.height + barOverhang * 2,\n            color: o.debug ? [0, 0, 0, 1] : [0, 0, 0, 0],\n            yAlign: 'middle',\n            xAlign: 'center',\n            position: [-barWidth, ((o.rows - 1) * o.space) / 2],\n        });\n        touchLeft.custom.secondaryTouchBounds = {\n            left: 0.2,\n            right: o.barWidth + 0.2,\n            top: 0.2,\n            bottom: 0.2,\n            priority: 2,\n        };\n        touchLeft.setMove({\n            freely: false,\n            element: element,\n        });\n        element.move.freely = false;\n        var touchRight = container.add({\n            make: 'rectangle',\n            name: 'touchRight',\n            width: 0.001,\n            height: (o.rows - 1) * o.space + o.height + barOverhang * 2,\n            color: o.debug ? [0, 0, 0, 1] : [0, 0, 0, 0],\n            yAlign: 'middle',\n            xAlign: 'center',\n            position: [o.length + o.barWidth, ((o.rows - 1) * o.space) / 2],\n        });\n        touchRight.custom.secondaryTouchBounds = {\n            left: o.barWidth + 0.2,\n            right: 0.2,\n            top: 0.2,\n            bottom: 0.2,\n            priority: 2,\n        };\n        touchRight.setMove({\n            freely: false,\n            element: element,\n        });\n    }\n    if (o.barWidth > 0) {\n        container.add({\n            make: 'rectangle',\n            name: 'leftBar',\n            width: barWidth,\n            height: (o.rows - 1) * o.space + o.height + barOverhang * 2,\n            corner: {\n                radius: barWidth / 3,\n                sides: 10,\n            },\n            yAlign: 'middle',\n            xAlign: 'center',\n            position: [-barWidth / 2, ((o.rows - 1) * o.space) / 2],\n            color: o.debug ? [0.5, 0.5, 0.5, 0.2] : o.barColor.color,\n        });\n        container.add({\n            make: 'rectangle',\n            name: 'rightBar',\n            width: barWidth,\n            height: (o.rows - 1) * o.space + o.height + barOverhang * 2,\n            corner: {\n                radius: barWidth / 3,\n                sides: 10,\n            },\n            yAlign: 'middle',\n            xAlign: 'center',\n            position: [o.length + barWidth / 2, ((o.rows - 1) * o.space) / 2],\n            color: o.debug ? [0.5, 0.5, 0.5, 0.2] : o.barColor.color,\n        });\n    }\n    if (o.count) {\n        container.add({\n            make: 'text',\n            name: 'count',\n            text: \"\".concat(o.count.prefix, \"0\"),\n            xAlign: 'center',\n            yAlign: 'middle',\n            font: {\n                family: defaultFontFamilyMath,\n                size: o.count.size,\n            },\n            position: Fig.parsePoint(o.count.position).add(Fig.parsePoint(o.count.offset)),\n        });\n    }\n    var resetButton = null;\n    if (o.reset) {\n        var resetFont = {\n            size: o.reset.font.size,\n            family: o.reset.font.family,\n            glyphs: 'latin',\n            weight: '300',\n            render: 'gl',\n        };\n        setAtlasId(resetFont);\n        resetButton = element._container.add({\n            make: 'collections.button',\n            name: 'reset',\n            label: {\n                text: o.reset.label,\n                font: resetFont,\n                color: o.reset.color.label.color,\n            },\n            colorFill: o.reset.color.fill.color,\n            position: Fig.parsePoint([o.reset.x, o.reset.y]).add(Fig.parsePoint(o.reset.offset)),\n            xAlign: 'center',\n            width: o.reset.width,\n            height: o.reset.height,\n            corner: {\n                radius: o.reset.height / 2,\n                sides: 10,\n            },\n            line: null,\n            touchBorder: 0.05,\n        });\n        resetButton.notifications.add('onClick', function () {\n            element.reset();\n        });\n    }\n    element.reset = function (duration) {\n        if (duration === void 0) { duration = 0.5; }\n        if (o.start != null) {\n            element.showAnswer(o.start, duration, true);\n        }\n        else {\n            element.showAnswer(Array(o.rows).fill(0), duration, true);\n        }\n        element.custom.toLeftCount = 0;\n        element.custom.toRightCount = 0;\n        element.stopGroupMove();\n    };\n    element.custom.toLeftCount = 0;\n    element.custom.toRightCount = 0;\n    var allBeads = [];\n    for (var i = 0; i < o.rows; i += 1) {\n        var beads = [];\n        container.add({\n            name: \"rod\".concat(i),\n            make: 'line',\n            width: o.rod,\n            color: o.barColor.color,\n            length: o.length,\n            position: [0, (o.rows - 1) * o.space - i * o.space],\n        });\n        var _loop_1 = function (j) {\n            // const d = 1.35\n            var bead = container.add({\n                name: \"bead\".concat(i).concat(j),\n                make: 'collection',\n                elements: [\n                    {\n                        make: 'rectangle',\n                        name: 'fill',\n                        corner: {\n                            radius: o.radius,\n                            sides: o.sides,\n                        },\n                        width: o.size,\n                        height: o.height,\n                        color: j % 10 < 5 ? o.fill1.color : o.fill2.color,\n                    },\n                    {\n                        make: 'rectangle',\n                        name: 'line',\n                        corner: {\n                            radius: o.radius,\n                            sides: o.sides,\n                        },\n                        width: o.size,\n                        height: o.height,\n                        line: { width: o.lineWidth, widthIs: 'inside' },\n                        color: j % 10 < 5 ? o.line1.color : o.line2.color,\n                    },\n                ],\n                position: [\n                    o.size / 2 + o.length - o.beads * o.size + j * o.size,\n                    (o.rows - 1) * o.space - i * o.space,\n                ],\n            });\n            bead.custom.color = {\n                fill: j % 10 < 5 ? o.fill1 : o.fill2,\n                line: j % 10 < 5 ? o.line1 : o.line2,\n            };\n            if (o.muted != null && j >= o.beads - o.muted[i]) {\n                bead._fill.setColor(j % 10 < 5 ? o.fill1.muted : o.fill2.muted);\n                bead._line.setColor(j % 10 < 5 ? o.line1.muted : o.line2.muted);\n                bead.custom.color = {\n                    fill: j % 10 < 5 ? o.fill1.muted : o.fill2.muted,\n                    line: j % 10 < 5 ? o.line1.muted : o.line2.muted,\n                };\n            }\n            allBeads.push(bead);\n            var freely = {\n                bounceLoss: 1,\n                deceleration: 10000000,\n            };\n            if (o.move === 'individual') {\n                freely = {\n                    bounceLoss: 1,\n                    deceleration: o.length,\n                };\n            }\n            bead.setMove({\n                bounds: new Fig.Line([o.size / 2 + j * o.size, o.space * (o.rows - 1) - o.space * i], [\n                    o.size / 2 + o.length - (o.beads - j) * o.size,\n                    o.space * (o.rows - 1) - o.space * i,\n                ]),\n                freely: freely,\n                bounce: 0,\n            });\n            bead.moveGroup = function () {\n                var p = bead.getPosition();\n                for (var ii = 0; ii < bead.custom.group.length; ii += 1) {\n                    var b = bead.custom.group[ii];\n                    var pp = b.getPosition();\n                    if (bead.custom.groupDirection === 'right') {\n                        b.setPosition(p.x + (ii + 1) * o.size, pp.y);\n                    }\n                    if (bead.custom.groupDirection === 'left') {\n                        b.setPosition(p.x - (ii + 1) * o.size, pp.y);\n                    }\n                }\n                if (o.count) {\n                    if (o.count.style === 'left') {\n                        element._container._count.setText(\"\".concat(o.count.prefix).concat(element.getCount()));\n                    }\n                }\n            };\n            // bead.endMoveGroup = () => {\n            //   // const p = bead.getPosition();\n            //   for (let ii = 0; ii < bead.custom.group.length; ii += 1) {\n            //     const b = bead.custom.group[ii];\n            //     const pp = b.getPosition().round(2);\n            //     if (pp.x == b.custom.rightPosition) {\n            //       b.setOpacity(0.5);\n            //     } else {\n            //       b.setOpacity(1);\n            //     }\n            //   }\n            // };\n            bead.toLeft = function (velocity) {\n                if (velocity === void 0) { velocity = o.length; }\n                bead.toEnd(velocity, 'left');\n            };\n            bead.toRight = function (velocity) {\n                if (velocity === void 0) { velocity = o.length; }\n                bead.toEnd(velocity, 'right');\n            };\n            bead.toEnd = function (velocity, end) {\n                if (velocity === void 0) { velocity = o.length; }\n                if (end === void 0) { end = 'left'; }\n                var target = bead.move.bounds.boundary.p1;\n                if (end === 'right') {\n                    target = bead.move.bounds.boundary.p2;\n                }\n                var publish = end === 'right' ? 'moveRight' : 'moveLeft';\n                toAdd.animations\n                    .new()\n                    .trigger(function () {\n                    element.hasTouchableElements = false;\n                    // for (let ii = 0; ii < rows[bead.custom.row].length; ii += 1) {\n                    //   rows[bead.custom.row][ii].isTouchable = false;\n                    // }\n                })\n                    .position({\n                    element: bead,\n                    target: target,\n                    velocity: velocity,\n                    progression: 'easeout',\n                    afterFrame: function () {\n                        if (o.move === 'individual') {\n                            bead.notifications.publish(publish);\n                        }\n                        else {\n                            bead.moveGroup();\n                        }\n                    },\n                })\n                    .trigger(function () {\n                    // for (let ii = 0; ii < rows[bead.custom.row].length; ii += 1) {\n                    //   rows[bead.custom.row][ii].isTouchable = true;\n                    // }\n                    // bead.endMoveGroup()\n                    element.stopGroupMove();\n                    element.hasTouchableElements = true;\n                })\n                    .start();\n            };\n            bead.custom.rightPosition = bead.getPosition().round(2).x;\n            beads.push(bead);\n            bead.custom.secondaryTouchBounds = o.secondaryTouchBounds;\n            bead.custom.row = i;\n            bead.isLeft = function () {\n                var p = bead.getPosition();\n                return p.x < bead.custom.rightPosition;\n            };\n        };\n        for (var j = 0; j < o.beads; j += 1) {\n            _loop_1(j);\n        }\n        rows.push(beads);\n    }\n    element.stopGroupMove = function () {\n        if (o.colorRight) {\n            for (var i = 0; i < allBeads.length; i += 1) {\n                var bead = allBeads[i];\n                var x = bead.getPosition().round(2).x;\n                if (x < bead.custom.rightPosition) {\n                    // bead.setOpacity(1);\n                    bead._fill.setColor(bead.custom.color.fill.color);\n                    bead._line.setColor(bead.custom.color.line.color);\n                }\n                else {\n                    bead._fill.setColor(bead.custom.color.fill.right);\n                    bead._line.setColor(bead.custom.color.line.right);\n                }\n            }\n        }\n        if (o.count) {\n            if (o.count.style === 'left') {\n                element._container._count.setText(\"\".concat(o.count.prefix).concat(element.getCount()));\n            }\n            if (o.count.style === 'moves') {\n                var totalMoves = element.custom.toLeftCount + element.custom.toRightCount;\n                element._container._count.setText(\"\".concat(o.count.prefix).concat(totalMoves));\n            }\n            if (o.count.style === 'movesLeft') {\n                var totalMoves = element.custom.toLeftCount;\n                element._container._count.setText(\"\".concat(o.count.prefix).concat(totalMoves));\n            }\n            if (o.count.style === 'movesRight') {\n                var totalMoves = element.custom.toRightCount;\n                element._container._count.setText(\"\".concat(o.count.prefix).concat(totalMoves));\n            }\n        }\n    };\n    element.startGroupMove = function (bead, beads) {\n        if (o.colorRight) {\n            bead._fill.setColor(bead.custom.color.fill.color);\n            bead._line.setColor(bead.custom.color.line.color);\n            for (var i = 0; i < beads.length; i += 1) {\n                var bead_1 = beads[i];\n                bead_1._fill.setColor(bead_1.custom.color.fill.color);\n                bead_1._line.setColor(bead_1.custom.color.line.color);\n            }\n        }\n    };\n    var _loop_2 = function (i) {\n        var _loop_3 = function (j) {\n            var bead = rows[i][j];\n            if (o.move === 'individual') {\n                bead.notifications.add('onClick', function () {\n                    bead.custom.p = bead.getPosition();\n                    window.clickHandled = true;\n                });\n                bead.notifications.add('moved', function () {\n                    var p = bead.getPosition();\n                    if (p.x > bead.custom.p.x) {\n                        bead.notifications.publish('moveRight');\n                    }\n                    else if (p.x < bead.custom.p.x) {\n                        bead.notifications.publish('moveLeft');\n                    }\n                    bead.custom.p = bead.getPosition();\n                });\n            }\n            if (o.move === 'group') {\n                bead.notifications.add('onClick', function () {\n                    window.clickHandled = true;\n                    bead.custom.group = [];\n                    var isLeft = true;\n                    var p = bead.getPosition().round(2);\n                    if (p.x == bead.custom.rightPosition) {\n                        isLeft = false;\n                    }\n                    if (isLeft) {\n                        for (var jj = j + 1; jj < o.beads; jj += 1) {\n                            if (rows[i][jj].getPosition().x <\n                                // @ts-expect-error TS2339\n                                rows[i][jj].move.bounds.boundary.p1.x + 0.05) {\n                                bead.custom.group.push(rows[i][jj]);\n                            }\n                        }\n                    }\n                    else {\n                        for (var jj = j - 1; jj >= 0; jj -= 1) {\n                            if (rows[i][jj].getPosition().x >\n                                // @ts-expect-error TS2339\n                                rows[i][jj].move.bounds.boundary.p2.x - 0.05) {\n                                bead.custom.group.push(rows[i][jj]);\n                            }\n                        }\n                    }\n                    bead.custom.p = bead.getPosition();\n                    bead.custom.groupDirection = isLeft ? 'right' : 'left';\n                    element.startGroupMove(bead, bead.custom.group);\n                    bead.custom.startLeft = isLeft;\n                });\n                bead.notifications.add('moved', function () {\n                    var p = bead.getPosition();\n                    if (p.x > bead.custom.p.x + 0.05) {\n                        bead.custom.direction = 'right';\n                        bead.custom.p = bead.getPosition();\n                    }\n                    else if (p.x < bead.custom.p.x - 0.05) {\n                        bead.custom.direction = 'left';\n                        bead.custom.p = bead.getPosition();\n                    }\n                    bead.moveGroup();\n                });\n                bead.notifications.add('stopBeingMoved', function () {\n                    fig.answerChanged();\n                    if (bead.custom.direction === 'left') {\n                        bead.toLeft();\n                        if (!bead.custom.startLeft) {\n                            element.custom.toLeftCount += 1;\n                        }\n                    }\n                    else {\n                        bead.toRight();\n                        if (bead.custom.startLeft) {\n                            element.custom.toRightCount += 1;\n                        }\n                    }\n                    // bead.endMoveGroup()\n                    element.stopGroupMove();\n                });\n            }\n            var leftBead = j == 0 ? null : rows[i][j - 1];\n            var rightBead = j == o.beads - 1 ? null : rows[i][j + 1];\n            bead.custom.leftBead = leftBead;\n            bead.custom.rightBead = rightBead;\n            if (leftBead) {\n                leftBead.notifications.add('moveRight', function () {\n                    var p = bead.getPosition();\n                    var leftBeadP = leftBead.getPosition();\n                    if (p.x - leftBeadP.x < o.size) {\n                        bead.setPosition(leftBeadP.x + o.size, p.y);\n                        bead.notifications.publish('moveRight');\n                    }\n                });\n            }\n            if (rightBead) {\n                rightBead.notifications.add('moveLeft', function () {\n                    var p = bead.getPosition();\n                    var rightBeadP = rightBead.getPosition();\n                    if (rightBeadP.x - p.x < o.size) {\n                        bead.setPosition(rightBeadP.x - o.size, p.y);\n                        bead.notifications.publish('moveLeft');\n                    }\n                });\n            }\n        };\n        for (var j = 0; j < o.beads; j += 1) {\n            _loop_3(j);\n        }\n    };\n    for (var i = 0; i < o.rows; i += 1) {\n        _loop_2(i);\n    }\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    if (o.debug) {\n        element.add({\n            make: 'polygon',\n            radius: 0.05,\n            sides: 10,\n            position: [0, 0],\n        });\n        container.add({\n            make: 'polygon',\n            radius: 0.03,\n            color: [0, 0, 1, 1],\n            position: [0, 0],\n            sides: 10,\n        });\n    }\n    element.custom.worksWith = {\n        trash: true,\n    };\n    element.getCount = function () {\n        var count = 0;\n        for (var i = 0; i < o.rows; i += 1) {\n            for (var j = 0; j < o.beads; j += 1) {\n                var bead = rows[i][j];\n                var p = bead.getPosition();\n                // @ts-expect-error TS2339\n                if (p.x < bead.move.bounds.boundary.p1.x + 0.01) {\n                    count += 1;\n                }\n            }\n        }\n        return count;\n    };\n    element.custom.getState = function (isSlot) {\n        var p = element.getPosition();\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        var regex = new RegExp('^' + e_name);\n        var createdFrom = o.createdFrom\n            ? o.createdFrom.replace(regex, '').slice(1)\n            : null;\n        var rowsState = [];\n        var counts = [];\n        for (var i = 0; i < o.rows; i += 1) {\n            var beadsState = [];\n            var count = 0;\n            for (var j = 0; j < o.beads; j += 1) {\n                var bead = rows[i][j];\n                var p_1 = bead.getPosition();\n                // @ts-expect-error TS2339\n                if (p_1.x < bead.move.bounds.boundary.p1.x + 0.01) {\n                    beadsState.push('L');\n                    count += 1;\n                    // @ts-expect-error TS2339\n                }\n                else if (p_1.x > bead.move.bounds.boundary.p2.x - 0.01) {\n                    beadsState.push('R');\n                }\n                else {\n                    beadsState.push(p_1.round(3).x);\n                }\n            }\n            counts.push(count);\n            rowsState.push(beadsState);\n        }\n        var state = {\n            c: createdFrom,\n            e: e_name,\n            h: !element.isShown,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            r: rowsState,\n            tc: element.custom.toLeftCount + element.custom.toRightCount,\n        };\n        if (isSlot) {\n            var partial = [];\n            return {\n                full: counts,\n                partial: partial,\n                left_count: element.custom.toLeftCount,\n                right_count: element.custom.toRightCount,\n            };\n        }\n        return state;\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        element.custom.moved = true;\n        // if (stats.h) {\n        var controlElement = fig.getElement(stats.e + '.' + stats.c);\n        if (controlElement != null) {\n            controlElement.snapshot();\n        }\n        if (stats.h) {\n            element.setOpacity(0.15);\n        }\n        if (o.count && stats.tc != null) {\n            element._container._count.setText(\"\".concat(o.count.prefix).concat(stats.tc));\n        }\n        for (var i = 0; i < stats.r.length; i += 1) {\n            for (var j = 0; j < stats.r[i].length; j += 1) {\n                var bead = rows[i][j];\n                var x = stats.r[i][j];\n                var y = bead.getPosition().y;\n                if (x === 'L') {\n                    // @ts-expect-error TS2339\n                    bead.setPosition(bead.move.bounds.boundary.p1);\n                }\n                else if (x === 'R') {\n                    // @ts-expect-error TS2339\n                    bead.setPosition(bead.move.bounds.boundary.p2);\n                }\n                else {\n                    bead.setPosition(new Fig.Point(x, y));\n                }\n            }\n        }\n    };\n    element.enableBeads = function (enable) {\n        if (enable === void 0) { enable = true; }\n        for (var i = 0; i < rows.length; i += 1) {\n            for (var j = 0; j < rows[i].length; j += 1) {\n                var bead = rows[i][j];\n                bead.isTouchable = enable;\n            }\n        }\n        if (element._container._reset) {\n            element._container._reset.isTouchable = enable;\n            if (enable) {\n                element._container._reset.setOpacity(1);\n            }\n            else {\n                element._container._reset.setOpacity(0.5);\n            }\n        }\n    };\n    /**\n     * Show answer can accept:\n     * @param showIn\n     * @param duration\n     * @param enableTouch\n     */\n    element.showAnswer = function (showIn, duration, enableTouch) {\n        if (duration === void 0) { duration = 2; }\n        if (enableTouch === void 0) { enableTouch = false; }\n        if (!Array.isArray(showIn)) {\n            var show = showIn.steps;\n            element.enableBeads(false);\n            // Name every completion trigger via fnMap (owner = toAdd) so showAnswer\n            // survives speech pause/resume: it fires from an exec cue inside a speech:\n            // array, and an inline .trigger is dropped from figure.getState() — one\n            // non-serializable step drops the WHOLE builder, so a pause mid-move would\n            // freeze the beads and lose the enable/count/group-stop side-effects. These\n            // callbacks are stateless w.r.t. the loop, so shared names are safe.\n            toAdd.fnMap.add('rnrShowReset', function () {\n                element.custom.toLeftCount = 0;\n                element.custom.toRightCount = 0;\n            });\n            toAdd.fnMap.add('rnrShowGroupStop', function () {\n                element.stopGroupMove();\n            });\n            toAdd.fnMap.add('rnrShowStep', function () {\n                if (o.move === 'group') {\n                    element.custom.toLeftCount += 1;\n                    element.stopGroupMove();\n                }\n            });\n            toAdd.fnMap.add('rnrShowEnable', function () {\n                element.enableBeads();\n                element.custom.intendedTouchable = true;\n            });\n            var animations = toAdd.animations.new();\n            if (showIn.resetCount) {\n                element.custom.toLeftCount = 0;\n                element.custom.toRightCount = 0;\n            }\n            if (showIn.reset) {\n                animations = animations.trigger({ callback: 'rnrShowReset' });\n                var beadAnimations = [];\n                for (var i = 0; i < rows.length; i += 1) {\n                    for (var j = 0; j < rows[i].length; j += 1) {\n                        var bead = rows[i][j];\n                        var p = bead.getPosition().round(4);\n                        // @ts-expect-error TS2339\n                        var left = bead.move.bounds.boundary.p1.round(4);\n                        // @ts-expect-error TS2339\n                        var right = bead.move.bounds.boundary.p2.round(4);\n                        var toPos = null;\n                        if (o.start == null) {\n                            if (p.x !== right.x) {\n                                toPos = right;\n                            }\n                        }\n                        else {\n                            if (j < o.start[i] && p.x === right.x) {\n                                toPos = left;\n                            }\n                            else if (j >= o.start[i] && p.x === left.x) {\n                                toPos = right;\n                            }\n                        }\n                        if (toPos != null) {\n                            beadAnimations.push(bead.animations.position({\n                                element: bead,\n                                target: toPos,\n                                duration: duration,\n                            }));\n                        }\n                    }\n                }\n                if (beadAnimations.length > 0) {\n                    animations = animations.inParallel(beadAnimations);\n                    if (o.move === 'group') {\n                        animations = animations.trigger({ callback: 'rnrShowGroupStop' });\n                    }\n                    var delay = showIn.reset === true ? 0.5 : showIn.reset;\n                    animations = animations.delay(delay);\n                }\n            }\n            for (var k = 0; k < show.length; k += 1) {\n                var s = show[k];\n                if (Array.isArray(s)) {\n                    s = { rows: s };\n                }\n                var delay = s.delay == null ? 0.5 : s.delay;\n                var d = s.duration == null ? duration : s.duration;\n                var beadAnimations = [];\n                for (var i = 0; i < rows.length; i += 1) {\n                    for (var j = 0; j < rows[i].length; j += 1) {\n                        var bead = rows[i][j];\n                        var target = (j < s.rows[i]\n                            ? // @ts-expect-error TS2339\n                                bead.move.bounds.boundary.p1\n                            : // @ts-expect-error TS2339\n                                bead.move.bounds.boundary.p2).round(4);\n                        beadAnimations.push(bead.animations.position({\n                            element: bead,\n                            target: target,\n                            duration: d,\n                        }));\n                    }\n                }\n                animations = animations.delay(delay);\n                animations = animations.inParallel(beadAnimations);\n                animations = animations.trigger({ callback: 'rnrShowStep' });\n            }\n            if (enableTouch) {\n                animations = animations.trigger({ callback: 'rnrShowEnable' });\n            }\n            animations.start();\n        }\n        else {\n            var show = showIn;\n            element.enableBeads(false);\n            // fnMap-named trigger (owner = toAdd) so the post-move enable survives speech\n            // pause/resume; an inline .trigger would drop the whole builder. See above.\n            toAdd.fnMap.add('rnrShowEnable', function () {\n                element.enableBeads();\n                element.custom.intendedTouchable = true;\n            });\n            var beadAnimations = [];\n            for (var i = 0; i < rows.length; i += 1) {\n                for (var j = 0; j < rows[i].length; j += 1) {\n                    var bead = rows[i][j];\n                    bead.isTouchable = false;\n                    var target = (j < show[i]\n                        ? // @ts-expect-error TS2339\n                            bead.move.bounds.boundary.p1\n                        : // @ts-expect-error TS2339\n                            bead.move.bounds.boundary.p2).round(4);\n                    var p = bead.getPosition().round(4);\n                    if (target.x !== p.x) {\n                        beadAnimations.push(bead.animations.position({\n                            element: bead,\n                            target: target,\n                            duration: duration,\n                        }));\n                    }\n                }\n            }\n            var answerAnim = toAdd.animations.new().inParallel(beadAnimations);\n            if (enableTouch) {\n                answerAnim = answerAnim.trigger({ callback: 'rnrShowEnable' });\n            }\n            answerAnim.start();\n        }\n    };\n    element.makeTouchable = function (touchable) {\n        if (touchable === void 0) { touchable = true; }\n        element.custom.intendedTouchable = touchable;\n        for (var i = 0; i < rows.length; i += 1) {\n            for (var j = 0; j < rows[i].length; j += 1) {\n                var bead = rows[i][j];\n                bead.isTouchable = touchable;\n            }\n        }\n    };\n    element.makeNotTouchable = function () {\n        element.makeTouchable(false);\n    };\n    setupManipulative(element, null, o);\n    element.trash = function () {\n        element.hide();\n        element.custom.state.h = true;\n        element.notifications.publish('hidden');\n    };\n    // if (o.isTouchable) {\n    //   element.setMove({freely: false});\n    // }\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n        if (element.custom.state.h) {\n            element.hide();\n        }\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n        // element.highlightContainer();\n    });\n    element.notificationHelper.add(element, 'onClick', function () {\n        window.clickHandled = true;\n        var selector = getSelectedSelector(fig);\n        if (selector != null) {\n            element.custom.clickStart = null;\n            if (selector.custom.method === 'trash') {\n                element.trash();\n                selector.highlightWorksWith();\n                selector.checkDeselect();\n                return;\n            }\n        }\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element.name);\n        window.clickHandled = true;\n    });\n    element.unhighlight = function () { };\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition();\n    });\n    if (!o.static) {\n        element.custom.manipulativeType =\n            o.slot === false ? 'rekenrek' : 'rekenrekSlot';\n    }\n    element.custom.getBoundingRect = function (space) {\n        // const p = element.getBoundingRect(space);\n        // return new Fig.Rect(p.x, p.y, o.width, o.height);\n        return element.getBoundingRect(space);\n    };\n    element._container.custom.secondaryTouchBounds = 0.1;\n    element.setColors = function (colorStyle) {\n        if (o.barWidth > 0) {\n            container._leftBar.setColor(o.barColor[colorStyle]);\n            container._rightBar.setColor(o.barColor[colorStyle]);\n        }\n        if (resetButton) {\n            if (o.reset.color.fill[colorStyle] != null) {\n                resetButton._fill.setColor(o.reset.color.fill[colorStyle]);\n            }\n            if (o.reset.color.label[colorStyle] != null) {\n                resetButton._label.setColor(o.reset.color.label[colorStyle]);\n            }\n        }\n        for (var i = 0; i < o.rows; i += 1) {\n            container.elements[\"rod\".concat(i)].setColor(o.barColor[colorStyle]);\n            for (var j = 0; j < o.beads; j += 1) {\n                var bead = rows[i][j];\n                var fill_1 = j % 10 < 5 ? o.fill1 : o.fill2;\n                var line = j % 10 < 5 ? o.line1 : o.line2;\n                if (fill_1 != false) {\n                    bead._fill.setColor(fill_1[colorStyle]);\n                }\n                if (line != false) {\n                    bead._line.setColor(line[colorStyle]);\n                }\n            }\n        }\n    };\n    element.dim = function () {\n        element.setColors('dim');\n    };\n    element.unhighlight = function () {\n        element.setColors('color');\n    };\n    element.highlight = function () {\n        element.setColors('highlight');\n    };\n    if (o.start) {\n        element.showAnswer(o.start, 0, true);\n    }\n    if (o.move === 'group') {\n        element.stopGroupMove();\n    }\n    element.custom.disableInteraction = function () {\n        element.setColors('disabled');\n    };\n    element.custom.enableInteraction = function () {\n        element.setColors('color');\n    };\n    // After the figure-wide disableInteraction has snapshotted wasDisabled on\n    // every shown element, correct the bead/reset snapshots to reflect intent\n    // rather than whatever transient isTouchable they had when submit fired.\n    if (fig.custom.disableInteractionCallbacks) {\n        fig.custom.disableInteractionCallbacks.push(function () {\n            if (!element.custom.intendedTouchable)\n                return;\n            for (var i = 0; i < rows.length; i += 1) {\n                for (var j = 0; j < rows[i].length; j += 1) {\n                    var bead = rows[i][j];\n                    if (bead.custom.wasDisabled != null) {\n                        bead.custom.wasDisabled.isTouchable = true;\n                    }\n                }\n            }\n            if (resetButton != null && resetButton.custom.wasDisabled != null) {\n                resetButton.custom.wasDisabled.isTouchable = true;\n            }\n        });\n    }\n    return element;\n};\nexport { rekenrek, createRekenrek, RATIO, };\n","import { joinObjects } from '../tools/joinObjects';\nimport { NotificationHelper } from '../tools/notifications';\nimport { getSelectedSelector } from './manage';\nimport { setupManipulative } from './tools';\nimport { setAtlasId } from '../tools/equation';\nvar RATIO = 550 / 235;\n/**\n * The clock keeps time with an angle (in radians).\n * angle = 0 is 12 o'clock\n * angle = Math.PI / 2 12:15\n * angle = Math.PI 12:30\n * angle = Math.PI * 2 * 3 = 3 o'clock\n * angle = Math.PI * 2 * 4 = 4 o'clock\n * angle = Math.PI * 2 * 5 + Math.PI / 2 = 5:15\n *\n * The minute hand angle is 0 at horizontal to the right, and goes positive\n * in the counter-clockwise direction.\n */\nfunction minuteAngleToAngle(minuteAngle) {\n    return -minuteAngle + Math.PI / 2;\n}\nfunction minuteAngleToMinuteTime(minuteAngle) {\n    var angle = minuteAngleToAngle(minuteAngle);\n    return Fig.round((angle % (Math.PI * 2)) / (Math.PI * 2) * 60, 10);\n}\nfunction hourAngleToAngle(hourAngle) {\n    return (-hourAngle + Math.PI / 2) * 12;\n}\nfunction hourAngleToHourTime(hourAngle) {\n    var angle = hourAngleToAngle(hourAngle);\n    var hour = Fig.round(angle / (Math.PI * 2), 8);\n    if (hour >= 13) {\n        while (hour >= 13) {\n            hour = Fig.round(hour - 12, 8);\n        }\n    }\n    if (hour < 1) {\n        while (hour < 1) {\n            hour = Fig.round(hour + 12, 8);\n        }\n    }\n    return hour;\n}\nfunction angleToTime(angle) {\n    var minute = Fig.round((angle % (Math.PI * 2)) / (Math.PI * 2) * 60, 8);\n    var hour = Fig.round(angle / (Math.PI * 2), 8);\n    // Use tolerance instead of exact equality. Rounding in minuteAngleToAngle\n    // can push the angle slightly below an exact multiple of 2π (e.g. just\n    // under 6π for 3:00). Then angle % 2π yields ≈ 2π instead of ≈ 0, and\n    // dividing by 2π and multiplying by 60 gives minute ≈ 59.99999995 — close\n    // to 60 but not equal. Without the tolerance this near-60 value survives\n    // the round-trip through timeToAngle, adding an extra 2π of rotation and\n    // jumping the hour by one.\n    if (minute >= 60 - 1e-6) {\n        minute = 0;\n    }\n    if (hour >= 13) {\n        while (hour >= 13) {\n            hour -= 12;\n        }\n    }\n    if (hour < 1) {\n        while (hour < 1) {\n            hour += 12;\n        }\n    }\n    return [hour, minute];\n}\nfunction roundTime(time) {\n    var minute = time[1];\n    var hour = time[0];\n    if (minute > 59.9999) {\n        hour += 1;\n        minute = 0;\n    }\n    if (hour > 12) {\n        hour = 1;\n    }\n    return [hour, minute];\n}\nfunction timeToAngle(hourMinute) {\n    var hour = Math.floor(hourMinute[0]);\n    var minute = hourMinute[1];\n    return hour * Math.PI * 2 + minute * Math.PI * 2 / 60;\n}\nfunction angleToMinuteAngle(angle) {\n    return -angle + Math.PI / 2;\n}\nfunction angleToHourAngle(angle) {\n    // return (-angle + Math.PI / 2) / Math.PI / 2;\n    return -((angle / Math.PI / 2) * Math.PI / 6) + Math.PI / 2;\n}\nfunction addMinutesToTime(time, minutes) {\n    var h = Math.floor(time[0]);\n    var m = time[1] + minutes;\n    while (m < 0) {\n        m += 60;\n        h -= 1;\n    }\n    while (m >= 60) {\n        m -= 60;\n        h += 1;\n    }\n    while (h < 1) {\n        h += 12;\n    }\n    while (h > 12) {\n        h -= 12;\n    }\n    return [h, m];\n}\nfunction getColor(option, colorName) {\n    if (Array.isArray(colorName)) {\n        return colorName;\n    }\n    if (option[colorName] == null) {\n        return option.color;\n    }\n    return option[colorName];\n}\nfunction createClock(fig, eqn_name, toElement, o, boundMove) {\n    var newO = Fig.joinObjects({}, o, {\n        name: o.name,\n        // scale: o.createScale,\n        fromPalette: true,\n        boundMove: boundMove,\n    });\n    // element.custom.count += 1;\n    var to = toElement;\n    if (to == null) {\n        to = eqn_name;\n    }\n    return clock(to, newO, fig);\n}\nvar clock = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        static: {\n            minuteHand: {\n                isTouchable: false,\n                controlsHour: false,\n            },\n            hourHand: {\n                isTouchable: false,\n            },\n        },\n        small: {\n            radius: 0.4,\n            minuteHand: {\n                isTouchable: false,\n                length: 0.65,\n                arrow: {\n                    width: 0.04,\n                },\n            },\n            hourHand: {\n                isTouchable: false,\n                length: 0.4,\n                arrow: {\n                    width: 0.05,\n                },\n            },\n            minuteLabels: false,\n            minuteTicks: {\n                length: 0.05,\n                width: 0.008,\n                // color: [0.6, 0.6, 0.6, 1],\n            },\n            space: 0,\n            hourTicks: {\n                length: 0.08,\n                width: 0.02,\n                // color: [0.4, 0.4, 0.4, 1],\n                style: 'line',\n            },\n            hourLabels: {\n                fontSize: 0.18,\n                offset: -0.2,\n                // color: [0.4, 0.4, 0.4, 1],\n            },\n        },\n        HoursOnly: {\n            minuteHand: {\n                isTouchable: false,\n                controlsHour: false,\n            },\n            hourHand: {\n                isTouchable: true,\n            },\n        },\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        radius: 1,\n        fontSize: 0.01,\n        minuteHand: true,\n        hourHand: true,\n        line1: true,\n        line2: true,\n        lineWidth: 0.005,\n        baseline: 'bottom',\n        hourTicks: true,\n        minuteTicks: true,\n        hourLabels: true,\n        space: 0,\n        center: true,\n        markerLines: true,\n        arc: true,\n        slot: false,\n        border: true,\n        fill: true,\n        helper: false,\n    }, styleDefaults, options);\n    // console.log(options)\n    if (o.border !== false) {\n        o.border = Fig.joinObjects({\n            color: [0.8, 0.8, 0.8, 1],\n            width: o.lineWidth,\n        }, o.border === true ? {} : o.border);\n    }\n    if (o.fill !== false) {\n        o.fill = Fig.joinObjects({\n            color: [1, 1, 1, 1],\n        }, o.fill === true ? {} : o.fill);\n    }\n    if (o.hourTicks !== false) {\n        o.hourTicks = Fig.joinObjects({\n            color: [0.4, 0.4, 0.4, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            correct: figure.custom.colorCorrect,\n            incorrect: figure.custom.colorIncorrect,\n            pulse: [0, 0, 1, 1],\n            correctness: false,\n            length: 0.05,\n            width: o.lineWidth * 2,\n            step: 1,\n            style: 'line',\n        }, o.hourTicks === true ? {} : o.hourTicks);\n    }\n    if (o.hourLabels !== false) {\n        o.hourLabels = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            helper: [0, 0, 1, 1],\n            correct: figure.custom.colorCorrect,\n            incorrect: figure.custom.colorIncorrect,\n            pulse: [0, 0, 1, 1],\n            correctness: false,\n            fontSize: 0.15,\n            step: o.hourTicks != false ? o.hourTicks.step : 1,\n            offset: -0.15,\n        }, o.hourLabels === true ? {} : o.hourLabels);\n    }\n    if (o.minuteTicks !== false) {\n        o.minuteTicks = Fig.joinObjects({\n            color: [0.6, 0.6, 0.6, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            correct: figure.custom.colorCorrect,\n            incorrect: figure.custom.colorIncorrect,\n            pulse: [0, 0, 1, 1],\n            correctness: false,\n            length: 0.03,\n            width: o.lineWidth * 1,\n            step: 1,\n        }, o.minuteTicks === true ? {} : o.minuteTicks);\n    }\n    if (o.minuteLabels !== false) {\n        o.minuteLabels = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            correct: figure.custom.colorCorrect,\n            incorrect: figure.custom.colorIncorrect,\n            pulse: [0, 0, 1, 1],\n            correctness: false,\n            fontSize: 0.08,\n            step: 5,\n            offset: 0.1,\n        }, o.minuteLabels === true ? {} : o.minuteLabels);\n    }\n    if (o.center !== false) {\n        o.center = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            highlight: [0.8, 0.8, 0.8, 1],\n            pulse: [0, 0, 1, 1],\n            radius: 0.04,\n            sides: 20,\n        }, o.center === true ? {} : o.center);\n    }\n    if (o.arc !== false) {\n        o.arc = Fig.joinObjects({\n            color: [0, 0, 1, 0.3],\n            radius: o.radius,\n        }, o.arc === true ? {} : o.arc);\n    }\n    if (o.markerLines !== false) {\n        o.markerLines = Fig.joinObjects({\n            color: [0, 0, 1, 1],\n            dash: [0.1, 0.01],\n            width: 0.01,\n            radius: o.radius * 1.1,\n        }, o.markerLines === true ? {} : o.markerLines);\n    }\n    if (o.minuteHand !== false) {\n        o.minuteHand = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            correct: [40 / 255, 167 / 255, 69 / 255, 1],\n            incorrect: [244 / 255, 52 / 255, 4 / 255, 1],\n            pulse: [0, 0, 1, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            width: 0.03,\n            length: 0.75,\n            isTouchable: false,\n            controlsHour: false,\n            arrow: false,\n            // start: 10,\n        }, o.minuteHand === true ? {} : o.minuteHand);\n    }\n    if (o.hourHand !== false) {\n        o.hourHand = Fig.joinObjects({\n            color: [0.2, 0.2, 0.2, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            correct: [40 / 255, 167 / 255, 69 / 255, 1],\n            incorrect: [244 / 255, 52 / 255, 4 / 255, 1],\n            highlight: [0.1, 0.1, 0.1, 1],\n            pulse: [0, 0, 1, 1],\n            width: 0.05,\n            length: 0.4,\n            isTouchable: false,\n            arrow: false,\n            // start: 10,\n        }, o.hourHand === true ? {} : o.hourHand);\n    }\n    // console.log(o)\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    element.custom.helper = o.helper;\n    element.notificationHelper = new NotificationHelper();\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [\n            o.radius,\n            o.baseline == 'bottom' ? o.radius : 0,\n        ],\n    });\n    element.custom.subslots = [];\n    var fill = null;\n    \"\";\n    if (o.fill) {\n        fill = container.add({\n            make: 'polygon',\n            name: 'fill',\n            radius: o.radius,\n            color: o.fill.color,\n            sides: 200,\n            position: [0, 0],\n        });\n    }\n    if (o.border) {\n        container.add({\n            make: 'polygon',\n            name: 'border',\n            radius: o.radius + o.border.width / 2,\n            color: o.border.color,\n            line: {\n                width: o.border.width,\n                // widthIs: 'inside',\n            },\n            sides: 200,\n            position: [0, 0],\n        });\n    }\n    if (o.markerLines != false) {\n        for (var i = 0; i < 2; i += 1) {\n            var line = container.add({\n                make: 'line',\n                name: \"markerLine\".concat(i),\n                color: o.markerLines.color,\n                position: [0, 0],\n                angle: 0,\n                length: o.markerLines.radius,\n                width: o.markerLines.width,\n                dash: o.markerLines.dash,\n            });\n            line.hide();\n        }\n        element.setMarkerLine = function (line, minute) {\n            var angle = angleToMinuteAngle(timeToAngle([1, minute]));\n            container.elements[\"markerLine\".concat(line)].show();\n            container.elements[\"markerLine\".concat(line)].setRotation(angle);\n        };\n        element.hideMarkerLine = function (line) {\n            container.elements[\"markerLine\".concat(line)].hide();\n        };\n        element.hideMarkerLines = function () {\n            for (var i = 0; i < 2; i += 1) {\n                container.elements[\"markerLine\".concat(i)].hide();\n            }\n        };\n    }\n    var arc = null;\n    if (o.arc !== false) {\n        arc = container.add({\n            make: 'arc',\n            name: 'arc',\n            color: o.arc.color,\n            fillCenter: true,\n            startAngle: Math.PI / 2,\n            position: [0, 0],\n            angle: Math.PI / 10,\n            radius: o.arc.radius,\n            sides: 100,\n        });\n        arc.hide();\n        element.setArc = function (setArcOptions) {\n            var startAngle;\n            var endAngle;\n            if (setArcOptions.followHour) {\n                startAngle = angleToHourAngle(timeToAngle(setArcOptions.startTime));\n                endAngle = angleToHourAngle(timeToAngle(setArcOptions.endTime));\n            }\n            else {\n                var end = setArcOptions.endMinute;\n                var start = setArcOptions.startMinute;\n                if (start > end) {\n                    end += 60;\n                }\n                startAngle = angleToMinuteAngle(timeToAngle([1, start]));\n                endAngle = angleToMinuteAngle(timeToAngle([1, end]));\n            }\n            arc.show();\n            arc.custom.updatePoints({\n                angle: Math.abs(endAngle - startAngle),\n                startAngle: endAngle\n            });\n        };\n        element.hideArc = function () {\n            arc.hide();\n        };\n    }\n    if (o.minuteTicks !== false) {\n        for (var i = 0; i < 60; i += o.minuteTicks.step) {\n            var angle = Math.PI / 2 - (i * 6) * Math.PI / 180;\n            var length_1 = o.radius * o.minuteTicks.length;\n            var r = o.radius * (1 - o.space) - length_1 / 2;\n            var m = container.add({\n                make: 'rectangle',\n                name: i > 0 ? \"minute\".concat(i) : 'minute60',\n                // width: o.minuteTicks.width,\n                // angle,\n                // width: 0.001,\n                height: length_1,\n                width: o.minuteTicks.width * o.radius,\n                color: o.minuteTicks.color,\n                position: [\n                    r * Math.cos(angle),\n                    r * Math.sin(angle),\n                ],\n            });\n            m.setRotation(angle + Math.PI / 2);\n        }\n    }\n    if (o.hourTicks !== false) {\n        for (var i = 0; i < 12; i += o.hourTicks.step) {\n            var angle = Math.PI / 2 - (i * 30) * Math.PI / 180;\n            var length_2 = o.radius * o.hourTicks.length;\n            var r = o.radius * (1 - o.space);\n            if (o.hourTicks.style === 'circle') {\n                container.add({\n                    make: 'polygon',\n                    name: i > 0 ? \"hour\".concat(i) : 'hour12',\n                    angle: angle,\n                    // width: o.hourTicks.width,\n                    // length,\n                    radius: length_2 / 2,\n                    sides: 30,\n                    color: o.hourTicks.color,\n                    position: [\n                        r * Math.cos(angle),\n                        r * Math.sin(angle),\n                    ],\n                });\n            }\n            else if (o.hourTicks.style === 'line') {\n                var angle_1 = Math.PI / 2 - (i * 30) * Math.PI / 180;\n                var length_3 = o.radius * o.hourTicks.length;\n                var r_1 = o.radius * (1 - o.space) - length_3 / 2;\n                var m = container.add({\n                    make: 'rectangle',\n                    name: i > 0 ? \"hour\".concat(i) : 'hour12',\n                    height: length_3,\n                    width: o.hourTicks.width * o.radius,\n                    color: o.hourTicks.color,\n                    position: [\n                        r_1 * Math.cos(angle_1),\n                        r_1 * Math.sin(angle_1),\n                    ],\n                });\n                m.setRotation(angle_1 + Math.PI / 2);\n            }\n        }\n    }\n    if (o.hourLabels !== false) {\n        var hourFont = {\n            size: o.hourLabels.fontSize * o.radius,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n        };\n        setAtlasId(hourFont);\n        for (var i = 0; i < 12; i += o.hourLabels.step) {\n            var angle = Math.PI / 2 - (i * 30) * Math.PI / 180;\n            var r = ((1 - o.space) + o.hourLabels.offset) * o.radius;\n            container.add({\n                make: 'text',\n                name: i > 0 ? \"hourLabel\".concat(i) : 'hourLabel12',\n                text: i > 0 ? \"\".concat(i) : '12',\n                color: o.hourLabels.color,\n                position: [\n                    r * Math.cos(angle),\n                    r * Math.sin(angle),\n                ],\n                xAlign: 'center',\n                yAlign: 'middle',\n                font: hourFont,\n            });\n        }\n    }\n    if (o.minuteLabels !== false) {\n        var minuteFont = {\n            size: o.minuteLabels.fontSize * o.radius,\n            render: 'gl',\n        };\n        setAtlasId(minuteFont);\n        for (var i = 0; i < 60; i += o.minuteLabels.step) {\n            var angle = Math.PI / 2 - (i * 6) * Math.PI / 180;\n            var r = ((1 - o.space) + o.minuteLabels.offset) * o.radius;\n            container.add({\n                make: 'text',\n                name: i > 0 ? \"minuteLabel\".concat(i) : 'minuteLabel60',\n                text: i > 0 ? \"\".concat(i) : '60',\n                color: o.minuteLabels.color,\n                position: [\n                    r * Math.cos(angle),\n                    r * Math.sin(angle),\n                ],\n                xAlign: 'center',\n                yAlign: 'middle',\n                font: minuteFont,\n            });\n        }\n    }\n    var hourHand = null;\n    var hourHandMover = null;\n    if (o.hourHand !== false) {\n        // let start = 0;\n        // if (o.hourHand.start !== null) {\n        //   start = o.hourHand.start;\n        // }\n        // console.log(\"Hour hand\", start, hourToAngle(start) * 180 / Math.PI);\n        var arrow = null;\n        var length_4 = o.hourHand.length;\n        if (o.hourHand.arrow) {\n            arrow = {\n                end: joinObjects({\n                    width: o.hourHand.width * 2,\n                    head: 'triangle',\n                }, o.hourHand.arrow === true ? {} : o.hourHand.arrow),\n            };\n            // console.log(arrow)\n            length_4 = o.hourHand.length - o.hourHand.width;\n        }\n        hourHand = container.add({\n            make: 'collection',\n            name: 'hourHand',\n            elements: [\n                {\n                    name: 'line',\n                    make: 'line',\n                    color: o.hourHand.color,\n                    position: [0, 0],\n                    angle: 0,\n                    length: length_4 * o.radius,\n                    width: o.hourHand.width * o.radius,\n                }\n            ],\n            // arrow: arrow,\n        });\n        if (arrow) {\n            hourHand.add({\n                make: 'line',\n                name: 'arrow',\n                color: o.hourHand.color,\n                position: [0, 0],\n                angle: 0,\n                length: o.hourHand.length * o.radius,\n                width: o.hourHand.width * o.radius,\n                arrow: arrow,\n            });\n        }\n        element.custom.subslots.push(hourHand);\n        // hourHand.setRotation(hourToAngle(start));\n        if (o.hourHand.isTouchable) {\n            hourHandMover = container.add({\n                make: 'line',\n                name: 'hourHandMover',\n                color: [1, 0, 0, o.debug ? 0.1 : 0],\n                position: [0, 0],\n                angle: 0,\n                length: o.hourHand.length * o.radius,\n                width: 0.3,\n                move: {\n                    type: 'rotation',\n                    freely: false,\n                }\n            });\n            hourHandMover.notifications.add('stopBeingMoved', function () {\n                if (o.hourHand.snap) {\n                    var snapNum = 12;\n                    if (typeof o.hourHand.snap === 'number') {\n                        snapNum = o.hourHand.snap;\n                    }\n                    var hourAngle = Fig.round(hourHandMover.getRotation() / (Math.PI * 2) * snapNum, 0) / snapNum * Math.PI * 2;\n                    hourHandMover.setRotation(hourAngle);\n                }\n            });\n            hourHandMover.notifications.add('startBeingMoved', function () {\n                hourHand.setColor(o.hourHand.color);\n            });\n            hourHandMover.notifications.add('setTransform', function () {\n                if (hourHandMover.custom.moving) {\n                    return;\n                }\n                hourHandMover.custom.moving = true;\n                var hourAngle = hourHandMover.getRotation();\n                var angle = hourAngleToAngle(hourAngle);\n                element.custom.time = angleToTime(angle);\n                if (o.hourHand.controlsMinute) {\n                    element.setTime(element.custom.time);\n                }\n                else {\n                    if (o.hourHand.snap) {\n                        var snapNum = 12;\n                        if (typeof o.hourHand.snap === 'number') {\n                            snapNum = o.hourHand.snap;\n                        }\n                        var snapAngle = Fig.round(hourHandMover.getRotation() / (Math.PI * 2) * snapNum, 0) / snapNum * Math.PI * 2;\n                        hourHand.setRotation(snapAngle);\n                    }\n                    else {\n                        hourHand.setRotation(hourHandMover.getRotation());\n                    }\n                }\n                hourHandMover.custom.moving = false;\n            });\n            hourHand.notifications.add('setTransform', function () {\n                if (element.custom.helper) {\n                    var thisHour = Math.floor(Fig.round(hourAngleToHourTime(hourHand.getRotation()), 3));\n                    var lastHour = element.custom.lastHour || thisHour;\n                    lastHour = lastHour % 12;\n                    if (lastHour === 0) {\n                        lastHour = 12;\n                    }\n                    thisHour = thisHour % 12;\n                    if (thisHour === 0) {\n                        thisHour = 12;\n                    }\n                    if (lastHour !== thisHour) {\n                        element.unhighlightHour(lastHour, 0.2);\n                        element.highlightHour(thisHour, 'helper', 1, 1.7, 0.2);\n                    }\n                    element.custom.lastHour = thisHour;\n                }\n            });\n        }\n    }\n    var minuteHand = null;\n    var minuteHandMover = null;\n    if (o.minuteHand !== false) {\n        // let start = 0;\n        // if (o.start !== null) {\n        //   start = o.start;\n        // }\n        var arrow = null;\n        var length_5 = o.minuteHand.length;\n        if (o.minuteHand.arrow) {\n            arrow = {\n                end: joinObjects({\n                    width: o.minuteHand.width * 2,\n                    head: 'triangle',\n                }, o.minuteHand.arrow === true ? {} : o.minuteHand.arrow),\n            };\n            length_5 = o.minuteHand.length - o.minuteHand.width;\n        }\n        minuteHand = container.add({\n            make: 'collection',\n            name: 'minuteHand',\n            elements: [\n                {\n                    name: 'line',\n                    make: 'line',\n                    color: o.minuteHand.color,\n                    position: [0, 0],\n                    angle: 0,\n                    length: length_5 * o.radius,\n                    width: o.minuteHand.width * o.radius,\n                }\n            ],\n        });\n        if (arrow) {\n            minuteHand.add({\n                make: 'line',\n                name: 'arrow',\n                color: o.minuteHand.color,\n                position: [0, 0],\n                angle: 0,\n                length: o.minuteHand.length * o.radius,\n                width: o.minuteHand.width * o.radius,\n                arrow: arrow,\n            });\n        }\n        element.custom.subslots.push(minuteHand);\n        if (o.minuteHand.isTouchable) {\n            minuteHandMover = container.add({\n                make: 'line',\n                name: 'minuteHandMover',\n                color: [0, 0, 1, o.debug ? 0.1 : 0],\n                position: [0, 0],\n                angle: 0,\n                length: o.minuteHand.length * o.radius,\n                width: 0.3,\n                move: {\n                    type: 'rotation',\n                    freely: false,\n                }\n            });\n            minuteHandMover.notifications.add('stopBeingMoved', function () {\n                if (o.minuteHand.snap) {\n                    var delta = o.minuteHand.snap === 'hour' ? 12 : 60;\n                    var minuteAngle = Fig.round(minuteHandMover.getRotation() / (Math.PI * 2) * delta, 0) / delta * Math.PI * 2;\n                    minuteHandMover.setRotation(minuteAngle);\n                }\n            });\n            minuteHandMover.notifications.add('startBeingMoved', function () {\n                minuteHand.setColor(o.hourHand.color);\n            });\n            minuteHandMover.notifications.add('setTransform', function () {\n                if (minuteHandMover.custom.moving) {\n                    return;\n                }\n                minuteHandMover.custom.moving = true;\n                var minuteAngle = minuteHandMover.getRotation();\n                var angle = minuteAngleToAngle(minuteAngle);\n                element.custom.time = angleToTime(angle);\n                if (o.minuteHand.controlsHour) {\n                    element.setTime(element.custom.time);\n                }\n                else {\n                    if (o.minuteHand.snap) {\n                        var delta = o.minuteHand.snap === 'hour' ? 12 : 60;\n                        var snapAngle = Fig.round(minuteHandMover.getRotation() / (Math.PI * 2) * delta, 0) / delta * Math.PI * 2;\n                        minuteHand.setRotation(snapAngle);\n                    }\n                    else {\n                        minuteHand.setRotation(minuteHandMover.getRotation());\n                    }\n                }\n                minuteHandMover.custom.moving = false;\n            });\n        }\n    }\n    if (o.center !== false) {\n        container.add({\n            make: 'polygon',\n            name: 'center',\n            radius: o.center.radius * o.radius,\n            color: o.center.color,\n            sides: o.center.sides,\n            position: [0, 0],\n        });\n    }\n    element.setTime = function (hourMinute) {\n        // Round before floor to avoid floating-point errors (e.g. 4.99999999 → 4)\n        var hour = Math.floor(Math.round(hourMinute[0] * 1e6) / 1e6);\n        var minute = hourMinute[1];\n        if (minute < 0) {\n            while (minute < 0) {\n                minute += 60;\n            }\n        }\n        var angle = timeToAngle([hour, minute]);\n        // console.log(hourMinute, hour, minute, angle)\n        element.custom.time = [hour, minute];\n        if (minuteHandMover != null) {\n            minuteHandMover.custom.moving = true;\n            minuteHandMover.setRotation(angleToMinuteAngle(angle));\n            minuteHandMover.custom.moving = false;\n        }\n        if (minuteHand != null) {\n            minuteHand.setRotation(angleToMinuteAngle(angle));\n        }\n        if (hourHandMover != null) {\n            hourHandMover.custom.moving = true;\n            // console.log('set', hourMinute, [hour, minute], angle, angleToHourAngle(angle));\n            hourHandMover.setRotation(angleToHourAngle(angle));\n            hourHandMover.custom.moving = false;\n        }\n        if (hourHand != null) {\n            hourHand.setRotation(angleToHourAngle(angle));\n        }\n    };\n    element.colorHourHand = function (color) {\n        if (hourHand != null) {\n            hourHand.setColor(color);\n        }\n    };\n    element.colorMinuteHand = function (color) {\n        if (minuteHand != null) {\n            minuteHand.setColor(color);\n        }\n    };\n    element.setTime(o.start);\n    element.goToTime = function (hourMinute, options) {\n        if (options === void 0) { options = {}; }\n        var gtto = joinObjects({\n            velocity: 0.75,\n            direction: 'shortest',\n        }, options);\n        if (options.arc) {\n            gtto.arc = Fig.joinObjects({\n                hour: false,\n            }, options.arc);\n        }\n        if (o.minuteHand.controlsHour || o.hourHand.controlsMinute) {\n            var startAngle_1 = timeToAngle(element.custom.time);\n            var targetAngle = timeToAngle(hourMinute);\n            var delta_1 = targetAngle - startAngle_1;\n            if (gtto.direction === 'clockwise') {\n                if (targetAngle < startAngle_1) {\n                    delta_1 = targetAngle + 12 * Math.PI * 2 - startAngle_1;\n                }\n            }\n            else if (gtto.direction === 'counter-clockwise') {\n                if (targetAngle > startAngle_1) {\n                    delta_1 = targetAngle - 12 * Math.PI * 2 - startAngle_1;\n                }\n            }\n            else if (gtto.direction === 'shortest') {\n                if (targetAngle > startAngle_1 && delta_1 > Math.PI * 2 * 6) {\n                    delta_1 = targetAngle - 12 * Math.PI * 2 - startAngle_1;\n                }\n                else if (targetAngle < startAngle_1 && delta_1 < -Math.PI * 2 * 6) {\n                    delta_1 = targetAngle + 12 * Math.PI * 2 - startAngle_1;\n                }\n            }\n            var d = gtto.duration;\n            if (d == null) {\n                d = Math.abs(delta_1) / (Math.PI * 2) / gtto.velocity;\n            }\n            element.fnMap.add('goToTimeCallback', function (p) {\n                // const percent = p < 0.5 ? 4 * p * p * p : 1 - Math.pow(-2 * p + 2, 3) / 2;\n                // const percent = -(Math.cos(Math.PI * p) - 1) / 2;\n                var percent = p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2;\n                var a = delta_1 * percent + startAngle_1;\n                element.setTime(angleToTime(a));\n                if (gtto.arc) {\n                    if (gtto.arc.hour === false) {\n                        element.setArc({\n                            startMinute: gtto.arc.start == null ? angleToTime(startAngle_1)[1] : gtto.arc.start,\n                            endMinute: element.custom.time[1],\n                            followHour: false,\n                        });\n                    }\n                    else {\n                        element.setArc({\n                            startTime: gtto.arc.start == null ? angleToTime(startAngle_1) : gtto.arc.start,\n                            endTime: element.custom.time,\n                            followHour: true,\n                        });\n                    }\n                }\n            });\n            element.fnMap.add('goToTimeFinishedCallback', function () {\n                element.notifications.publish('goToTimeFinished');\n            });\n            element.fnMap.add('goToTimeStartCallback', function () {\n                element.notifications.publish('goToTimeStart');\n            });\n            element.animations.new('GoToTime')\n                .trigger({ callback: 'goToTimeStartCallback' })\n                .custom({\n                callback: 'goToTimeCallback',\n                duration: d,\n            })\n                .trigger({ callback: 'goToTimeFinishedCallback' })\n                .start();\n        }\n        else {\n            var angle = timeToAngle(hourMinute);\n            var targetAngleM = angleToMinuteAngle(angle) % (Math.PI * 2);\n            var targetAngleH = angleToHourAngle(angle);\n            var d = gtto.duration;\n            var deltaM_1 = 0;\n            var deltaH_1 = 0;\n            var startAngleM_1 = 0;\n            var startAngleH_1 = 0;\n            if (minuteHand) {\n                startAngleM_1 = minuteHand.getRotation() % (Math.PI * 2);\n                deltaM_1 = targetAngleM - startAngleM_1;\n            }\n            if (hourHand) {\n                startAngleH_1 = hourHand.getRotation();\n                deltaH_1 = targetAngleH - startAngleH_1;\n            }\n            if (d == null) {\n                d = Math.max(Math.abs(deltaM_1) / (Math.PI * 2) / gtto.velocity, Math.abs(deltaH_1) / (Math.PI * 2) / gtto.velocity);\n            }\n            element.fnMap.add('goToTimeCallback', function (p) {\n                var percent = p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2;\n                // const a = delta * percent + startAngle;\n                if (minuteHand) {\n                    minuteHand.setRotation(deltaM_1 * percent + startAngleM_1);\n                }\n                if (hourHand) {\n                    hourHand.setRotation(deltaH_1 * percent + startAngleH_1);\n                }\n                // minuteHand.setRotation(deltaM * percent + startAngleM)\n                // hourHand.setRotation(deltaH * percent + startAngleH)\n            });\n            element.fnMap.add('setTimeTrigger', function () {\n                element.setTime(hourMinute);\n            });\n            element.animations.new()\n                .custom({\n                callback: 'goToTimeCallback',\n                duration: d,\n            })\n                .trigger({ callback: 'setTimeTrigger' })\n                .start();\n        }\n    };\n    // element.reset = (duration: number = 0.5) => {\n    //   // if (o.start != null) {\n    //   //   element.showAnswer(o.start, duration, true);\n    //   // } else {\n    //   //   element.showAnswer(Array(o.rows).fill(0), duration, true);\n    //   // }\n    //   // element.custom.toLeftCount = 0;\n    //   // element.custom.toRightCount = 0;\n    //   // element.stopGroupMove();\n    // };\n    // element.highlight()\n    // True if block is snapped in position to a slot\n    element.custom.isSnapped = false;\n    if (o.debug) {\n        element.add({\n            make: 'polygon',\n            radius: 0.05,\n            sides: 10,\n            position: [0, 0],\n        });\n        container.add({\n            make: 'polygon',\n            radius: 0.03,\n            color: [0, 0, 1, 1],\n            position: [0, 0],\n            sides: 10,\n        });\n        container.add({\n            make: 'polygon',\n            name: 'debugPoint',\n            radius: 0.05,\n            sides: 10,\n            position: [0, 0],\n            color: [0, 0, 1, 1],\n        });\n    }\n    element.custom.worksWith = {\n        trash: true,\n    };\n    element.getTime = function () {\n        return [5, 40];\n    };\n    element.custom.getState = function (isSlot) {\n        var p = element.getPosition();\n        var e_name;\n        if (typeof eqn_name === 'string') {\n            e_name = eqn_name;\n        }\n        else {\n            e_name = eqn_name.getPath();\n        }\n        var regex = new RegExp('^' + e_name);\n        var createdFrom = o.createdFrom\n            ? o.createdFrom.replace(regex, '').slice(1)\n            : null;\n        var mh = minuteHand != null ? Fig.round(minuteAngleToMinuteTime(minuteHand.getRotation()), 5) : 0;\n        if (mh === 60) {\n            mh = 0;\n        }\n        var hh = hourHand != null ? Fig.round(hourAngleToHourTime(hourHand.getRotation()), 7) : 0;\n        if (hh === 0) {\n            hh = 12;\n        }\n        var state = {\n            c: createdFrom,\n            e: e_name,\n            h: !element.isShown,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            mh: minuteHand != null ? Fig.round(minuteHand.getRotation(), 10) : 0,\n            hh: hourHand != null ? Fig.round(hourHand.getRotation(), 10) : 0,\n            t: element.custom.time\n        };\n        if (isSlot) {\n            var partial = [];\n            return {\n                full: { hour: hh, minute: mh, time: element.custom.time },\n                partial: partial,\n            };\n        }\n        return state;\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        element.custom.moved = true;\n        // if (stats.h) {\n        var controlElement = fig.getElement(stats.e + '.' + stats.c);\n        if (controlElement != null) {\n            controlElement.snapshot();\n        }\n        if (stats.h) {\n            element.setOpacity(0.15);\n        }\n        // SET STATE HERE\n        element.setTime(stats.t);\n        if (minuteHand) {\n            minuteHand.transform.updateRotation(stats.mh);\n        }\n        if (hourHand) {\n            hourHand.transform.updateRotation(stats.hh);\n        }\n    };\n    /**\n     * Show answer can accept:\n     * @param showIn\n     * @param duration\n     * @param enableTouch\n     */\n    element.showAnswer = function (showIn, velocity, enableTouch) {\n        if (velocity === void 0) { velocity = 0.75; }\n        if (enableTouch === void 0) { enableTouch = false; }\n        if (Array.isArray(showIn)) {\n            element.goToTime(showIn, { direction: 'shortest', velocity: velocity });\n        }\n        else {\n            element.goToTime(showIn.time, { direction: 'shortest', velocity: velocity });\n        }\n    };\n    element.makeTouchable = function (touchable) {\n        if (touchable === void 0) { touchable = true; }\n        // minuteHand.isTouchable = touchable;\n        // hourHand.isTouchable = touchable;\n    };\n    element.makeNotTouchable = function () {\n        element.makeTouchable(false);\n    };\n    setupManipulative(element, null, o);\n    element.trash = function () {\n        element.hide();\n        element.custom.state.h = true;\n        element.notifications.publish('hidden');\n    };\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n        if (element.custom.state.h) {\n            element.hide();\n        }\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition();\n    });\n    element.notificationHelper.add(element, 'onClick', function () {\n        window.clickHandled = true;\n        var selector = getSelectedSelector(fig);\n        if (selector != null) {\n            element.custom.clickStart = null;\n            if (selector.custom.method === 'trash') {\n                element.trash();\n                selector.highlightWorksWith();\n                selector.checkDeselect();\n                return;\n            }\n        }\n        element.custom.clickStart = performance.now();\n        element.startBeingMoved();\n        element.parent.toFront(element.name);\n        window.clickHandled = true;\n    });\n    element.unhighlight = function () { };\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition();\n    });\n    if (!o.static) {\n        element.custom.manipulativeType =\n            o.slot === false ? 'clock' : 'clockSlot';\n    }\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    element._container.custom.secondaryTouchBounds = 0.1;\n    element.resetColors = function () {\n        element.setColors('color');\n    };\n    element.setColors = function (colorStyle, except, duration) {\n        if (colorStyle === void 0) { colorStyle = 'color'; }\n        if (except === void 0) { except = []; }\n        if (duration === void 0) { duration = 0; }\n        if (minuteHand && o.minuteHand[colorStyle] && !except.includes('minuteHand')) {\n            if (duration == 0) {\n                minuteHand.setColor(o.minuteHand[colorStyle]);\n            }\n            else {\n                minuteHand.animations.new().color({\n                    target: o.minuteHand[colorStyle],\n                    duration: duration,\n                }).start();\n            }\n        }\n        if (hourHand && o.hourHand[colorStyle] && !except.includes('hourHand')) {\n            if (duration == 0) {\n                hourHand.setColor(o.hourHand[colorStyle]);\n            }\n            else {\n                hourHand.animations.new().color({\n                    target: o.hourHand[colorStyle],\n                    duration: duration,\n                }).start();\n            }\n        }\n        for (var i = 0; i < 12; i += o.hourTicks.step) {\n            var hourTick = container.get(\"hour\".concat(i + 1));\n            if (hourTick && o.hourTicks[colorStyle]) {\n                if (duration == 0) {\n                    hourTick.setColor(o.hourTicks[colorStyle]);\n                }\n                else {\n                    hourTick.animations.new().color({\n                        target: o.hourTicks[colorStyle],\n                        duration: duration,\n                    }).start();\n                }\n            }\n        }\n        for (var i = 0; i < 60; i += o.minuteTicks.step) {\n            var minuteTick = container.get(\"minute\".concat(i + 1));\n            if (minuteTick && o.minuteTicks[colorStyle]) {\n                if (duration == 0) {\n                    minuteTick.setColor(o.minuteTicks[colorStyle]);\n                }\n                else {\n                    minuteTick.animations.new().color({\n                        target: o.minuteTicks[colorStyle],\n                        duration: duration,\n                    }).start();\n                }\n            }\n        }\n        if (!except.includes('hourLabels')) {\n            for (var i = 0; i < 12; i += o.hourTicks.step) {\n                var hourLabel = container.get(\"hourLabel\".concat(i + 1));\n                if (hourLabel && o.hourLabels[colorStyle]) {\n                    if (duration == 0) {\n                        hourLabel.setColor(o.hourLabels[colorStyle]);\n                    }\n                    else {\n                        hourLabel.animations.new().color({\n                            target: o.hourLabels[colorStyle],\n                            duration: duration,\n                        }).start();\n                    }\n                }\n            }\n        }\n        for (var i = 0; i < 60; i += o.minuteTicks.step) {\n            var minuteLabel = container.get(\"minuteLabel\".concat(i + 1));\n            if (minuteLabel && o.minuteLabels[colorStyle]) {\n                if (duration == 0) {\n                    minuteLabel.setColor(o.minuteLabels[colorStyle]);\n                }\n                else {\n                    minuteLabel.animations.new().color({\n                        target: o.minuteLabels[colorStyle],\n                        duration: duration,\n                    }).start();\n                }\n            }\n        }\n        if (container._center != null && o.center[colorStyle]) {\n            if (duration == 0) {\n                container._center.setColor(o.center[colorStyle]);\n            }\n            else {\n                container._center.animations.new().color({\n                    target: o.center[colorStyle],\n                    duration: duration,\n                }).start();\n            }\n        }\n    };\n    element.dim = function () {\n        element.setColors('dim');\n    };\n    element.unhighlight = function () {\n        element.setColors('color');\n    };\n    element.highlight = function () {\n        element.setColors('highlight');\n    };\n    if (o.start) {\n        element.setTime(o.start);\n    }\n    if (o.move === 'group') {\n        element.stopGroupMove();\n    }\n    element.custom.disableInteraction = function () {\n        element.setColors('disabled', ['hourHand', 'minuteHand']);\n    };\n    element.custom.enableInteraction = function () {\n        element.setColors('color', ['hourHand', 'minuteHand']);\n    };\n    element.shakeMinuteHand = function () {\n        if (minuteHand != null) {\n            minuteHand.pulse({\n                rotation: 0.12,\n                min: -0.12,\n                frequency: 2,\n                duration: 1,\n                centerOn: minuteHand.getPosition('figure'),\n            });\n        }\n    };\n    element.shakeHourHand = function () {\n        if (hourHand != null) {\n            hourHand.pulse({\n                rotation: -0.12,\n                min: 0.12,\n                frequency: 2,\n                duration: 1,\n                centerOn: hourHand.getPosition('figure'),\n            });\n        }\n    };\n    element.highlightHourHand = function () {\n        if (hourHand != null) {\n            hourHand.animations.new()\n                .inParallel([\n                hourHand.animations.color({\n                    target: o.hourHand.pulse,\n                    duration: 0.5,\n                }),\n                hourHand.animations.scale({\n                    target: 1.1,\n                    duration: 1,\n                }),\n            ])\n                .start();\n        }\n    };\n    element.unhighlightHourHand = function () {\n        if (hourHand != null) {\n            hourHand.animations.new()\n                .inParallel([\n                hourHand.animations.color({\n                    target: o.hourLabels.color,\n                    duration: 0.5,\n                    delay: 0.5,\n                }),\n                hourHand.animations.scale({\n                    target: 1,\n                    duration: 1,\n                }),\n            ])\n                .start();\n        }\n    };\n    element.highlightMinuteHand = function () {\n        if (minuteHand != null) {\n            minuteHand.animations.new()\n                .inParallel([\n                minuteHand.animations.color({\n                    target: o.minuteHand.pulse,\n                    duration: 0.5,\n                }),\n                minuteHand.animations.scale({\n                    target: 1.1,\n                    duration: 1,\n                }),\n            ])\n                .start();\n        }\n    };\n    element.unhighlightMinuteHand = function () {\n        if (minuteHand != null) {\n            minuteHand.animations.new()\n                .inParallel([\n                minuteHand.animations.color({\n                    target: o.hourLabels.color,\n                    duration: 0.5,\n                    delay: 0.5,\n                }),\n                minuteHand.animations.scale({\n                    target: 1,\n                    duration: 1,\n                }),\n            ])\n                .start();\n        }\n    };\n    element.shakeHands = function () {\n        element.shakeMinuteHand();\n        element.shakeHourHand();\n    };\n    element.pulseHour = function (hour) {\n        var hourElem = element._container[\"_hour\".concat(hour)];\n        var hourLabel = element._container[\"_hourLabel\".concat(hour)];\n        hourElem.animations.new()\n            .inParallel([\n            hourElem.animations.color({\n                target: o.hourTicks.pulse,\n                duration: 0.5,\n            }),\n            hourLabel.animations.color({\n                target: o.hourLabels.pulse,\n                duration: 0.5,\n            }),\n            hourElem.animations.scale({\n                target: 1.5,\n                duration: 1,\n            }),\n            hourLabel.animations.scale({\n                target: 1.3,\n                duration: 1,\n            }),\n        ])\n            .inParallel([\n            hourElem.animations.color({\n                target: o.hourLabels.color,\n                duration: 0.5,\n                delay: 0.5,\n            }),\n            hourLabel.animations.color({\n                target: o.hourLabels.color,\n                duration: 0.5,\n                delay: 0.5,\n            }),\n            hourElem.animations.scale({\n                target: 1,\n                duration: 1,\n            }),\n            hourLabel.animations.scale({\n                target: 1,\n                duration: 1,\n            })\n        ])\n            .start();\n    };\n    element.highlightHour = function (hour, color, tickScale, hourScale, duration) {\n        if (color === void 0) { color = \"incorrect\"; }\n        if (tickScale === void 0) { tickScale = 1; }\n        if (hourScale === void 0) { hourScale = 1.7; }\n        if (duration === void 0) { duration = 0.5; }\n        var hourElem = element._container[\"_hour\".concat(hour)];\n        var hourLabel = element._container[\"_hourLabel\".concat(hour)];\n        var hourTicksColor = Array.isArray(color) ? color : getColor(o.hourTicks, color);\n        var hourLabelsColor = Array.isArray(color) ? color : getColor(o.hourLabels, color);\n        // console.log(hour, `_hour${hour}`, hourElem)\n        hourElem.animations.new()\n            .inParallel([\n            hourElem.animations.color({\n                target: hourTicksColor,\n                duration: duration,\n            }),\n            hourLabel.animations.color({\n                target: hourLabelsColor,\n                duration: duration,\n            }),\n            hourElem.animations.scale({\n                target: tickScale,\n                duration: duration,\n            }),\n            hourLabel.animations.scale({\n                target: hourScale,\n                duration: duration,\n            }),\n        ])\n            .start();\n    };\n    element.custom.showCorrectness = function (correctness) {\n        var getCorrectnessColor = function (section, colorStyle) {\n            var _a, _b;\n            if (colorStyle === 'correct' && ((_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect))\n                return fig.custom.colorCorrect;\n            if (colorStyle === 'incorrect' && ((_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect))\n                return fig.custom.colorIncorrect;\n            return section[colorStyle];\n        };\n        if (typeof correctness === 'object') {\n            if (hourHand != null && correctness.hourHand != null) {\n                var result = correctness.hourHand;\n                var colorStyle = result === 1 ? 'correct' : (result === 2 || result === 6) ? 'incorrect' : 'color';\n                hourHand.setColor(getCorrectnessColor(o.hourHand, colorStyle));\n                if (o.hourTicks !== false && o.hourTicks.correctness) {\n                    for (var i = 0; i < 12; i += o.hourTicks.step) {\n                        var hourTick = container.get(\"hour\".concat(i + 1));\n                        if (hourTick && o.hourTicks[colorStyle]) {\n                            hourTick.setColor(getCorrectnessColor(o.hourTicks, colorStyle));\n                        }\n                    }\n                }\n                if (o.hourLabels !== false && o.hourLabels.correctness) {\n                    for (var i = 0; i < 12; i += o.hourTicks.step) {\n                        var hourLabel = container.get(\"hourLabel\".concat(i + 1));\n                        if (hourLabel && o.hourLabels[colorStyle]) {\n                            hourLabel.setColor(getCorrectnessColor(o.hourLabels, colorStyle));\n                        }\n                    }\n                }\n            }\n            if (minuteHand != null && correctness.minuteHand != null) {\n                var result = correctness.minuteHand;\n                var colorStyle = result === 1 ? 'correct' : (result === 2 || result === 6) ? 'incorrect' : 'color';\n                minuteHand.setColor(getCorrectnessColor(o.minuteHand, colorStyle));\n                if (o.minuteTicks !== false && o.minuteTicks.correctness) {\n                    for (var i = 0; i < 60; i += o.minuteTicks.step) {\n                        var minuteTick = container.get(\"minute\".concat(i + 1));\n                        if (minuteTick && o.minuteTicks[colorStyle]) {\n                            minuteTick.setColor(getCorrectnessColor(o.minuteTicks, colorStyle));\n                        }\n                    }\n                }\n                if (o.minuteLabels !== false && o.minuteLabels.correctness) {\n                    for (var i = 0; i < 60; i += o.minuteTicks.step) {\n                        var minuteLabel = container.get(\"minuteLabel\".concat(i + 1));\n                        if (minuteLabel && o.minuteLabels[colorStyle]) {\n                            minuteLabel.setColor(getCorrectnessColor(o.minuteLabels, colorStyle));\n                        }\n                    }\n                }\n            }\n        }\n    };\n    element.unhighlightHour = function (hour, duration) {\n        if (duration === void 0) { duration = 0.5; }\n        var hourElem = element._container[\"_hour\".concat(hour)];\n        var hourLabel = element._container[\"_hourLabel\".concat(hour)];\n        hourElem.animations.new()\n            .inParallel([\n            hourElem.animations.color({\n                target: o.hourLabels.color,\n                duration: duration,\n            }),\n            hourLabel.animations.color({\n                target: o.hourLabels.color,\n                duration: duration,\n            }),\n            hourElem.animations.scale({\n                target: 1,\n                duration: duration,\n            }),\n            hourLabel.animations.scale({\n                target: 1,\n                duration: duration,\n            })\n        ])\n            .start();\n    };\n    element.enableHelper = function (duration) {\n        if (duration === void 0) { duration = 0.2; }\n        element.custom.helper = true;\n        var thisHour = Math.floor(Fig.round(hourAngleToHourTime(hourHand.getRotation()), 3));\n        // element.highlightHour(element.custom.time[0]);\n        element.highlightHour(thisHour, 'helper', 1, 1.7, duration);\n        element.custom.lastHour = thisHour;\n    };\n    element.disableHelper = function (duration) {\n        if (duration === void 0) { duration = 0.2; }\n        element.custom.helper = false;\n        if (element.custom.lastHour != null) {\n            element.unhighlightHour(element.custom.lastHour, duration);\n        }\n    };\n    if (o.hourHand.isTouchable || o.minuteHand.isTouchable) {\n        fill.setTouchable();\n        fill.notifications.add('onClick', function (event) {\n            var p = event[1];\n            p = event[0].pointFromSpaceToSpace(p, 'gl', 'local');\n            if (container._debugPoint != null) {\n                container._debugPoint.setPosition(p);\n            }\n            var a = p.toPolar().angle;\n            if (a < 0) {\n                a += Math.PI * 2;\n            }\n            var angle;\n            var time;\n            if (o.minuteHand.isTouchable) {\n                if (o.minuteHand.snap) {\n                    var delta = o.minuteHand.snap === 'hour' ? 12 : 60;\n                    a = Fig.round(a / (Math.PI * 2) * delta, 0) / delta * Math.PI * 2;\n                }\n                angle = minuteAngleToAngle(a);\n                var angleDelta = Fig.tools.g2.getDeltaAngle(a, minuteHand.getRotation());\n                var deltaMinutes = Math.round(angleDelta * 180 / Math.PI / 6);\n                time = addMinutesToTime(element.custom.time, deltaMinutes);\n            }\n            else {\n                if (o.hourHand.snap) {\n                    var snapNum = 12;\n                    if (typeof o.hourHand.snap === 'number') {\n                        snapNum = o.hourHand.snap;\n                    }\n                    a = Fig.round(a / (Math.PI * 2) * snapNum, 0) / snapNum * Math.PI * 2;\n                }\n                angle = hourAngleToAngle(a);\n                time = angleToTime(angle);\n                time[0] = Math.floor(time[0]);\n                if (time[1] < 0) {\n                    time[1] += 60;\n                }\n            }\n            element.goToTime([Math.floor(time[0]), time[1]], { duration: 0.5, direction: 'shortest' });\n        });\n    }\n    element.arcGoTo = function (fromMinute, toMinute, duration) {\n        if (duration === void 0) { duration = 1; }\n        arc.show();\n        var to = toMinute;\n        while (to < fromMinute) {\n            to += 60;\n        }\n        var from = fromMinute;\n        element.fnMap.add('ArcGoToCallback', function (p) {\n            element.setArc({\n                startMinute: from,\n                endMinute: (to - from) * p + from,\n            });\n        });\n        element.animations.new('ArcGoTo')\n            .custom({\n            duration: duration,\n            callback: 'ArcGoToCallback',\n        })\n            .start();\n    };\n    element.getRoundedTime = function () {\n        var time = element.custom.time;\n        return roundTime(time);\n    };\n    return element;\n};\nexport { clock, createClock, RATIO, };\n","import { getAnswerInput } from '../tools/getAnswerInput';\nimport { createEntryField } from '../tools/input';\nimport { NotificationHelper } from '../tools/notifications';\nvar entryField = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var STYLES = {\n        default: {},\n        single: {\n            select: false,\n        },\n        multi: {\n            select: false,\n        },\n        fixed: {\n            close_button: false,\n            appear: 'fixedBottom',\n        },\n        fixedSpace: {\n            close_button: false,\n            appear: 'fixedBottomSpace',\n        },\n    };\n    var styleDefaults = STYLES[options.style ? options.style : 'default'];\n    var o = Fig.joinObjects({\n        charset: 'INT_STACK',\n        width: 0.4,\n        height: null,\n        max_char: 5,\n        max_char_nest: 5,\n        max_nest: 0,\n        init: [],\n        endCursor: true,\n        appear: 'bottom',\n        scale: 1,\n        style: 'single',\n        select: true,\n        font_size: null,\n        hide_keyboard_on_click: false,\n        hide_keyboard_on_submit: false,\n        enter_key_submit: true,\n        init_label: ['?'],\n        close_button: false,\n        x_buffer: 0.05,\n    }, styleDefaults, options);\n    var KEYBOARDS = {\n        INT_STACK: [\n            ['1', '2', '3', '4', '5', [0.15]],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], 'del'],\n        ],\n        INT_FLAT: [\n            // ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', [0.15], ['Delete', 2]],\n            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', [0.15], ['del', 1]],\n            // [[8], ['Delete', 2]],\n        ],\n        INT_ARROW_FLAT: [\n            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', [0.15], 'left', 'right', [0.15], ['del', 1]],\n        ],\n        INT_HARROWS: [\n            ['1', '2', '3', '4', '5', [0.15]],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], 'left', 'right', [0.15], ['Delete', 2]],\n        ],\n        INT_ARROWS: [\n            ['1', '2', '3', '4', '5', [0.15], [1], 'up'],\n            // 0.15,\n            [\n                '6',\n                '7',\n                '8',\n                '9',\n                '0',\n                [0.15],\n                'left',\n                'down',\n                'right',\n                [0.15],\n                ['Delete', 2],\n            ],\n        ],\n        DEC: [\n            ['1', '2', '3', '4', '5', [0.15]],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], '.', [0.15], 'del'],\n        ],\n        DEC_FLAT: [\n            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', [0.15], 'del'],\n        ],\n        FRAC: [\n            ['1', '2', '3', '4', '5', [0.15], 'frac'],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], 'left', 'right', [0.15], 'del'],\n        ],\n        FRAC_FLAT: [\n            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', [0.15], 'frac', [0.15], 'del'],\n        ],\n        REPEATER: [\n            ['1', '2', '3', '4', '5', [0.15], 'repeater'],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], '.', [0.15], ['Delete', 2]],\n        ],\n        POW: [\n            ['1', '2', '3', '4', '5', [0.15], 'pow'],\n            // 0.15,\n            ['6', '7', '8', '9', '0', [0.15], 'left', 'right', [0.15], ['Delete', 2]],\n        ],\n        PHRASE: [\n            [\n                '1',\n                '2',\n                '3',\n                '4',\n                '5',\n                [0.15],\n                '+',\n                'minus',\n                [0.15],\n                ['Delete', 2],\n                [0.7],\n            ],\n            [\n                '6',\n                '7',\n                '8',\n                '9',\n                '0',\n                [0.15],\n                'times',\n                'div',\n                [0.15],\n                'left',\n                'right',\n            ],\n        ],\n        PHRASE_TIMES: [\n            ['1', '2', '3', '4', '5', [0.15], 'times', [0.15]],\n            ['6', '7', '8', '9', '0', [0.15], ['Delete', 2]],\n        ],\n        PHRASE_TIMES_FLAT: [\n            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', [0.15], 'times', [0.15], 'del'],\n        ],\n    };\n    var keyboardDef = KEYBOARDS[o.charset];\n    var validKeys = [];\n    for (var r = 0; r < keyboardDef.length; r += 1) {\n        var row = keyboardDef[r];\n        if (typeof row === 'number') {\n            continue;\n        }\n        for (var b = 0; b < row.length; b += 1) {\n            var button = row[b];\n            if (Array.isArray(button)) {\n                if (typeof button[0] === 'string') {\n                    validKeys.push(button[0]);\n                }\n            }\n            else {\n                validKeys.push(button);\n            }\n        }\n    }\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    createEntryField({\n        keyboardKeys: keyboardDef,\n        maxChars: o.max_char,\n        position: [0, 0],\n        setWidth: o.width,\n        setHeight: o.height,\n        autoWidth: true,\n        maxCharNest: o.max_char_nest,\n        maxNest: o.max_nest,\n        init: o.init,\n        scaleIn: o.scale,\n        addTo: element,\n        valid_keys: validKeys,\n        scenarios: {},\n        expectedAnswer: null,\n        appearIn: o.appear,\n        honing: false,\n        endCursor: o.endCursor,\n        forSlides: false,\n        eqnOptions: {},\n        name: 'entryField',\n        style: o.style,\n        select: o.select,\n        fontSize: o.font_size,\n        enterKeySubmit: o.enter_key_submit,\n        hideKeyboardOnClick: o.hide_keyboard_on_click,\n        hideKeyboardOnSubmit: o.hide_keyboard_on_submit,\n        xBuffer: o.x_buffer,\n        initLabel: o.init_label,\n        closeButton: o.close_button,\n        onSubmit: function () {\n            var manipulativeAnswerIntput = getAnswerInput();\n            manipulativeAnswerIntput.elements['submit'].click();\n        },\n    });\n    element.name = o.name;\n    element.notificationHelper = new NotificationHelper();\n    if (o.debug) {\n        element.add({\n            make: 'polygon',\n            radius: 0.05,\n            sides: 10,\n            position: [0, 0],\n        });\n    }\n    element.custom.worksWith = {\n    // trash: true,\n    };\n    element.custom.showCorrectness = function (result) {\n        element._entryField.showCorrectness(result);\n    };\n    element.custom.getState = function () {\n        var partial = [];\n        return {\n            full: element._entryField.summarize(),\n            partial: partial,\n        };\n    };\n    element.disable = function () {\n        element._entryField.disable();\n    };\n    element.notifications.add('setTransform', function () {\n        if (figure.custom._keyboard_div.style.visibility !== 'hidden') {\n            element._entryField.locate();\n        }\n    });\n    element.showAnswer = function (show, \n    // duration: number = 1,\n    enableTouch, showOptions) {\n        if (enableTouch === void 0) { enableTouch = false; }\n        if (showOptions === void 0) { showOptions = {}; }\n        if (figure.custom._keyboard_input === element._entryField.uid) {\n            figure.custom._keyboard_input = null;\n        }\n        element._entryField.showAnswer({ show: show }, false, false, showOptions);\n    };\n    element.custom.state = element.custom.getState();\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (figure.custom._keyboard_input === element._entryField.uid) {\n            element._entryField.select();\n        }\n        else {\n            element._entryField.hideCursor();\n        }\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        if (figure.custom._keyboard_input === element._entryField.uid) {\n            element._entryField.select();\n        }\n    });\n    element.unhighlight = function () { };\n    element.custom.manipulativeType = 'entryFieldSlot';\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    element.setColors = function (colorStyle) { };\n    element.dim = function () { };\n    element.unhighlight = function () { };\n    element.highlight = function () { };\n    if (o.start) {\n        element.showAnswer(o.start, 0, true);\n    }\n    return element;\n};\nexport { entryField, createEntryField, };\n","import { createRekenrek, } from './rekenrek';\nimport { getLocalScene } from '../tools/scene';\nvar rekenrekControl = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        appear: 'top',\n        space: 0.1,\n        rows: 2,\n        beads: 10,\n        createScale: 1,\n        boundMove: true,\n        toElement: toAdd,\n        line: true,\n        fill: true,\n        width: 0.3,\n        height: 0.3,\n        radius: 0.05,\n        sides: 10,\n        rekenrek: {\n            length: 4,\n            size: 0.15,\n        },\n        offset: [0, 0],\n        buffer: { left: 0, top: 0, bottom: 0, right: 0 },\n        resetSpace: 0.15,\n    }, options);\n    if (o.rekenrek.name == null) {\n        o.rekenrek.name = \"__M_RNR_\".concat(o.rows, \"_\").concat(o.beads);\n    }\n    if (o.line !== false) {\n        o.line = Fig.joinObjects({\n            width: 0.003,\n            // color: [0.5, 0.5, 0.5, 1],\n            color: [0.5, 0.5, 0.5, 1],\n            shown: [0.7, 0.7, 0.7, 1],\n            hidden: [0.5, 0.5, 0.5, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            snapshot: [1, 1, 1, 1],\n            dash: [],\n        }, o.line === true ? {} : o.line);\n    }\n    if (o.fill !== false) {\n        o.fill = Fig.joinObjects({\n            color: [1, 1, 1, 1],\n            shown: [0.95, 0.95, 0.95, 0],\n            hidden: [1, 1, 1, 1],\n            dim: [0.95, 0.95, 0.95, 1],\n            snapshot: [0.5, 0.5, 1, 1],\n        }, o.fill === true ? {} : o.fill);\n    }\n    // Fig.joinObjects(o, options.controlOnly);\n    var element = toAdd.add({\n        make: 'collection',\n        name: o.name,\n    });\n    var container = element.add({\n        make: 'collection',\n        name: 'container',\n    });\n    if (o.fill) {\n        container.add({\n            make: 'rectangle',\n            name: 'fill',\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: o.fill.color,\n            width: o.width,\n            height: o.height,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    var s = 0.8;\n    container.add({\n        name: 'icon',\n        make: 'rectangle',\n        width: o.width,\n        height: o.height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        texture: {\n            src: window.location.origin + \"/static/img/manipulative-rekenrek.png\",\n            mapFrom: new Fig.Rect(0, 0, 1, 1),\n            mapTo: new Fig.Rect((o.width - o.width * s) / 2, (o.height - o.height * s) / 2, o.width * s, o.height * s),\n            loadColor: [0, 0, 0, 0],\n        },\n        // position: [o.space[0], o.space[1]],\n    });\n    if (o.line) {\n        container.add({\n            make: 'rectangle',\n            name: 'line',\n            xAlign: 'left',\n            yAlign: 'bottom',\n            width: o.width,\n            line: o.line,\n            height: o.height,\n            color: o.line.color,\n            corner: {\n                radius: o.radius,\n                sides: o.sides,\n            },\n        });\n    }\n    var dimElement = container.add({\n        make: 'rectangle',\n        name: 'dim',\n        xAlign: 'left',\n        yAlign: 'bottom',\n        color: [1, 1, 1, 0.5],\n        width: o.width,\n        height: o.height,\n        corner: {\n            radius: o.radius,\n            sides: o.sides,\n        },\n    });\n    dimElement.hide();\n    element.preserveChildColor = true;\n    element.custom.manipulativeType = null;\n    element.custom.manipulativeControlType = 'times_table';\n    var appear = o.appear;\n    ///////////////////////////////////\n    element.setTouchable();\n    element.custom.count = 0;\n    element.custom.create = function (name) {\n        if (name === void 0) { name = null; }\n        var new_element = createRekenrek(fig, eqn_name, o.toElement, Fig.joinObjects({}, o.rekenrek, {\n            rows: o.rows,\n            beads: o.beads,\n            createdFrom: element.getPath(),\n        }), o.boundMove);\n        toAdd.notifications.add('layoutForms', function () {\n            var isHidden = new_element.custom.state.h;\n            new_element.show();\n            new_element.setPosition(new_element.custom.state.p);\n            // This is needed after the show as when an element is hidden, getBoundingRect\n            // returns 0\n            new_element.setMoveBounds();\n            if (isHidden) {\n                new_element.hide();\n                new_element.custom.state.h = true;\n            }\n        });\n        var rect = element.getBoundingRect('figure');\n        var rectBottomLeft = new_element.pointFromSpaceToSpace([rect.left, rect.bottom], 'figure', 'local');\n        var rectTopRight = new_element.pointFromSpaceToSpace([rect.right, rect.top], 'figure', 'local');\n        var r = new Fig.Rect(rectBottomLeft.x, rectBottomLeft.y, rectTopRight.x - rectBottomLeft.x, rectTopRight.y - rectBottomLeft.y);\n        var newRect = new_element.getBoundingRect();\n        var x = 0;\n        var y = 0;\n        var midY = r.bottom + r.height / 2 - newRect.height / 2;\n        var midX = r.left + r.width / 2 - newRect.width / 2;\n        if (appear === 'right') {\n            x = r.right;\n            y = midY;\n        }\n        else if (appear === 'left') {\n            x = r.left - newRect.width;\n            y = midY;\n        }\n        else if (appear === 'top') {\n            y = r.top;\n            x = midX;\n        }\n        else if (appear === 'bottom') {\n            y = r.bottom - newRect.height;\n            x = midX;\n        }\n        x += o.offset[0];\n        y += o.offset[1];\n        var localScene = getLocalScene(new_element);\n        // const scene = new_element.getScene();\n        var buffer = o.buffer;\n        // const buffer = new Fig.Point(o.buffer[0], o.buffer[1]);\n        var deltaX = 0;\n        var deltaY = 0;\n        if (x < localScene.left + buffer.left) {\n            deltaX += localScene.left + buffer.left - x;\n        }\n        if (x + newRect.width > localScene.right - buffer.right) {\n            deltaX -= x + newRect.width - localScene.right + buffer.right;\n        }\n        if (y < localScene.bottom + buffer.bottom) {\n            deltaY += localScene.bottom + buffer.bottom - y;\n        }\n        if (y + newRect.height > localScene.top - buffer.top) {\n            deltaY -= y + newRect.height - localScene.top + buffer.top;\n        }\n        var delta = new Fig.Point(deltaX, deltaY);\n        new_element.setPosition(x + delta.x, y + delta.y);\n        // new_element.custom.initialPosition = new_element.getPosition();\n        fig.beingMovedElement = new_element;\n        new_element.startBeingMoved();\n        new_element.custom.startMove = performance.now();\n        new_element.setMoveBounds();\n        var t2 = new Fig.Point(x + delta.x, y + delta.y);\n        switch (appear) {\n            case 'right':\n                if (t2.x + o.space + newRect.width < localScene.right - buffer.right) {\n                    t2.x += o.space;\n                }\n                break;\n            case 'left':\n                if (t2.x - o.space > localScene.left + buffer.left) {\n                    t2.x -= o.space;\n                }\n                break;\n            case 'top':\n                if (t2.y + o.space + newRect.height < localScene.top - buffer.top) {\n                    t2.y += o.space;\n                }\n                break;\n            case 'bottom':\n                if (t2.y - o.space > localScene.bottom + buffer.bottom) {\n                    t2.y -= o.space;\n                }\n                break;\n        }\n        new_element.custom.initialPosition = t2;\n        element.notifications.add('autoCreate', function () {\n            new_element.setPosition(t2);\n        });\n        new_element.notifications.add('stopBeingMoved', function () {\n            var new_p = new_element.getPosition();\n            if (performance.now() - new_element.custom.startMove < 200 ||\n                new_p.sub(new_element.custom.initialPosition).distance() <\n                    new_element.custom.s) {\n                new_element.custom.state.p = t2;\n                // new_element.setPosition(t2);\n                // new_element.custom.moved = true;\n                // new_element.pulse({scale: 1.05, duration: 0.5, frequency: 2});\n                element.animations\n                    .new()\n                    .trigger(function () {\n                    new_element.hasTouchableElements = false;\n                    new_element.custom.moved = true;\n                })\n                    .inParallel([\n                    element.animations.position({\n                        target: t2,\n                        duration: 0.5,\n                        progression: 'easeout',\n                        element: new_element,\n                    }),\n                    // element.animations.scale({\n                    //   start: 0,\n                    //   target: 1,\n                    //   duration: 0.5,\n                    //   progression: 'easeout',\n                    //   element: new_element,\n                    // })\n                ])\n                    .trigger(function () {\n                    new_element.hasTouchableElements = true;\n                    new_element.custom.state.p = new_element.getPosition();\n                })\n                    .start();\n            }\n        }, 1);\n        return new_element;\n    };\n    element.showTable = function () {\n        element.custom.element.show();\n        element.custom.element.custom.state.h = false;\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.shown);\n            // element._container._fill.hide();\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.shown);\n            // element._container._line.hide();\n        }\n        // element._container._label.setColor(o.label.shown);\n        element._container._dim.show();\n        var rect = element.custom.element.getBoundingRect('figure');\n        var scene = element.custom.element.getScene();\n        if (rect.left > scene.right - o.resetSpace ||\n            rect.right < scene.left + o.resetSpace ||\n            rect.bottom > scene.top - o.resetSpace ||\n            rect.top < scene.bottom + o.resetSpace) {\n            element.custom.element.setPosition(element.custom.element.custom.initialPosition);\n        }\n    };\n    element.hideTable = function () {\n        element.custom.element.hide();\n        element.custom.element.custom.state.h = true;\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.hidden);\n            // element._container._fill.show();\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.hidden);\n            // element._container._line.show();\n        }\n        // element._container._label.setColor(o.label.hidden);\n        element._container._dim.hide();\n    };\n    element.unhighlight = function () {\n        if (element.custom.element == null) {\n            if (o.fill) {\n                element._container._fill.setColor(o.fill.color);\n            }\n            if (o.line) {\n                element._container._line.setColor(o.line.color);\n            }\n            element._container._dim.hide();\n            // element._container._label.setColor(o.label.color);\n        }\n        else if (element.custom.element.isShown) {\n            if (o.fill) {\n                element._container._fill.setColor(o.fill.shown);\n            }\n            if (o.line) {\n                element._container._line.setColor(o.line.shown);\n            }\n            element._container._dim.show();\n            // element._container._label.setColor(o.label.shown);\n        }\n        else if (element.custom.element.isShown === false) {\n            if (o.fill) {\n                element._container._fill.setColor(o.fill.hidden);\n            }\n            if (o.line) {\n                element._container._line.setColor(o.line.hidden);\n            }\n            element._container._dim.hide();\n            // element._container._label.setColor(o.label.hidden);\n        }\n        element.isTouchable = true;\n    };\n    element.dim = function () {\n        element.isTouchable = false;\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.dim);\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.dim);\n        }\n        element._container._dim.show();\n        // element._container._label.setColor(o.label.dim);\n    };\n    element.snapshot = function () {\n        if (o.fill) {\n            element._container._fill.setColor(o.fill.snapshot);\n        }\n        if (o.line) {\n            element._container._line.setColor(o.line.snapshot);\n        }\n        element._container._dim.hide();\n        // element._container._label.setColor(o.label.snapshot);\n    };\n    element.custom.secondaryTouchBounds = 0.1;\n    element.notifications.add('onClick', function () {\n        window.clickHandled = true;\n        if (element.custom.element == null) {\n            element.custom.element = element.custom.create();\n            element.custom.element.notifications.add('hidden', function () {\n                element.hideTable();\n            });\n            element.showTable();\n            return;\n        }\n        if (element.custom.element.isShown) {\n            element.hideTable();\n        }\n        else {\n            element.showTable();\n            element.custom.element.pulse({\n                scale: 1.05,\n                duration: 0.5,\n                frequency: 2,\n            });\n        }\n    });\n    return element;\n};\nexport { rekenrekControl, };\n","// import {linearBlocks} from './linearBlocks';\nimport { selectorManipulative } from './selector';\nimport { rekenrekControl } from './rekenrekControl';\nimport { TRASH_MANIPULATIVES } from './tools';\nvar rekenrekMenu = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        justify: 'right',\n        scale: 1,\n        position: [0, 0],\n        appear: null,\n        space: 0.025,\n        boundMove: true,\n        rekenrek: {\n            size: 0.19 * 0.4,\n            rod: 0.02 * 0.4,\n            length: 4.6 * 0.4,\n            space: 0.7 * 0.4,\n            rows: 2,\n            beads: 10,\n            move: 'individual',\n            lineWidth: 0.003,\n            isTouchable: true,\n        },\n        controls: [],\n        autoShow: 0,\n        control: {\n            width: 0.2,\n            height: 0.2,\n            space: 0.05,\n        },\n        width: 0.15,\n        height: 0.15,\n        edgeSpace: 0.02,\n    }, options);\n    var name = o.name, scale = o.scale, position = o.position, justify = o.justify, space = o.space, width = o.width, height = o.height;\n    var xAlign = o.xAlign;\n    if (xAlign == null) {\n        switch (justify) {\n            case 'left':\n                xAlign = 'left';\n                break;\n            case 'right':\n                xAlign = 'right';\n                break;\n            case 'top':\n                xAlign = 'right';\n                break;\n            case 'bottom':\n                xAlign = 'left';\n                break;\n        }\n    }\n    var orientation = o.orientation;\n    if (orientation == null) {\n        orientation = justify === 'right' || justify === 'left' ? 'h' : 'v';\n    }\n    var appear = o.appear;\n    if (appear == null) {\n        appear = justify;\n    }\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n    });\n    element.setScale(scale);\n    var controls = [];\n    controls.push(rekenrekControl(element, {\n        name: \"__M_RR\",\n        // n: i,\n        toElement: toAdd,\n        appear: appear,\n        space: 0.2,\n        boundMove: o.boundMove,\n        width: o.width,\n        height: o.height,\n        radius: o.width * 0.2,\n        rekenrek: o.rekenrek,\n        buffer: { left: 0, right: 0, top: 0.24, bottom: 0.1 },\n    }, fig));\n    var x = -(controls.length * width + (controls.length - 1) * space) / 2;\n    var y = (controls.length * height + (controls.length - 1) * space) / 2;\n    for (var i = 0; i < controls.length; i += 1) {\n        var b = controls[i];\n        var r = b.getBoundingRect();\n        switch (justify) {\n            case 'right':\n                b.setPosition(-r.right + width + o.edgeSpace, y - height);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'left':\n                b.setPosition(0 / width / 2 - o.edgeSpace, y - height);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'top':\n                b.setPosition(x, -r.height / 2 + height - o.edgeSpace);\n                x += b.getBoundingRect().width + space;\n                break;\n            case 'bottom':\n                b.setPosition(x, r.height / 2 - height + o.edgeSpace);\n                x += b.getBoundingRect().width + space;\n                break;\n        }\n    }\n    var f = element.parent.getPosition('figure');\n    element.custom.controlElements = [];\n    for (var i = 0; i < o.controls.length; i += 1) {\n        var selector = selectorManipulative(element.parent, {\n            name: \"\".concat(element.name, \"_\").concat(o.controls[i]),\n            method: o.controls[i],\n            width: o.control.width,\n            height: o.control.height,\n            select: TRASH_MANIPULATIVES,\n        }, fig);\n        element.custom.controlElements.push(selector);\n        selector.drawNumber = -1;\n        var scene = selector.getScene();\n        selector.setPosition(new Fig.Point(scene.left, scene.bottom)\n            .sub(f)\n            .add((o.control.width + o.control.space) * i, 0));\n        selector.custom.initialPosition = selector.getPosition();\n    }\n    element.preserveChildColor = true;\n    if (o.autoShow != null) {\n        controls[o.autoShow].click();\n        controls[o.autoShow].notifications.publish('autoCreate');\n    }\n};\nexport { rekenrekMenu };\n","import { createTimesTable, } from './timesTable';\nimport { getLocalScene } from '../tools/scene';\nimport { setAtlasId } from '../tools/equation';\nvar timesTableControl = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var controlOptions = Fig.joinObjects({\n        appear: 'right',\n        space: 0.05,\n        xAlign: 'centerRight',\n        n: 2,\n        createScale: 1,\n        boundMove: true,\n        toElement: toAdd,\n        line: true,\n        fill: true,\n        width: 0.2,\n        height: 0.2,\n        radius: 0.05,\n        sides: 10,\n        table: {},\n        font: {\n            size: 0.1,\n            color: colors.COLOR_GROKKOLI_BLUE,\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        label: {\n            color: colors.COLOR_GROKKOLI_BLUE,\n            hidden: colors.COLOR_GROKKOLI_BLUE,\n            snapshot: [1, 1, 1, 1],\n            shown: [0.7, 0.7, 0.7, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n        },\n        offset: [0, 0],\n        buffer: { left: 0, top: 0, bottom: 0, right: 0 },\n        resetSpace: 0.15,\n    }, options);\n    setAtlasId(controlOptions.font);\n    if (controlOptions.line !== false) {\n        controlOptions.line = Fig.joinObjects({\n            width: 0.003,\n            // color: [0.5, 0.5, 0.5, 1],\n            color: [0.7, 0.7, 0.7, 1],\n            shown: [0.7, 0.7, 0.7, 0],\n            hidden: [0.7, 0.7, 0.7, 1],\n            dim: [0.8, 0.8, 0.8, 1],\n            snapshot: [1, 1, 1, 1],\n            dash: [],\n        }, controlOptions.line === true ? {} : controlOptions.line);\n    }\n    if (controlOptions.fill !== false) {\n        controlOptions.fill = Fig.joinObjects({\n            color: [1, 1, 1, 1],\n            shown: [0.95, 0.95, 0.95, 0],\n            hidden: [1, 1, 1, 1],\n            dim: [0.95, 0.95, 0.95, 1],\n            snapshot: [0.5, 0.5, 1, 1],\n        }, controlOptions.fill === true ? {} : controlOptions.fill);\n    }\n    Fig.joinObjects(controlOptions, options.controlOnly);\n    var element = toAdd.add({\n        make: 'collection',\n        name: controlOptions.name,\n    });\n    var container = element.add({\n        make: 'collection',\n        name: 'container',\n    });\n    if (controlOptions.fill) {\n        container.add({\n            make: 'rectangle',\n            name: 'fill',\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: controlOptions.fill.color,\n            width: controlOptions.width,\n            height: controlOptions.height,\n            corner: {\n                radius: controlOptions.radius,\n                sides: controlOptions.sides,\n            },\n        });\n    }\n    if (controlOptions.line) {\n        container.add({\n            make: 'rectangle',\n            name: 'line',\n            xAlign: 'left',\n            yAlign: 'bottom',\n            width: controlOptions.width,\n            line: controlOptions.line,\n            height: controlOptions.height,\n            color: controlOptions.line.color,\n            corner: {\n                radius: controlOptions.radius,\n                sides: controlOptions.sides,\n            },\n        });\n    }\n    container.add({\n        name: 'label',\n        make: 'text',\n        text: \"\\u00D7\".concat(controlOptions.n),\n        xAlign: 'center',\n        yAlign: 'middle',\n        font: controlOptions.font,\n        position: [controlOptions.width / 2, controlOptions.height / 2],\n        color: controlOptions.label.color,\n    });\n    element.preserveChildColor = true;\n    element.custom.manipulativeType = null;\n    element.custom.manipulativeControlType = 'times_table';\n    var appear = controlOptions.appear;\n    ///////////////////////////////////\n    element.setTouchable();\n    element.custom.count = 0;\n    element.custom.create = function (name) {\n        if (name === void 0) { name = null; }\n        var new_element = createTimesTable(fig, eqn_name, controlOptions.toElement, Fig.joinObjects({}, controlOptions.table, {\n            name: \"__M_TT\",\n            n: controlOptions.n,\n            createdFrom: element.getPath(),\n        }), controlOptions.boundMove);\n        toAdd.notifications.add('layoutForms', function () {\n            var isHidden = new_element.custom.state.h;\n            new_element.show();\n            new_element.setPosition(new_element.custom.state.p);\n            // This is needed after the show as when an element is hidden, getBoundingRect\n            // returns 0\n            new_element.setMoveBounds();\n            if (isHidden) {\n                new_element.hide();\n                new_element.custom.state.h = true;\n            }\n        });\n        var rect = element.getBoundingRect('figure');\n        var rectBottomLeft = new_element.pointFromSpaceToSpace([rect.left, rect.bottom], 'figure', 'local');\n        var rectTopRight = new_element.pointFromSpaceToSpace([rect.right, rect.top], 'figure', 'local');\n        var r = new Fig.Rect(rectBottomLeft.x, rectBottomLeft.y, rectTopRight.x - rectBottomLeft.x, rectTopRight.y - rectBottomLeft.y);\n        var newRect = new_element.getBoundingRect();\n        var x = 0;\n        var y = 0;\n        var midY = r.bottom + r.height / 2 - newRect.height / 2;\n        var midX = r.left + r.width / 2 - newRect.width / 2;\n        if (appear === 'right') {\n            x = r.right;\n            y = midY;\n        }\n        else if (appear === 'left') {\n            x = r.left - newRect.width;\n            y = midY;\n        }\n        else if (appear === 'top') {\n            y = r.top;\n            x = midX;\n        }\n        else if (appear === 'bottom') {\n            y = r.bottom - newRect.height;\n            x = midX;\n        }\n        x += controlOptions.offset[0];\n        y += controlOptions.offset[1];\n        var localScene = getLocalScene(new_element);\n        // const scene = new_element.getScene();\n        var buffer = controlOptions.buffer;\n        // const buffer = new Fig.Point(controlOptions.buffer[0], controlOptions.buffer[1]);\n        var deltaX = 0;\n        var deltaY = 0;\n        if (x < localScene.left + buffer.left) {\n            deltaX += localScene.left + buffer.left - x;\n        }\n        if (x + newRect.width > localScene.right - buffer.right) {\n            deltaX -= x + newRect.width - localScene.right + buffer.right;\n        }\n        if (y < localScene.bottom + buffer.bottom) {\n            deltaY += localScene.bottom + buffer.bottom - y;\n        }\n        if (y + newRect.height > localScene.top - buffer.top) {\n            deltaY -= y + newRect.height - localScene.top + buffer.top;\n        }\n        var delta = new Fig.Point(deltaX, deltaY);\n        new_element.setPosition(x + delta.x, y + delta.y);\n        // new_element.custom.initialPosition = new_element.getPosition();\n        fig.beingMovedElement = new_element;\n        new_element.startBeingMoved();\n        new_element.custom.startMove = performance.now();\n        new_element.setMoveBounds();\n        var t2 = new Fig.Point(x + delta.x, y + delta.y);\n        switch (appear) {\n            case 'right':\n                if (t2.x + controlOptions.space + newRect.width <\n                    localScene.right - buffer.right) {\n                    t2.x += controlOptions.space;\n                }\n                break;\n            case 'left':\n                if (t2.x - controlOptions.space > localScene.left + buffer.left) {\n                    t2.x -= controlOptions.space;\n                }\n                break;\n            case 'top':\n                if (t2.y + controlOptions.space + newRect.height <\n                    localScene.top - buffer.top) {\n                    t2.y += controlOptions.space;\n                }\n                break;\n            case 'bottom':\n                if (t2.y - controlOptions.space > localScene.bottom + buffer.bottom) {\n                    t2.y -= controlOptions.space;\n                }\n                break;\n        }\n        new_element.custom.initialPosition = t2;\n        new_element.notifications.add('stopBeingMoved', function () {\n            var new_p = new_element.getPosition();\n            if (performance.now() - new_element.custom.startMove < 200 ||\n                new_p.sub(new_element.custom.initialPosition).distance() <\n                    new_element.custom.s) {\n                new_element.custom.state.p = t2;\n                element.animations\n                    .new()\n                    .trigger(function () {\n                    new_element.hasTouchableElements = false;\n                    new_element.custom.moved = true;\n                })\n                    .inParallel([\n                    element.animations.position({\n                        target: t2,\n                        duration: 0.5,\n                        progression: 'easeout',\n                        element: new_element,\n                    }),\n                    // element.animations.scale({\n                    //   start: 0,\n                    //   target: 1,\n                    //   duration: 0.5,\n                    //   progression: 'easeout',\n                    //   element: new_element,\n                    // })\n                ])\n                    .trigger(function () {\n                    new_element.hasTouchableElements = true;\n                })\n                    .start();\n            }\n        }, 1);\n        return new_element;\n    };\n    element.showTable = function () {\n        element.custom.element.show();\n        element.custom.element.custom.state.h = false;\n        if (controlOptions.fill) {\n            element._container._fill.setColor(controlOptions.fill.shown);\n            // element._container._fill.hide();\n        }\n        if (controlOptions.line) {\n            element._container._line.setColor(controlOptions.line.shown);\n            // element._container._line.hide();\n        }\n        element._container._label.setColor(controlOptions.label.shown);\n        var rect = element.custom.element.getBoundingRect('figure');\n        var scene = element.custom.element.getScene();\n        if (rect.left > scene.right - controlOptions.resetSpace ||\n            rect.right < scene.left + controlOptions.resetSpace ||\n            rect.bottom > scene.top - controlOptions.resetSpace ||\n            rect.top < scene.bottom + controlOptions.resetSpace) {\n            element.custom.element.setPosition(element.custom.element.custom.initialPosition);\n        }\n    };\n    element.hideTable = function () {\n        element.custom.element.hide();\n        element.custom.element.custom.state.h = true;\n        if (controlOptions.fill) {\n            element._container._fill.setColor(controlOptions.fill.hidden);\n            // element._container._fill.show();\n        }\n        if (controlOptions.line) {\n            element._container._line.setColor(controlOptions.line.hidden);\n            // element._container._line.show();\n        }\n        element._container._label.setColor(controlOptions.label.hidden);\n    };\n    element.unhighlight = function () {\n        if (element.custom.element == null) {\n            if (controlOptions.fill) {\n                element._container._fill.setColor(controlOptions.fill.color);\n            }\n            if (controlOptions.line) {\n                element._container._line.setColor(controlOptions.line.color);\n            }\n            element._container._label.setColor(controlOptions.label.color);\n        }\n        else if (element.custom.element.isShown) {\n            if (controlOptions.fill) {\n                element._container._fill.setColor(controlOptions.fill.shown);\n            }\n            if (controlOptions.line) {\n                element._container._line.setColor(controlOptions.line.shown);\n            }\n            element._container._label.setColor(controlOptions.label.shown);\n        }\n        else if (element.custom.element.isShown === false) {\n            if (controlOptions.fill) {\n                element._container._fill.setColor(controlOptions.fill.hidden);\n            }\n            if (controlOptions.line) {\n                element._container._line.setColor(controlOptions.line.hidden);\n            }\n            element._container._label.setColor(controlOptions.label.hidden);\n        }\n        element.isTouchable = true;\n    };\n    element.dim = function () {\n        element.isTouchable = false;\n        if (controlOptions.fill) {\n            element._container._fill.setColor(controlOptions.fill.dim);\n        }\n        if (controlOptions.line) {\n            element._container._line.setColor(controlOptions.line.dim);\n        }\n        element._container._label.setColor(controlOptions.label.dim);\n    };\n    element.snapshot = function () {\n        if (controlOptions.fill) {\n            element._container._fill.setColor(controlOptions.fill.snapshot);\n        }\n        if (controlOptions.line) {\n            element._container._line.setColor(controlOptions.line.snapshot);\n        }\n        element._container._label.setColor(controlOptions.label.snapshot);\n    };\n    element.custom.secondaryTouchBounds = 0.1;\n    element.notifications.add('onClick', function () {\n        window.clickHandled = true;\n        if (element.custom.element == null) {\n            element.custom.element = element.custom.create();\n            element.custom.element.notifications.add('hidden', function () {\n                element.hideTable();\n            });\n            element.showTable();\n            return;\n        }\n        if (element.custom.element.isShown) {\n            element.hideTable();\n        }\n        else {\n            element.showTable();\n        }\n    });\n    return element;\n};\nexport { timesTableControl, };\n","// import {linearBlocks} from './linearBlocks';\nimport { selectorManipulative } from './selector';\nimport { timesTableControl } from './timesTableControl';\nimport { TRASH_MANIPULATIVES } from './tools';\nvar timesTableMenu = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        justify: 'right',\n        scale: 1,\n        position: [0, 0],\n        appear: null,\n        space: 0.025,\n        boundMove: false,\n        table: {\n            width: 0.35,\n        },\n        controls: [],\n        control: {\n            width: 0.2,\n            height: 0.2,\n            space: 0.05,\n        },\n        width: 0.1,\n        height: 0.1,\n        edgeSpace: 0.02,\n    }, options);\n    var name = o.name, scale = o.scale, position = o.position, justify = o.justify, space = o.space, width = o.width, height = o.height;\n    var xAlign = o.xAlign;\n    if (xAlign == null) {\n        switch (justify) {\n            case 'left':\n                xAlign = 'left';\n                break;\n            case 'right':\n                xAlign = 'right';\n                break;\n            case 'top':\n                xAlign = 'right';\n                break;\n            case 'bottom':\n                xAlign = 'left';\n                break;\n        }\n    }\n    var orientation = o.orientation;\n    if (orientation == null) {\n        orientation = justify === 'right' || justify === 'left' ? 'h' : 'v';\n    }\n    var appear = o.appear;\n    if (appear == null) {\n        appear = justify;\n    }\n    var element = toAdd.add({\n        name: name,\n        make: 'collection',\n        position: position,\n    });\n    element.setScale(scale);\n    var tables = [];\n    for (var i = 2; i <= 12; i += 1) {\n        tables.push(timesTableControl(element, {\n            name: \"__M_TT\".concat(i),\n            n: i,\n            toElement: toAdd,\n            appear: appear,\n            boundMove: o.boundMove,\n            width: o.width,\n            height: o.height,\n            radius: o.width * 0.2,\n            font: {\n                size: o.width / 2,\n            },\n            table: o.table,\n            buffer: { left: 0, right: 0, top: 0.24, bottom: 0.1 },\n        }, fig));\n    }\n    var x = -(tables.length * width + (tables.length - 1) * space) / 2;\n    var y = (tables.length * height + (tables.length - 1) * space) / 2;\n    for (var i = 0; i < tables.length; i += 1) {\n        var b = tables[i];\n        var r = b.getBoundingRect();\n        switch (justify) {\n            case 'right':\n                b.setPosition(-r.right + width + o.edgeSpace, y - height);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'left':\n                b.setPosition(0 / width / 2 - o.edgeSpace, y - height);\n                y -= b.getBoundingRect().height + space;\n                break;\n            case 'top':\n                b.setPosition(x, -r.height / 2 + height - o.edgeSpace);\n                x += b.getBoundingRect().width + space;\n                break;\n            case 'bottom':\n                b.setPosition(x, r.height / 2 - height + o.edgeSpace);\n                x += b.getBoundingRect().width + space;\n                break;\n        }\n    }\n    var f = element.parent.getPosition('figure');\n    element.custom.controlElements = [];\n    for (var i = 0; i < o.controls.length; i += 1) {\n        var selector = selectorManipulative(element.parent, {\n            name: \"\".concat(element.name, \"_\").concat(o.controls[i]),\n            method: o.controls[i],\n            width: o.control.width,\n            height: o.control.height,\n            select: TRASH_MANIPULATIVES,\n        }, fig);\n        element.custom.controlElements.push(selector);\n        selector.drawNumber = -1;\n        var scene = selector.getScene();\n        selector.setPosition(new Fig.Point(scene.left, scene.bottom)\n            .sub(f)\n            .add((o.control.width + o.control.space) * i, 0));\n        selector.custom.initialPosition = selector.getPosition();\n    }\n    element.preserveChildColor = true;\n};\nexport { timesTableMenu };\n","import { trashManipulative } from './trash';\nvar trashControlManipulative = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var trash = trashManipulative(eqn_name, options, fig);\n    trash.custom.manipulativeType = null;\n    trash.notificationHelper.cleanup();\n    trash._container.isMovable = false;\n    trash.setTouchable();\n    trash.notifications.add('onClick', function () {\n        var newSelector = trashManipulative(eqn_name, Fig.joinObjects({}, options, { name: \"\".concat(options.name, \"_temp\") }), fig);\n        newSelector.setPositionToElement(trash);\n        fig.beingMovedElement = newSelector._container;\n        newSelector.startBeingMoved();\n        toAdd.notifications.add('layoutForms', function () {\n            newSelector.show();\n            newSelector.setPosition(newSelector.custom.state.p);\n        });\n    });\n    return trash;\n};\nexport { trashControlManipulative, };\n","import { joinObjects } from '../tools/joinObjects';\nimport { setupManipulative } from './tools';\nvar customSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = options;\n    // The path used by setManipulatives() to re-resolve this element on reload\n    // (`figure.get(`${state.e}.${name}`)`). Mirror clock/rekenrek's e_name.\n    var e_name;\n    if (typeof eqn_name === 'string') {\n        e_name = eqn_name;\n    }\n    else {\n        e_name = eqn_name.getPath();\n    }\n    // setManipulatives() re-resolves a control-created slot as `state.e + '.' +\n    // state.c`, so `c` must be relative to e_name. Strip the e_name prefix from\n    // createdFrom (mirror clock.ts). Null when not created from a control.\n    var createdFromRegex = new RegExp('^' + e_name);\n    var createdFrom = o.createdFrom != null\n        ? o.createdFrom.replace(createdFromRegex, '').slice(1)\n        : null;\n    // An empty collection — the author adds all visuals as children in the js\n    // block. Its position is controlled by the equation layout.\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n    });\n    element.custom.manipulativeType = 'customSlot';\n    element.custom._e = e_name;\n    // Register the element on the figure by name so the question's js/customInit\n    // block can retrieve it (path-independent): `figure.customSlots.<name>`. The\n    // js block runs before equation layout has finished, so authors should wire\n    // their hooks on the figure 'ready' event (by which point the slot is created)\n    // rather than synchronously when their js block first runs.\n    var figAny = fig;\n    if (figAny.customSlots == null) {\n        figAny.customSlots = {};\n    }\n    figAny.customSlots[o.name] = element;\n    // Dual-mode getState. The author assigns `custom.getState = (isSlot) => ...`\n    // returning ONLY their own data; the accessor below stores that as the inner\n    // hook and, on the no-arg (reload) path, merges in the bookkeeping that\n    // setManipulatives()/getManipulativesState() rely on: `e` (the element path\n    // used to re-resolve it on reload) and `h` (hidden). Position is owned by the\n    // equation layout, so it is intentionally not captured or restored.\n    var userGetState = function (isSlot) {\n        return isSlot ? { full: [], partial: [] } : {};\n    };\n    Object.defineProperty(element.custom, 'getState', {\n        configurable: true,\n        enumerable: true,\n        get: function () {\n            return function (isSlot) {\n                var data = userGetState(isSlot);\n                if (isSlot) {\n                    return data;\n                }\n                return joinObjects({}, {\n                    e: e_name,\n                    c: createdFrom,\n                    h: !element.isShown,\n                }, data);\n            };\n        },\n        set: function (fn) {\n            userGetState = fn;\n        },\n    });\n    // Author-overridable hooks (default no-ops so nothing throws if omitted). The\n    // author only ever assigns these on `custom`.\n    element.custom.setState = function () { };\n    element.custom.showAnswer = function () { };\n    element.custom.showCorrectness = function () { };\n    element.custom.disable = function () { };\n    element.custom.highlight = function () { };\n    element.custom.unhighlight = function () { };\n    // Bridge the element-level methods the generic slot/manipulative code calls\n    // (answerInput.ts invokes slot.showAnswer and slot.disable, like every other\n    // slot type) to the author's custom hooks. The remaining stubs satisfy generic\n    // manipulative-iteration code (e.g. selectors) that may call them unguarded.\n    element.showAnswer = function () {\n        var _a;\n        var args = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            args[_i] = arguments[_i];\n        }\n        return (_a = element.custom).showAnswer.apply(_a, args);\n    };\n    element.disable = function () { return element.custom.disable(); };\n    element.unhighlight = function () { return element.custom.unhighlight(); };\n    element.highlight = function () { return element.custom.highlight(); };\n    setupManipulative(element, null, o);\n    return element;\n};\nexport { customSlot };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\nvar templateManipulative = function (eqn_name, options, fig) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        width: 0.4,\n        height: 0.4,\n        color: [0.4, 0.4, 0.4, 1],\n        yOffset: 0,\n        isTouchable: true,\n        boundMove: true,\n        debug: false,\n    }, options);\n    // --- STRUCTURE ----------------------------------------------------------\n    // `element` is the movable top-level collection. `container` holds the\n    // visuals at the y-offset so the move anchor stays at the baseline.\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    // --- VISUALS ------------------------------------------------------------\n    // Replace this block with your manipulative's appearance.\n    container.add({\n        name: 'block',\n        make: 'rectangle',\n        width: o.width,\n        height: o.height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        color: o.color,\n        corner: { radius: 0.02, sides: 5 },\n    });\n    if (o.debug) {\n        container.add({\n            make: 'rectangle',\n            line: { width: 0.01 },\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n        });\n    }\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    element.notificationHelper = new NotificationHelper();\n    // setupManipulative wires the shared helpers: trash(), setMoveBounds(),\n    // bounds shadow, preserveChildColor. Pass `null` for selectBorder unless this\n    // is a select-style (click-to-select) manipulative.\n    setupManipulative(element, null, o);\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    // computeState() builds the serializable state. It's kept as a local function\n    // so internal bookkeeping (the 'moved' handler, the layoutForms restore below)\n    // can keep element.custom.state current even when the public getState is gated\n    // off — see the `tracksState` block.\n    function computeState() {\n        var p = element.getPosition();\n        // `eqn_name` may be a string path or the resolved collection — normalise to\n        // a path so setManipulatives() can re-find this element on restore.\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        return { e: e_name, p: [Fig.round(p.x, 3), Fig.round(p.y, 3)] };\n    }\n    // getState/setState are the OPT-IN to answer save/restore: the manage.ts layer\n    // (getManipulativesState / setManipulatives) only persists and restores a\n    // manipulative that defines them. Define them ONLY when the manipulative can\n    // actually change — here, when it's draggable (isTouchable !== false). A\n    // static, display-only instance defines neither, so it contributes nothing to\n    // every answer payload and is never restored from a snapshot. (For a select-\n    // or reshape-style manipulative, widen this condition to cover those too.)\n    var tracksState = o.isTouchable !== false;\n    if (tracksState) {\n        element.custom.getState = computeState;\n        element.custom.setState = function (stats) {\n            element.setPosition(Fig.parsePoint(stats.p));\n            element.custom.moved = true;\n        };\n    }\n    // Maintained in-memory regardless, so the interaction handlers below have a\n    // state object to update; it only reaches an answer via the public getState.\n    element.custom.state = computeState();\n    // On relayout (e.g. font loading) the equation repositions children; restore\n    // the learner's position if they've moved the element.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    // --- INTERACTION --------------------------------------------------------\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        // toArray(2) keeps the in-memory state.p a [x, y] tuple matching its\n        // declared type (getPosition() returns a FigureOne Point).\n        element.custom.state.p = element.getPosition().toArray(2);\n    });\n    element.notificationHelper.add(element._container, 'onClick', function () {\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n    });\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition().toArray(2);\n        // Tell the engine the answer may have changed so it can re-check. Use the\n        // injected `fig` (not the global `figure`) — addManipulative may pass a\n        // non-global figure.\n        fig.answerChanged();\n    });\n    // Called generically by the answer-input \"show answer\" flow\n    // (answerInput.ts) to freeze every manipulative once the answer is revealed.\n    // The call is existence-guarded, so this is optional — but without it the\n    // block stays draggable after the answer is shown.\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    // Register for answer processing. MUST be snake_case and match the YAML.\n    element.custom.manipulativeType = 'template_manipulative';\n    // Enlarges the touch target so small elements are easy to grab.\n    element._container.custom.secondaryTouchBounds = 0.1;\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    else {\n        container.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    return element;\n};\nexport { templateManipulative, };\n","var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n        if (ar || !(i in from)) {\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n            ar[i] = from[i];\n        }\n    }\n    return to.concat(ar || Array.prototype.slice.call(from));\n};\nimport { setupManipulative, outlineVertices } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\nvar poly = function (eqn_name, options, fig) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    // Expand the `style` preset into a base `angles`/`lines` bundle. Returned\n    // partial sits *under* the caller's options (joined below), so any explicit\n    // angles/lines/select still win. 'simple'/unknown -> nothing extra (outline\n    // only). Highlight/dim colours are fixed defaults the caller can override.\n    // Every pad size below is the *visible* radius / width rather than touchRadius /\n    // touchWidth, even though these pads are invisible by default. Both touch\n    // dimensions already fall back to the visible ones (see buildCornerPads /\n    // buildSidePads), so this gives the same generous default target AND keeps the\n    // two in step: an author who enlarges `radius` to draw the pad gets a touch area\n    // that grows with it, instead of a visible handle that lies about what actually\n    // responds. An explicit touchRadius / touchWidth still wins over both. (Same\n    // reasoning as pressPreset below.)\n    function stylePreset(style) {\n        var HL = [0, 0.45, 1, 1]; // selection highlight (blue)\n        if (style === 'solid') {\n            // Filled shape, no visible outline: hide the base stroke (transparent\n            // colour). The fill colour is defaulted to the polygon `color` after the\n            // merge below (an explicit `fill` still wins).\n            return { lines: { line: { color: [0, 0, 0, 0] } } };\n        }\n        if (style === 'select_angles') {\n            return {\n                angles: {\n                    all: {\n                        show: false, // no angle marks — only the selection ring shows.\n                        pad: { selectable: true, radius: 0.12 },\n                        selectCircle: { radius: 0.15, color: HL, lineWidth: 0.015 },\n                    },\n                },\n            };\n        }\n        if (style === 'select_sides') {\n            return {\n                lines: {\n                    all: {\n                        pad: { selectable: true, width: 0.12 },\n                        // A small oval (fixed length) on the side midpoint, shown on select.\n                        selectShape: { shape: 'oval', color: HL, width: 0.1, length: 0.1 },\n                    },\n                },\n            };\n        }\n        if (style === 'side_shift') {\n            // Invisible (visible defaults false) but movable side pads.\n            return { lines: { all: { pad: { movable: true, width: 0.12 } } } };\n        }\n        return {};\n    }\n    // Expand the top-level `press` block into the pads (and the decorations those\n    // pads drive) that make it work, so the common case is one line of YAML rather\n    // than four blocks. Like stylePreset this sits *under* the caller's options, so\n    // an explicit `squareAngles` / `growLines` / pad still wins — and it only turns\n    // on what was asked for, leaving the other half untouched.\n    function pressPreset(press) {\n        if (press == null)\n            return {};\n        var out = {};\n        // Pad sizes are the *visible* radius / width, so the touch area tracks them —\n        // see the note on stylePreset above.\n        if (press.corners === 'square') {\n            // `show: false` keeps this from drawing angle arcs the author didn't ask\n            // for (same reasoning as select_angles) — the square is the whole cue.\n            out.angles = { all: { show: false, pad: { press: 'square', radius: 0.12 } } };\n            out.squareAngles = true; // one default square per corner, built hidden.\n        }\n        if (press.sides === 'extend') {\n            out.lines = { all: { pad: { press: 'extend', width: 0.12 } } };\n            out.growLines = 2; // the usual \"extend these two sides\" pair.\n        }\n        return out;\n    }\n    var o = Fig.joinObjects({\n        close: true,\n        color: [0.4, 0.4, 0.4, 1],\n        yOffset: 0,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        alignTo: 'polyline',\n        touchBorderBuffer: 0.1,\n        select: 'multiple',\n        // isTouchable intentionally left undefined (default not draggable). The\n        // move setup at the end treats undefined as \"inert\", true as \"draggable\",\n        // and false as \"no interaction at all (also disables pads)\".\n        boundMove: true,\n        debug: false,\n    }, stylePreset(options != null ? options.style : undefined), pressPreset(options != null ? options.press : undefined), options);\n    // The 'solid' style fills the interior with the polygon `color` by default\n    // (its outline is hidden by the preset above). An explicit `fill` still wins,\n    // since it's already merged into `o` at this point.\n    if (o.style === 'solid' && o.fill == null)\n        o.fill = o.color;\n    // ========================================================================\n    // ORCHESTRATOR — modelled on FigureOne's CollectionsPolyline\n    // (node_modules/figureone/index.js): `vertices` is the single source of truth\n    // and updateGeometry() reflows every layer the way updatePoints() does there —\n    // extended for our pads/overlays/select-shapes/marks/selection state. One\n    // declared-but-unbuilt feature remains (the `kind: 'brace'` annotation),\n    // flagged with a TODO at its build site.\n    // FigureOne elements are dynamically typed, so element handles are `any`\n    // (mirrors `.add()` returning `any`).\n    // ========================================================================\n    // --- ELEMENT TREE -------------------------------------------------------\n    // `element` is the movable top-level collection; `container` holds the\n    // polygon and carries the alignment/y-offset transform (applyAlignment sets\n    // its position) so vertices stay at their natural coordinates. Layers are\n    // added in draw order (first = bottom): angles, base line, overlays, sides,\n    // pads, select — angles sit below the base outline, the select indicators\n    // (selectShapes + selectCircles) sit on top of everything.\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    container.isFormIgnored = true;\n    // Layers are created lazily by createLayers() — only when the options request\n    // elements for them — so empty collections aren't added. The base outline is\n    // the exception (always drawn). Held as `any` like every FigureOne handle.\n    var padsLayer = null;\n    // Selection indicators (side selectShapes + angle selectCircles) live together\n    // in this layer, created last so it draws on top of everything else.\n    var selectLayer = null;\n    var baseLineLayer = null;\n    var fillLayer = null; // polygon interior fill (drawn behind the outline)\n    var overlaysLayer = null;\n    var anglesLayer = null;\n    // Corner square overlays — drawn with the angle marks (under the base outline,\n    // so the polygon stroke sits on top of a square edge laid along it). Squares\n    // flagged `front: true` go in a second layer lifted above everything instead.\n    var squaresLayer = null;\n    var squaresFrontLayer = null;\n    // Grow lines — drawn ABOVE the base outline (a line laid on a side must cover\n    // that side, not hide under it) but below the side/angle labels. Lines flagged\n    // `front: true` go in a second layer lifted above everything instead.\n    var growLinesLayer = null;\n    var growLinesFrontLayer = null;\n    // Curve overlays — laid on the sides they trace, so like the grow lines they\n    // draw above the base outline (an overlay must cover its segments) and below\n    // the labels. `front: true` overlays go in a second, lifted layer.\n    var curvesLayer = null;\n    var curvesFrontLayer = null;\n    var sidesLayer = null;\n    var gridLayer = null; // background reference grid (drawn behind everything)\n    // --- GEOMETRY STATE -----------------------------------------------------\n    // `vertices` is the single source of truth (local coords); `initial` is the\n    // layout geometry, used to diff PolyState.corners on save. The per-layer\n    // registries hold the built child elements so updateGeometry() can drive them.\n    var vertices = resolveDefinition(options);\n    // When a grid with a `snap` is given, translate the whole polygon so the named\n    // vertex lands on its grid coordinate (x, y) -> local point (x*step, y*step).\n    // Done before `initial` is captured so the snapped layout is the baseline.\n    applyGridSnap();\n    // Baseline used to diff PolyState.corners. Vertices live at their natural\n    // (defined) draw-space coordinates: alignment is applied as a transform on\n    // the `container` collection (see applyAlignment), never by moving vertices,\n    // so this stays put.\n    var initial = vertices.map(function (v) { return Fig.getPoint([v.x, v.y]); });\n    var baseLine = null; // primitives.polyline — the shared base stroke\n    var fillElement = null; // primitives.generic — the polygon interior fill\n    var counterEl = null; // live \"N selected\" text readout (o.counter)\n    var debugLine = null; // debug-only outline of the near-touch outset border\n    var cornerPads = []; // visible regular-polygon handle per vertex\n    var sidePads = []; // visible rounded-rect handle per side\n    // Invisible movable \"drag\" pads sit over the visible handles. FigureOne moves\n    // these smoothly (incrementally), so the mouse is tracked cleanly even with\n    // snapping; the visible handle + geometry snap in real time off their\n    // position. The actively-dragged one is exempt from updateGeometry's reflow.\n    var cornerDragPads = [];\n    var sideDragPads = [];\n    var activeDragPad = null;\n    // Side pads whose length tracks the edge (the default when `pad.length` is\n    // omitted): the rectangle is built at `sidePadBaseW` and scaled along its\n    // local x to the current edge length in updateGeometry.\n    var sidePadFull = [];\n    var sidePadBaseW = [];\n    // Same, for the (independently sized) side drag pads.\n    var sideDragFull = [];\n    var sideDragBaseW = [];\n    var sideEls = []; // COL_Line per side (label + dimension line)\n    var sideOffsets = []; // label/annotation offset per side\n    // Label spec for sides whose label is the measured length (text: 'value'), so\n    // updateGeometry can recompute + reformat the reported length as the side\n    // changes. undefined for literal / blank labels.\n    var sideValueFmt = [];\n    var braceEls = []; // optional annotation (brace / dimension line) per side\n    var braceOffsets = []; // perpendicular offset of each annotation\n    var sideMarkEls = []; // congruence marks group (ticks / chevrons) per side\n    // Desired-hidden state of each side's marks group: true while the group should\n    // stay hidden (set by `marks.startHidden` at build, updated by show/hideSideMarks).\n    // showAll() re-hides these after FigureOne's blanket reveal so they don't pop back.\n    var sideMarksHidden = [];\n    // Re-entrancy guard: updateGeometry repositions pads, which fires their\n    // setTransformCallback again — suppress that to avoid an infinite loop.\n    var suppressPad = false;\n    var overlayEls = []; // interaction-reactive stroke per side\n    var selectShapeEls = []; // oval/rect selection indicator per side\n    // Rebuilt at proper dimensions (never scaled) to enclose the current edge in\n    // updateGeometry: `geom` holds the geometry-affecting make options (corner /\n    // line / sides) re-passed to updatePoints, `width` is the thickness across the\n    // edge, `margin` the extra length added at each end, and `length` (when set) a\n    // fixed along-edge length that overrides margin + edge tracking. `banded`\n    // marks a filled rectangle on a curve segment, drawn instead as a generic\n    // band in absolute coordinates (see curveBandTriangles) with `corner` the\n    // radius used at the run's two ends.\n    var selectShapeMeta = [];\n    var angleEls = []; // COL_Angle per corner\n    // Desired-hidden state of each corner's resting arc/fill: true while it should\n    // stay hidden (set by `angles.startHidden` at build, updated by show/hideAngleMark).\n    // showAll() re-hides these after FigureOne's blanket reveal so they don't pop back.\n    var angleMarkHidden = [];\n    var angleSelectCircles = []; // selection ring per corner\n    var angleSelectVertices = []; // regular-polygon vertex marker per corner\n    var angleSelectCorners = []; // corner-bracket polyline per corner\n    var angleSelectCornerLen = []; // each corner bracket's arm length\n    var angleSelectMarks = []; // select-state arc/fill overlay per corner\n    // Corner square overlays (o.squareAngles). The group is what show/hide acts on;\n    // the fill / outline shapes are kept separately so updateGeometry can re-point\n    // them as the polygon deforms, and `size`/`align` are stashed to recompute the\n    // corner points from the live vertices. `squareHidden[i]` is the desired-hidden\n    // state (true from build — squares start hidden), re-asserted by showAll().\n    var squareEls = [];\n    var squareFillEls = [];\n    var squareLineEls = [];\n    var squareSizes = [];\n    var squareAligns = [];\n    var squareHidden = [];\n    // Grow lines (o.growLines). Each line's drawn points are derived from the two\n    // numbers alongside it: `growLineAnchors[i]` is the side it lies on and\n    // `growLineExts[i]` is how far it currently reaches past that side's start /\n    // end (0, 0 = exactly covering the side). Everything — build, reflow, both\n    // animations — goes through growLinePoints(anchor, ext0, ext1), so a grown\n    // line keeps its extension while the polygon is dragged or morphed under it.\n    // `growLinePlacing[i]` is set while a placeLine animation owns the line's\n    // points, so the reflow leaves it alone until it lands.\n    // `growLineHidden[i]` is the desired-hidden state (false from build unless\n    // `visible: false`), re-asserted by showAll() like the corner squares.\n    var growLineEls = [];\n    var growLineAnchors = [];\n    var growLineExts = [];\n    var growLinePlacing = [];\n    var growLineHidden = [];\n    // hideWhenSelected lines (`growLineHideOnSelect[i]`), and whether one is\n    // currently hidden because its side is selected (`growLineSelHidden[i]`),\n    // kept apart from growLineHidden so deselecting restores the author's choice.\n    var growLineHideOnSelect = [];\n    var growLineSelHidden = [];\n    // Set while a press is holding a hidden line visible for its extension, so\n    // the matching retract knows to fade it back out (see pressExtend).\n    var growLinePressShown = [];\n    // Press bookkeeping (see pressExtend). `growLineGrown[i]` is the *intended*\n    // extended/retracted state — set the moment a press starts, not when its\n    // animation lands, so pressing the same side twice in quick succession reverses\n    // instead of repeating. `growLineOrder` is a recency queue, most recently used\n    // first: any press involving a line moves it to the front, so the line taken\n    // when a bare side is pressed is the one at the back (the least recently used).\n    // Seeded in reverse build order so the lines are claimed 0, 1, 2, … at first.\n    var growLineGrown = [];\n    var growLineOrder = [];\n    // Curve overlays (o.curves). `curveSides[i]` is the run of side indices curve\n    // i covers, in order (it may wrap past the closing side, and covers every side\n    // when the whole shape is one closed curve — `curveClosed[i]`). The run is the\n    // single source of truth: the overlay's points are re-derived from it and the\n    // live vertices on every reflow, so an overlay tracks a dragged or morphed\n    // shape. `curveHidden[i]` is the desired-hidden state (true from build unless\n    // `visible`), re-asserted by showAll() like the corner squares.\n    var curveSides = [];\n    var curveClosed = [];\n    // `curveEls[i]` is the handle showCurve()/showAll() drive: the polyline\n    // itself, or — when `roundEnds` asked for caps — the collection holding the\n    // polyline and its two end discs, so the whole overlay reveals as one.\n    // `curveLineEls[i]` is always the polyline (what refreshCurve repoints), and\n    // `curveCapEls[i]` its two caps (start, end) when there are any.\n    var curveEls = [];\n    var curveLineEls = [];\n    var curveCapEls = [];\n    var curveHidden = [];\n    // Invisible touch targets for *selectable* (non-movable) pads. Like the drag\n    // pads, they track their vertex/edge in updateGeometry; tapping one toggles\n    // the associated angle/side in the selection sets below.\n    var cornerSelectPads = [];\n    var sideSelectPads = [];\n    var sideSelectFull = []; // side select pad length tracks the edge\n    var sideSelectBaseW = [];\n    // Which vertices carry a corner pad whose press is 'square' — the corners that\n    // need the union touch border refreshCornerPressTouchBorder() rebuilds on every\n    // reflow. The pad's own size is not recorded here: the union is built from its\n    // live `drawBorder`, so it tracks whatever the pad was actually made with.\n    var cornerPressesSquare = [];\n    // Selection / interaction state. A selectable pad toggles its index here;\n    // applyStates() reflects the sets onto every angle/side's appearance. An angle\n    // or side is in its `select` state when in these sets, `highlight` when in the\n    // highlight sets (programmatic — hover/pulse), and `dim` when something else is\n    // selected; otherwise resting. Selection is persisted in PolyState (sa/ss/sv/sc).\n    // Angle, vertex and corner are three independent corner-anchored selections,\n    // each driving its own indicator (angle mark + selectCircle / selectVertex\n    // marker / selectCorner bracket), so the same vertex can be selected as one\n    // kind without lighting up the others.\n    var selectedAngles = new Set();\n    var selectedSides = new Set();\n    var selectedVertices = new Set();\n    var selectedCorners = new Set();\n    var highlightedAngles = new Set();\n    var highlightedSides = new Set();\n    // Every corner-anchored / side selection set, used by 'single' mode (clear all\n    // before adding one) and clearSelection().\n    var allSelectionSets = [\n        selectedAngles, selectedSides, selectedVertices, selectedCorners,\n    ];\n    // Map a selection-kind keyword to its set. Accepts the singular pad kinds\n    // ('angle'/'vertex'/'corner'/'side') and the plural counter `of` values\n    // ('angles'/'vertices'/'corners'/'sides'); defaults to the angle set.\n    function selectionSetForKind(kind) {\n        if (kind === 'side' || kind === 'sides')\n            return selectedSides;\n        if (kind === 'vertex' || kind === 'vertices')\n            return selectedVertices;\n        if (kind === 'corner' || kind === 'corners')\n            return selectedCorners;\n        return selectedAngles;\n    }\n    // Add/remove `index` from a selection set, honouring the `select` mode: in\n    // 'single' mode, turning a selection on first clears every other selection\n    // (across all kinds — angle, side, vertex, corner) so at most one item is ever\n    // selected. Turning one off just removes it. In 'multiple' mode (default) the\n    // kinds are independent. Shared by tap handling and the programmatic API so\n    // both obey the mode.\n    function applySelectMode(set, index, on) {\n        if (on && o.select === 'single') {\n            allSelectionSets.forEach(function (s) { return s.clear(); });\n        }\n        if (on)\n            set.add(index);\n        else\n            set.delete(index);\n    }\n    // --- SELECTION-INDICATOR FADING ------------------------------------------\n    // The select* / highlight* methods take an optional `duration`: when non-zero\n    // every selection indicator whose visibility flips in that call dissolves in /\n    // out instead of switching instantly. The duration is handed to applyStates()\n    // through this variable (rather than an argument) because applyStates() is\n    // also reached from pads, setState and showAll, which must all stay instant —\n    // applyStatesFading() sets it for exactly one call and clears it again.\n    // Only show/hide transitions fade; the `dim` / `highlight` recolour of the\n    // *other* sides and angles is a colour change, not an opacity one, and stays\n    // instant.\n    var stateFadeDuration = 0;\n    // Visibility applyStates() last applied to each selection indicator, keyed by\n    // the string naming its dissolve animation. Compared against the desired state\n    // so a fade only starts when the visibility actually flips: applyStates() is\n    // re-run on every selection change and by showAll(), and re-asserting the same\n    // state must not restart (or flash) a dissolve already in flight. `isShown`\n    // can't stand in for this — an indicator mid dissolve-out is still shown.\n    var indicatorShown = {};\n    // Keys with a dissolve running right now, so the unchanged-state re-assert\n    // below leaves them alone and lets the fade settle them itself.\n    var indicatorFading = {};\n    // Show / hide one selection indicator for applyStates(). Instant unless a\n    // duration is in force AND this indicator's desired visibility just flipped.\n    // Elements that aren't built (no selectCircle configured, say) are skipped.\n    function applyIndicator(el, key, show) {\n        if (el == null)\n            return;\n        var changed = indicatorShown[key] !== show;\n        indicatorShown[key] = show;\n        if (changed) {\n            // duration 0 makes dissolveDecoration instant — and it also cancels any\n            // in-flight fade and clears the leftover opacity, which a bare show() /\n            // hide() would not.\n            dissolveDecoration(el, key, show, stateFadeDuration);\n            return;\n        }\n        if (indicatorFading[key])\n            return;\n        // Unchanged: re-assert anyway. showAll() reveals the whole tree behind\n        // applyStates()' back, so the hidden indicators must be re-hidden even when\n        // nothing about the selection changed.\n        if (show)\n            el.show();\n        else\n            el.hide();\n    }\n    // Run applyStates() with every changed selection indicator dissolving over\n    // `duration` seconds. 0 (the default everywhere) is the plain instant path.\n    function applyStatesFading(duration) {\n        stateFadeDuration = duration;\n        try {\n            applyStates();\n        }\n        finally {\n            stateFadeDuration = 0;\n        }\n    }\n    // Side / angle counts and index math follow CollectionsPolyline's handling\n    // of open vs closed polygons.\n    var sideCount = function () {\n        return (o.close ? vertices.length : vertices.length - 1);\n    };\n    var angleCount = function () {\n        return (o.close ? vertices.length : vertices.length - 2);\n    };\n    // Second endpoint index of side i (wraps to 0 on the closing edge).\n    var sideEndIndex = function (i) {\n        return (i === sideCount() - 1 && o.close ? 0 : i + 1);\n    };\n    // Vertex indices [before, vertex, after] for angle i.\n    var angleVertexIndices = function (i) {\n        var p1 = i;\n        var p2 = i + 1;\n        var p3 = i + 2;\n        if (i === angleCount() - 2 && o.close)\n            p3 = 0;\n        if (i === angleCount() - 1 && o.close) {\n            p2 = 0;\n            p3 = 1;\n        }\n        return [p1, p2, p3];\n    };\n    // Inverse of the seat above: the angle whose vertex (p2) is vertex `v`. Angle a\n    // sits at vertex (a+1) mod n for a closed polygon, so vertex v hosts angle\n    // (v-1) mod n. Open polygons drop the wrap — their endpoints (v=0, v=n-1) have\n    // no interior angle, returning an out-of-range index the caller must check.\n    // Used so a corner pad at vertex v drives/selects the angle drawn at that\n    // corner (not the same-numbered angle, which sits one vertex along).\n    var angleIndexForVertex = function (v) {\n        return (o.close ? (v - 1 + vertices.length) % vertices.length : v - 1);\n    };\n    // The three points of a corner bracket at angle `i`: a point `length` along the\n    // arm toward the previous vertex, the corner vertex itself, then a point\n    // `length` along the arm toward the next vertex. Drives selectCorner at build\n    // and re-follows the sides in updateGeometry. Falls back to the raw vertex when\n    // an arm is degenerate (zero-length edge).\n    var cornerBracketPoints = function (i, length) {\n        var _a = angleVertexIndices(i), p1 = _a[0], p2 = _a[1], p3 = _a[2];\n        var v = vertices[p2];\n        var along = function (q) {\n            var dx = q.x - v.x;\n            var dy = q.y - v.y;\n            var len = Math.hypot(dx, dy);\n            if (len === 0)\n                return Fig.getPoint([v.x, v.y]);\n            return Fig.getPoint([v.x + (dx / len) * length, v.y + (dy / len) * length]);\n        };\n        return [along(vertices[p1]), Fig.getPoint([v.x, v.y]), along(vertices[p3])];\n    };\n    // The four corners of the square overlaid on corner `i` (see PolySquareSpec),\n    // in order, starting at the polygon vertex: [vertex, vertex + base*size,\n    // + perpendicular*size, vertex + perpendicular*size]. `base` is the unit\n    // direction from the vertex along one of the two edges meeting there —\n    // `align` picks which ('previous'/'next' name the edge explicitly; 'auto'\n    // takes the edge closest to horizontal/vertical, i.e. whose direction is\n    // nearest a multiple of 90°). The perpendicular is then rotated toward the\n    // *other* edge, so the square always opens into the corner. Recomputed from\n    // the live vertices at build and on every reflow. Returns null for a\n    // degenerate corner (both edges zero length), where there's no direction to\n    // align to.\n    var squarePoints = function (i, size, align) {\n        var _a;\n        var _b = angleVertexIndices(i), p1 = _b[0], p2 = _b[1], p3 = _b[2];\n        var v = vertices[p2];\n        // Unit direction from the vertex toward `q`, or null if they coincide.\n        var dir = function (q) {\n            var dx = q.x - v.x;\n            var dy = q.y - v.y;\n            var len = Math.hypot(dx, dy);\n            if (len === 0)\n                return null;\n            return [dx / len, dy / len];\n        };\n        var dPrev = dir(vertices[p1]);\n        var dNext = dir(vertices[p3]);\n        if (dPrev == null && dNext == null)\n            return null;\n        // How far a direction sits from the nearest multiple of 90° (0 = exactly\n        // horizontal or vertical). Used by 'auto' to pick the axis-aligned edge.\n        var axisOffset = function (d) {\n            var quarter = Math.PI / 2;\n            var r = Math.atan2(d[1], d[0]) % quarter;\n            if (r < 0)\n                r += quarter;\n            return Math.min(r, quarter - r);\n        };\n        var base;\n        if (align === 'previous')\n            base = dPrev != null ? dPrev : dNext;\n        else if (align === 'next')\n            base = dNext != null ? dNext : dPrev;\n        else if (dPrev == null || dNext == null)\n            base = dPrev != null ? dPrev : dNext;\n        else\n            base = axisOffset(dPrev) <= axisOffset(dNext) ? dPrev : dNext;\n        if (base == null)\n            return null;\n        // The edge the square does NOT lie along — it's the side the square opens\n        // toward. Falls back to the base edge when the corner only has one edge.\n        var other = (_a = (base === dPrev ? dNext : dPrev)) !== null && _a !== void 0 ? _a : base;\n        // Rotating `base` by +90° gives (-by, bx), which is always on `base`'s\n        // positive-cross side; flip it when `other` is on the negative side so the\n        // square is drawn inside the corner rather than away from it.\n        var sign = base[0] * other[1] - base[1] * other[0] >= 0 ? 1 : -1;\n        var perp = [-sign * base[1], sign * base[0]];\n        var at = function (a, b) {\n            return Fig.getPoint([v.x + base[0] * a + perp[0] * b, v.y + base[1] * a + perp[1] * b]);\n        };\n        return [at(0, 0), at(size, 0), at(size, size), at(0, size)];\n    };\n    // The square's fill as two triangles (a TRIANGLES generic, like the polygon\n    // fill) from its four corners.\n    var squareTriangles = function (pts) {\n        return [pts[0], pts[1], pts[2], pts[0], pts[2], pts[3]];\n    };\n    // Wrap a caller-supplied side index into range (so placeLine(i, n) is side 0\n    // and a negative index counts back from the end).\n    var normalizeSide = function (i) {\n        var n = sideCount();\n        if (n <= 0)\n            return 0;\n        return ((Math.round(i) % n) + n) % n;\n    };\n    // The two drawn endpoints of a grow line anchored to side `side` and reaching\n    // `ext0` past that side's start vertex and `ext1` past its end vertex (both\n    // measured along the side's own direction, so 0/0 covers the side exactly and\n    // a negative value pulls the end inside it). Recomputed from the live vertices\n    // at build, on every reflow and on every animation frame. Returns null for a\n    // degenerate (zero-length) side, which has no direction to extend along.\n    var growLinePoints = function (side, ext0, ext1) {\n        var a = vertices[side];\n        var b = vertices[sideEndIndex(side)];\n        if (a == null || b == null)\n            return null;\n        var dx = b.x - a.x;\n        var dy = b.y - a.y;\n        var len = Math.hypot(dx, dy);\n        if (len === 0)\n            return null;\n        var ux = dx / len;\n        var uy = dy / len;\n        // Never let the two ends cross (a line shortened past zero length): hold the\n        // total at a hairline instead, so updatePoints always gets two distinct points.\n        var e0 = ext0;\n        var e1 = ext1;\n        var total = len + e0 + e1;\n        if (total < 0.001) {\n            var pull = (0.001 - total) / 2;\n            e0 += pull;\n            e1 += pull;\n        }\n        return [\n            Fig.getPoint([a.x - ux * e0, a.y - uy * e0]),\n            Fig.getPoint([b.x + ux * e1, b.y + uy * e1]),\n        ];\n    };\n    // The drawn points of curve overlay `i`: the run's first vertex followed by\n    // the end vertex of each side in the run. A closed curve (one covering every\n    // side) drops the repeated last point — the polyline is built with\n    // `close: true`, which draws that join itself. Recomputed from the live\n    // vertices at build and on every reflow, so an overlay follows a dragged or\n    // morphed shape. Returns null for an unknown curve index.\n    var curvePoints = function (i) {\n        var sides = curveSides[i];\n        if (sides == null || sides.length === 0)\n            return null;\n        var pts = [vertices[sides[0]]];\n        sides.forEach(function (s) { return pts.push(vertices[sideEndIndex(s)]); });\n        if (curveClosed[i])\n            pts.pop(); // last === first; `close` draws that edge.\n        return pts;\n    };\n    // The detected curve run side `i` belongs to, with its neighbours in the run\n    // (null at an open run's ends), or null when the side isn't on a curve.\n    function curveRunOf(i) {\n        for (var c = 0; c < curveSides.length; c += 1) {\n            var sides = curveSides[c];\n            var k = sides.indexOf(i);\n            if (k === -1)\n                continue;\n            var last = sides.length - 1;\n            var wrap = curveClosed[c];\n            return {\n                prev: k > 0 ? sides[k - 1] : wrap ? sides[last] : null,\n                next: k < last ? sides[k + 1] : wrap ? sides[0] : null,\n            };\n        }\n        return null;\n    }\n    // Triangles for the selection band of curve segment `i` (absolute coords),\n    // `width` thick. Where the segment meets a neighbour in its run the band ends\n    // on the mitre line between the two, so neighbouring bands tile exactly with\n    // no overlap or notch. At an open run's end it extends `margin` past the\n    // vertex with corners of radius `corner` — the same end a rounded selectShape\n    // rectangle has (corner = margin = width/2 gives a round cap).\n    function curveBandTriangles(i, width, margin, corner) {\n        var a = vertices[i];\n        var b = vertices[sideEndIndex(i)];\n        var h = width / 2;\n        var unit = function (p, q) {\n            var len = Math.hypot(q.x - p.x, q.y - p.y) || 1;\n            return [(q.x - p.x) / len, (q.y - p.y) / len];\n        };\n        var _a = unit(a, b), dx = _a[0], dy = _a[1];\n        var n = [-dy, dx]; // left normal of this side\n        var at = function (p, u, v, ox, oy) { return (\n        // u along (ox, oy), v along its left normal (-oy, ox)\n        Fig.getPoint([p.x + u * ox - v * oy, p.y + u * oy + v * ox])); };\n        // Where the band ends at vertex `p`, from the right edge to the left edge as\n        // seen looking out of the side along (ox, oy).\n        var end = function (p, ox, oy, other) {\n            if (other != null && other < sideCount()) {\n                var _a = unit(vertices[other], vertices[sideEndIndex(other)]), ux = _a[0], uy = _a[1];\n                var mx = n[0] - uy;\n                var my = n[1] + ux;\n                var mLen = Math.hypot(mx, my);\n                if (mLen > 1e-9) {\n                    mx /= mLen;\n                    my /= mLen;\n                    var s = h / (mx * n[0] + my * n[1]);\n                    // Our left normal is the outward view's left when looking along d,\n                    // its right when looking back along -d.\n                    var sign = ox * dx + oy * dy > 0 ? 1 : -1;\n                    return [\n                        Fig.getPoint([p.x - sign * mx * s, p.y - sign * my * s]),\n                        Fig.getPoint([p.x + sign * mx * s, p.y + sign * my * s]),\n                    ];\n                }\n            }\n            var r = Math.max(0, Math.min(corner, h));\n            if (r === 0)\n                return [at(p, margin, -h, ox, oy), at(p, margin, h, ox, oy)];\n            var steps = 8;\n            var pts = [at(p, 0, -h, ox, oy)];\n            [[-h + r, -Math.PI / 2], [h - r, 0]].forEach(function (_a) {\n                var cv = _a[0], start = _a[1];\n                for (var k = 0; k <= steps; k += 1) {\n                    var t = start + (k / steps) * (Math.PI / 2);\n                    pts.push(at(p, margin - r + r * Math.cos(t), cv + r * Math.sin(t), ox, oy));\n                }\n            });\n            pts.push(at(p, 0, h, ox, oy));\n            return pts;\n        };\n        var run = curveRunOf(i);\n        var outline = __spreadArray(__spreadArray([], end(b, dx, dy, run != null ? run.next : null), true), end(a, -dx, -dy, run != null ? run.prev : null), true);\n        // Convex, so a fan about the side's midpoint covers it.\n        var c = Fig.getPoint([(a.x + b.x) / 2, (a.y + b.y) / 2]);\n        var tris = [];\n        outline.forEach(function (p, k) {\n            tris.push(c, p, outline[(k + 1) % outline.length]);\n        });\n        return tris;\n    }\n    // Find the polygon's curves and record them in curveSides / curveClosed.\n    //\n    // A curve is drawn as many tiny straight segments, so we look for exactly\n    // that: a maximal run of consecutive sides where every side is short (<=\n    // maxLength), each neighbouring pair is about the same length (within\n    // `tolerance` of the longer), and each neighbouring pair turns by no more than\n    // maxAngle. The length test is what separates a curve from the shape's real\n    // sides; the turn test is what separates it from a staircase of small equal\n    // steps. Both are pairwise, so a run may drift in length/direction overall as\n    // long as each step is gentle — which is what an arc traced at uneven\n    // resolution actually looks like.\n    //\n    // Runs may wrap past the closing side of a closed polygon, and a shape that is\n    // curved the whole way round (a 50-gon \"circle\") is one closed run covering\n    // every side. Called once, before the layers are created, so detection is\n    // fixed for the life of the manipulative.\n    function detectCurves() {\n        var c = o.curves;\n        if (c == null || c === false)\n            return;\n        var cfg = c === true ? {} : c;\n        var n = sideCount();\n        if (n < 2)\n            return;\n        var lens = [];\n        var dirs = []; // side direction in radians\n        var perimeter = 0;\n        for (var i = 0; i < n; i += 1) {\n            var a = vertices[i];\n            var b = vertices[sideEndIndex(i)];\n            var dx = b.x - a.x;\n            var dy = b.y - a.y;\n            lens.push(Math.hypot(dx, dy));\n            dirs.push(Math.atan2(dy, dx));\n            perimeter += lens[i];\n        }\n        // Default the length ceiling to a proportion of the perimeter rather than a\n        // fixed distance, so the same shape scaled up or down detects the same way.\n        var maxLength = cfg.maxLength != null ? cfg.maxLength : perimeter * 0.05;\n        var tolerance = cfg.tolerance != null ? cfg.tolerance : 0.15;\n        var maxAngle = (cfg.maxAngle != null ? cfg.maxAngle : 45) * (Math.PI / 180);\n        var minSides = cfg.minSides != null ? Math.max(2, Math.floor(cfg.minSides)) : 3;\n        // Zero-length sides have no direction, so they can't be part of a curve.\n        var short = lens.map(function (l) { return l > 0 && l <= maxLength; });\n        // Turn from side i to side j, folded into [0, PI] (direction of the turn\n        // doesn't matter — an S-bend is still one curve).\n        var turn = function (i, j) {\n            var d = dirs[j] - dirs[i];\n            while (d > Math.PI)\n                d -= 2 * Math.PI;\n            while (d < -Math.PI)\n                d += 2 * Math.PI;\n            return Math.abs(d);\n        };\n        // Do sides i and j (neighbours) continue the same curve?\n        var joins = function (i, j) {\n            if (!short[i] || !short[j])\n                return false;\n            var longer = Math.max(lens[i], lens[j]);\n            if (Math.abs(lens[i] - lens[j]) > tolerance * longer)\n                return false;\n            return turn(i, j) <= maxAngle;\n        };\n        // linked[i]: side i continues into the next side (wrapping only when closed).\n        var linked = [];\n        for (var i = 0; i < n; i += 1) {\n            var j = (i + 1) % n;\n            linked[i] = (o.close === true || i < n - 1) && joins(i, j);\n        }\n        var record = function (sides, closed) {\n            if (sides.length < minSides)\n                return;\n            curveSides.push(sides);\n            curveClosed.push(closed);\n        };\n        // Curved all the way round: one closed run over every side (no run start to\n        // find, since every side continues into the next).\n        if (o.close === true && linked.every(function (l) { return l; })) {\n            var all = [];\n            for (var i = 0; i < n; i += 1)\n                all.push(i);\n            record(all, true);\n            return;\n        }\n        // Otherwise every run begins at a short side its predecessor doesn't reach.\n        for (var i = 0; i < n; i += 1) {\n            var prev = (i - 1 + n) % n;\n            var continued = (o.close === true || i > 0) && linked[prev];\n            if (!short[i] || continued)\n                continue;\n            var sides = [i];\n            var cur = i;\n            while (linked[cur] && sides.length < n) {\n                cur = (cur + 1) % n;\n                sides.push(cur);\n            }\n            record(sides, false);\n        }\n    }\n    // --- GEOMETRY RESOLUTION (PolyDefinition -> vertices) -------------------\n    // Fallback shape when no (recognised) definition is supplied, so `make: poly`\n    // with no options still draws something sensible: a unit square at the origin.\n    // NB: keep these as function declarations (hoisted) — resolveDefinition is\n    // called above this point in the function body. Inline the default values\n    // rather than referencing an outer const, which would still be in its TDZ\n    // (undefined once compiled) at that earlier call site.\n    // n vertices evenly spaced on a circumcircle of `radius` about `center`,\n    // first vertex at angle `rotation`.\n    function regularVertices(sides, radius, rotation, center) {\n        var c = Fig.getPoint(center);\n        var step = (Math.PI * 2) / sides;\n        var points = [];\n        for (var i = 0; i < sides; i += 1) {\n            var a = rotation + i * step;\n            points.push(Fig.getPoint([\n                c.x + radius * Math.cos(a),\n                c.y + radius * Math.sin(a),\n            ]));\n        }\n        return points;\n    }\n    // Default orientation when `rotation` is omitted: the bottom side is\n    // horizontal (flat bottom). The bottom edge's two vertices straddle the\n    // downward vertical, so the first vertex sits half a step past -90°. This\n    // depends on the side count (e.g. flat-bottom triangle, axis-aligned square,\n    // flat-bottom pentagon).\n    function defaultRegularRotation(sides) {\n        return -Math.PI / 2 + Math.PI / sides;\n    }\n    function resolveDefinition(def) {\n        var _a, _b, _c;\n        if (def != null && def.by === 'points') {\n            return def.points.map(function (p) { return Fig.getPoint(p); });\n        }\n        if (def != null && def.by === 'regular') {\n            return regularVertices(def.sides, def.radius, (_a = def.rotation) !== null && _a !== void 0 ? _a : defaultRegularRotation(def.sides), (_b = def.center) !== null && _b !== void 0 ? _b : [0, 0]);\n        }\n        if (def != null && def.by === 'outline') {\n            return outlineVertices(def.outline, (_c = def.start) !== null && _c !== void 0 ? _c : [0, 0]);\n        }\n        // No recognised definition -> draw the default regular polygon (square),\n        // flat-bottom like any other regular polygon.\n        return regularVertices(4, 1, defaultRegularRotation(4), [0, 0]);\n    }\n    // Resolve a morph target (see PolyMorphTarget) to a vertex list, reusing the\n    // same builders as the initial definition. A string names a `morphs` registry\n    // entry; a bare array is a list of points; an object is an inline definition\n    // (a `by:`-tagged PolyDefinition, or a loose points / outline / regular bag).\n    // Unknown targets warn and fall back to the current vertices (a no-op morph).\n    // NB: a function declaration (hoisted) so the morph API below can call it; it\n    // leans on regularVertices/defaultRegularRotation/resolveDefinition, all also\n    // hoisted.\n    function resolveMorphShape(target) {\n        if (typeof target === 'string') {\n            var reg = o.morphs;\n            var def = reg != null ? reg[target] : undefined;\n            if (def != null)\n                return resolveMorphShape(def);\n            // Reserved name: 'init' always refers to the polygon's initial shape (the\n            // `by:`/points definition captured at build as `initial`), so you can morph\n            // back to the starting geometry without redeclaring it in `morphs`. A\n            // morphs entry of the same name still wins (it's checked first above), so\n            // the reserved name can be overridden.\n            if (target === 'init')\n                return initial.map(function (v) { return Fig.getPoint([v.x, v.y]); });\n            // eslint-disable-next-line no-console\n            console.warn(\"poly.morph: no morphs entry named '\".concat(target, \"'; ignoring.\"));\n            return vertices.slice();\n        }\n        if (Array.isArray(target)) {\n            return target.map(function (p) { return Fig.getPoint(p); });\n        }\n        if (target != null) {\n            if (target.by != null)\n                return resolveDefinition(target);\n            if (target.points != null) {\n                return target.points.map(function (p) { return Fig.getPoint(p); });\n            }\n            if (target.outline != null) {\n                return outlineVertices(target.outline, target.start != null ? target.start : [0, 0]);\n            }\n            if (target.sides != null && target.radius != null) {\n                return regularVertices(target.sides, target.radius, target.rotation != null ? target.rotation : defaultRegularRotation(target.sides), target.center != null ? target.center : [0, 0]);\n            }\n        }\n        // eslint-disable-next-line no-console\n        console.warn('poly.morph: unrecognised target; ignoring.');\n        return vertices.slice();\n    }\n    // Resample a polygon to exactly `n` points spread evenly by arc length around\n    // its perimeter (the closing edge is included when o.close). Used to reconcile\n    // a morph target whose vertex count differs from the polygon's fixed count, so\n    // the silhouette is preserved (resampled) rather than the morph being rejected.\n    // Returns the points unchanged when they already number `n`.\n    function resampleToCount(pts, n) {\n        if (pts.length === n)\n            return pts;\n        if (pts.length === 0 || n <= 0)\n            return [];\n        var closed = o.close !== false;\n        var segCount = closed ? pts.length : pts.length - 1;\n        var segLen = [];\n        var total = 0;\n        for (var i = 0; i < segCount; i += 1) {\n            var a = pts[i];\n            var b = pts[(i + 1) % pts.length];\n            var len = Math.hypot(b.x - a.x, b.y - a.y);\n            segLen.push(len);\n            total += len;\n        }\n        // Degenerate (all points coincident): just repeat the first point.\n        if (total === 0) {\n            var a = pts[0];\n            var rep = [];\n            for (var k = 0; k < n; k += 1)\n                rep.push(Fig.getPoint([a.x, a.y]));\n            return rep;\n        }\n        var out = [];\n        for (var k = 0; k < n; k += 1) {\n            // Closed: spread over [0, total) (periodic). Open: over [0, total] so the\n            // first/last samples sit on the endpoints.\n            var frac = closed ? k / n : (n === 1 ? 0 : k / (n - 1));\n            var d = frac * total;\n            var i = 0;\n            while (i < segLen.length && d > segLen[i]) {\n                d -= segLen[i];\n                i += 1;\n            }\n            if (i >= segLen.length) {\n                var last = pts[closed ? 0 : pts.length - 1];\n                out.push(Fig.getPoint([last.x, last.y]));\n                continue;\n            }\n            var a = pts[i];\n            var b = pts[(i + 1) % pts.length];\n            var t = segLen[i] === 0 ? 0 : d / segLen[i];\n            out.push(Fig.getPoint([a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t]));\n        }\n        return out;\n    }\n    // Translate every vertex so that grid.snap.corner lands on grid coordinate\n    // (x, y) — i.e. the local point (x*step, y*step). The shape is preserved; this\n    // just positions the polygon on the grid (in place of xAlign/yAlign aligning\n    // the polygon — with a grid, alignment positions the grid instead). No-op when\n    // there's no grid or no snap.\n    function applyGridSnap() {\n        var g = o.grid;\n        if (g == null || g.snap == null)\n            return;\n        var i = g.snap.corner;\n        if (i < 0 || i >= vertices.length)\n            return;\n        var dx = g.snap.x * g.step - vertices[i].x;\n        var dy = g.snap.y * g.step - vertices[i].y;\n        vertices = vertices.map(function (p) { return Fig.getPoint([p.x + dx, p.y + dy]); });\n    }\n    // --- ALIGNMENT (offset the `container` to a known spot in draw space) ---\n    // Vertices/annotations stay at their natural defined coordinates; we just\n    // translate the container collection so the polygon lands where xAlign/yAlign\n    // ask: by default left-most point at x=0, bottom-most at y=0. 'center'/\n    // 'middle' anchor the bounding-box centre, 'right'/'top' the far edge,\n    // 'absolute' leaves that axis untouched (container x or y stays at 0, +\n    // yOffset). `alignTo: 'all'` measures the whole built collection (annotations\n    // included); otherwise just the polyline vertices — so this must run after\n    // build() for the 'all' bounds to include the annotations.\n    function applyAlignment() {\n        if (o.xAlign === 'absolute' && o.yAlign === 'absolute')\n            return;\n        var left = Infinity;\n        var right = -Infinity;\n        var bottom = Infinity;\n        var top = -Infinity;\n        if (o.grid != null) {\n            // With a grid, alignment positions the grid's bounding box; the polygon\n            // rides along (it's already placed on the grid via grid.snap).\n            left = 0;\n            right = (o.grid.numX - 1) * o.grid.step;\n            bottom = 0;\n            top = (o.grid.numY - 1) * o.grid.step;\n        }\n        else if (o.alignTo === 'all') {\n            var r = container.getBoundingRect('draw');\n            left = r.left;\n            right = r.right;\n            bottom = r.bottom;\n            top = r.top;\n        }\n        else {\n            vertices.forEach(function (p) {\n                if (p.x < left)\n                    left = p.x;\n                if (p.x > right)\n                    right = p.x;\n                if (p.y < bottom)\n                    bottom = p.y;\n                if (p.y > top)\n                    top = p.y;\n            });\n        }\n        var dx = 0;\n        if (o.xAlign === 'left')\n            dx = -left;\n        else if (o.xAlign === 'center')\n            dx = -(left + right) / 2;\n        else if (o.xAlign === 'right')\n            dx = -right;\n        var dy = 0;\n        if (o.yAlign === 'bottom')\n            dy = -bottom;\n        else if (o.yAlign === 'middle')\n            dy = -(bottom + top) / 2;\n        else if (o.yAlign === 'top')\n            dy = -top;\n        // yOffset stays an additive vertical nudge on top of the alignment.\n        container.setPosition(dx, o.yOffset + dy);\n    }\n    // Give a layer an empty border so it's excluded from the manipulative's\n    // measured size (its bounding box) — unless alignTo: 'all', which measures the\n    // whole collection. Used for the interaction/decoration layers so the element\n    // border stays the polyline (+ annotations). Setting the border on the layer\n    // collection is reliable (a child redrawing won't clobber it); see the same\n    // technique on the counter wrapper and in baseTenBlocksSlot. No-op if the\n    // layer wasn't created.\n    function excludeFromSize(layer) {\n        if (layer != null && o.alignTo !== 'all')\n            layer.border = [[]];\n    }\n    // --- BUILD (create the per-index elements in each layer) ----------------\n    // Create only the layers that will hold something, in draw order (bottom ->\n    // top: angles, base line, overlays, sides, pads, select). Angles draw *below*\n    // the base outline so the polygon's stroke sits on top of the angle arcs/\n    // fills; the select layer (selectShapes + selectCircles) draws on top of\n    // everything so the selection indicator is never occluded. The need* flags\n    // mirror each build*'s own create condition exactly, so a layer exists iff its\n    // build* will add to it — no empty collections. The base outline is always\n    // drawn.\n    function createLayers() {\n        // Curves are detected from the geometry, so this must run before the need*\n        // pass below can ask whether any overlay wants a layer.\n        detectCurves();\n        var needPads = false;\n        var needSelectShapes = false;\n        var needSelectCircles = false;\n        var needOverlays = false;\n        var needAngles = false;\n        var needSides = false;\n        var needSquares = false;\n        var needSquaresFront = false;\n        var needGrowLines = false;\n        var needGrowLinesFront = false;\n        var needCurves = false;\n        var needCurvesFront = false;\n        for (var i = 0; i < vertices.length; i += 1) {\n            var a = resolveAngleSpec(i);\n            if (a != null && a.pad != null)\n                needPads = true;\n        }\n        for (var i = 0; i < sideCount(); i += 1) {\n            var l = resolveLineSpec(i);\n            if (l == null)\n                continue;\n            if (l.pad != null)\n                needPads = true;\n            if (l.selectShape != null)\n                needSelectShapes = true;\n            if (l.overlay != null)\n                needOverlays = true;\n            if (l.label !== undefined || l.annotation !== undefined || l.marks != null) {\n                needSides = true;\n            }\n        }\n        for (var i = 0; i < angleCount(); i += 1) {\n            var a = resolveAngleSpec(i);\n            if (a == null)\n                continue;\n            // The arc and the selection ring are independent: an angle can show its\n            // ring on select without drawing a mark (show: false), e.g. select_angles.\n            if (a.show !== false)\n                needAngles = true;\n            // A select-state overlay (its own arc/fill) also lives in the angles\n            // layer, so it's needed even when the resting mark is hidden.\n            if (a.states != null && a.states.select != null)\n                needAngles = true;\n            if ((a.selectCircle != null && a.selectCircle !== false)\n                || (a.selectVertex != null && a.selectVertex !== false)\n                || (a.selectCorner != null && a.selectCorner !== false)) {\n                needSelectCircles = true;\n            }\n        }\n        // Squares are configured independently of `angles` (a corner can carry a\n        // square without an angle mark), so they get their own pass over the corners.\n        // `front` squares live in their own (top) layer, so each layer is only\n        // created if some square actually asks for it.\n        for (var i = 0; i < angleCount(); i += 1) {\n            var sq = resolveSquareSpec(i);\n            if (sq == null || sq.show === false)\n                continue;\n            if (sq.front === true)\n                needSquaresFront = true;\n            else\n                needSquares = true;\n        }\n        // Grow lines aren't tied to a corner or a side either — they're a pool of\n        // `count` lines, split across the two layers the same way squares are.\n        for (var i = 0; i < growLineCount(); i += 1) {\n            var g = resolveGrowLineSpec(i);\n            if (g == null || g.show === false)\n                continue;\n            if (g.front === true)\n                needGrowLinesFront = true;\n            else\n                needGrowLines = true;\n        }\n        // Curve overlays are indexed by detected curve, not by side, so they get\n        // their own pass too — split across the two layers like the grow lines.\n        for (var i = 0; i < curveSides.length; i += 1) {\n            var cv = resolveCurveSpec(i);\n            if (cv == null || cv.show === false)\n                continue;\n            if (cv.front === true)\n                needCurvesFront = true;\n            else\n                needCurves = true;\n        }\n        var addLayer = function (name) {\n            return container.add({ name: name, make: 'collection' });\n        };\n        // The reference grid draws first (very bottom) so the polygon and all its\n        // annotations sit on top of it.\n        if (o.grid != null)\n            gridLayer = addLayer('grid');\n        // Interior fill behind everything but the grid, so the outline, angle marks\n        // and labels all draw on top of it.\n        if (o.fill != null)\n            fillLayer = addLayer('fill');\n        // Angles before the base line so the polygon stroke draws over the marks.\n        if (needAngles)\n            anglesLayer = addLayer('angles');\n        // Corner squares sit with the angle marks, under the base outline, so a\n        // square edge laid along a polygon edge reads as one line (the stroke on\n        // top) rather than two.\n        if (needSquares)\n            squaresLayer = addLayer('squares');\n        baseLineLayer = addLayer('baseLine');\n        if (needOverlays)\n            overlaysLayer = addLayer('overlays');\n        // Grow lines sit above the outline (the opposite of squares — a line laid on\n        // a side is meant to cover it) but under the labels, which stay readable.\n        if (needGrowLines)\n            growLinesLayer = addLayer('growLines');\n        // Curve overlays sit with the grow lines (above the outline they cover,\n        // below the labels), and after them so a revealed curve reads as the topmost\n        // marking on the shape.\n        if (needCurves)\n            curvesLayer = addLayer('curves');\n        if (needSides)\n            sidesLayer = addLayer('sides');\n        // Pads draw above the marks/outline as the visible/grabbable handles. They\n        // live inside `container` like everything else — when any pad is interactive\n        // the whole-manipulative move is turned off (the two are mutually exclusive,\n        // see the move setup), so `container` isn't touchable and native touch\n        // recurses into these pads. Otherwise pads are inert decoration.\n        if (needPads)\n            padsLayer = addLayer('pads');\n        // Selection indicators draw last (very top) so the lit selectShape/\n        // selectCircle sits in front of the outline, marks, labels and pads.\n        if (needSelectShapes || needSelectCircles)\n            selectLayer = addLayer('select');\n        // ... and the `front: true` overlays above even those — they are meant to\n        // read as an object laid over the shape. Both are re-lifted after build()\n        // (which appends the debug outline) so nothing ends up on top of them.\n        if (needGrowLinesFront)\n            growLinesFrontLayer = addLayer('growLinesFront');\n        if (needCurvesFront)\n            curvesFrontLayer = addLayer('curvesFront');\n        if (needSquaresFront)\n            squaresFrontLayer = addLayer('squaresFront');\n        // By default the manipulative's measured size is just the polyline outline\n        // plus any annotations (side/angle labels & marks live in the angles/sides\n        // layers, which only exist when shown). The interaction/decoration layers —\n        // pads (touch targets that extend past the corners), selection indicators\n        // and overlays — are given an empty border so they don't inflate the\n        // bounding box (which otherwise shows as phantom space around the shape when\n        // laid out in an expression). alignTo: 'all' opts back into measuring the\n        // whole collection.\n        excludeFromSize(overlaysLayer);\n        excludeFromSize(padsLayer);\n        excludeFromSize(selectLayer);\n        // Corner squares are a hidden-by-default overlay that can stick out past the\n        // shape (a square held against an acute corner), so like the other\n        // decoration layers they're kept out of the measured size — revealing one\n        // must never reflow the host equation.\n        excludeFromSize(squaresLayer);\n        excludeFromSize(squaresFrontLayer);\n        // Grow lines are excluded unconditionally (not via excludeFromSize, which\n        // `alignTo: 'all'` opts out of): a line grown to the scene boundary is many\n        // times the size of the polygon, and letting that into the measured border\n        // would blow up the host equation's layout mid-animation.\n        if (growLinesLayer != null)\n            growLinesLayer.border = [[]];\n        if (growLinesFrontLayer != null)\n            growLinesFrontLayer.border = [[]];\n        // Curve overlays lie on the outline (they never reach past it by more than\n        // half a line width), so they're kept out of the measured size the same way\n        // the other decoration layers are — revealing one must not reflow the host.\n        excludeFromSize(curvesLayer);\n        excludeFromSize(curvesFrontLayer);\n    }\n    // True when some corner or side pad satisfies `test`.\n    function anyPad(test) {\n        for (var i = 0; i < vertices.length; i += 1) {\n            var p = resolveAngleSpec(i);\n            var pad = p != null ? p.pad : undefined;\n            if (pad != null && test(pad))\n                return true;\n        }\n        for (var i = 0; i < sideCount(); i += 1) {\n            var l = resolveLineSpec(i);\n            var pad = l != null ? l.pad : undefined;\n            if (pad != null && test(pad))\n                return true;\n        }\n        return false;\n    }\n    // True when any pad takes touch at all — movable, selectable *or* pressable.\n    // Pad interaction and whole-manipulative move are mutually exclusive, so this\n    // gates the move (and turns on hasTouchableElements so taps reach the pads).\n    var hasTouchPads = function () { return anyPad(function (pad) { return padMovable(pad) || pad.selectable === true || pad.press != null; }); };\n    // True when any pad can change the *answer* — movable (reshapes the polygon)\n    // or selectable (toggles a selection set). Deliberately narrower than\n    // hasTouchPads: a press is a presentation cue, so a press-only poly stays out\n    // of the save/restore + answer payload entirely (see tracksState).\n    var hasAnswerPads = function () { return anyPad(function (pad) { return padMovable(pad) || pad.selectable === true; }); };\n    // `movable` is truthy as either `true` or a constraints object.\n    function padMovable(pad) {\n        return pad.movable != null && pad.movable !== false;\n    }\n    // Normalise a movable x/y constraint: [min, max] as-is; a number n -> the\n    // symmetric range [-n, n] (so 0 locks the axis); omitted -> null (unbounded).\n    function parseRange(v) {\n        if (v == null)\n            return null;\n        if (Array.isArray(v))\n            return [v[0], v[1]];\n        return [-v, v];\n    }\n    // Debug-only: draw a light green outline of an (otherwise invisible) touch\n    // target so its size/position is visible. Kept as a separate outline so the\n    // touch pad itself stays a filled, full-area touch shape. Stored on the host\n    // pad's custom.debugBorder and kept in sync by syncDebugBorder().\n    function addDebugBorder(host, shape, initRef, name) {\n        if (!o.debug)\n            return;\n        var dbg = padsLayer.add(Fig.joinObjects({}, shape, {\n            name: name,\n            position: [initRef.x, initRef.y],\n            color: [0, 0.7, 0, 0.7],\n            line: { width: 0.004 },\n        }));\n        dbg.isTouchable = false;\n        dbg.border = [[]]; // debug aid — never part of the measured size.\n        host.custom.debugBorder = dbg;\n    }\n    // Add an invisible movable \"drag\" pad over a visible handle. FigureOne moves\n    // it incrementally and we never reset it mid-drag (updateGeometry exempts the\n    // active drag pad), so it tracks the mouse cleanly. Each move snaps + clamps\n    // its position (relative to `initRef`) and drives the polygon via `onMove`,\n    // so the visible handle and geometry snap in *real time*. On release the drag\n    // pad realigns to its (snapped) vertex and the answer is re-checked.\n    function addDragPad(name, shape, // make-options for the pad shape (matches the visible handle)\n    initRef, pad, onMove) {\n        var dragPad = padsLayer.add(Fig.joinObjects({}, shape, {\n            name: name,\n            position: [initRef.x, initRef.y],\n            color: [0, 0, 0, 0], // invisible touch target.\n        }));\n        addDebugBorder(dragPad, shape, initRef, \"\".concat(name, \"Debug\"));\n        dragPad.setMovable();\n        dragPad.move.freely = false; // no momentum: rest exactly where released.\n        var cfg = typeof pad.movable === 'object' ? pad.movable : {};\n        var xr = parseRange(cfg.x);\n        var yr = parseRange(cfg.y);\n        var snap = cfg.snap;\n        var constrain = function (x, y) {\n            if (snap != null && snap > 0) {\n                x = initRef.x + Math.round((x - initRef.x) / snap) * snap;\n                y = initRef.y + Math.round((y - initRef.y) / snap) * snap;\n            }\n            if (xr != null)\n                x = Math.min(initRef.x + xr[1], Math.max(initRef.x + xr[0], x));\n            if (yr != null)\n                y = Math.min(initRef.y + yr[1], Math.max(initRef.y + yr[0], y));\n            return { x: x, y: y };\n        };\n        var fnName = \"_polyDrag_\".concat(name);\n        dragPad.fnMap.add(fnName, function (transform) {\n            if (suppressPad)\n                return;\n            var t = transform.t();\n            if (t == null)\n                return;\n            activeDragPad = dragPad; // exempt this pad from updateGeometry's reflow.\n            onMove(constrain(t.x, t.y));\n        });\n        dragPad.setTransformCallback = fnName;\n        element.notificationHelper.add(dragPad, 'stopBeingMoved', function () {\n            var p = dragPad.getPosition();\n            onMove(constrain(p.x, p.y)); // settle the geometry on the snapped point.\n            activeDragPad = null;\n            updateGeometry(vertices); // realign the (now inactive) drag pad to its vertex.\n            fig.answerChanged();\n        });\n        return dragPad;\n    }\n    // Add an invisible touchable \"tap\" pad over a visible handle (the tappable\n    // counterpart of a drag pad — not movable). Tracks its vertex/edge in\n    // updateGeometry like the drag pads do. A tap does either or both of:\n    //   - `kind` non-null: toggle `index` in that selection set and reflow the\n    //     interaction states. This is answer state, so it fires answerChanged.\n    //   - `press` set: run the presentation action for `index` (toggle the corner's\n    //     square / drive the grow lines). Not answer state — nothing persisted, no\n    //     answerChanged.\n    // They compose because they touch different state; a select-only pad passes no\n    // `press`, a press-only pad passes `kind: null`.\n    function addTapPad(name, shape, initRef, kind, index, press) {\n        var selectPad = padsLayer.add(Fig.joinObjects({}, shape, {\n            name: name,\n            position: [initRef.x, initRef.y],\n            color: [0, 0, 0, 0], // invisible touch target.\n        }));\n        addDebugBorder(selectPad, shape, initRef, \"\".concat(name, \"Debug\"));\n        selectPad.setTouchable();\n        element.notificationHelper.add(selectPad, 'onClick', function () {\n            if (kind != null) {\n                var set = selectionSetForKind(kind); // angle / side / vertex / corner\n                applySelectMode(set, index, !set.has(index)); // toggle (single-aware)\n                applyStates();\n                element.custom.state = computeState();\n                fig.answerChanged();\n            }\n            if (press === 'square')\n                pressSquare(index);\n            else if (press === 'extend')\n                pressExtend(index);\n            window.clickHandled = true; // don't also trigger any ancestor handler.\n        });\n        return selectPad;\n    }\n    // Build a pad's visible handle from its shape options. A single primitive with\n    // a `line` draws as an outline *only* (no fill), so fill + border needs two\n    // shapes wrapped in a collection. Returns whatever element updateGeometry can\n    // position/rotate/scale (a single shape or a 2-shape collection).\n    function padVisual(name, shape, pad) {\n        if (pad.visible !== true) {\n            // Invisible: a transparent placeholder (touch is handled by the drag pad).\n            return padsLayer.add(Fig.joinObjects({}, shape, { name: name, color: [0, 0, 0, 0] }));\n        }\n        if (pad.border == null) {\n            // Fill only.\n            return padsLayer.add(Fig.joinObjects({}, shape, { name: name, color: pad.fill != null ? pad.fill : o.color }));\n        }\n        // Fill + border: filled shape underneath, outline shape on top.\n        var col = padsLayer.add({ name: name, make: 'collection' });\n        if (pad.fill != null) {\n            col.add(Fig.joinObjects({}, shape, { name: 'fill', color: pad.fill }));\n        }\n        col.add(Fig.joinObjects({}, shape, {\n            name: 'border',\n            color: pad.border,\n            line: { width: pad.lineWidth != null ? pad.lineWidth : 0.01, color: pad.border },\n        }));\n        return col;\n    }\n    function build() {\n        buildGrid();\n        buildFill();\n        buildBaseLine();\n        // Side pads FIRST, so the corner pads draw — and so take touch — above them.\n        // A side pad spans its whole edge, so it always covers both of that edge's\n        // corners, and FigureOne gives a touch to the topmost element containing the\n        // point. Built the other way round, a tap on a corner would be swallowed by\n        // whichever side pad happens to reach it, and the small deliberate target\n        // (the corner) could never be hit at all.\n        buildSidePads();\n        buildCornerPads();\n        buildSides();\n        buildSideMarks();\n        buildAngles();\n        buildSquares();\n        buildGrowLines();\n        buildCurves();\n        buildOverlays();\n        buildSelectShapes();\n        buildCounter();\n        buildDebug();\n    }\n    // The current readout string: prefix + the selected count + suffix. Counts the\n    // selection set named by `counter.of` (angles / sides / vertices / corners;\n    // default angles).\n    function counterText() {\n        var c = o.counter;\n        if (c == null)\n            return '';\n        var set = selectionSetForKind(c.of != null ? c.of : 'angles');\n        var prefix = c.prefix != null ? c.prefix : '';\n        var suffix = c.suffix != null ? c.suffix : '';\n        return \"\".concat(prefix).concat(set.size).concat(suffix);\n    }\n    // Place the counter relative to the polygon's current bounding box: a named\n    // anchor (xAlign/yAlign) unless an explicit xPosition/yPosition is given, then\n    // nudged by `offset`. Called from updateGeometry so it tracks the deforming\n    // polygon. The text is centered on this point (xAlign/yAlign 'center'/'middle'\n    // on the text element itself, set at build).\n    function positionCounter() {\n        if (counterEl == null || o.counter == null)\n            return;\n        var c = o.counter;\n        var left = Infinity;\n        var right = -Infinity;\n        var bottom = Infinity;\n        var top = -Infinity;\n        vertices.forEach(function (p) {\n            if (p.x < left)\n                left = p.x;\n            if (p.x > right)\n                right = p.x;\n            if (p.y < bottom)\n                bottom = p.y;\n            if (p.y > top)\n                top = p.y;\n        });\n        var x;\n        if (c.xPosition != null)\n            x = c.xPosition;\n        else if (c.xAlign === 'left')\n            x = left;\n        else if (c.xAlign === 'right')\n            x = right;\n        else\n            x = (left + right) / 2; // 'center' default\n        var y;\n        if (c.yPosition != null)\n            y = c.yPosition;\n        else if (c.yAlign === 'bottom')\n            y = bottom;\n        else if (c.yAlign === 'middle')\n            y = (bottom + top) / 2;\n        else\n            y = top; // 'top' default\n        var off = c.offset != null ? Fig.getPoint(c.offset) : Fig.getPoint([0, 0]);\n        counterEl.setPosition(x + off.x, y + off.y);\n    }\n    // Refresh the readout text and reposition it. Called whenever the selection\n    // changes (applyStates) so the count stays current.\n    function updateCounter() {\n        if (counterEl == null || o.counter == null)\n            return;\n        // hideZero: keep the counter out of sight until something is selected.\n        var set = selectionSetForKind(o.counter.of != null ? o.counter.of : 'angles');\n        if (o.counter.hideZero && set.size === 0) {\n            counterEl.hide();\n            return;\n        }\n        counterEl.show();\n        counterEl.setText(counterText());\n        positionCounter();\n    }\n    // The counter text element, added straight to the container (so it rides the\n    // alignment/y-offset transform with the rest of the polygon). Positioned in\n    // updateGeometry once the geometry is final.\n    function buildCounter() {\n        if (o.counter == null)\n            return;\n        var c = o.counter;\n        // Wrap the text in a collection so inSize: false can exclude the counter\n        // from the polygon's measured bounds (so the collection's right edge stays\n        // the polygon's right edge, and the shape still centers in its slot). A text\n        // element recomputes its own border on setText, clobbering a make-option\n        // border — so the reliable place for the empty border is the wrapper\n        // collection (same technique as baseTenBlocksSlot's inSize handling). The\n        // wrapper sits at the origin; positionCounter moves the inner text.\n        var wrap = container.add({ name: 'counter', make: 'collection' });\n        if (c.inSize !== true)\n            wrap.border = [[]];\n        counterEl = wrap.add({\n            make: 'text',\n            name: 'text',\n            text: counterText(),\n            xAlign: 'center',\n            yAlign: 'middle',\n            color: c.color != null ? c.color : o.color,\n            font: {\n                family: defaultFontFamilyMath,\n                size: c.size != null ? c.size : 0.2,\n            },\n        });\n    }\n    // Guarantee an internal counter exists, building it on demand if the author\n    // didn't configure one (used by the dynamic countAngle() API). `counterOptions`\n    // is merged over any configured `counter` block so a late-created counter can\n    // still be styled/placed; a no-op once the counter element exists.\n    function ensureCounter(counterOptions) {\n        if (counterEl != null)\n            return;\n        o.counter = Fig.joinObjects({}, o.counter != null ? o.counter : {}, counterOptions != null ? counterOptions : {});\n        buildCounter();\n        positionCounter();\n    }\n    // The background reference grid: numX vertical + numY horizontal lines spaced\n    // `step`, spanning (numX-1)*step by (numY-1)*step from the local origin. Static\n    // (a fixed reference) — not touched by updateGeometry as the polygon reshapes.\n    function buildGrid() {\n        if (gridLayer == null || o.grid == null)\n            return;\n        var g = o.grid;\n        var width = g.width != null ? g.width : 0.005;\n        var color = g.color != null ? g.color : [0.7, 0.7, 0.7, 1];\n        var w = (g.numX - 1) * g.step;\n        var h = (g.numY - 1) * g.step;\n        for (var i = 0; i < g.numX; i += 1) {\n            var x = i * g.step;\n            gridLayer.add({\n                name: \"gridV\".concat(i),\n                make: 'polyline',\n                points: [[x, 0], [x, h]],\n                width: width,\n                color: color,\n                dash: g.dash,\n            });\n        }\n        for (var j = 0; j < g.numY; j += 1) {\n            var y = j * g.step;\n            gridLayer.add({\n                name: \"gridH\".concat(j),\n                make: 'polyline',\n                points: [[0, y], [w, y]],\n                width: width,\n                color: color,\n                dash: g.dash,\n            });\n        }\n    }\n    // Debug overlay: a light closed outline tracing the secondary near-touch\n    // border (the polygon outset by touchBorderBuffer). Added straight to the\n    // container, last, so it draws on top. Refreshed in updateGeometry().\n    function buildDebug() {\n        if (!o.debug)\n            return;\n        debugLine = container.add({\n            name: 'debugTouchBorder',\n            make: 'polyline',\n            points: outsetPolygon(vertices, o.touchBorderBuffer),\n            close: true,\n            width: 0.005,\n            color: [0.4, 0.5, 1, 0.4], // light, semi-transparent.\n        });\n        // The outset outline extends past the polyline; as a debug aid it must never\n        // contribute to the manipulative's measured size.\n        debugLine.border = [[]];\n    }\n    // Each build* is spec-driven: it only creates an element when the `angles` /\n    // `lines` options actually ask for it, so a bare `make: poly` draws just the\n    // base outline (no pads, angle marks, labels, overlays, marks or\n    // select-shapes). Interaction states and selection are wired in applyStates();\n    // the only deeper spec not yet mapped is the `kind: 'brace'` annotation.\n    // Normalise the `angles` option to the spec for index i, or null when that\n    // angle is off. Shared shape: `false`/omitted -> off; `true` -> defaults;\n    // object -> `all` defaults overridden by `each[i]` (`each[i] === false` ->\n    // off). Same logic mirrored in resolveLineSpec for `lines`.\n    function resolveAngleSpec(i) {\n        var a = o.angles;\n        if (a == null || a === false)\n            return null;\n        if (a === true)\n            return {};\n        var each = a.each != null ? a.each[i] : undefined;\n        if (each === false)\n            return null;\n        var all = a.all != null ? a.all : {};\n        if (each == null || each === true)\n            return all;\n        return Fig.joinObjects({}, all, each);\n    }\n    // Same `all`/`each` shape as resolveAngleSpec, for the corner square overlays.\n    function resolveSquareSpec(i) {\n        var s = o.squareAngles;\n        if (s == null || s === false)\n            return null;\n        if (s === true)\n            return {};\n        var each = s.each != null ? s.each[i] : undefined;\n        if (each === false)\n            return null;\n        var all = s.all != null ? s.all : {};\n        if (each == null || each === true)\n            return all;\n        return Fig.joinObjects({}, all, each);\n    }\n    // How many grow lines to build: an explicit `count`, or a bare number\n    // (`growLines: 3`), or the default pair — always stretched to cover the\n    // highest `each` index so `each: { 3: {...} }` doesn't silently do nothing.\n    function growLineCount() {\n        var g = o.growLines;\n        if (g == null || g === false)\n            return 0;\n        if (g === true)\n            return 2;\n        if (typeof g === 'number')\n            return Math.max(0, Math.floor(g));\n        var n = g.count != null ? Math.max(0, Math.floor(g.count)) : 0;\n        if (g.each != null) {\n            Object.keys(g.each).forEach(function (k) {\n                var i = parseInt(k, 10);\n                if (!Number.isNaN(i) && i + 1 > n)\n                    n = i + 1;\n            });\n        }\n        return n > 0 ? n : 2;\n    }\n    // Same `all`/`each` shape as resolveAngleSpec, for the grow lines. The pool\n    // forms (`true` / a bare count) have no per-line options, so every line in\n    // them resolves to defaults.\n    function resolveGrowLineSpec(i) {\n        var g = o.growLines;\n        if (g == null || g === false)\n            return null;\n        if (i >= growLineCount())\n            return null;\n        if (g === true || typeof g === 'number')\n            return {};\n        var each = g.each != null ? g.each[i] : undefined;\n        if (each === false)\n            return null;\n        var all = g.all != null ? g.all : {};\n        if (each == null || each === true)\n            return all;\n        return Fig.joinObjects({}, all, each);\n    }\n    // Same `all`/`each` shape as resolveAngleSpec, for the curve overlays. Indexed\n    // by *detected* curve (see detectCurves), so `each` keys only mean anything up\n    // to curveSides.length — a key past the last curve is silently unused, since\n    // there is no curve for it to style.\n    function resolveCurveSpec(i) {\n        var c = o.curves;\n        if (c == null || c === false)\n            return null;\n        if (i >= curveSides.length)\n            return null;\n        if (c === true)\n            return {};\n        var each = c.each != null ? c.each[i] : undefined;\n        if (each === false)\n            return null;\n        var all = c.all != null ? c.all : {};\n        if (each == null || each === true)\n            return all;\n        return Fig.joinObjects({}, all, each);\n    }\n    function resolveLineSpec(i) {\n        var l = o.lines;\n        if (l == null || l === false)\n            return null;\n        if (l === true)\n            return {};\n        var each = l.each != null ? l.each[i] : undefined;\n        if (each === false)\n            return null;\n        var all = l.all != null ? l.all : {};\n        if (each == null || each === true)\n            return all;\n        return Fig.joinObjects({}, all, each);\n    }\n    // The shared base stroke (the `lines.line` field), falling back to the\n    // manipulative's color and a default hairline width.\n    function baseStroke() {\n        var l = o.lines;\n        var line = l != null && l !== true && l !== false && l.line != null ? l.line : {};\n        return {\n            width: line.width != null ? line.width : 0.0125,\n            color: line.color != null ? line.color : o.color,\n            dash: line.dash,\n        };\n    }\n    // Map our PolyAngleSpec.label / PolyLineSpec.label `text` to a FigureOne label\n    // string. The sentinel 'value' explicitly requests the measured value (the\n    // angle in degrees, or the side length); any other string is shown literally;\n    // omitting text (or null) gives a blank label (slot drawn, no text).\n    function labelText(text) {\n        if (text === 'value')\n            return null; // FigureOne: null => measured value.\n        if (text == null)\n            return ''; // omitted / null => blank.\n        return text; // custom literal.\n    }\n    // Format a measured side length for a `text: 'value'` label, applying the\n    // label's valueScale (report relative to it), dec (decimal places) and\n    // forceDec (keep trailing zeros) options. We compute the string ourselves —\n    // rather than COL_Line's auto length — so these knobs are honoured.\n    function formatLength(len, lbl) {\n        var scale = lbl.valueScale != null && lbl.valueScale !== 0 ? lbl.valueScale : 1;\n        var dec = lbl.dec != null ? Math.max(0, lbl.dec) : 1;\n        var s = (len / scale).toFixed(dec);\n        // Default trims trailing zeros (\"11.0\" -> \"11\"); forceDec keeps them.\n        return lbl.forceDec ? s : String(parseFloat(s));\n    }\n    // Map our annotation `arrows` spec to a FigureOne COL_Line `arrow` option.\n    // true -> default barb heads both ends; an object selects/customises each\n    // end (true -> default barb, or a FigureOneArrow for full control).\n    function mapArrows(arrows) {\n        if (arrows == null || arrows === false)\n            return undefined;\n        var head = function (end) {\n            return (end === true ? { head: 'barb' } : end);\n        };\n        if (arrows === true)\n            return { start: { head: 'barb' }, end: { head: 'barb' } };\n        var out = {};\n        if (arrows.start)\n            out.start = head(arrows.start);\n        if (arrows.end)\n            out.end = head(arrows.end);\n        return Object.keys(out).length > 0 ? out : undefined;\n    }\n    // Ear-clipping triangulation of the polygon interior. Returns a flat list of\n    // points in groups of three (one triangle each) to feed a TRIANGLES generic.\n    // Unlike a centroid fan this fills concave simple polygons too — which the\n    // `outline` edge-walk readily produces (L-shapes, arrows, …). It assumes a\n    // *simple* (non-self-intersecting) polygon: if a corner is dragged across an\n    // edge the shape self-crosses and the fill may render imperfectly. O(n²),\n    // trivial at our handful-of-vertices scale. Recomputed as the shape deforms.\n    function fillTriangles() {\n        var n = vertices.length;\n        if (n < 3)\n            return [];\n        // 2× signed area; its sign is the winding. We clip on an index ring forced\n        // CCW so the convexity test below (\"left turn\") is consistent either way.\n        var area2 = 0;\n        for (var i = 0; i < n; i += 1) {\n            var a = vertices[i];\n            var b = vertices[(i + 1) % n];\n            area2 += a.x * b.y - b.x * a.y;\n        }\n        var ring = [];\n        for (var i = 0; i < n; i += 1)\n            ring.push(i);\n        if (area2 < 0)\n            ring.reverse();\n        // (b-a) × (c-b): > 0 is a left turn (a convex corner in CCW order).\n        var cross = function (a, b, c) {\n            return (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);\n        };\n        // Point-in-triangle via edge-sign test: p is inside abc iff it's on the same\n        // side of all three edges (all cross products share a sign).\n        var inTriangle = function (p, a, b, c) {\n            var d1 = cross(a, b, p);\n            var d2 = cross(b, c, p);\n            var d3 = cross(c, a, p);\n            var hasNeg = d1 < 0 || d2 < 0 || d3 < 0;\n            var hasPos = d1 > 0 || d2 > 0 || d3 > 0;\n            return !(hasNeg && hasPos);\n        };\n        var tris = [];\n        // Clip ears until a single triangle is left. `guard` backstops a stall on a\n        // degenerate/self-intersecting ring so this can never loop forever.\n        var guard = 0;\n        while (ring.length > 3 && guard < n * n) {\n            guard += 1;\n            var clipped = false;\n            for (var k = 0; k < ring.length; k += 1) {\n                var iPrev = ring[(k - 1 + ring.length) % ring.length];\n                var iCur = ring[k];\n                var iNext = ring[(k + 1) % ring.length];\n                var a = vertices[iPrev];\n                var b = vertices[iCur];\n                var c = vertices[iNext];\n                if (cross(a, b, c) <= 0)\n                    continue; // reflex/collinear tip -> not an ear.\n                // An ear's triangle must enclose no other vertex of the ring.\n                var contains = false;\n                for (var m = 0; m < ring.length; m += 1) {\n                    var idx = ring[m];\n                    if (idx === iPrev || idx === iCur || idx === iNext)\n                        continue;\n                    if (inTriangle(vertices[idx], a, b, c)) {\n                        contains = true;\n                        break;\n                    }\n                }\n                if (contains)\n                    continue;\n                tris.push(a, b, c); // emit the ear...\n                ring.splice(k, 1); // ...and drop its tip from the ring.\n                clipped = true;\n                break;\n            }\n            if (!clipped)\n                break; // no ear found (degenerate) -> stop with what we have.\n        }\n        if (ring.length === 3) {\n            tris.push(vertices[ring[0]], vertices[ring[1]], vertices[ring[2]]);\n        }\n        return tris;\n    }\n    // The interior fill: a single filled generic drawn behind the outline. Inert\n    // decoration — touch is handled by the base line — so it's left untouchable.\n    function buildFill() {\n        if (fillLayer == null || o.fill == null)\n            return;\n        fillElement = fillLayer.add({\n            name: 'fill',\n            make: 'generic',\n            points: fillTriangles(),\n            drawType: 'TRIANGLES',\n            color: o.fill,\n        });\n        fillElement.isTouchable = false;\n    }\n    function buildBaseLine() {\n        var stroke = baseStroke();\n        baseLine = baseLineLayer.add({\n            name: 'line',\n            make: 'polyline',\n            points: vertices,\n            close: o.close,\n            width: stroke.width,\n            color: stroke.color,\n            dash: stroke.dash,\n            // Touch area is the filled polygon (the vertex contour), not the thin\n            // stroke — so a grab anywhere inside the shape registers. The container\n            // aggregates this border; secondaryTouchBounds: 'border' (below) tests\n            // against it via point-in-polygon. Refreshed in updateGeometry().\n            touchBorder: vertices,\n        });\n    }\n    function buildCornerPads() {\n        var _loop_1 = function (i) {\n            // The corner pad sits at vertex i, but its spec and selection target are\n            // the angle *drawn at* vertex i, which (by FigureOne's seating) is angle\n            // (i-1) mod n, not angle i. Resolve against that angle so `angles.each`\n            // overrides and tap-to-select line up with the angle the user sees here.\n            // (For closed polygons every vertex has an angle; open-poly endpoints\n            // don't, so fall back to the vertex index for the spec lookup.)\n            var ai = angleIndexForVertex(i);\n            var hasAngle = ai >= 0 && ai < angleCount();\n            var spec = resolveAngleSpec(hasAngle ? ai : i);\n            var pad = spec != null ? spec.pad : undefined;\n            if (pad == null)\n                return \"continue\"; // no pad requested -> no corner touch target.\n            var radius = pad.radius != null ? pad.radius : 0.05;\n            var shape = { make: 'polygon', sides: pad.sides != null ? pad.sides : 20, radius: radius };\n            var p = padVisual(\"cornerPad\".concat(i), shape, pad);\n            cornerPads[i] = p;\n            p.isTouchable = false; // the (invisible) drag pad handles touch.\n            if (padMovable(pad)) {\n                // An invisible drag pad tracks the mouse; dragging moves this vertex,\n                // and the polygon reflows through moveCorner -> updateGeometry.\n                // Constraints are relative to the initial vertex position. touchRadius\n                // sizes this grab target independently of the visible handle.\n                var touchR = pad.touchRadius != null ? pad.touchRadius : radius;\n                var dragShape = { make: 'polygon', sides: shape.sides, radius: touchR };\n                cornerDragPads[i] = addDragPad(\"cornerDrag\".concat(i), dragShape, initial[i], pad, function (pos) { return moveCorner(i, Fig.getPoint([pos.x, pos.y])); });\n            }\n            else if (pad.selectable === true || (pad.press != null && hasAngle)) {\n                // Tap-to-select: an invisible touch pad at vertex i toggles the corner\n                // drawn there (ai). `pad.selects` picks which corner-anchored indicator\n                // a tap lights — 'angle' (default, the selectCircle/angle mark), 'vertex'\n                // (selectVertex marker) or 'corner' (selectCorner bracket). All three are\n                // keyed by the same angle index, so the toggle index is the same.\n                // The same pad carries `pad.press` (toggle this corner's square), which\n                // needs a real angle index — so it is only wired on a corner that has one\n                // (an open polygon's two endpoints don't).\n                var touchR = pad.touchRadius != null ? pad.touchRadius : radius;\n                var selShape = { make: 'polygon', sides: shape.sides, radius: touchR };\n                var selects = pad.selects != null ? pad.selects : 'angle';\n                cornerSelectPads[i] = addTapPad(\"cornerSelect\".concat(i), selShape, initial[i], pad.selectable === true ? selects : null, hasAngle ? ai : i, hasAngle ? pad.press : undefined);\n                // A pad that presses a square needs a touch area covering that square as\n                // well as its own disc — see refreshCornerPressTouchBorder, which builds\n                // it on every reflow (including the one straight after build()).\n                if (hasAngle && pad.press === 'square')\n                    cornerPressesSquare[i] = true;\n            }\n        };\n        for (var i = 0; i < vertices.length; i += 1) {\n            _loop_1(i);\n        }\n    }\n    // Ensure a selectable corner pad exists for angle `angleIndex`, building it (and\n    // the pads layer) on demand. Shared by the dynamic countAngle() API so a corner\n    // the author never made selectable can still be tapped to select its angle. The\n    // pad seats on the vertex that *hosts* angleIndex (angleVertexIndices()[1]) — the\n    // inverse of buildCornerPads' vertex->angle seating — and toggles angleIndex when\n    // tapped. `padOptions` overrides the pad styling/size (over any configured pad).\n    // No-op (returns the existing seat) if that corner already has a select pad.\n    function createCornerSelectPad(angleIndex, padOptions) {\n        var v = angleVertexIndices(angleIndex)[1]; // vertex hosting this angle\n        if (cornerSelectPads[v] != null)\n            return v;\n        if (padsLayer == null) {\n            padsLayer = container.add({ name: 'pads', make: 'collection' });\n            excludeFromSize(padsLayer); // keep pads out of measured size (see createLayers)\n        }\n        var base = resolveAngleSpec(angleIndex);\n        var pad = Fig.joinObjects({}, base != null && base.pad != null ? base.pad : {}, { selectable: true }, padOptions != null ? padOptions : {});\n        var radius = pad.radius != null ? pad.radius : 0.05;\n        var shape = { make: 'polygon', sides: pad.sides != null ? pad.sides : 20, radius: radius };\n        // The visible handle (invisible unless pad.visible) — only if one isn't there.\n        if (cornerPads[v] == null) {\n            cornerPads[v] = padVisual(\"cornerPad\".concat(v), shape, pad);\n            cornerPads[v].isTouchable = false;\n        }\n        var touchR = pad.touchRadius != null ? pad.touchRadius : radius;\n        var selShape = { make: 'polygon', sides: shape.sides, radius: touchR };\n        cornerSelectPads[v] = addTapPad(\"cornerSelect\".concat(v), selShape, initial[v], 'angle', angleIndex);\n        // build() seats pads at `initial`; if the polygon has since deformed, snap the\n        // new pad (and its handle) to the current vertex (updateGeometry keeps them\n        // there afterwards).\n        cornerSelectPads[v].setPosition(vertices[v]);\n        cornerPads[v].setPosition(vertices[v]);\n        // The element was made (non-)touchable at build time from the pads present\n        // then; adding a pad later requires re-enabling touch so it receives taps.\n        element.hasTouchableElements = true;\n        return v;\n    }\n    function buildSidePads() {\n        var _loop_2 = function (i) {\n            var spec = resolveLineSpec(i);\n            var pad = spec != null ? spec.pad : undefined;\n            if (pad == null)\n                return \"continue\"; // no pad requested -> no side touch target.\n            var jj = sideEndIndex(i);\n            var initMid = {\n                x: (initial[i].x + initial[jj].x) / 2,\n                y: (initial[i].y + initial[jj].y) / 2,\n            };\n            // `length` runs along the edge, `width` across it. Default length = the\n            // side's length, tracking the edge as the polygon deforms (via a scale in\n            // updateGeometry); an explicit `length` is fixed instead. (The FigureOne\n            // rectangle's `width`/`height` are its local x/y = along/across the edge.)\n            var initEdgeLen = Math.hypot(initial[jj].x - initial[i].x, initial[jj].y - initial[i].y);\n            var fullLength = pad.length == null;\n            var padLength = fullLength ? initEdgeLen : pad.length;\n            var padWidth = pad.width != null ? pad.width : 0.05;\n            sidePadFull[i] = fullLength;\n            sidePadBaseW[i] = padLength;\n            var shape = {\n                make: 'rectangle',\n                width: padLength,\n                height: padWidth,\n                corner: { radius: pad.corner != null ? pad.corner : 0.01, sides: 5 },\n            };\n            var p = padVisual(\"sidePad\".concat(i), shape, pad);\n            sidePads[i] = p;\n            p.isTouchable = false; // the (invisible) drag pad handles touch.\n            if (padMovable(pad)) {\n                // Dragging translates the whole edge by the drag delta (the pad's new\n                // centre minus the current edge midpoint). Constraints are relative to\n                // the initial edge midpoint. The grab target's thickness (touchWidth)\n                // and length (touchLength) are independent of the visible handle;\n                // touchLength omitted -> tracks the edge like the default visible pad.\n                var dragFull = pad.touchLength == null;\n                var dragBaseW = dragFull ? initEdgeLen : pad.touchLength;\n                sideDragFull[i] = dragFull;\n                sideDragBaseW[i] = dragBaseW;\n                var dragShape = {\n                    make: 'rectangle',\n                    width: dragBaseW,\n                    height: pad.touchWidth != null ? pad.touchWidth : padWidth,\n                    corner: shape.corner,\n                };\n                sideDragPads[i] = addDragPad(\"sideDrag\".concat(i), dragShape, initMid, pad, function (pos) {\n                    var a = vertices[i];\n                    var b = vertices[sideEndIndex(i)];\n                    moveSide(i, Fig.getPoint([\n                        pos.x - (a.x + b.x) / 2,\n                        pos.y - (a.y + b.y) / 2,\n                    ]));\n                });\n            }\n            else if (pad.selectable === true || pad.press != null) {\n                // Tap-to-select: an invisible touch pad (tracking the edge) toggles this\n                // side. Sized like a default drag pad — full edge length unless\n                // touchLength is given — so it scales with the edge in updateGeometry.\n                // The same pad carries `pad.press` (drive the grow lines onto this side).\n                var selFull = pad.touchLength == null;\n                var selBaseW = selFull ? initEdgeLen : pad.touchLength;\n                sideSelectFull[i] = selFull;\n                sideSelectBaseW[i] = selBaseW;\n                var selShape = {\n                    make: 'rectangle',\n                    width: selBaseW,\n                    height: pad.touchWidth != null ? pad.touchWidth : padWidth,\n                    corner: shape.corner,\n                };\n                sideSelectPads[i] = addTapPad(\"sideSelect\".concat(i), selShape, initMid, pad.selectable === true ? 'side' : null, i, pad.press);\n            }\n        };\n        for (var i = 0; i < sideCount(); i += 1) {\n            _loop_2(i);\n        }\n    }\n    function buildSides() {\n        // A side runs p1=vertex i -> p2=next; FigureOne's 'positive' label location\n        // is the CCW side of that, which is the polygon's interior for CCW winding.\n        // So the interior location is 'positive' for CCW, 'negative' for CW;\n        // `outside` flips it. (Same idea as the angle `direction`.)\n        var interiorLoc = isCCW(vertices) ? 'positive' : 'negative';\n        var flip = function (loc) { return (loc === 'positive' ? 'negative' : 'positive'); };\n        for (var i = 0; i < sideCount(); i += 1) {\n            sideOffsets[i] = 0;\n            var spec = resolveLineSpec(i);\n            // The base outline already strokes every edge; a per-side COL_Line is\n            // only needed to carry a label or annotation. Skip it otherwise so we\n            // don't draw a second line over the border.\n            if (spec == null || (spec.label === undefined && spec.annotation === undefined)) {\n                continue;\n            }\n            // Sides default to the exterior side; only `outside: false` puts the\n            // label/annotation inside.\n            var labelLocation = spec.outside === false ? interiorLoc : flip(interiorLoc);\n            var j = sideEndIndex(i);\n            // Label rides an invisible (width 0) COL_Line on the edge. Only when a\n            // label is requested.\n            if (spec.label !== undefined) {\n                // For text: 'value' we compute + format the length ourselves (so dec /\n                // forceDec / valueScale apply) and refresh it in updateGeometry, instead\n                // of using COL_Line's built-in auto length.\n                var isValue = spec.label.text === 'value';\n                sideValueFmt[i] = isValue ? spec.label : undefined;\n                var len0 = Math.hypot(vertices[j].y - vertices[i].y, vertices[j].x - vertices[i].x);\n                sideEls[i] = sidesLayer.add({\n                    name: \"side\".concat(i),\n                    make: 'collections.line',\n                    p1: vertices[i],\n                    p2: vertices[j],\n                    width: 0, // width 0 hides COL_Line's own line; the label still shows.\n                    label: {\n                        text: isValue ? formatLength(len0, spec.label) : labelText(spec.label.text),\n                        color: spec.label.color,\n                        scale: spec.label.size != null ? spec.label.size : 1,\n                        offset: spec.label.space,\n                        // Interior side by default; `outside` flips it (winding-aware).\n                        location: labelLocation,\n                        // Math content -> use the math font (arial), not the body font.\n                        font: { family: defaultFontFamilyMath },\n                    },\n                });\n            }\n            // Annotation between the side and its label: a dimension line (parallel,\n            // optional arrows) or a brace. `space` is its gap from the edge; it sits\n            // on the same side as the label (interior/exterior per `outside`).\n            if (spec.annotation !== undefined) {\n                var ann = spec.annotation;\n                var space = ann.space != null ? ann.space : 0.1;\n                // +offset is the interior side for CCW winding (matches the label's\n                // 'positive' location); flip for exterior. Sides default to exterior.\n                var sideSign = isCCW(vertices) ? 1 : -1;\n                var offset = (spec.outside === false ? sideSign : -sideSign) * space;\n                braceOffsets[i] = offset;\n                if (ann.kind === 'line') {\n                    braceEls[i] = sidesLayer.add({\n                        name: \"annotation\".concat(i),\n                        make: 'collections.line',\n                        p1: vertices[i],\n                        p2: vertices[j],\n                        offset: offset,\n                        width: ann.width != null ? ann.width : 0.008,\n                        color: ann.color != null ? ann.color : o.color,\n                        dash: ann.dash,\n                        arrow: mapArrows(ann.arrows),\n                    });\n                }\n                // TODO: ann.kind === 'brace' (standalone brace symbol spanning the edge).\n            }\n        }\n    }\n    // Congruence marks across a side: a group of short lines centered on the side\n    // midpoint, in a local frame where +x runs along the edge and +y is\n    // perpendicular. The group is positioned/rotated onto the edge in\n    // updateGeometry, so the marks themselves are static here. `straight` draws\n    // lines perpendicular to the side (spanning ±length/2 across it); `chevron`\n    // draws chevrons \">\" pointing along the edge (half-angle `angle`). `count`\n    // repeats the mark, evenly spread along the edge and centered on the midpoint.\n    function buildSideMarks() {\n        for (var i = 0; i < sideCount(); i += 1) {\n            var spec = resolveLineSpec(i);\n            if (spec == null || spec.marks == null)\n                continue;\n            var m = spec.marks;\n            var style = m.style === 'chevron' ? 'chevron' : 'straight';\n            var count = m.count != null ? m.count : 1;\n            var length_1 = m.length != null ? m.length : 0.08;\n            var stroke = baseStroke();\n            var width = m.width != null ? m.width : stroke.width;\n            var color = m.color != null ? m.color : stroke.color;\n            var spacing = m.spacing != null ? m.spacing : style === 'chevron' ? 0.05 : 0.03;\n            var half = length_1 / 2;\n            // Chevron arm run along the edge from the perpendicular span and half-angle\n            // (45° -> a square \">\"). Guarded so a near-0/90° angle can't blow up tan().\n            // `direction` (-1) negates the arm run so the chevron points the other way\n            // (drawn at 180°); 1 (default) leaves its natural direction.\n            var direction = m.direction === -1 ? -1 : 1;\n            var angle = ((m.angle != null ? m.angle : 45) * Math.PI) / 180;\n            var t = Math.tan(angle);\n            var dx = style === 'chevron' ? (direction * half) / (Math.abs(t) > 1e-3 ? t : 1e-3) : 0;\n            var group = sidesLayer.add({ name: \"marks\".concat(i), make: 'collection' });\n            for (var k = 0; k < count; k += 1) {\n                var ox = (k - (count - 1) / 2) * spacing; // along-edge offset, centered\n                var points = style === 'chevron'\n                    ? [[ox - dx, half], [ox, 0], [ox - dx, -half]]\n                    : [[ox, -half], [ox, half]];\n                group.add({ name: \"mark\".concat(k), make: 'polyline', points: points, width: width, color: color });\n            }\n            sideMarkEls[i] = group;\n            // Built hidden when requested, so the marks don't flash before a runtime\n            // reveal. showSideMarks(i) brings them in; showAll() honours the flag.\n            if (m.startHidden) {\n                group.hide();\n                sideMarksHidden[i] = true;\n            }\n        }\n    }\n    function buildAngles() {\n        for (var i = 0; i < angleCount(); i += 1)\n            createAngle(i);\n    }\n    // Build the angle mark, select-state overlay and selection ring for angle `i`.\n    // Shared by buildAngles (the initial pass, no override) and the dynamic\n    // countAngle() API, which may need to create an angle that wasn't configured\n    // up front. `specOverride` is merged *over* the configured spec (so countAngle\n    // can force `show: true` even under style: select_angles); without it the\n    // configured spec is used unchanged. The angles/select layers are created\n    // lazily, so an angle added after build still lands in a real collection\n    // (appended on top of the outline rather than under it — fine for the\n    // attention-drawing count animation).\n    function createAngle(i, specOverride) {\n        var a = o.angles;\n        // 'square' (the default when unset) auto-draws the perpendicular notch on\n        // corners that are actually right angles; 'arc' forces a curved arc at 90°.\n        var rightAngle = a != null && a !== true && a !== false ? a.rightAngle : undefined;\n        // The arms are [prev, vertex, next]; with positive `direction` FigureOne\n        // draws the mark on the CCW side of that, which is the *exterior* for a\n        // CCW polygon. So the interior side is -1 for CCW winding, +1 for CW;\n        // `outside` flips it. direction is preserved across setAngle(), so it\n        // doesn't need re-applying in updateGeometry().\n        var interiorDir = isCCW(vertices) ? -1 : 1;\n        {\n            var base = resolveAngleSpec(i);\n            var spec = specOverride != null\n                ? Fig.joinObjects({}, base != null ? base : {}, specOverride)\n                : base;\n            if (spec == null)\n                return;\n            if (anglesLayer == null) {\n                anglesLayer = container.add({ name: 'angles', make: 'collection' });\n            }\n            var _a = angleVertexIndices(i), p1 = _a[0], p2 = _a[1], p3 = _a[2];\n            // Resting arc geometry/appearance — computed up front (not just inside the\n            // `show` block) so the select-state overlay below can default its width /\n            // arc-count / radius to the same values the resting mark uses.\n            var baseArcs = spec.arcs != null ? spec.arcs : 1;\n            var baseWidth = spec.lineWidth != null ? spec.lineWidth : 0.01;\n            var baseRadius = spec.radius != null ? spec.radius : 0.2;\n            // Default the concentric-arc gap (only relevant when arcs > 1) to a few\n            // line-widths so `arcs: 2|3` shows distinct arcs without the author also\n            // setting arcSpacing. A step of 0 would draw them coincident.\n            var baseSpacing = spec.arcSpacing != null ? spec.arcSpacing : baseArcs > 1 ? baseWidth * 3 : 0;\n            // Arc smoothness -> gap avoidance. FigureOne draws an angle arc as\n            // floor(angle / (2*PI/sides)) straight segments (curve `sides` defaults to\n            // 100 => 3.6 deg/segment) and centres the sub-segment remainder, so each\n            // end of the arc can stop a fraction of a segment short of its arm. That\n            // leaves a small but visible gap between the arc and the polygon's sides,\n            // worst on shapes whose interior angle isn't a multiple of the segment\n            // angle (triangle / hexagon / heptagon / octagon). Raise `sides` so the\n            // leftover is negligible. The shortfall is an ARC LENGTH ~= radius*(PI/sides),\n            // so scale the count with the arc's (outer) radius to bound the gap to a\n            // fixed ~0.0015 units rather than picking one count that's too coarse for\n            // large arcs and wastefully fine for small ones.\n            var arcSidesForRadius = function (radius) {\n                return Math.max(100, Math.ceil((Math.PI * radius) / 0.0015));\n            };\n            // The angle mark (arc / fill). Skipped when show: false — the corner can\n            // still be selectable and show its ring (e.g. style: select_angles).\n            if (spec.show !== false) {\n                var useFill = spec.fillColor != null;\n                angleEls[i] = anglesLayer.add({\n                    name: \"angle\".concat(i),\n                    make: 'collections.angle',\n                    p1: vertices[p1],\n                    p2: vertices[p2],\n                    p3: vertices[p3],\n                    direction: spec.outside === true ? -interiorDir : interiorDir,\n                    color: useFill\n                        ? spec.fillColor\n                        : spec.lineColor != null ? spec.lineColor : o.color,\n                    curve: {\n                        num: baseArcs,\n                        step: baseSpacing,\n                        radius: baseRadius,\n                        width: baseWidth,\n                        fill: useFill,\n                        sides: arcSidesForRadius(baseRadius + (baseArcs - 1) * baseSpacing),\n                        autoRightAngle: rightAngle !== 'arc',\n                    },\n                    label: spec.label != null\n                        ? {\n                            text: labelText(spec.label.text),\n                            color: spec.label.color,\n                            scale: spec.label.size != null ? spec.label.size : 1,\n                            offset: spec.label.space,\n                            // Math content -> use the math font (arial) rather than the\n                            // figure default body font (montserrat).\n                            font: { family: defaultFontFamilyMath },\n                        }\n                        : undefined,\n                });\n                // Built hidden when requested, so the arc doesn't flash before a runtime\n                // reveal. showAngleMark(i) brings it in; showAll() honours the flag.\n                if (spec.startHidden) {\n                    angleEls[i].hide();\n                    angleMarkHidden[i] = true;\n                }\n            }\n            // The select-state mark: a separate arc/fill shown only while this corner\n            // is selected, layered just over the resting mark. Its width / arc-count\n            // default to the resting mark's, but `states.select` can override them\n            // (lineWidth, arcs) and switch line<->fill (fillColor) — so selection can\n            // be cued by a thicker arc or a filled sector, not only a colour change.\n            // Built as its own element (like the side overlay); applyStates() toggles\n            // it. radius tracks the resting mark so the two stay concentric.\n            var selState = spec.states != null ? spec.states.select : undefined;\n            if (selState != null) {\n                var selFill = selState.fillColor != null;\n                var selArcs = selState.arcs != null ? selState.arcs : baseArcs;\n                var selWidth = selState.lineWidth != null ? selState.lineWidth : baseWidth;\n                var selSpacing = selState.arcSpacing != null\n                    ? selState.arcSpacing\n                    : selArcs > 1 ? selWidth * 3 : 0;\n                var mark = anglesLayer.add({\n                    name: \"angleSelect\".concat(i),\n                    make: 'collections.angle',\n                    p1: vertices[p1],\n                    p2: vertices[p2],\n                    p3: vertices[p3],\n                    direction: spec.outside === true ? -interiorDir : interiorDir,\n                    color: selFill\n                        ? selState.fillColor\n                        : selState.lineColor != null ? selState.lineColor : o.color,\n                    curve: {\n                        num: selArcs,\n                        step: selSpacing,\n                        radius: baseRadius,\n                        width: selWidth,\n                        fill: selFill,\n                        sides: arcSidesForRadius(baseRadius + (selArcs - 1) * selSpacing),\n                        autoRightAngle: rightAngle !== 'arc',\n                    },\n                });\n                mark.hide();\n                angleSelectMarks[i] = mark;\n            }\n            // The \"you picked this\" ring around the vertex. Hidden at rest; shown\n            // while the corner is selected (applyStates). Repositioned to the vertex\n            // in updateGeometry. Added to the top `select` layer so it draws in front\n            // of everything. Built independently of the mark, so it works even when\n            // the mark is hidden (select_angles). States (select/dim/highlight)\n            // recolour the angle mark itself and are applied in applyStates().\n            if (spec.selectCircle != null && spec.selectCircle !== false) {\n                var sc = spec.selectCircle;\n                var hasFill = sc.fill != null;\n                if (selectLayer == null) {\n                    selectLayer = container.add({ name: 'select', make: 'collection' });\n                }\n                var circle = selectLayer.add({\n                    name: \"selectCircle\".concat(i),\n                    make: 'polygon',\n                    sides: 40,\n                    radius: sc.radius != null ? sc.radius : 0.15,\n                    position: vertices[p2],\n                    color: hasFill ? sc.fill : sc.color != null ? sc.color : o.color,\n                    // Outline only unless a fill is given (a ring around the vertex).\n                    line: hasFill\n                        ? undefined\n                        : { width: sc.lineWidth != null ? sc.lineWidth : 0.01 },\n                });\n                circle.hide();\n                angleSelectCircles[i] = circle;\n            }\n            // A small regular-polygon marker sitting on the vertex (selectVertex).\n            // Like selectCircle it's hidden at rest, shown on select, and lives in the\n            // top `select` layer; repositioned to the vertex in updateGeometry.\n            if (spec.selectVertex != null && spec.selectVertex !== false) {\n                var sv = spec.selectVertex;\n                var hasFill = sv.fill != null;\n                if (selectLayer == null) {\n                    selectLayer = container.add({ name: 'select', make: 'collection' });\n                }\n                var marker = selectLayer.add({\n                    name: \"selectVertex\".concat(i),\n                    make: 'polygon',\n                    sides: sv.sides != null ? sv.sides : 4,\n                    radius: sv.radius != null ? sv.radius : 0.1,\n                    rotation: ((sv.rotation != null ? sv.rotation : 0) * Math.PI) / 180,\n                    position: vertices[p2],\n                    color: hasFill ? sv.fill : sv.color != null ? sv.color : o.color,\n                    // Outline only unless a fill is given.\n                    line: hasFill\n                        ? undefined\n                        : { width: sv.lineWidth != null ? sv.lineWidth : 0.01 },\n                });\n                marker.hide();\n                angleSelectVertices[i] = marker;\n            }\n            // A two-segment corner bracket hugging the corner (selectCorner). Its arms\n            // run a short way along the two sides meeting at the vertex; hidden at rest,\n            // shown on select, and its points re-follow the sides in updateGeometry.\n            if (spec.selectCorner != null && spec.selectCorner !== false) {\n                var cc = spec.selectCorner;\n                var len = cc.length != null ? cc.length : 0.15;\n                if (selectLayer == null) {\n                    selectLayer = container.add({ name: 'select', make: 'collection' });\n                }\n                var width = cc.lineWidth != null ? cc.lineWidth : 0.01;\n                var cap = {\n                    head: 'circle', radius: width / 2, sides: 20, align: 'mid',\n                };\n                var bracket = selectLayer.add({\n                    name: \"selectCorner\".concat(i),\n                    make: 'polyline',\n                    points: cornerBracketPoints(i, len),\n                    width: width,\n                    color: cc.color != null ? cc.color : o.color,\n                    arrow: cc.roundEnds === true ? { start: cap, end: cap } : undefined,\n                });\n                bracket.hide();\n                angleSelectCorners[i] = bracket;\n                angleSelectCornerLen[i] = len;\n            }\n        }\n    }\n    // The corner square overlays: for each corner with a `squareAngles` spec, a\n    // group holding an optional filled interior and an optional outline, both\n    // built from squarePoints() and re-pointed in updateGeometry as the polygon\n    // deforms. The fill and outline are separate shapes (a single primitive with a\n    // `line` draws the outline *only*), so a square can be filled and bordered at\n    // once. Every group is built hidden — showSquareAngle(i, true) reveals it.\n    function buildSquares() {\n        if (squaresLayer == null && squaresFrontLayer == null)\n            return;\n        for (var i = 0; i < angleCount(); i += 1) {\n            var spec = resolveSquareSpec(i);\n            if (spec == null || spec.show === false)\n                continue;\n            // `front` squares go in the top layer, the rest under the base outline.\n            var layer = spec.front === true ? squaresFrontLayer : squaresLayer;\n            if (layer == null)\n                continue;\n            var size = spec.size != null ? spec.size : 0.2;\n            var align = spec.align != null ? spec.align : 'auto';\n            var width = spec.lineWidth != null ? spec.lineWidth : 0.01;\n            var pts = squarePoints(i, size, align);\n            if (pts == null)\n                continue; // degenerate corner — nothing to align to.\n            var group = layer.add({ name: \"square\".concat(i), make: 'collection' });\n            if (spec.fill != null) {\n                squareFillEls[i] = group.add({\n                    name: 'fill',\n                    make: 'generic',\n                    points: squareTriangles(pts),\n                    drawType: 'TRIANGLES',\n                    color: spec.fill,\n                });\n            }\n            if (width > 0) {\n                squareLineEls[i] = group.add({\n                    name: 'line',\n                    make: 'polyline',\n                    points: pts,\n                    close: true,\n                    width: width,\n                    color: spec.color != null ? spec.color : o.color,\n                });\n            }\n            group.hide(); // hidden until showSquareAngle(i, true).\n            squareEls[i] = group;\n            squareSizes[i] = size;\n            squareAligns[i] = align;\n            squareHidden[i] = true;\n        }\n    }\n    // The grow lines: one plain polyline each, laid exactly on its starting side\n    // (extensions 0/0) and defaulting to the polygon's own stroke so it is\n    // invisible until it is coloured or grown. `visible: false` builds it hidden\n    // instead (showGrowLine(i, true) reveals it). Nothing is animated at build —\n    // growLine()/placeLine() drive them from here on.\n    function buildGrowLines() {\n        if (growLinesLayer == null && growLinesFrontLayer == null)\n            return;\n        var stroke = baseStroke();\n        for (var i = 0; i < growLineCount(); i += 1) {\n            var spec = resolveGrowLineSpec(i);\n            if (spec == null || spec.show === false)\n                continue;\n            var layer = spec.front === true ? growLinesFrontLayer : growLinesLayer;\n            if (layer == null)\n                continue;\n            var anchor = normalizeSide(spec.side != null ? spec.side : i);\n            var inset = spec.inset != null ? spec.inset : 0;\n            var ext = typeof inset === 'number'\n                ? [-inset, -inset] : [-inset[0], -inset[1]];\n            if (spec.length != null) {\n                var rest = growLinePoints(anchor, 0, 0);\n                if (rest == null)\n                    continue; // degenerate side — nothing to lie along.\n                var half = (spec.length - Math.hypot(rest[1].x - rest[0].x, rest[1].y - rest[0].y)) / 2;\n                ext = [half, half];\n            }\n            var pts = growLinePoints(anchor, ext[0], ext[1]);\n            if (pts == null)\n                continue; // degenerate side — nothing to lie along.\n            var width = spec.width != null ? spec.width : stroke.width;\n            var cap = {\n                head: 'circle', radius: width / 2, sides: 20, align: 'mid',\n            };\n            growLineEls[i] = layer.add({\n                name: \"growLine\".concat(i),\n                make: 'polyline',\n                points: pts,\n                width: width,\n                color: spec.color != null ? spec.color : o.color,\n                arrow: spec.roundEnds === true ? { start: cap, end: cap } : undefined,\n            });\n            growLineAnchors[i] = anchor;\n            growLineExts[i] = ext;\n            growLinePlacing[i] = false;\n            growLineGrown[i] = false;\n            growLinePressShown[i] = false;\n            growLineHidden[i] = spec.visible === false;\n            growLineHideOnSelect[i] = spec.hideWhenSelected === true;\n            growLineSelHidden[i] = false;\n            if (growLineHidden[i])\n                growLineEls[i].hide();\n            // Seeded most-recently-used-first, so unshifting in build order leaves the\n            // lowest index at the back: the first press claims line 0, the next line 1.\n            growLineOrder.unshift(i);\n        }\n    }\n    // The curve overlays: one polyline per detected curve, traced along the whole\n    // run of segments in a single element. That is the point of doing it this way —\n    // a polyline joins its interior corners as corners, so only the run's two ends\n    // are drawn as line ends, and the overlay reads as one smooth stroke instead of\n    // a chain of separate little lines with a cap at every join. Built hidden\n    // (unless `visible`), like the corner squares — showCurve(i, true) reveals it.\n    function buildCurves() {\n        if (curvesLayer == null && curvesFrontLayer == null)\n            return;\n        var stroke = baseStroke();\n        var _loop_3 = function (i) {\n            var spec = resolveCurveSpec(i);\n            if (spec == null || spec.show === false)\n                return \"continue\";\n            var layer = spec.front === true ? curvesFrontLayer : curvesLayer;\n            if (layer == null)\n                return \"continue\";\n            var pts = curvePoints(i);\n            if (pts == null)\n                return \"continue\";\n            var width = spec.width != null ? spec.width : stroke.width;\n            var color = spec.color != null ? spec.color : o.color;\n            // A closed run has no ends, so there is nothing to cap (see roundEnds).\n            var capped = spec.roundEnds === true && !curveClosed[i];\n            // Capped overlays live in their own collection so showCurve / showAll /\n            // the dissolve drive the polyline and both caps together; uncapped ones\n            // stay a bare polyline named `curve${i}`, exactly as before.\n            var host = capped\n                ? layer.add({ name: \"curve\".concat(i), make: 'collection' })\n                : layer;\n            curveLineEls[i] = host.add({\n                name: capped ? 'line' : \"curve\".concat(i),\n                make: 'polyline',\n                points: pts,\n                close: curveClosed[i],\n                width: width,\n                color: color,\n                dash: spec.dash,\n            });\n            if (capped) {\n                // radius = width/2 against a `widthIs: 'mid'` stroke, so each disc sits\n                // flush with the stroke's two edges and reads as a round cap rather than\n                // a blob stuck on the end.\n                curveCapEls[i] = [pts[0], pts[pts.length - 1]].map(function (p, k) { return host.add({\n                    name: \"cap\".concat(k),\n                    make: 'polygon',\n                    sides: 20,\n                    radius: width / 2,\n                    color: color,\n                    position: p,\n                }); });\n            }\n            curveEls[i] = capped ? host : curveLineEls[i];\n            curveHidden[i] = spec.visible !== true;\n            if (curveHidden[i])\n                curveEls[i].hide();\n        };\n        for (var i = 0; i < curveSides.length; i += 1) {\n            _loop_3(i);\n        }\n    }\n    // Re-derive curve overlay `i`'s drawn points from its run of sides and the\n    // live vertices, so it keeps hugging the shape as it deforms. The end caps\n    // ride the run's two end points, so they track the deformation too.\n    function refreshCurve(i) {\n        if (curveLineEls[i] == null)\n            return;\n        var pts = curvePoints(i);\n        if (pts == null)\n            return;\n        curveLineEls[i].custom.updatePoints({ points: pts });\n        var caps = curveCapEls[i];\n        if (caps != null) {\n            caps[0].setPosition(pts[0]);\n            caps[1].setPosition(pts[pts.length - 1]);\n        }\n    }\n    // Re-derive line `i`'s drawn points from its anchor + extensions. Called on\n    // every reflow and at the end of both animations. Skipped while a placeLine\n    // animation owns the points (it is interpolating between two anchors, and\n    // already re-reads the live vertices each frame).\n    function refreshGrowLine(i) {\n        var line = growLineEls[i];\n        if (line == null || growLinePlacing[i])\n            return;\n        var pts = growLinePoints(growLineAnchors[i], growLineExts[i][0], growLineExts[i][1]);\n        if (pts != null)\n            line.custom.updatePoints({ points: pts });\n    }\n    function buildOverlays() {\n        for (var i = 0; i < sideCount(); i += 1) {\n            var spec = resolveLineSpec(i);\n            if (spec == null || spec.overlay == null)\n                continue;\n            overlayEls[i] = overlaysLayer.add({\n                name: \"overlay\".concat(i),\n                make: 'polyline',\n                points: [vertices[i], vertices[sideEndIndex(i)]],\n                width: spec.overlay.width != null ? spec.overlay.width : 0.02,\n                color: spec.overlay.color != null ? spec.overlay.color : o.color,\n            });\n            // Hidden at rest; applyStates()/applyOverlayState() show it and apply\n            // overlay.states (select/dim/highlight) when the side's state changes.\n            overlayEls[i].hide();\n        }\n    }\n    function buildSelectShapes() {\n        for (var i = 0; i < sideCount(); i += 1) {\n            var spec = resolveLineSpec(i);\n            if (spec == null || spec.selectShape == null)\n                continue;\n            var ss = spec.selectShape;\n            var isRect = ss.shape === 'rectangle';\n            var hasFill = ss.fill != null;\n            var color = hasFill ? ss.fill : ss.color != null ? ss.color : o.color;\n            var line = hasFill\n                ? undefined\n                : { width: ss.lineWidth != null ? ss.lineWidth : 0.01 };\n            var width = ss.width != null ? ss.width : 0.12; // thickness across edge\n            var margin = ss.margin != null ? ss.margin : 0.06; // extra length each end\n            var length_2 = ss.length; // fixed along-edge length, overrides margin\n            // Geometry-affecting make options (everything except width/height), re-used\n            // to resize via updatePoints in updateGeometry. An oval is a real `ellipse`\n            // (not a scaled disc), the rectangle a real rounded `rectangle`, both built\n            // at the edge's true dimensions so the stroke width and corners stay\n            // correct — no non-uniform scaling.\n            var geom = isRect\n                ? { corner: { radius: ss.corner != null ? ss.corner : 0, sides: 5 }, line: line }\n                : { sides: 40, line: line };\n            // A filled rectangle on a curve segment is drawn as a band mitred into its\n            // run neighbours, so a selected curve reads as one smooth stroke rounded\n            // only at its two ends — not a chain of rounded rectangles whose\n            // overlapping ends scallop the outline.\n            if (isRect && hasFill && length_2 == null && curveRunOf(i) != null) {\n                var corner = ss.corner != null ? ss.corner : 0;\n                selectShapeMeta[i] = {\n                    width: width,\n                    margin: margin,\n                    geom: geom,\n                    banded: true,\n                    corner: corner,\n                };\n                selectShapeEls[i] = selectLayer.add({\n                    name: \"selectShape\".concat(i),\n                    make: 'generic',\n                    points: curveBandTriangles(i, width, margin, corner),\n                    drawType: 'TRIANGLES',\n                    color: color,\n                });\n                selectShapeEls[i].hide();\n                continue;\n            }\n            var j = sideEndIndex(i);\n            var edgeLen = Math.hypot(vertices[j].x - vertices[i].x, vertices[j].y - vertices[i].y);\n            selectShapeEls[i] = selectLayer.add(Fig.joinObjects({}, geom, {\n                name: \"selectShape\".concat(i),\n                make: isRect ? 'rectangle' : 'ellipse',\n                width: length_2 != null ? length_2 : edgeLen + 2 * margin,\n                height: width,\n                color: color,\n            }));\n            selectShapeMeta[i] = { width: width, margin: margin, length: length_2, geom: geom };\n            selectShapeEls[i].hide(); // shown only while the side is selected.\n        }\n    }\n    // Expand a polygon outward by `buffer` (constant-width miter offset). Used for\n    // the secondary near-touch area. Returns the points unchanged when buffer is 0\n    // or the polygon is degenerate. Winding is detected from the signed area so\n    // the offset is always outward; the miter length is capped at sharp corners.\n    // Polygon winding: true when the vertices run counter-clockwise (positive\n    // signed area). Used both for outward offsetting and for choosing the\n    // interior side of angle marks.\n    function isCCW(pts) {\n        var area2 = 0;\n        for (var i = 0; i < pts.length; i += 1) {\n            var a = pts[i];\n            var b = pts[(i + 1) % pts.length];\n            area2 += a.x * b.y - b.x * a.y;\n        }\n        return area2 > 0;\n    }\n    function outsetPolygon(pts, buffer) {\n        var n = pts.length;\n        if (n < 3 || buffer === 0)\n            return pts;\n        var ccw = isCCW(pts);\n        var unit = function (dx, dy) {\n            var len = Math.sqrt(dx * dx + dy * dy) || 1;\n            return [dx / len, dy / len];\n        };\n        var out = [];\n        for (var i = 0; i < n; i += 1) {\n            var prev = pts[(i - 1 + n) % n];\n            var cur = pts[i];\n            var next = pts[(i + 1) % n];\n            var _a = unit(cur.x - prev.x, cur.y - prev.y), e1x = _a[0], e1y = _a[1];\n            var _b = unit(next.x - cur.x, next.y - cur.y), e2x = _b[0], e2y = _b[1];\n            // Outward edge normals (rotate edge dir; sign from winding).\n            var n1x = ccw ? e1y : -e1y;\n            var n1y = ccw ? -e1x : e1x;\n            var n2x = ccw ? e2y : -e2y;\n            var n2y = ccw ? -e2x : e2x;\n            var mx = n1x + n2x;\n            var my = n1y + n2y;\n            var mlen = Math.sqrt(mx * mx + my * my);\n            if (mlen < 1e-6) {\n                mx = n1x;\n                my = n1y;\n            }\n            else {\n                mx /= mlen;\n                my /= mlen;\n            }\n            // Miter length = buffer / cos(half-angle); cap at sharp corners.\n            var cos = mx * n1x + my * n1y;\n            var scale = cos > 0.2 ? buffer / cos : buffer / 0.2;\n            out.push(Fig.getPoint([cur.x + mx * scale, cur.y + my * scale]));\n        }\n        return out;\n    }\n    // Keep a drag pad's debug outline (if any, debug mode only) overlaid on it by\n    // copying its transform — so it tracks position, rotation and scale, including\n    // while the pad is being actively dragged.\n    function syncDebugBorder(dragPad) {\n        if (dragPad == null || dragPad.custom.debugBorder == null)\n            return;\n        var dbg = dragPad.custom.debugBorder;\n        dbg.setPosition(dragPad.getPosition());\n        dbg.setRotation(dragPad.getRotation());\n        var sc = dragPad.getScale();\n        dbg.setScale(sc.x, sc.y);\n    }\n    // A corner pad is a disc centred on the vertex, but the square its press\n    // toggles is anchored AT that vertex and opens into the corner — reaching\n    // `size * sqrt(2)` out to its far corner, well past a disc sized for the vertex\n    // alone. Left as-is, most of the visible square is not the corner's touch\n    // target: a tap there falls through to the side pad running underneath (and\n    // extends the side) or hits nothing at all, even though the square is the whole\n    // affordance the learner is aiming at.\n    //\n    // So the pad's touch area is the union of the two. FigureOne tests each island\n    // of a multi-part touchBorder separately (point-in-polygon, see\n    // FigureElementPrimitive.isBeingTouched), so the disc and the square are simply\n    // listed side by side — no hull, and no filler geometry between them. The disc\n    // island is the pad's own `drawBorder` (what the default `touchBorder: 'border'`\n    // would have used), so this only ever *adds* to the target, and honours whatever\n    // `radius` / `touchRadius` / `sides` the pad was built with.\n    //\n    // Called on every reflow because an 'auto' square re-picks and re-follows its\n    // base edge as the polygon deforms. The square island is included whether or not\n    // the square is currently shown, so the corner's target doesn't move under the\n    // learner's finger as they toggle it.\n    function refreshCornerPressTouchBorder(v) {\n        if (!cornerPressesSquare[v])\n            return;\n        var pad = cornerSelectPads[v];\n        if (pad == null)\n            return;\n        var disc = pad.drawBorder;\n        // No usable draw border to extend -> leave the pad on its default touch\n        // border rather than replacing it with something smaller.\n        if (!Array.isArray(disc) || disc.length === 0)\n            return;\n        var ai = angleIndexForVertex(v);\n        // Only corners that actually carry a square (a `show: false` square spec\n        // builds none) get the second island; the rest keep the plain disc.\n        var pts = squareEls[ai] != null\n            ? squarePoints(ai, squareSizes[ai], squareAligns[ai])\n            : null;\n        if (pts == null) {\n            pad.touchBorder = disc;\n            return;\n        }\n        // squarePoints() is in the polygon's space; the touch border is in the pad's\n        // own draw space, whose origin is the vertex the pad sits on.\n        var origin = vertices[v];\n        var square = pts.map(function (p) { return Fig.getPoint([p.x - origin.x, p.y - origin.y]); });\n        pad.touchBorder = disc.concat([square]);\n        if (o.debug)\n            syncPressSquareDebug(pad, v, square);\n    }\n    // Debug-only companion to the above: addDebugBorder outlines the pad's disc, so\n    // without this the `debug` outline would understate the touch area by exactly\n    // the square we just added. Built on first use rather than in buildCornerPads\n    // because the square's size/align aren't known until buildSquares has run,\n    // which is after the pads are built (see build()).\n    function syncPressSquareDebug(pad, v, square) {\n        var dbg = pad.custom.debugPressSquare;\n        if (dbg == null) {\n            dbg = padsLayer.add({\n                name: \"cornerPressSquare\".concat(v, \"Debug\"),\n                make: 'polyline',\n                points: square,\n                close: true,\n                width: 0.004,\n                color: [0, 0.7, 0, 0.7],\n            });\n            dbg.isTouchable = false;\n            dbg.border = [[]]; // debug aid — never part of the measured size.\n            pad.custom.debugPressSquare = dbg;\n        }\n        else {\n            dbg.custom.updatePoints({ points: square });\n        }\n        dbg.setPosition(vertices[v]);\n    }\n    // --- SELECTION / INTERACTION STATES -------------------------------------\n    // Which state an item is in, given its selection/highlight flags and whether\n    // anything at all is selected. Precedence: a selected item shows `select`\n    // even if also highlighted; an unselected highlighted item shows `highlight`;\n    // any other item shows `dim` while something else is selected; else resting.\n    function stateFor(selected, highlighted, anySelected) {\n        if (selected)\n            return 'select';\n        if (highlighted)\n            return 'highlight';\n        if (anySelected)\n            return 'dim';\n        return 'rest';\n    }\n    // Resting colour of an angle mark: its fill colour if it fills, else its line\n    // colour, else the manipulative colour.\n    function angleRestingColor(spec) {\n        if (spec.fillColor != null)\n            return spec.fillColor;\n        if (spec.lineColor != null)\n            return spec.lineColor;\n        return o.color;\n    }\n    // The colour override for a given state, or null when that state defines none\n    // (so the mark keeps its resting colour). Width/arc-count changes aren't\n    // animated — colour is the state cue for angle marks.\n    function angleStateColor(spec, state) {\n        if (state === 'rest' || spec.states == null)\n            return null;\n        var s = spec.states[state];\n        if (s == null)\n            return null;\n        if (s.fillColor != null)\n            return s.fillColor;\n        if (s.lineColor != null)\n            return s.lineColor;\n        return null;\n    }\n    // Show/hide and restyle a side's overlay stroke for the given state. The\n    // overlay is hidden at rest; shown in `select` (using states.select over the\n    // base overlay look), and in `dim`/`highlight` only when that state defines an\n    // appearance (otherwise it stays hidden).\n    function applyOverlayState(i, spec, state) {\n        var overlay = spec.overlay;\n        if (overlay == null || overlayEls[i] == null)\n            return;\n        var base = { color: overlay.color, width: overlay.width };\n        var stateOverride = state !== 'rest' && overlay.states != null ? overlay.states[state] : undefined;\n        var look = null;\n        if (state === 'select') {\n            look = Fig.joinObjects({}, base, stateOverride != null ? stateOverride : {});\n        }\n        else if (state !== 'rest' && stateOverride != null) {\n            look = Fig.joinObjects({}, base, stateOverride);\n        }\n        if (look == null) {\n            applyIndicator(overlayEls[i], \"overlay\".concat(i), false);\n            return;\n        }\n        // Restyle before revealing, so a dissolve-in fades up the new look rather\n        // than the one left over from the previous state.\n        overlayEls[i].setColor(look.color != null ? look.color : o.color);\n        var a = vertices[i];\n        var b = vertices[sideEndIndex(i)];\n        overlayEls[i].custom.updatePoints({\n            points: [a, b],\n            width: look.width != null ? look.width : 0.02,\n        });\n        applyIndicator(overlayEls[i], \"overlay\".concat(i), true);\n    }\n    // Reflect the selection/highlight sets onto every angle and side: recolour\n    // angle marks per their state, show/hide each selectCircle, restyle each\n    // overlay, and show/hide each selectShape. Cheap to call on every selection\n    // change (and after setState).\n    function applyStates() {\n        var anySelected = selectedAngles.size + selectedSides.size > 0;\n        for (var i = 0; i < angleCount(); i += 1) {\n            var spec = resolveAngleSpec(i);\n            if (spec == null)\n                continue;\n            var state = stateFor(selectedAngles.has(i), highlightedAngles.has(i), anySelected);\n            var hasSelMark = angleSelectMarks[i] != null;\n            // Recolour the resting mark per state (only if a mark was drawn). When a\n            // dedicated select overlay exists it shows the selected look, so the base\n            // mark stays at its resting colour on select (the overlay sits on top);\n            // dim/highlight still recolour the base mark. Recolour just the arc/fill\n            // (`_curve`), not the whole angle — setColor on the angle collection would\n            // cascade to the `label` child and clobber its own (build-time) colour.\n            if (angleEls[i] != null) {\n                var c = void 0;\n                if (state === 'select' && hasSelMark) {\n                    c = angleRestingColor(spec);\n                }\n                else {\n                    var color = angleStateColor(spec, state);\n                    c = color != null ? color : angleRestingColor(spec);\n                }\n                var curve = angleEls[i]._curve;\n                if (curve != null)\n                    curve.setColor(c);\n                else\n                    angleEls[i].setColor(c);\n            }\n            // Show the select-state overlay while selected (independent of the resting\n            // mark, so it works even when that mark is hidden, show: false).\n            applyIndicator(angleSelectMarks[i], \"selectAngleMark\".concat(i), state === 'select');\n            // ... and show the selection ring while selected (independent of the\n            // mark, so select_angles — ring only, no mark — works).\n            applyIndicator(angleSelectCircles[i], \"selectCircle\".concat(i), state === 'select');\n            // The vertex marker and corner bracket are independent selections — each\n            // shows from its own set, NOT the angle `state`, so a corner can be lit as\n            // a bracket while its angle mark stays unselected (and vice versa).\n            applyIndicator(angleSelectVertices[i], \"selectVertex\".concat(i), selectedVertices.has(i));\n            applyIndicator(angleSelectCorners[i], \"selectCorner\".concat(i), selectedCorners.has(i));\n        }\n        for (var i = 0; i < sideCount(); i += 1) {\n            var spec = resolveLineSpec(i);\n            if (spec == null)\n                continue;\n            var state = stateFor(selectedSides.has(i), highlightedSides.has(i), anySelected);\n            applyIndicator(selectShapeEls[i], \"selectShape\".concat(i), state === 'select');\n            applyOverlayState(i, spec, state);\n        }\n        refreshGrowLineSelection(stateFadeDuration);\n        // Refresh the selected-count readout (if any) now the selection is current.\n        updateCounter();\n        // Question-level hook: lets content JS keep its own decorations in step\n        // with the selection (e.g. hide a \"tap here\" hint while its corner is\n        // selected). Called after every selection change — a tap, selectX,\n        // clearSelection, setState — with the current selection and the fade\n        // duration (seconds; 0 = instant).\n        var onSelection = element.custom.onSelectionApplied;\n        if (typeof onSelection === 'function') {\n            onSelection({\n                angles: Array.from(selectedAngles),\n                sides: Array.from(selectedSides),\n                vertices: Array.from(selectedVertices),\n                corners: Array.from(selectedCorners),\n            }, stateFadeDuration);\n        }\n    }\n    // Hide / show each hideWhenSelected grow line to match whether the side it\n    // lies on is selected (see PolyGrowLineSpec.hideWhenSelected).\n    function refreshGrowLineSelection(duration) {\n        for (var i = 0; i < growLineEls.length; i += 1) {\n            var line = growLineEls[i];\n            if (line == null || !growLineHideOnSelect[i])\n                continue;\n            var selected = selectedSides.has(growLineAnchors[i]);\n            if (selected === growLineSelHidden[i])\n                continue;\n            growLineSelHidden[i] = selected;\n            dissolveDecoration(line, \"growLineFade\".concat(i), !growLineHidden[i] && !selected, duration);\n        }\n    }\n    // --- REFLOW (our updatePoints — drives every layer from `vertices`) -----\n    function updateGeometry(next) {\n        vertices = next;\n        // Repositioning pads below re-fires their setTransformCallback; suppress\n        // that re-entrancy while we drive every layer from `vertices`.\n        suppressPad = true;\n        // Refresh the drawn points and the (exact) native touch border together so\n        // both track the polygon as it deforms.\n        if (baseLine != null) {\n            baseLine.custom.updatePoints({ points: vertices, touchBorder: vertices });\n        }\n        // Re-triangulate the interior fill so it tracks the deforming polygon.\n        if (fillElement != null) {\n            fillElement.custom.updatePoints({ points: fillTriangles() });\n        }\n        // Secondary near-touch grab area: the polygon outset by touchBorderBuffer\n        // (point-in-polygon tested in getTouchableElements, addManipulative.ts).\n        var outset = outsetPolygon(vertices, o.touchBorderBuffer);\n        container.custom.secondaryTouchBounds = outset;\n        if (debugLine != null)\n            debugLine.custom.updatePoints({ points: outset });\n        for (var i = 0; i < vertices.length; i += 1) {\n            if (cornerPads[i] != null)\n                cornerPads[i].setPosition(vertices[i]);\n            // Realign the drag pad too — except the one being actively dragged, which\n            // owns its (mouse-tracking) position until release.\n            if (cornerDragPads[i] != null && cornerDragPads[i] !== activeDragPad) {\n                cornerDragPads[i].setPosition(vertices[i]);\n            }\n            syncDebugBorder(cornerDragPads[i]); // follows the drag pad (incl. while dragged)\n            if (cornerSelectPads[i] != null) {\n                cornerSelectPads[i].setPosition(vertices[i]);\n                syncDebugBorder(cornerSelectPads[i]);\n                // The square this corner presses re-follows its base edge as the polygon\n                // deforms, so the pad's union touch border is rebuilt with it.\n                refreshCornerPressTouchBorder(i);\n            }\n        }\n        for (var i = 0; i < sideCount(); i += 1) {\n            var j = sideEndIndex(i);\n            var a = vertices[i];\n            var b = vertices[j];\n            if (sideEls[i] != null) {\n                sideEls[i].setEndPoints(a, b, sideOffsets[i]);\n                // Recompute the reported length for 'value' labels as the side changes.\n                if (sideValueFmt[i] != null) {\n                    var len = Math.hypot(b.y - a.y, b.x - a.x);\n                    sideEls[i].setLabel(formatLength(len, sideValueFmt[i]));\n                }\n            }\n            // Per-side layers that track the edge (a, b):\n            var mid = Fig.getPoint([(a.x + b.x) / 2, (a.y + b.y) / 2]);\n            var edgeAngle = Math.atan2(b.y - a.y, b.x - a.x);\n            // Congruence marks: ride the edge midpoint, rotated along the edge.\n            if (sideMarkEls[i] != null) {\n                sideMarkEls[i].setPosition(mid);\n                sideMarkEls[i].setRotation(edgeAngle);\n            }\n            // Full-length pads scale along their local x (which the rotation aligns\n            // to the edge) so their length matches the current edge. The visible and\n            // drag pads can have different base lengths, so they scale separately.\n            var edgeLen = Math.hypot(b.x - a.x, b.y - a.y);\n            if (sidePads[i] != null) {\n                sidePads[i].setPosition(mid);\n                sidePads[i].setRotation(edgeAngle);\n                if (sidePadFull[i])\n                    sidePads[i].setScale(edgeLen / sidePadBaseW[i], 1);\n            }\n            if (sideDragPads[i] != null && sideDragPads[i] !== activeDragPad) {\n                sideDragPads[i].setPosition(mid);\n                sideDragPads[i].setRotation(edgeAngle);\n                if (sideDragFull[i])\n                    sideDragPads[i].setScale(edgeLen / sideDragBaseW[i], 1);\n            }\n            syncDebugBorder(sideDragPads[i]);\n            if (sideSelectPads[i] != null) {\n                sideSelectPads[i].setPosition(mid);\n                sideSelectPads[i].setRotation(edgeAngle);\n                if (sideSelectFull[i])\n                    sideSelectPads[i].setScale(edgeLen / sideSelectBaseW[i], 1);\n                syncDebugBorder(sideSelectPads[i]);\n            }\n            if (overlayEls[i] != null)\n                overlayEls[i].custom.updatePoints({ points: [a, b] });\n            if (selectShapeEls[i] != null && selectShapeMeta[i].banded === true) {\n                var m = selectShapeMeta[i];\n                selectShapeEls[i].custom.updatePoints({\n                    points: curveBandTriangles(i, m.width, m.margin, m.corner || 0),\n                });\n            }\n            else if (selectShapeEls[i] != null) {\n                selectShapeEls[i].setPosition(mid);\n                selectShapeEls[i].setRotation(edgeAngle);\n                // Rebuild at the edge's true dimensions (length along + margin each end,\n                // thickness across) rather than scaling, so the stroke and corners stay\n                // undistorted. Re-pass `geom` so corner/line/sides survive the rebuild.\n                // A fixed `length` overrides the edge-tracking (edgeLen + 2*margin).\n                var m = selectShapeMeta[i];\n                selectShapeEls[i].custom.updatePoints(Fig.joinObjects({}, m.geom, {\n                    width: m.length != null ? m.length : edgeLen + 2 * m.margin,\n                    height: m.width,\n                }));\n            }\n            if (braceEls[i] != null && braceEls[i].setEndPoints != null) {\n                // Dimension-line annotation: re-span the edge at its stored offset.\n                braceEls[i].setEndPoints(a, b, braceOffsets[i]);\n            }\n            // TODO: brace annotation reflow (once the brace kind is built).\n        }\n        for (var i = 0; i < angleCount(); i += 1) {\n            var _a = angleVertexIndices(i), p1 = _a[0], p2 = _a[1], p3 = _a[2];\n            if (angleEls[i] != null) {\n                angleEls[i].setAngle({\n                    p1: vertices[p1],\n                    p2: vertices[p2],\n                    p3: vertices[p3],\n                });\n            }\n            if (angleSelectMarks[i] != null) {\n                angleSelectMarks[i].setAngle({\n                    p1: vertices[p1],\n                    p2: vertices[p2],\n                    p3: vertices[p3],\n                });\n            }\n            if (angleSelectCircles[i] != null) {\n                angleSelectCircles[i].setPosition(vertices[p2]);\n            }\n            if (angleSelectVertices[i] != null) {\n                angleSelectVertices[i].setPosition(vertices[p2]);\n            }\n            // Re-seat the corner square on the (possibly moved) vertex: its base edge\n            // re-picks/re-follows the polygon edge, so a square on a corner being\n            // dragged keeps hugging it — and an 'auto' square swaps to the other edge\n            // if that one becomes the more axis-aligned of the two.\n            if (squareEls[i] != null) {\n                var pts = squarePoints(i, squareSizes[i], squareAligns[i]);\n                if (pts != null) {\n                    if (squareFillEls[i] != null) {\n                        squareFillEls[i].custom.updatePoints({ points: squareTriangles(pts) });\n                    }\n                    if (squareLineEls[i] != null) {\n                        squareLineEls[i].custom.updatePoints({ points: pts });\n                    }\n                }\n            }\n            // Re-trace the corner bracket so its arms keep following the two sides.\n            if (angleSelectCorners[i] != null) {\n                angleSelectCorners[i].custom.updatePoints({\n                    points: cornerBracketPoints(i, angleSelectCornerLen[i]),\n                });\n            }\n        }\n        // Re-lay each grow line on its (possibly moved) side, keeping however far it\n        // has been grown past the ends — so a dragged corner or a morph carries an\n        // extended line with it instead of leaving it behind.\n        for (var i = 0; i < growLineEls.length; i += 1)\n            refreshGrowLine(i);\n        // Re-trace each curve overlay over its (possibly moved) run of segments. The\n        // run itself is fixed at build — a morph that flattens a curve leaves the\n        // overlay tracing what are now straight sides rather than dropping it.\n        for (var i = 0; i < curveEls.length; i += 1)\n            refreshCurve(i);\n        // Keep the counter readout anchored to the (possibly reshaped) bounding box.\n        positionCounter();\n        suppressPad = false;\n        element.custom.state = computeState();\n    }\n    // --- PAD DRAG SEMANTICS -------------------------------------------------\n    // A corner pad moves its own vertex; a side pad translates both endpoints so\n    // the whole edge follows. Both route through updateGeometry, so an animation\n    // that drives a pad reshapes the polygon and reflows annotations identically.\n    function moveCorner(i, p) {\n        var next = vertices.slice();\n        next[i] = Fig.getPoint(p);\n        updateGeometry(next);\n    }\n    function moveSide(i, delta) {\n        var j = sideEndIndex(i);\n        // Parse `delta` (accept an [x, y] array as well as a point) so this matches\n        // moveCorner's signature — both are exposed on element.custom.\n        var d = Fig.getPoint(delta);\n        var next = vertices.slice();\n        next[i] = Fig.getPoint([next[i].x + d.x, next[i].y + d.y]);\n        next[j] = Fig.getPoint([next[j].x + d.x, next[j].y + d.y]);\n        updateGeometry(next);\n    }\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    element.notificationHelper = new NotificationHelper();\n    // setupManipulative wires the shared helpers: trash(), setMoveBounds(),\n    // bounds shadow, preserveChildColor. selectBorder is null here — angle/side\n    // selection is handled per-pad rather than as a whole-manipulative select.\n    setupManipulative(element, null, o);\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    // computeState() builds the serializable PolyState. It's kept as a local\n    // function (not only element.custom.getState) because internal bookkeeping\n    // refreshes element.custom.state even on a static poly — e.g. updateGeometry()\n    // at build, or a guide's countAngle() — and that must not depend on the public\n    // method existing.\n    function computeState() {\n        var p = element.getPosition();\n        // `eqn_name` may be a string path or the resolved collection — normalise to\n        // a path so setManipulatives() can re-find this element on restore.\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        // Sparse: store only the corners that differ from their initial layout.\n        var corners = {};\n        vertices.forEach(function (v, i) {\n            if (initial[i] == null)\n                return;\n            if (v.x !== initial[i].x || v.y !== initial[i].y) {\n                corners[i] = [Fig.round(v.x, 3), Fig.round(v.y, 3)];\n            }\n        });\n        var out = {\n            e: e_name, p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            corners: corners,\n        };\n        // Selection is part of the answer state; store it sparsely (sorted).\n        if (selectedAngles.size > 0)\n            out.sa = Array.from(selectedAngles).sort(function (x, y) { return x - y; });\n        if (selectedSides.size > 0)\n            out.ss = Array.from(selectedSides).sort(function (x, y) { return x - y; });\n        if (selectedVertices.size > 0)\n            out.sv = Array.from(selectedVertices).sort(function (x, y) { return x - y; });\n        if (selectedCorners.size > 0)\n            out.sc = Array.from(selectedCorners).sort(function (x, y) { return x - y; });\n        return out;\n    }\n    // Only define the public getState/setState — the save/restore opt-in the\n    // manage.ts layer checks for — when the poly can actually change: a\n    // selectable or movable pad (hasAnswerPads), or a movable whole shape\n    // (isTouchable: true). A static, display-only poly defines neither, so\n    // getManipulativesState/setManipulatives skip it and it contributes nothing\n    // to the answer payload and is never restored from a snapshot. Note this is\n    // hasAnswerPads, not hasTouchPads: a press-only poly is interactive but only\n    // as a presentation cue, so it stays out of the answer payload too (the cost\n    // being that its squares / grow lines reset to their built state on reload).\n    var tracksState = o.isTouchable !== false && (hasAnswerPads() || o.isTouchable === true);\n    if (tracksState) {\n        element.custom.getState = computeState;\n        element.custom.setState = function (stats) {\n            element.setPosition(Fig.parsePoint(stats.p));\n            var next = initial.map(function (v, i) {\n                return (stats.corners && stats.corners[i] != null\n                    ? Fig.getPoint(stats.corners[i])\n                    : Fig.getPoint([v.x, v.y]));\n            });\n            updateGeometry(next);\n            // Restore the selection sets, then reflect them onto the appearance.\n            allSelectionSets.forEach(function (s) { return s.clear(); });\n            if (stats.sa != null)\n                stats.sa.forEach(function (i) { return selectedAngles.add(i); });\n            if (stats.ss != null)\n                stats.ss.forEach(function (i) { return selectedSides.add(i); });\n            if (stats.sv != null)\n                stats.sv.forEach(function (i) { return selectedVertices.add(i); });\n            if (stats.sc != null)\n                stats.sc.forEach(function (i) { return selectedCorners.add(i); });\n            applyStates();\n            element.custom.moved = true;\n        };\n    }\n    // Exposed so animation / tests can drive geometry directly (see file header).\n    element.custom.updateGeometry = updateGeometry;\n    element.custom.moveCorner = moveCorner;\n    element.custom.moveSide = moveSide;\n    // Selection / highlight API for animation, guides and tests. `on` omitted\n    // toggles; pass true (select) / false (deselect) to force.\n    // clearSelection() empties both sets.\n    // selectAngle/selectSide mirror a learner tapping the select pad exactly:\n    // they apply the selection (single-aware), reflow appearance, update the saved\n    // state, and notify the engine via fig.answerChanged() so the answer is\n    // re-checked. (They don't set window.clickHandled — there's no real click/\n    // ancestor handler to suppress.)\n    // highlight* are different: a transient hover/pulse cue, independent of the\n    // `select` cardinality and the answer state, so they never fire answerChanged.\n    //\n    // Every one of them takes a trailing `duration` (seconds): 0 (the default, and\n    // what a learner's tap always uses) switches the indicators instantly, and a\n    // positive value dissolves in / out whichever indicators this call turns on or\n    // off — the selectShape / overlay on a side, the select-state mark, ring,\n    // vertex marker or corner bracket on a corner. Only the appearing / vanishing\n    // indicators fade: the answer state itself flips immediately (so the engine\n    // sees the selection at once, mid-fade), and the `dim` recolour applied to the\n    // other sides and angles is instant, being a colour change rather than an\n    // opacity one.\n    var toggleInto = function (set, i, on) {\n        if (on != null ? on : !set.has(i))\n            set.add(i);\n        else\n            set.delete(i);\n    };\n    element.custom.applyStates = applyStates;\n    element.custom.selectAngle = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        applySelectMode(selectedAngles, i, on != null ? on : !selectedAngles.has(i));\n        applyStatesFading(duration);\n        element.custom.state = computeState();\n        fig.answerChanged();\n    };\n    element.selectAngle = element.custom.selectAngle;\n    element.custom.selectSide = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        applySelectMode(selectedSides, i, on != null ? on : !selectedSides.has(i));\n        applyStatesFading(duration);\n        element.custom.state = computeState();\n        fig.answerChanged();\n    };\n    element.selectSide = element.custom.selectSide;\n    // selectVertex / selectCorner select a corner's selectVertex marker /\n    // selectCorner bracket — independent of selectAngle, so a vertex can be lit on\n    // one corner and an angle on another without showing all three at once. Keyed\n    // by the same angle (corner) index the `angles` option block uses to configure\n    // the indicator. Like selectAngle: single-aware, reflows appearance, updates\n    // saved state and fires answerChanged.\n    element.custom.selectVertex = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        applySelectMode(selectedVertices, i, on != null ? on : !selectedVertices.has(i));\n        applyStatesFading(duration);\n        element.custom.state = computeState();\n        fig.answerChanged();\n    };\n    element.selectVertex = element.custom.selectVertex;\n    element.custom.selectCorner = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        applySelectMode(selectedCorners, i, on != null ? on : !selectedCorners.has(i));\n        applyStatesFading(duration);\n        element.custom.state = computeState();\n        fig.answerChanged();\n    };\n    element.selectCorner = element.custom.selectCorner;\n    // Light corner `i` / side `i` in its `highlight` look (the states.highlight\n    // override on the angle mark or the side overlay). `on` omitted toggles.\n    // Presentation only — no answerChanged, nothing persisted. Aliased onto the\n    // element like the other cues, since that is the only path a speech token can\n    // reach (|e:P1,highlightSide,0,True| looks up element[method], not .custom).\n    // A side's highlight look is drawn by the overlay, so it can be dissolved in /\n    // out with `duration` like the selections; an angle's is a recolour of the\n    // existing mark, which stays instant whatever duration is passed.\n    element.custom.highlightAngle = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        toggleInto(highlightedAngles, i, on);\n        applyStatesFading(duration);\n    };\n    element.highlightAngle = element.custom.highlightAngle;\n    element.custom.highlightSide = function (i, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        toggleInto(highlightedSides, i, on);\n        applyStatesFading(duration);\n    };\n    element.highlightSide = element.custom.highlightSide;\n    // Show or hide one of the built-hidden decoration groups (a side's congruence\n    // marks, a corner's angle arc, a corner's square), optionally dissolving over\n    // `duration` seconds — 0 switches instantly. `key` names this decoration's\n    // animation and its fnMap callbacks, so each one animates independently.\n    //\n    // The dissolve is driven by fnMap-registered callbacks rather than FigureOne's\n    // built-in dissolveIn/dissolveOut so the animation is SERIALIZABLE and survives\n    // a speech pause/resume inside a play: an inline callback is dropped from\n    // figure.getState(), which would strand the decoration mid-fade. (Same pattern\n    // as morph below and clock.ts.) fnMap is element-scoped and the keys are\n    // per-decoration, so they never collide; the from/to closure survives in memory\n    // (same-context pause).\n    //\n    // Callers own the desired-visibility bookkeeping (sideMarksHidden /\n    // angleMarkHidden / squareHidden) that showAll() re-asserts; this only drives\n    // the element.\n    function dissolveDecoration(group, key, show, duration) {\n        // Cancel an in-flight dissolve on this decoration so a reversed call starts\n        // from the live opacity rather than two animations fighting over it. 'freeze'\n        // (rather than the default) leaves the opacity where it is and skips the old\n        // settle trigger — that trigger closes over the *previous* call's direction,\n        // so completing it here could hide what we are about to fade in. Guarded —\n        // older FigureOne builds may not expose animations.cancel.\n        if (element.animations != null && element.animations.cancel != null) {\n            element.animations.cancel(key, 'freeze');\n        }\n        if (duration <= 0) {\n            indicatorFading[key] = false;\n            group.setOpacity(1); // clear any opacity left by a cancelled dissolve\n            if (show)\n                group.show();\n            else\n                group.hide();\n            return;\n        }\n        indicatorFading[key] = true;\n        // Dissolve from the decoration's *current* opacity, so reversing mid-fade\n        // picks up where it left off instead of jumping to full/zero first. A hidden\n        // one starts transparent and is shown immediately, so a fade-in is visible\n        // from nothing.\n        var from = group.isShown ? group.opacity : 0;\n        var to = show ? 1 : 0;\n        if (show) {\n            // show() BEFORE setOpacity: FigureOne's show() resets opacity to 1, so\n            // seeding the start opacity first would be clobbered and the decoration\n            // would flash at full opacity for the frame before the first animation\n            // callback runs.\n            group.show();\n            group.setOpacity(from);\n        }\n        element.fnMap.add(\"\".concat(key, \"Fade\"), function (p) {\n            group.setOpacity(from + (to - from) * p);\n        });\n        element.fnMap.add(\"\".concat(key, \"FadeEnd\"), function () {\n            // Settle: a faded-out decoration is hidden outright and its opacity\n            // restored, so a later show() (or showAll) doesn't reveal an invisible one.\n            indicatorFading[key] = false;\n            group.setOpacity(1);\n            if (!show)\n                group.hide();\n        });\n        element.animations.new(key)\n            .custom({ callback: \"\".concat(key, \"Fade\"), duration: duration, progression: 'linear' })\n            .trigger({ callback: \"\".concat(key, \"FadeEnd\") })\n            .start();\n    }\n    // Show / hide side `index`'s congruence marks (the ticks / chevrons built by\n    // buildSideMarks). `duration` (seconds) animates the change with a dissolve;\n    // 0 (default) shows/hides instantly. `on` omitted toggles current visibility;\n    // pass true (show) / false (hide) to force. No-op for a side that has no marks\n    // group. Marks aren't part of the answer state, so this never fires\n    // answerChanged — it's a presentation cue, like highlight*.\n    element.custom.showSideMarks = function (index, duration, on) {\n        if (duration === void 0) { duration = 0; }\n        var group = sideMarkEls[index];\n        if (group == null)\n            return;\n        var show = on != null ? on : !group.isShown;\n        // Track desired visibility so showAll() re-asserts it (a startHidden mark\n        // revealed here stays revealed; one hidden here stays hidden through a reveal).\n        sideMarksHidden[index] = !show;\n        dissolveDecoration(group, \"sideMarks\".concat(index), show, duration);\n    };\n    element.showSideMarks = element.custom.showSideMarks;\n    // Convenience inverse of showSideMarks: hide side `index`'s marks (animated\n    // over `duration` seconds, or instantly when 0/omitted).\n    element.custom.hideSideMarks = function (index, duration) {\n        if (duration === void 0) { duration = 0; }\n        element.custom.showSideMarks(index, duration, false);\n    };\n    element.hideSideMarks = element.custom.hideSideMarks;\n    // Show / hide corner `index`'s resting angle arc/fill (the mark built by\n    // createAngle) — the angle analogue of showSideMarks, for arcs built with\n    // `angles.startHidden`. `duration` (seconds) animates with a dissolve; 0\n    // (default) is instant. `on` omitted toggles; pass true (show) / false (hide)\n    // to force. No-op for a corner with no arc (show: false, never built). This is\n    // the resting mark only — the select-state overlay is driven by selectAngle.\n    // Presentation cue (not answer state), so it never fires answerChanged.\n    element.custom.showAngleMark = function (index, duration, on) {\n        if (duration === void 0) { duration = 0; }\n        var mark = angleEls[index];\n        if (mark == null)\n            return;\n        var show = on != null ? on : !mark.isShown;\n        // Track desired visibility so showAll() re-asserts it (see sideMarksHidden).\n        angleMarkHidden[index] = !show;\n        dissolveDecoration(mark, \"angleMark\".concat(index), show, duration);\n    };\n    element.showAngleMark = element.custom.showAngleMark;\n    // Convenience inverse of showAngleMark: hide corner `index`'s arc (animated\n    // over `duration` seconds, or instantly when 0/omitted).\n    element.custom.hideAngleMark = function (index, duration) {\n        if (duration === void 0) { duration = 0; }\n        element.custom.showAngleMark(index, duration, false);\n    };\n    element.hideAngleMark = element.custom.hideAngleMark;\n    // Show / hide corner `index`'s square overlay (built by buildSquares). `on`\n    // omitted toggles current visibility; pass true (show) / false (hide) to\n    // force. `duration` (seconds) dissolves the square in / out; 0 (default) is\n    // instant. No-op for a corner with no square configured. Note the argument\n    // order differs from showSideMarks/showAngleMark (`on` before `duration`).\n    // Squares aren't answer state, so this never fires answerChanged — it's a\n    // presentation cue, like highlight* and showAngleMark.\n    element.custom.showSquareAngle = function (index, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        var group = squareEls[index];\n        if (group == null)\n            return;\n        // Toggle off the *desired* state, not isShown: a group mid dissolve-out is\n        // still `isShown`, so toggling off that would keep hiding it instead of\n        // reversing the fade (which dissolveDecoration handles from the live opacity).\n        // Matters for a learner pressing a corner twice in quick succession.\n        var show = on != null ? on : squareHidden[index] === true;\n        // Track desired visibility so showAll() re-asserts it — a form reveal must\n        // not pop a square into view, and must not re-hide one shown here.\n        squareHidden[index] = !show;\n        dissolveDecoration(group, \"squareAngle\".concat(index), show, duration);\n    };\n    element.showSquareAngle = element.custom.showSquareAngle;\n    // Convenience inverse of showSquareAngle: hide corner `index`'s square\n    // (animated over `duration` seconds, or instantly when 0/omitted).\n    element.custom.hideSquareAngle = function (index, duration) {\n        if (duration === void 0) { duration = 0; }\n        element.custom.showSquareAngle(index, false, duration);\n    };\n    element.hideSquareAngle = element.custom.hideSquareAngle;\n    // --- CURVE OVERLAYS -----------------------------------------------------\n    // Show / hide curve `index`'s overlay (built by buildCurves). Same contract as\n    // showSquareAngle: `on` omitted toggles, true/false forces; `duration`\n    // (seconds) dissolves it in / out, 0 (default) is instant. No-op for an index\n    // that isn't a detected curve, or whose overlay was turned off with\n    // `each: { i: false }`. Not answer state — a presentation cue, so it never\n    // fires answerChanged.\n    element.custom.showCurve = function (index, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        var el = curveEls[index];\n        if (el == null)\n            return;\n        // Toggle off the *desired* state, not isShown (see showSquareAngle): an\n        // overlay mid dissolve-out is still shown, and toggling that would keep\n        // hiding it instead of reversing the fade.\n        var show = on != null ? on : curveHidden[index] === true;\n        // Track desired visibility so showAll() re-asserts it.\n        curveHidden[index] = !show;\n        dissolveDecoration(el, \"curve\".concat(index), show, duration);\n    };\n    element.showCurve = element.custom.showCurve;\n    // Convenience inverse of showCurve: hide curve `index`'s overlay (animated\n    // over `duration` seconds, or instantly when 0/omitted).\n    element.custom.hideCurve = function (index, duration) {\n        if (duration === void 0) { duration = 0; }\n        element.custom.showCurve(index, false, duration);\n    };\n    element.hideCurve = element.custom.hideCurve;\n    // How many curves were detected (see detectCurves). 0 when `curves` is off or\n    // the shape has none — so content can branch on whether a shape is curved at\n    // all without knowing which shape it drew.\n    element.custom.curveCount = function () { return curveSides.length; };\n    element.curveCount = element.custom.curveCount;\n    // What curve `index` actually covers: the run of side indices (in order,\n    // possibly wrapping past the closing side), whether it goes all the way round,\n    // its total arc length, and whether its overlay is currently showing. Null for\n    // an index that isn't a detected curve. Curve indices are derived rather than\n    // authored, so this is how content (and tests) find out which curve is which.\n    element.custom.curveInfo = function (index) {\n        var sides = curveSides[index];\n        if (sides == null)\n            return null;\n        var length = 0;\n        sides.forEach(function (s) {\n            var a = vertices[s];\n            var b = vertices[sideEndIndex(s)];\n            if (a != null && b != null)\n                length += Math.hypot(b.x - a.x, b.y - a.y);\n        });\n        return {\n            sides: sides.slice(),\n            closed: curveClosed[index] === true,\n            length: length,\n            shown: curveEls[index] != null && curveHidden[index] !== true,\n        };\n    };\n    element.curveInfo = element.custom.curveInfo;\n    // --- GROW LINES ---------------------------------------------------------\n    // Stop whatever animation currently owns grow line `index` and settle it, so\n    // the next call starts from a definite anchor + extension pair rather than two\n    // animations fighting over the same points. 'freeze' (rather than the default)\n    // leaves the drawn points alone and skips the old settle trigger, which closes\n    // over the *previous* call's target. An interrupted placeLine is committed to\n    // its destination side — the anchor is already stored there, so clearing the\n    // flag and reflowing snaps it home instead of stranding it between two sides.\n    // Guarded: older FigureOne builds may not expose animations.cancel.\n    function settleGrowLine(index) {\n        if (element.animations != null && element.animations.cancel != null) {\n            element.animations.cancel(\"growLine\".concat(index), 'freeze');\n        }\n        if (growLinePlacing[index]) {\n            growLinePlacing[index] = false;\n            refreshGrowLine(index);\n        }\n    }\n    // How far past each end of its side line `index` would have to reach for both\n    // ends to land on the figure's scene boundary, inset by `gap` (0 = exactly on\n    // the boundary, positive = stop that far short of it, negative = overshoot\n    // past it). The two ends are computed independently, so an angled line runs\n    // out to whichever edge — left/right or top/bottom — it meets first, rather\n    // than both ends growing by the same amount.\n    //\n    // The maths is done in FIGURE space: the polygon is positioned (and possibly\n    // scaled) by its host equation, so its own draw-space coordinates mean nothing\n    // against the scene rectangle until they're mapped through. The result is\n    // mapped back to draw units via the length ratio of the same segment in both\n    // spaces, which keeps rotation and scale correct.\n    function growLineBoundsExts(index, gap) {\n        var line = growLineEls[index];\n        var scene = fig.scene;\n        var rest = growLinePoints(growLineAnchors[index], 0, 0);\n        if (line == null || scene == null || rest == null)\n            return [0, 0];\n        if (line.pointFromSpaceToSpace == null)\n            return [0, 0];\n        var a = line.pointFromSpaceToSpace(rest[0], 'draw', 'figure');\n        var b = line.pointFromSpaceToSpace(rest[1], 'draw', 'figure');\n        var lenFig = Math.hypot(b.x - a.x, b.y - a.y);\n        var lenDraw = Math.hypot(rest[1].x - rest[0].x, rest[1].y - rest[0].y);\n        if (lenFig === 0 || lenDraw === 0)\n            return [0, 0];\n        var ux = (b.x - a.x) / lenFig;\n        var uy = (b.y - a.y) / lenFig;\n        var left = scene.left + gap;\n        var right = scene.right - gap;\n        var bottom = scene.bottom + gap;\n        var top = scene.top - gap;\n        // Distance from (px, py) along the unit direction (dx, dy) to the first\n        // inset edge it hits (the standard slab clip). A start point already outside\n        // the inset rectangle gives a negative distance — clamp to 0 so the line\n        // stays where it is rather than folding back on itself.\n        var reach = function (px, py, dx, dy) {\n            var t = Infinity;\n            if (dx > 0)\n                t = Math.min(t, (right - px) / dx);\n            else if (dx < 0)\n                t = Math.min(t, (left - px) / dx);\n            if (dy > 0)\n                t = Math.min(t, (top - py) / dy);\n            else if (dy < 0)\n                t = Math.min(t, (bottom - py) / dy);\n            if (!Number.isFinite(t))\n                return 0;\n            return t > 0 ? t : 0;\n        };\n        var scale = lenFig / lenDraw; // figure units per draw unit\n        return [\n            reach(a.x, a.y, -ux, -uy) / scale,\n            reach(b.x, b.y, ux, uy) / scale,\n        ];\n    }\n    // Animate line `index`'s two extensions to `target` over `duration` seconds\n    // (0 = jump). Shared by growLine and anything else that needs to move the\n    // extensions; the per-frame callback goes through the element's fnMap by NAME\n    // so the animation is SERIALIZABLE and survives a speech pause/resume inside a\n    // play — an inline .custom callback is dropped from figure.getState(), which\n    // would strand the line half grown. (Same pattern as morph / dissolveDecoration.)\n    function animateGrowLine(index, target, duration) {\n        settleGrowLine(index);\n        var key = \"growLine\".concat(index);\n        var from = [growLineExts[index][0], growLineExts[index][1]];\n        if (duration <= 0) {\n            growLineExts[index] = [target[0], target[1]];\n            refreshGrowLine(index);\n            return;\n        }\n        element.fnMap.add(\"\".concat(key, \"Grow\"), function (p) {\n            growLineExts[index] = [\n                from[0] + (target[0] - from[0]) * p,\n                from[1] + (target[1] - from[1]) * p,\n            ];\n            refreshGrowLine(index);\n        });\n        element.fnMap.add(\"\".concat(key, \"GrowEnd\"), function () {\n            growLineExts[index] = [target[0], target[1]];\n            refreshGrowLine(index);\n        });\n        element.animations.new(key)\n            .custom({ callback: \"\".concat(key, \"Grow\"), duration: duration, progression: 'easeinout' })\n            .trigger({ callback: \"\".concat(key, \"GrowEnd\") })\n            .start();\n    }\n    // Grow (or shrink) grow line `index` from wherever it currently reaches:\n    //\n    //   growLine(i, duration, value, 'bounds')  — (default mode) run both ends out\n    //     to the figure's scene boundary, leaving a `value` gap: 0 lands exactly on\n    //     the edge, positive stops that far short of it, negative overshoots past\n    //     it. Each end goes to whichever edge it meets first, so the line spans the\n    //     scene along the side's direction.\n    //   growLine(i, duration, value, 'length') — make the line `value` long in\n    //     total, both ends extending out equally from the side it lies on. A value\n    //     shorter than the side pulls the ends inside it (the line shrinks about\n    //     the side's midpoint); the line is never allowed to collapse past zero.\n    //\n    // `duration` (seconds) animates the change; 0 (default) is instant. `value`\n    // defaults to 0.2 (a small gap in 'bounds' mode). Grow lines aren't answer\n    // state, so this never fires answerChanged — it's a presentation cue.\n    // The extension pair line `index` must reach for the requested growth, or null\n    // for a degenerate side. Measured against the live layout (and its current\n    // anchor), so a poly that has been repositioned or morphed still runs its lines\n    // out to the real scene edges — and so the press path can defer this until the\n    // line has actually arrived on its new side.\n    function growTargetExts(index, value, mode) {\n        if (mode !== 'length')\n            return growLineBoundsExts(index, value);\n        var rest = growLinePoints(growLineAnchors[index], 0, 0);\n        if (rest == null)\n            return null;\n        var len = Math.hypot(rest[1].x - rest[0].x, rest[1].y - rest[0].y);\n        var half = (value - len) / 2;\n        return [half, half];\n    }\n    element.custom.growLine = function (index, duration, value, mode) {\n        if (duration === void 0) { duration = 0; }\n        if (value === void 0) { value = 0.2; }\n        if (mode === void 0) { mode = 'bounds'; }\n        if (growLineEls[index] == null)\n            return;\n        var target = growTargetExts(index, value, mode);\n        if (target == null)\n            return;\n        // Keep the press bookkeeping honest: a guide-driven grow leaves the line in\n        // the extended state (so a learner's press on that side retracts it) and\n        // counts as use (so their next press takes a different line).\n        growLineGrown[index] = target[0] !== 0 || target[1] !== 0;\n        touchGrowLine(index);\n        animateGrowLine(index, target, duration);\n    };\n    element.growLine = element.custom.growLine;\n    // Move grow line `index` onto the side that runs from vertex `pointIndex` to\n    // vertex `pointIndex + 1` (wrapping to vertex 0 past the last point), so it\n    // ends up perfectly overlapping that side — any growth it had is undone as it\n    // travels. `duration` (seconds) slides + rotates it across from wherever it is\n    // now; 0 (default) puts it there instantly. `pointIndex` wraps, so\n    // placeLine(i, poly.n) is side 0 and -1 is the last side. Like growLine this is\n    // a presentation cue and never fires answerChanged.\n    element.custom.placeLine = function (index, pointIndex, duration) {\n        if (duration === void 0) { duration = 0; }\n        var line = growLineEls[index];\n        if (line == null)\n            return;\n        settleGrowLine(index);\n        var from = growLineAnchors[index];\n        var fromExt = [growLineExts[index][0], growLineExts[index][1]];\n        var to = normalizeSide(pointIndex);\n        // Commit the destination immediately: the animation drives the drawn points\n        // itself (growLinePlacing blocks the reflow), so the stored anchor is already\n        // where the line is going — and an interrupted place lands there rather than\n        // between the two sides.\n        growLineAnchors[index] = to;\n        growLineExts[index] = [0, 0];\n        // A placed line ends up lying on its side (any growth undone), and the move\n        // counts as use — see touchGrowLine.\n        growLineGrown[index] = false;\n        touchGrowLine(index);\n        // A hideWhenSelected line now follows its new side's selection.\n        refreshGrowLineSelection(0);\n        if (duration <= 0) {\n            refreshGrowLine(index);\n            return;\n        }\n        var key = \"growLine\".concat(index);\n        growLinePlacing[index] = true;\n        // Both ends are re-read from the live vertices every frame (not captured\n        // once), so the line still tracks the polygon if it is dragged or morphed\n        // while the placement is in flight. fnMap-named for the same serializability\n        // reason as animateGrowLine.\n        element.fnMap.add(\"\".concat(key, \"Place\"), function (p) {\n            var a = growLinePoints(from, fromExt[0], fromExt[1]);\n            var b = growLinePoints(to, 0, 0);\n            if (a == null || b == null)\n                return;\n            line.custom.updatePoints({\n                points: [\n                    Fig.getPoint([\n                        a[0].x + (b[0].x - a[0].x) * p, a[0].y + (b[0].y - a[0].y) * p,\n                    ]),\n                    Fig.getPoint([\n                        a[1].x + (b[1].x - a[1].x) * p, a[1].y + (b[1].y - a[1].y) * p,\n                    ]),\n                ],\n            });\n        });\n        element.fnMap.add(\"\".concat(key, \"PlaceEnd\"), function () {\n            growLinePlacing[index] = false;\n            refreshGrowLine(index);\n        });\n        element.animations.new(key)\n            .custom({ callback: \"\".concat(key, \"Place\"), duration: duration, progression: 'easeinout' })\n            .trigger({ callback: \"\".concat(key, \"PlaceEnd\") })\n            .start();\n    };\n    element.placeLine = element.custom.placeLine;\n    // Show / hide grow line `index`. Same contract as showCurve: `on` omitted\n    // toggles, true/false forces; `duration` (seconds) dissolves it in / out, 0\n    // (default) is instant. Independent of where the line is or how far it reaches\n    // — a hidden line can still be placed and grown, it just isn't drawn — so a\n    // guide can hide a line, put it back on its side, and reveal it again on the\n    // next pair without the moves being seen. No-op for a line that was never\n    // built. Not answer state, so it never fires answerChanged.\n    element.custom.showGrowLine = function (index, on, duration) {\n        if (duration === void 0) { duration = 0; }\n        var line = growLineEls[index];\n        if (line == null)\n            return;\n        // Toggle off the *desired* state, not isShown (see showSquareAngle): a line\n        // mid dissolve-out is still shown, and toggling that would keep hiding it\n        // instead of reversing the fade.\n        var show = on != null ? on : growLineHidden[index] === true;\n        // Track desired visibility so showAll() re-asserts it.\n        growLineHidden[index] = !show;\n        // An explicit call takes the line out of the press's hands: a press that\n        // revealed it no longer owns re-hiding it.\n        growLinePressShown[index] = false;\n        dissolveDecoration(line, \"growLineFade\".concat(index), show && !growLineSelHidden[index], duration);\n    };\n    element.showGrowLine = element.custom.showGrowLine;\n    // Convenience inverse of showGrowLine: hide grow line `index` (animated over\n    // `duration` seconds, or instantly when 0/omitted).\n    element.custom.hideGrowLine = function (index, duration) {\n        if (duration === void 0) { duration = 0; }\n        element.custom.showGrowLine(index, false, duration);\n    };\n    element.hideGrowLine = element.custom.hideGrowLine;\n    // --- PRESSES (learner-driven squares / grow lines) ----------------------\n    // The tap actions behind `pad.press` (see PolyPadBase.press). Everything here\n    // is a presentation cue: it drives the same showSquareAngle / grow-line\n    // machinery a guide would, and like those it persists nothing and never fires\n    // answerChanged. The public element.pressCorner / element.pressSide below are\n    // exact twins of a tap, so guides and tests can drive the interaction (the same\n    // convention selectAngle follows for selection).\n    // A numeric field of the `press` options block, or its default.\n    function pressOpt(key, dflt) {\n        var p = o.press;\n        if (p == null || p[key] == null)\n            return dflt;\n        return p[key];\n    }\n    // How a pressed line extends. 'bounds' (default) runs it out to the scene edge.\n    function pressMode() {\n        var p = o.press;\n        return p != null && p.mode === 'length' ? 'length' : 'bounds';\n    }\n    // Mark line `index` as the most recently used, so it is the *last* one taken\n    // when a bare side is pressed. Called for every press that involves a line —\n    // a toggle counts as use just as a move does, so the line you just extended in\n    // place is not the one yanked away by your next press. The programmatic\n    // growLine/placeLine call it too, so a guide's placement is equally protected.\n    function touchGrowLine(index) {\n        var at = growLineOrder.indexOf(index);\n        if (at > -1)\n            growLineOrder.splice(at, 1);\n        growLineOrder.unshift(index);\n    }\n    // The least recently used line — the back of the recency queue, skipping any\n    // index that was never built (`show: false` / a degenerate side). -1 if none.\n    function leastUsedGrowLine() {\n        for (var i = growLineOrder.length - 1; i >= 0; i -= 1) {\n            if (growLineEls[growLineOrder[i]] != null)\n                return growLineOrder[i];\n        }\n        return -1;\n    }\n    // Move line `index` onto `side` and extend it out there, as one two-beat\n    // animation: it travels across (like placeLine), then grows (like growLine).\n    // It must be one animation because both of those animate under the same key and\n    // settle it first, so calling them back to back would cancel the travel.\n    function moveAndGrowLine(index, side, placeDuration, growDuration, value, mode) {\n        var line = growLineEls[index];\n        if (line == null)\n            return;\n        settleGrowLine(index);\n        var from = growLineAnchors[index];\n        var fromExt = [growLineExts[index][0], growLineExts[index][1]];\n        var to = normalizeSide(side);\n        // Commit the destination up front, exactly as placeLine does: the animation\n        // drives the drawn points itself (growLinePlacing blocks the reflow), so an\n        // interrupted press lands on the new side rather than between the two.\n        growLineAnchors[index] = to;\n        growLineExts[index] = [0, 0];\n        if (placeDuration <= 0) {\n            refreshGrowLine(index); // no travel — drop it on the side, then just grow.\n            var t = growTargetExts(index, value, mode);\n            animateGrowLine(index, t != null ? t : [0, 0], growDuration);\n            return;\n        }\n        var key = \"growLine\".concat(index);\n        growLinePlacing[index] = true;\n        // `target` is resolved on the grow leg's first frame rather than now, so the\n        // extension is measured from the side the line has by then arrived on (and\n        // reflects any repositioning / morphing during the travel) — the same lazy\n        // pattern morph uses for its `to`. All four callbacks go through fnMap by NAME\n        // so the whole two-beat move is SERIALIZABLE and survives a speech pause/\n        // resume; the names are press-specific so they never collide with the\n        // callbacks a plain placeLine / growLine registers under the same key.\n        var target = null;\n        var resolveTarget = function () {\n            if (target == null) {\n                var t = growTargetExts(index, value, mode);\n                target = t != null ? t : [0, 0];\n            }\n            return target;\n        };\n        element.fnMap.add(\"\".concat(key, \"PressPlace\"), function (p) {\n            var a = growLinePoints(from, fromExt[0], fromExt[1]);\n            var b = growLinePoints(to, 0, 0);\n            if (a == null || b == null)\n                return;\n            line.custom.updatePoints({\n                points: [\n                    Fig.getPoint([\n                        a[0].x + (b[0].x - a[0].x) * p, a[0].y + (b[0].y - a[0].y) * p,\n                    ]),\n                    Fig.getPoint([\n                        a[1].x + (b[1].x - a[1].x) * p, a[1].y + (b[1].y - a[1].y) * p,\n                    ]),\n                ],\n            });\n        });\n        element.fnMap.add(\"\".concat(key, \"PressPlaceEnd\"), function () {\n            growLinePlacing[index] = false;\n            growLineExts[index] = [0, 0];\n            refreshGrowLine(index);\n        });\n        element.fnMap.add(\"\".concat(key, \"PressGrow\"), function (p) {\n            var t = resolveTarget();\n            growLineExts[index] = [t[0] * p, t[1] * p];\n            refreshGrowLine(index);\n        });\n        element.fnMap.add(\"\".concat(key, \"PressGrowEnd\"), function () {\n            var t = resolveTarget();\n            growLineExts[index] = [t[0], t[1]];\n            refreshGrowLine(index);\n        });\n        var builder = element.animations.new(key)\n            .custom({\n            callback: \"\".concat(key, \"PressPlace\"), duration: placeDuration, progression: 'easeinout',\n        })\n            .trigger({ callback: \"\".concat(key, \"PressPlaceEnd\") });\n        // A zero grow duration skips the animated leg but still lands on the target\n        // (the settle trigger runs either way), rather than animating for 0 seconds.\n        if (growDuration > 0) {\n            builder = builder.custom({\n                callback: \"\".concat(key, \"PressGrow\"), duration: growDuration, progression: 'easeinout',\n            });\n        }\n        builder.trigger({ callback: \"\".concat(key, \"PressGrowEnd\") }).start();\n    }\n    // Press corner `index` (an angle/corner index): toggle its square overlay.\n    // No-op on a corner with no square configured.\n    function pressSquare(index) {\n        element.custom.showSquareAngle(index, undefined, pressOpt('squareDuration', 0.3));\n    }\n    // Keep a hidden line (`visible: false`, or one a guide hid) usable by presses:\n    // it is revealed the instant a press starts extending it, and faded back out\n    // over the retract that puts it back on its side — so the learner sees the\n    // stretch, and the shape is left as it was. Only a line the press itself\n    // revealed is re-hidden (growLinePressShown), so a line the guide has since\n    // shown outright is left alone.\n    function revealForPress(index, grow, duration) {\n        if (grow) {\n            if (!growLineHidden[index])\n                return; // already visible — nothing to do.\n            growLineHidden[index] = false;\n            growLinePressShown[index] = true;\n            dissolveDecoration(growLineEls[index], \"growLineFade\".concat(index), true, 0);\n            return;\n        }\n        if (!growLinePressShown[index])\n            return; // not ours to take away.\n        growLineHidden[index] = true;\n        growLinePressShown[index] = false;\n        dissolveDecoration(growLineEls[index], \"growLineFade\".concat(index), false, duration);\n    }\n    // Press side `index`:\n    //   - a line already on that side toggles between extended and lying exactly on\n    //     the side (it never moves);\n    //   - otherwise the least recently used line travels over and extends out.\n    // No-op when no grow lines are configured.\n    function pressExtend(index) {\n        if (growLineEls.length === 0)\n            return;\n        var side = normalizeSide(index);\n        var growDuration = pressOpt('growDuration', 0.8);\n        var value = pressOpt('value', 0.2);\n        var mode = pressMode();\n        // Anchors are committed the moment a move starts, so a line still travelling\n        // to this side counts as already on it — pressing again reverses the press.\n        var k = -1;\n        for (var i = 0; i < growLineEls.length; i += 1) {\n            if (growLineEls[i] != null && growLineAnchors[i] === side) {\n                k = i;\n                break;\n            }\n        }\n        if (k > -1) {\n            var grow = !growLineGrown[k];\n            // Set the intended state now, not when the animation lands, so two quick\n            // presses reverse each other instead of repeating the same one.\n            growLineGrown[k] = grow;\n            touchGrowLine(k);\n            revealForPress(k, grow, growDuration);\n            // Retracting always returns the line to exactly the side's length ([0, 0]),\n            // which is also the fallback if a degenerate side has no growth target.\n            var t = grow ? growTargetExts(k, value, mode) : null;\n            animateGrowLine(k, t != null ? t : [0, 0], growDuration);\n            return;\n        }\n        k = leastUsedGrowLine();\n        if (k < 0)\n            return;\n        growLineGrown[k] = true;\n        touchGrowLine(k);\n        revealForPress(k, true, growDuration);\n        moveAndGrowLine(k, side, pressOpt('placeDuration', 0.5), growDuration, value, mode);\n    }\n    // Programmatic twins of a learner's press, so guides / tests can drive the\n    // interaction exactly as a tap does (including the recency bookkeeping that\n    // decides which line moves next). `index` is a corner (angle) index for\n    // pressCorner and a side index for pressSide.\n    element.custom.pressCorner = function (index) { return pressSquare(index); };\n    element.pressCorner = element.custom.pressCorner;\n    element.custom.pressSide = function (index) { return pressExtend(index); };\n    element.pressSide = element.custom.pressSide;\n    // Read-only snapshot of grow line `index`: the side it lies on, how far it\n    // reaches past that side's two ends, and whether a press counts it as extended.\n    // Exposed for guides and tests (like updateGeometry / moveCorner above), which\n    // otherwise can't see any of it — a grown line's drawn points don't say which\n    // side it started from, and its extension is derived, not stored on the\n    // element. null for a line that was never built.\n    element.custom.growLineInfo = function (index) {\n        if (growLineEls[index] == null)\n            return null;\n        return {\n            side: growLineAnchors[index],\n            ext: [growLineExts[index][0], growLineExts[index][1]],\n            grown: growLineGrown[index] === true,\n        };\n    };\n    element.growLineInfo = element.custom.growLineInfo;\n    // Deselect everything (every kind at once). `duration` (seconds) dissolves the\n    // lit indicators out instead of switching them off; 0 (default) is instant.\n    element.custom.clearSelection = function (duration) {\n        if (duration === void 0) { duration = 0; }\n        allSelectionSets.forEach(function (s) { return s.clear(); });\n        applyStatesFading(duration);\n        element.custom.state = computeState();\n    };\n    element.clearSelection = element.custom.clearSelection;\n    // Count-one-angle step for a guided \"count the angles\" walkthrough. Idempotent\n    // building blocks so a guide can call it on an angle that has no mark and no\n    // counter yet:\n    //   - if no counter exists (and no external one is supplied), build the\n    //     internal counter from `options.counter`;\n    //   - if the corner hosting angle `index` has no selection pad, create one from\n    //     `options.pad` (so a corner the author never made selectable becomes\n    //     tappable);\n    //   - select angle `index`, pulse it for emphasis, and show the running count\n    //     of selected angles on the counter.\n    // `options` bundles `{ counter, pad }` option dicts (both optional).\n    // `counterElement` is an external text element to display the count on; when\n    // null/omitted the poly's own internal counter is used (created if needed).\n    element.custom.countAngle = function (index, options, counterElement) {\n        var opts = options != null ? options : {};\n        // Angle indices are 0-based and bounded by angleCount() (n for a closed\n        // polygon, n-2 for an open one). Bail on an out-of-range index rather than\n        // indexing past the vertex list (which crashes deep in pad creation).\n        if (index < 0 || index >= angleCount()) {\n            // eslint-disable-next-line no-console\n            console.warn(\"poly.countAngle: angle index \".concat(index, \" is out of range \")\n                + \"(0..\".concat(angleCount() - 1, \"); ignoring.\"));\n            return;\n        }\n        // Create the selection pad for this angle's corner if it isn't there yet, so\n        // the corner is tappable (its angle toggles on tap). A bare select pad is an\n        // invisible touch target, so countAngle defaults it to a *visible* highlight\n        // dot — otherwise nothing shows when you count. `options.pad` overrides the\n        // look (radius/fill/border/visible/etc).\n        var v = createCornerSelectPad(index, Fig.joinObjects({ visible: true, fill: [0, 0.45, 1, 1], radius: 0.08 }, opts.pad != null ? opts.pad : {}));\n        // Pick the counter to display on: an external element wins; otherwise ensure\n        // the internal one exists.\n        var counter = counterElement;\n        if (counter == null) {\n            ensureCounter(opts.counter);\n            counter = counterEl;\n        }\n        // Select the angle (single-aware) and reflect selection onto every layer.\n        // applyStates() refreshes the internal counter; do that before any external\n        // update below.\n        applySelectMode(selectedAngles, index, true);\n        applyStates();\n        // Pulse the angle for attention: the arc mark if one is drawn, else the lit\n        // selection ring, else the corner pad's visible handle (whichever exists).\n        var pulseTarget = angleEls[index] != null\n            ? angleEls[index]\n            : angleSelectCircles[index] != null\n                ? angleSelectCircles[index]\n                : cornerPads[v];\n        if (pulseTarget != null)\n            pulseTarget.pulse({ duration: 1, scale: 1.5 });\n        // Show the running count. The internal counter was just refreshed by\n        // applyStates(); an external element is set here to the same count, honouring\n        // any prefix/suffix passed in options.counter.\n        if (counter != null) {\n            if (counter !== counterEl) {\n                var c = opts.counter != null ? opts.counter : {};\n                var prefix = c.prefix != null ? c.prefix : '';\n                var suffix = c.suffix != null ? c.suffix : '';\n                counter.setText(\"\".concat(prefix).concat(selectedAngles.size).concat(suffix));\n            }\n            counter.show();\n        }\n        element.custom.state = computeState();\n    };\n    // Freeze or release the element's measured size border (see\n    // PolyMorphOptions.fixBorder). `true` snapshots the current border (in the\n    // element's own draw space) and pins `element.border` to it, so the footprint\n    // the host equation lays out against stops tracking the geometry — it holds\n    // until released. `false` restores the FigureOne 'children' default, so the\n    // border again aggregates from (and morphs with) the live shape. Guarded on\n    // getBorder so a build without it simply leaves the border alone.\n    function setBorderFixed(fixed) {\n        if (fixed) {\n            if (element.getBorder == null)\n                return;\n            element.border = element.getBorder('draw', 'border');\n        }\n        else {\n            element.border = 'children';\n        }\n    }\n    // --- MORPH (animated reshape) ------------------------------------------\n    // Animate the polygon from its current vertices to one or more target shapes.\n    // The vertex count is fixed (built per index), so each target is resolved to a\n    // vertex list and, if its count differs, resampled to the polygon's count\n    // (resampleToCount) — matched counts interpolate corner-to-corner. Every frame\n    // drives updateGeometry(), so pads, angle marks, side labels and the fill all\n    // reflow exactly as they do under a drag.\n    //\n    //   element.morph(target, options?)        — morph once to `target`.\n    //   element.morph(target, duration?)        — same, duration as a bare number.\n    //   element.morph([{ to, duration }, …], options?)  — a timed series.\n    //\n    // `target` (or a step's `to`) is a PolyMorphTarget: a `morphs` registry name\n    // (or the reserved 'init' for the starting shape), a points array, or an inline\n    // definition. The second arg is PolyMorphOptions\n    // ({ duration, progression, done, fixBorder }) or, for convenience (and so a\n    // speech token like `|e:P1,morph,triangle,1.5|` works), a bare duration number.\n    // Per-step duration/progression override the call defaults; `fixBorder`\n    // (default true) freezes the size border for the morph. Like highlight*/showSideMarks\n    // this is a presentation cue — it does not touch the answer state or fire\n    // answerChanged.\n    //\n    // Distinguishing a series from a single points-array target: a series is an\n    // array whose first element is a step object (has a `to` field); a points list\n    // is an array of points ([x, y] / {x, y}), which never has a `to`.\n    var isMorphStep = function (s) {\n        return s != null && !Array.isArray(s) && typeof s === 'object' && s.to !== undefined;\n    };\n    element.custom.morph = function (arg, options) {\n        // A bare number second arg is shorthand for { duration: n } (token-friendly).\n        var opts = typeof options === 'number'\n            ? { duration: options }\n            : options != null ? options : {};\n        var steps = Array.isArray(arg) && arg.length > 0 && isMorphStep(arg[0])\n            ? arg\n            : [{ to: arg }];\n        // Border handling: by default freeze the element's size border to its\n        // current (pre-morph) footprint so the host layout doesn't reflow as the\n        // shape animates — captured now, before the geometry starts changing, and\n        // left in place after the morph ends. `fixBorder: false` instead releases it\n        // back to the 'children' default so the border tracks (morphs with) the\n        // shape during this morph and stays tracking afterwards. setBorderFixed\n        // guards getBorder so older FigureOne builds degrade to a no-op.\n        setBorderFixed(opts.fixBorder !== false);\n        // Cancel any in-flight morph so a new one starts from the live geometry\n        // (and two morphs never fight over `vertices`). Guarded — older FigureOne\n        // builds may not expose animations.cancel.\n        if (element.animations != null && element.animations.cancel != null) {\n            element.animations.cancel('morph');\n        }\n        var builder = element.animations.new('morph');\n        steps.forEach(function (step, i) {\n            var duration = step.duration != null ? step.duration : opts.duration != null ? opts.duration : 1;\n            var progression = step.progression != null\n                ? step.progression\n                : opts.progression != null ? opts.progression : 'easeinout';\n            // `from` is captured on this step's first frame (= the previous step's end\n            // / the live geometry), so a chained series morphs each leg from where the\n            // last finished. `to` is resolved (and count-reconciled) at the same time.\n            // `p` arrives already eased by `progression`, so interpolation is linear in\n            // p and lands exactly on `to` at p === 1.\n            var from = null;\n            var to = null;\n            // Name the per-step callback via fnMap so the morph is SERIALIZABLE and survives\n            // speech pause/resume: an inline .custom callback is dropped from figure.getState(),\n            // freezing the shape mid-morph. fnMap is element-scoped and one 'morph' animation\n            // runs at a time (cancel above), so the per-step indexed names never collide; the\n            // from/to closure survives in memory (same-context pause). (Same pattern as clock.ts.)\n            element.fnMap.add(\"morphCb\".concat(i), function (p) {\n                if (from == null) {\n                    from = vertices.slice();\n                    to = resampleToCount(resolveMorphShape(step.to), from.length);\n                }\n                var next = from.map(function (v, j) {\n                    return Fig.getPoint([v.x + (to[j].x - v.x) * p, v.y + (to[j].y - v.y) * p]);\n                });\n                updateGeometry(next);\n            });\n            builder = builder.custom({ callback: \"morphCb\".concat(i), duration: duration, progression: progression });\n        });\n        if (opts.done != null) {\n            element.fnMap.add('morphDone', opts.done);\n            builder = builder.whenFinished('morphDone');\n        }\n        builder.start();\n    };\n    element.morph = element.custom.morph;\n    // Create the needed layers, build the tree, offset the container so the\n    // polygon is aligned in draw space (now the annotations exist, so\n    // `alignTo: 'all'` can measure them), then position everything once from the\n    // natural geometry.\n    createLayers();\n    build();\n    // build() adds the debug outline straight to `container` (after createLayers),\n    // so lift the select layer back to the very front — the selection indicators\n    // must sit in front of everything, including the debug border.\n    if (selectLayer != null)\n        container.toFront(selectLayer);\n    // `front: true` grow lines and squares go above even the selection indicators,\n    // so lift those layers last of all — squares last, so a square held against a\n    // corner reads as sitting on top of an extension line crossing it.\n    if (growLinesFrontLayer != null)\n        container.toFront(growLinesFrontLayer);\n    if (curvesFrontLayer != null)\n        container.toFront(curvesFrontLayer);\n    if (squaresFrontLayer != null)\n        container.toFront(squaresFrontLayer);\n    applyAlignment();\n    updateGeometry(vertices);\n    applyStates(); // resting appearance (nothing selected yet).\n    // FORM SHOW/HIDE — keep the deliberately-hidden decorations hidden.\n    // When this poly sits inside a host equation and a form reveals it, FigureOne\n    // shows the element by calling element.showAll() — both the instant path\n    // (EquationForm.showHide) and the animated dissolve path (the dissolveIn\n    // opacity step). showAll() recurses through the whole tree unconditionally\n    // (it ignores isShown / isFormIgnored), so on its own it would un-hide every\n    // selection decoration (selectCircle / selectVertex / selectCorner /\n    // selectShape, the select-state angle overlay) plus any hidden overlay or\n    // counter. Wrap showAll so that, right after FigureOne's blanket reveal, we\n    // re-assert the correct per-selection visibility via applyStates() — which\n    // drives exactly those elements. The net effect: a form only ever shows the\n    // polygon as it should appear (the polyline + its resting annotations), never\n    // its hidden internals. Side marks / angle arcs flagged hidden (via\n    // `startHidden` or a runtime hideSideMarks/hideAngleMark) aren't selection\n    // state, so applyStates() doesn't cover them — re-hide them explicitly here so\n    // the blanket reveal doesn't pop them back into view.\n    var baseShowAll = element.showAll.bind(element);\n    element.showAll = function showAllRestoringStates() {\n        baseShowAll();\n        applyStates();\n        sideMarkEls.forEach(function (group, i) {\n            if (group != null && sideMarksHidden[i])\n                group.hide();\n        });\n        angleEls.forEach(function (mark, i) {\n            if (mark != null && angleMarkHidden[i])\n                mark.hide();\n        });\n        // Corner squares are hidden from build and only ever revealed by an explicit\n        // showSquareAngle — so a form reveal must leave a hidden one hidden.\n        squareEls.forEach(function (group, i) {\n            if (group != null && squareHidden[i])\n                group.hide();\n        });\n        // Same for the curve overlays — hidden from build unless `visible`, and only\n        // revealed by an explicit showCurve.\n        curveEls.forEach(function (el, i) {\n            if (el != null && curveHidden[i])\n                el.hide();\n        });\n        // And the grow lines — visible from build unless `visible: false`, and then\n        // only shown by an explicit showGrowLine (or for the duration of a press).\n        growLineEls.forEach(function (el, i) {\n            if (el != null && (growLineHidden[i] || growLineSelHidden[i]))\n                el.hide();\n        });\n    };\n    // On relayout the host equation repositions children; restore the learner's\n    // position (if moved) and re-fit the move bounds.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    // --- INTERACTION --------------------------------------------------------\n    // Whole-manipulative drag (reposition). This is wired only when there are no\n    // interactive pads: pad interaction (drag/select) and whole-manipulative move\n    // are mutually exclusive (see the move setup at the end), so the two never\n    // compete for the same touch.\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition().toArray(2);\n    });\n    element.notificationHelper.add(element._container, 'onClick', function () {\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n    });\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition().toArray(2);\n        // Tell the engine the answer may have changed so it can re-check. Use the\n        // injected `fig` (not the global `figure`) — addManipulative may pass a\n        // non-global figure.\n        fig.answerChanged();\n    });\n    // Called generically by the answer-input \"show answer\" flow (answerInput.ts)\n    // to freeze every manipulative once the answer is revealed.\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    // The polygon's side count, exposed directly on the element for convenience\n    // (e.g. answer checks / guides that need \"how many sides\"). Stable — reshaping\n    // moves vertices but never changes their count.\n    element.n = sideCount();\n    // Opaque caller-supplied tag (e.g. 'circle' / 'semicircle'); does nothing here,\n    // just lives on the element for front-end code to query.\n    element.tag = o.tag;\n    // Register for answer processing. MUST be snake_case and match the YAML.\n    element.custom.manipulativeType = 'poly';\n    // Secondary (near-touch) grab area is a polygon — the fill outset by\n    // touchBorderBuffer — tested by point-in-polygon in getTouchableElements\n    // (addManipulative.ts), not a bounding rectangle. It's set/refreshed in\n    // updateGeometry() so it tracks the polygon as it deforms.\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    else if (hasTouchPads()) {\n        // Interactive pads and whole-manipulative move are mutually exclusive. With\n        // pads present, leave `container` un-movable/untouchable so native touch\n        // recurses into the pads; the pads handle their own touch/move.\n        element.hasTouchableElements = true;\n    }\n    else if (o.isTouchable === true) {\n        // Whole-manipulative drag is opt-in (isTouchable: true). It only applies\n        // when there are no interactive pads (the two are mutually exclusive).\n        container.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    else {\n        // Default: the polygon is inert (not draggable and not a near-touch grab\n        // target). Set isTouchable: true to make the whole shape draggable, or add\n        // a selectable/movable pad for per-corner/side interaction.\n        element.hasTouchableElements = false;\n    }\n    return element;\n};\nexport { poly, };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\n// A dashed diameter \"cut\" line for splitting a shape: dragged by its centre only\n// (no end pads), with a small rotate button just off one end. This is the shared\n// look of L1/L2/L3 in question_split_circle — an instance need only give its\n// point/angle/length and its snap target. `degrees` is the rotation step per button\n// press; the named styles below fix it to 30/45/90. Returns a fresh literal each call\n// so the presets share no nested references.\nvar rotateSplitterStyle = function (degrees) { return ({\n    align: 'center',\n    dash: [0.05, 0.02],\n    width: 0.01,\n    pads: {\n        end: false,\n        center: {\n            relative: true,\n            length: 1.1,\n            width: 0.01,\n            corner: 0.04,\n            touchLength: 1.1,\n            touchWidth: 0.01,\n            color: [0.5, 0.5, 1, 0],\n        },\n    },\n    rotateButton: {\n        degrees: degrees,\n        duration: 0.4,\n        radius: 0.1,\n        color: [0.3, 0.3, 0.3, 1],\n        percent: -0.07,\n        offset: [0, 0],\n    },\n}); };\n// Named option presets for `style`. A style is just a partial LineManipulativeOptions\n// bundle merged in below the caller's explicit options — so a style sets the look and\n// the caller supplies only what varies per instance (point / angle / length / snap).\n// rotate_splitter keeps the original 30° step; the _30/_45/_90 variants are identical\n// but rotate by 30/45/90 per press.\nvar LINE_STYLES = {\n    rotate_splitter: rotateSplitterStyle(30),\n    rotate_splitter_30: rotateSplitterStyle(30),\n    rotate_splitter_45: rotateSplitterStyle(45),\n    rotate_splitter_90: rotateSplitterStyle(90),\n};\n// Build the cut-button icon into `parent`: a \"fold\" (a flat rectangle on the left\n// lying on the page, and a sheared parallelogram on the right, darker, as the\n// folded-up flap) and a curved arrow over the top suggesting the fold motion. The\n// icon is drawn in a roughly [-1, 1] box and `scale`d (so it spans about ±scale);\n// `color` is the front fill.\nfunction addCutIcon(parent, color, scale) {\n    var c = color;\n    var alpha = c[3] != null ? c[3] : 1;\n    var shade = function (f) { return [c[0] * f, c[1] * f, c[2] * f, alpha]; };\n    var S = function (p) { return [p[0] * scale, p[1] * scale]; };\n    // Fold: two parallelograms sharing the vertical spine at x = 0. Each is drawn\n    // as two triangles (a generic TRIANGLES fill) plus a thin outline.\n    var sh = 0.5; // spine half-height\n    var pw = 0.7; // page width\n    var lean = 0.4; // outer edge lifts well above the spine -> a steep flap\n    var spineTop = [0, sh];\n    var spineBot = [0, -sh];\n    var leftQuad = [spineBot, [-pw, -sh], [-pw, sh], spineTop]; // flat rectangle\n    var rightQuad = [spineBot, spineTop, [pw / 2, sh + lean], [pw / 2, -sh + lean]]; // sheared flap\n    var triPts = function (q) {\n        return [q[0], q[1], q[2], q[0], q[2], q[3]].map(S);\n    };\n    parent.add({ name: 'foldFront', make: 'generic', points: triPts(leftQuad), drawType: 'TRIANGLES', color: color });\n    parent.add({ name: 'foldBack', make: 'generic', points: triPts(rightQuad), drawType: 'TRIANGLES', color: shade(0.55) });\n    parent.add({ name: 'foldFrontEdge', make: 'polyline', points: leftQuad.map(S), close: true, width: 0.012 * scale, color: shade(0.35) });\n    parent.add({ name: 'foldBackEdge', make: 'polyline', points: rightQuad.map(S), close: true, width: 0.012 * scale, color: shade(0.35) });\n    // Curved arrow arcing over the top of the fold, swept right -> left with the\n    // arrowhead at the upper-left end — the flap sweeping over onto the flat page.\n    var ar = 0.85;\n    var yc = 0.15; // arc circle centre (the arc crowns above this, over the fold)\n    var tStart = (75 * Math.PI) / 180; // lower-right end\n    var tEnd = (145 * Math.PI) / 180; // upper-left end\n    var N = 16;\n    var arcPts = [];\n    for (var i = 0; i <= N; i += 1) {\n        var t = tStart + ((tEnd - tStart) * i) / N;\n        arcPts.push(S([ar * Math.cos(t), yc + ar * Math.sin(t)]));\n    }\n    parent.add({ name: 'arrowArc', make: 'polyline', points: arcPts, width: 0.05 * scale, color: shade(0.8), arrow: { end: 'triangle' } });\n    // Arrowhead at the left end, oriented along the arc's travel direction (the\n    // last segment), so it stays correct whatever the arc angles are.\n    var end = arcPts[N];\n    var prev = arcPts[N - 1];\n    var dx = end[0] - prev[0];\n    var dy = end[1] - prev[1];\n    var len = Math.sqrt(dx * dx + dy * dy) || 1;\n    dx /= len;\n    dy /= len;\n    var hl = 0.26 * scale; // arrowhead length\n    var hw = 0.16 * scale; // arrowhead half-width\n    var head = [\n        [end[0] + dx * hl, end[1] + dy * hl], // tip\n        [end[0] - dy * hw, end[1] + dx * hw], // base, +perpendicular\n        [end[0] + dy * hw, end[1] - dx * hw], // base, -perpendicular\n    ];\n    parent.add({ name: 'arrowHead', make: 'generic', points: head, drawType: 'TRIANGLES', color: shade(0.8) });\n}\n// Build the rotate-button icon into `parent`: a circular arrow — most of a ring\n// drawn as a thick arc, with a triangular arrowhead at the leading end pointing\n// along the sweep. `ccw` orients the sweep (and so the arrowhead) to match the\n// rotation direction. Drawn in a roughly [-1, 1] box and `scale`d (spans ~±scale).\nfunction addRotateIcon(parent, color, scale, ccw) {\n    var c = color;\n    var alpha = c[3] != null ? c[3] : 1;\n    var shade = function (f) { return [c[0] * f, c[1] * f, c[2] * f, alpha]; };\n    var S = function (p) { return [p[0] * scale, p[1] * scale]; };\n    // A near-complete ring (sweeping ~310°) so it reads unmistakably as a circular\n    // arrow rather than a plain arc. A small gap is left for the arrowhead to sit in.\n    var r = 0.58;\n    var N = 40;\n    var sweep = (310 * Math.PI) / 180;\n    var t0 = (120 * Math.PI) / 180; // start of the sweep\n    var dir = ccw ? 1 : -1;\n    var arcPts = [];\n    for (var i = 0; i <= N; i += 1) {\n        var t = t0 + dir * sweep * (i / N);\n        arcPts.push(S([r * Math.cos(t), r * Math.sin(t)]));\n    }\n    parent.add({ name: 'rotArc', make: 'polyline', points: arcPts, width: 0.13 * scale, color: shade(0.85) });\n    // A bold arrowhead at the leading end, pointing along the sweep tangent so it reads\n    // as a rotation. Compute the end point + tangent from the angle directly — do NOT\n    // read arcPts back: parent.add() above converts that array's entries to Point\n    // objects, so indexing [0]/[1] on them afterward gives NaN (an invisible triangle).\n    var tEnd = t0 + dir * sweep;\n    var ex = r * Math.cos(tEnd); // end point (unscaled icon space)\n    var ey = r * Math.sin(tEnd);\n    var tx = -Math.sin(tEnd) * dir; // unit tangent in the sweep direction\n    var ty = Math.cos(tEnd) * dir;\n    var tl = Math.sqrt(tx * tx + ty * ty) || 1;\n    tx /= tl;\n    ty /= tl;\n    var hl = 0.5; // arrowhead length (unscaled)\n    var hw = 0.34; // arrowhead half-width (unscaled)\n    var head = [\n        S([ex + tx * hl, ey + ty * hl]), // tip\n        S([ex - ty * hw, ey + tx * hw]), // base, +perpendicular\n        S([ex + ty * hw, ey - tx * hw]), // base, -perpendicular\n    ];\n    parent.add({ name: 'rotHead', make: 'generic', points: head, drawType: 'TRIANGLES', color: shade(0.85) });\n}\nvar lineManipulative = function (eqn_name, options, fig) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    // Expand a named `style` preset (if any) UNDER the caller's explicit options, so\n    // anything set on the instance still wins. Do this before the base-defaults join\n    // and before the raw-pads read below, so a style's `pads: { end: false }` is\n    // honoured even when the instance passes no `pads` of its own.\n    var style = options && options.style && LINE_STYLES[options.style]\n        ? LINE_STYLES[options.style]\n        : null;\n    var styledOptions = style\n        ? Fig.joinObjects({}, style, options)\n        : options;\n    var o = Fig.joinObjects({\n        color: [0.1, 0.1, 0.1, 1],\n        width: 0.012,\n        dash: [], // solid line by default\n        minWidth: 0, // 0 = no minimum line length\n        pads: {\n            end: {\n                shape: 'circle', // 'circle' | 'polygon' | 'rectangle'\n                sides: 20, // polygon sides (shape: 'polygon')\n                radius: 0.06, // visible handle (circle/polygon)\n                color: [0, 0.45, 1, 1],\n                touchRadius: 0.12, // larger invisible grab target (circle/polygon)\n                length: 0.12, // visible handle along the line (rectangle)\n                width: 0.12, // visible handle across the line (rectangle)\n                corner: 0, // rounded cosmetic corners (rectangle)\n                touchLength: 0.2, // larger invisible grab target (rectangle)\n                touchWidth: 0.2,\n                offset: 0, // inset of the pad from the endpoint, along the line\n                movable: true, // false makes the end pads inert (only the centre moves)\n                relative: false, // sizes are fractions of line length when true\n            },\n            center: {\n                length: 0.2, // visible handle: along the line\n                width: 0.1, // visible handle: across the line\n                corner: 0.03, // rounded cosmetic corners\n                color: [0, 0.45, 1, 1],\n                touchLength: 0.24, // larger invisible grab target\n                touchWidth: 0.18,\n                relative: false, // sizes are fractions of line length when true\n            },\n        },\n        yOffset: 0,\n        isTouchable: true,\n        boundMove: true,\n        debug: false,\n    }, styledOptions);\n    // A pad group can be omitted entirely by passing `false`. Read the on/off state\n    // from the style-merged options (authoritative), and fall back to an empty object\n    // so the per-pad reads below stay safe when a group is disabled.\n    var optPads = (styledOptions && styledOptions.pads) || {};\n    var endEnabled = optPads.end !== false;\n    var centerEnabled = optPads.center !== false;\n    var endOpt = o.pads.end && typeof o.pads.end === 'object' ? o.pads.end : {};\n    var centerOpt = o.pads.center && typeof o.pads.center === 'object' ? o.pads.center : {};\n    // Min line length: end drags can't bring the two endpoints closer than this.\n    var minWidth = o.minWidth != null ? o.minWidth : 0;\n    // End-pad geometry: rectangles rotate to lie along the line, and any end pad\n    // may be inset from its endpoint by `endOffset` along the line.\n    var endOffset = endOpt.offset != null ? endOpt.offset : 0;\n    var endIsRect = endOpt.shape === 'rectangle';\n    var endMovable = endOpt.movable !== false; // ends draggable unless explicitly off.\n    // When set, a group's pad sizes are fractions of the line length: a pad is\n    // built at its nominal size and then scaled by the current line length, so a\n    // value of 0.3 renders at 0.3 x the line length and tracks it as it stretches.\n    var endRelative = endOpt.relative === true;\n    var centerRelative = centerOpt.relative === true;\n    // Snap config (see the `snap` option). snapEnabled gates everything; snapPads\n    // holds per-pad overrides (absent key = snap to the whole-line grid).\n    var snapEnabled = o.snap != null;\n    var snapPads = (o.snap && o.snap.pads) || {};\n    // Source of truth for the line's endpoints (local coordinates). Either given\n    // directly as p1/p2, or derived from a point + angle + length (see options).\n    var lineP1;\n    var lineP2;\n    if (o.point != null && o.length != null) {\n        var c = Fig.getPoint(o.point);\n        var ang = (o.angle != null ? o.angle : 0) * (Math.PI / 180);\n        var dx = Math.cos(ang) * o.length;\n        var dy = Math.sin(ang) * o.length;\n        if (o.align === 'end') {\n            lineP1 = c;\n            lineP2 = Fig.getPoint([c.x + dx, c.y + dy]);\n        }\n        else {\n            lineP1 = Fig.getPoint([c.x - dx / 2, c.y - dy / 2]);\n            lineP2 = Fig.getPoint([c.x + dx / 2, c.y + dy / 2]);\n        }\n    }\n    else {\n        lineP1 = Fig.getPoint(o.p1 != null ? o.p1 : [-0.5, 0]);\n        lineP2 = Fig.getPoint(o.p2 != null ? o.p2 : [0.5, 0]);\n    }\n    var midpoint = function () {\n        return Fig.getPoint([(lineP1.x + lineP2.x) / 2, (lineP1.y + lineP2.y) / 2]);\n    };\n    var lineAngle = function () {\n        return Math.atan2(lineP2.y - lineP1.y, lineP2.x - lineP1.x);\n    };\n    var lineLength = function () {\n        var dx = lineP2.x - lineP1.x;\n        var dy = lineP2.y - lineP1.y;\n        return Math.sqrt(dx * dx + dy * dy);\n    };\n    // Where an end pad is drawn: the endpoint, inset toward `other` by `endOffset`\n    // along the line (so the line tip pokes `endOffset` past the handle).\n    var endPadPos = function (end, other) {\n        if (endOffset === 0)\n            return end;\n        var dx = other.x - end.x;\n        var dy = other.y - end.y;\n        var d = Math.sqrt(dx * dx + dy * dy);\n        if (d < 1e-9)\n            return end;\n        return Fig.getPoint([end.x + (endOffset * dx) / d, end.y + (endOffset * dy) / d]);\n    };\n    // Inverse of endPadPos: recover the line endpoint from a dragged pad position.\n    // The tip sits `endOffset` further out along the ray from `other` through pad.\n    var endFromPad = function (pad, other) {\n        if (endOffset === 0)\n            return pad;\n        var dx = pad.x - other.x;\n        var dy = pad.y - other.y;\n        var d = Math.sqrt(dx * dx + dy * dy);\n        if (d < 1e-9)\n            return pad;\n        return Fig.getPoint([pad.x + (endOffset * dx) / d, pad.y + (endOffset * dy) / d]);\n    };\n    // Clamp an endpoint so the line is never shorter than minWidth: if it would\n    // come closer than minWidth to `other`, push it back out to the minWidth ring.\n    var clampMinWidth = function (end, other) {\n        if (minWidth <= 0)\n            return end;\n        var dx = end.x - other.x;\n        var dy = end.y - other.y;\n        var d = Math.sqrt(dx * dx + dy * dy);\n        if (d >= minWidth)\n            return end;\n        if (d < 1e-9)\n            return Fig.getPoint([other.x + minWidth, other.y]);\n        return Fig.getPoint([other.x + (minWidth * dx) / d, other.y + (minWidth * dy) / d]);\n    };\n    // --- STRUCTURE ----------------------------------------------------------\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    // Initialised here (before the pads are wired) because wirePad() registers\n    // pad listeners through it — see the plumbing section below for the rest.\n    element.notificationHelper = new NotificationHelper();\n    // --- VISUALS: THE LINE --------------------------------------------------\n    var lineEl = container.add({\n        name: 'line',\n        make: 'polyline',\n        points: [lineP1, lineP2],\n        width: o.width,\n        color: o.color,\n        // dash persists across updatePoints (the primitive merges its stored\n        // options), so the line stays dashed as the learner drags it.\n        dash: o.dash,\n    });\n    lineEl.isTouchable = false;\n    // --- VISUALS: PADS ------------------------------------------------------\n    var padsLayer = container.add({ name: 'pads', make: 'collection' });\n    // Re-entrancy guard: repositioning a move pad programmatically fires its\n    // setTransformCallback again — suppress that to avoid feedback loops.\n    var suppressPad = false;\n    // Add a cosmetic (visible, inert) pad and a move (invisible, movable) pad for\n    // one control. `shapeOf(dims)` builds the make-options for a given size, so\n    // cosmetic and move can differ in dimensions (and the move pad is plain).\n    function makeControl(name, at, cosmeticShape, moveShape, movable, hugLine) {\n        if (movable === void 0) { movable = true; }\n        if (hugLine === void 0) { hugLine = false; }\n        var cosmetic = padsLayer.add(Fig.joinObjects({}, cosmeticShape, { name: \"\".concat(name, \"Cosmetic\"), position: [at.x, at.y] }));\n        cosmetic.isTouchable = false; // purely decorative; the move pad handles touch.\n        // `hugLine`: shrink the move pad's across-line extent to the line's own width so\n        // it sits *on* the line, not in a wide band around it. Without this, two crossing\n        // lines' wide pads overlap in a band and the topmost always wins the touch — you\n        // grab a far line instead of the near one. A generous polygon secondary-touch\n        // border (set below) keeps it easy to grab; the polygon rides the pad's transform,\n        // so it rotates with the line and works for diagonals (an axis-aligned box would\n        // balloon to the line's bounding square and defeat the whole point).\n        var m = moveShape;\n        var rectHug = hugLine && m != null && m.make === 'rectangle';\n        if (rectHug) {\n            m = Fig.joinObjects({}, m, { height: o.width });\n        }\n        var move = padsLayer.add(Fig.joinObjects({}, m, {\n            name: \"\".concat(name, \"Move\"),\n            position: [at.x, at.y],\n            // Invisible unless debugging, in which case draw a faint outline so the\n            // (otherwise hidden) grab target's size/place is visible.\n            color: o.debug ? [0, 0.7, 0, 0.4] : [0, 0, 0, 0],\n        }));\n        if (movable) {\n            move.setMovable();\n            move.move.freely = false; // no momentum: rest exactly where released.\n            if (rectHug) {\n                // Polygon near-touch border in the pad's draw space: full length along the\n                // line, padded well beyond the (now hairline) pad across it. GRAB_MARGIN sets\n                // how far off the line still grabs it.\n                var GRAB_MARGIN = 0.1; // across the line, each side\n                var ALONG_MARGIN = 0.06; // a little past each end\n                var halfLen = (m.width || 0) / 2 + ALONG_MARGIN;\n                var halfAcross = o.width / 2 + GRAB_MARGIN;\n                move.custom.secondaryTouchBounds = [\n                    { x: -halfLen, y: -halfAcross },\n                    { x: halfLen, y: -halfAcross },\n                    { x: halfLen, y: halfAcross },\n                    { x: -halfLen, y: halfAcross },\n                ];\n            }\n            else {\n                move.custom.secondaryTouchBounds = 0.05; // ease near-miss grabs.\n            }\n        }\n        else {\n            // Inert control: still drawn and still repositioned to track the line (so a\n            // centre translate carries it), but it cannot be grabbed.\n            move.isTouchable = false;\n        }\n        return { move: move, cosmetic: cosmetic };\n    }\n    // End controls: a circle/polygon (sized by radius) or a rectangle (sized by\n    // length/width and rotated to lie along the line — see alignControls). For\n    // both, cosmetic = visible handle; move = (larger) invisible grab target.\n    function makeEndControl(name, at) {\n        if (endIsRect) {\n            return makeControl(name, at, {\n                make: 'rectangle',\n                width: endOpt.length,\n                height: endOpt.width,\n                corner: { radius: endOpt.corner, sides: 5 },\n                color: endOpt.color,\n            }, { make: 'rectangle', width: endOpt.touchLength, height: endOpt.touchWidth }, endMovable);\n        }\n        var sides = endOpt.shape === 'polygon' ? endOpt.sides : 20;\n        return makeControl(name, at, { make: 'polygon', sides: sides, radius: endOpt.radius, color: endOpt.color }, { make: 'polygon', sides: sides, radius: endOpt.touchRadius }, endMovable);\n    }\n    // Centre control: a rounded cosmetic rectangle over a plain move rectangle.\n    // `length` maps to the rectangle's local x (along the line once rotated),\n    // `width` to local y (across it).\n    var centerControl = centerEnabled\n        ? makeControl('center', midpoint(), {\n            make: 'rectangle',\n            width: centerOpt.length,\n            height: centerOpt.width,\n            corner: { radius: centerOpt.corner, sides: 5 },\n            color: centerOpt.color,\n        }, {\n            make: 'rectangle',\n            width: centerOpt.touchLength,\n            height: centerOpt.touchWidth,\n        }, true, // movable\n        true)\n        : null;\n    var end1Control = endEnabled\n        ? makeEndControl('end1', endPadPos(lineP1, lineP2))\n        : null;\n    var end2Control = endEnabled\n        ? makeEndControl('end2', endPadPos(lineP2, lineP1))\n        : null;\n    // Redraw the line from the current endpoints.\n    function updateLine() {\n        lineEl.custom.updatePoints({ points: [lineP1, lineP2] });\n    }\n    // Move a control to a point. `includeMove: false` leaves the move pad alone\n    // (used for the control being actively dragged — FigureOne owns its position\n    // until release — while its cosmetic still tracks it). Suppressed so setting\n    // the move pad's position doesn't re-enter the drag handler.\n    function placeControl(ctrl, p, includeMove) {\n        if (includeMove === void 0) { includeMove = true; }\n        if (ctrl == null)\n            return; // omitted pad group (pads.end/center: false).\n        suppressPad = true;\n        if (includeMove)\n            ctrl.move.setPosition([p.x, p.y]);\n        ctrl.cosmetic.setPosition([p.x, p.y]);\n        suppressPad = false;\n    }\n    // Align the controls to the current line: rotate the rectangle controls to lie\n    // along it (the centre always; the ends only when rectangles), and scale each\n    // pad group that is sized relative to the line to the current line length.\n    // Omitted groups (null controls) are skipped.\n    function alignControls() {\n        var a = lineAngle();\n        var L = lineLength();\n        suppressPad = true;\n        if (centerControl != null) {\n            centerControl.move.setRotation(a);\n            centerControl.cosmetic.setRotation(a);\n            if (centerRelative) {\n                centerControl.move.setScale(L);\n                centerControl.cosmetic.setScale(L);\n            }\n        }\n        if (end1Control != null && end2Control != null) {\n            if (endIsRect) {\n                end1Control.move.setRotation(a);\n                end1Control.cosmetic.setRotation(a);\n                end2Control.move.setRotation(a);\n                end2Control.cosmetic.setRotation(a);\n            }\n            if (endRelative) {\n                end1Control.move.setScale(L);\n                end1Control.cosmetic.setScale(L);\n                end2Control.move.setScale(L);\n                end2Control.cosmetic.setScale(L);\n            }\n        }\n        suppressPad = false;\n    }\n    // Buttons anchored along the line (cut / rotate). Each sits at `percent` of the\n    // way from p1 to p2 plus an [x, y] offset, so placeAnchoredButtons keeps it there\n    // as the line is dragged or rotated. No-op with no buttons. cutBtn is kept as a\n    // named handle so the cut flow can toggle its opacity.\n    var cutBtn = null;\n    var anchoredButtons = [];\n    function placeAnchoredButtons() {\n        for (var i = 0; i < anchoredButtons.length; i += 1) {\n            var b = anchoredButtons[i];\n            b.el.setPosition([\n                lineP1.x + b.percent * (lineP2.x - lineP1.x) + b.offX,\n                lineP1.y + b.percent * (lineP2.y - lineP1.y) + b.offY,\n            ]);\n        }\n    }\n    // Reposition every control from the current endpoints (none being dragged).\n    // Used on restore / programmatic set. End pads sit at their inset positions.\n    function updatePadsFromLine() {\n        placeControl(end1Control, endPadPos(lineP1, lineP2));\n        placeControl(end2Control, endPadPos(lineP2, lineP1));\n        placeControl(centerControl, midpoint());\n        alignControls();\n        placeAnchoredButtons();\n    }\n    updatePadsFromLine(); // initial placement + alignment.\n    // Wire one control's drag. The move pad captures the drag; `onMove` maps its\n    // new position onto the line endpoints and re-syncs the others. The dragged\n    // move pad owns its own position (we never reset it here).\n    // setTransformCallback is invoked via fnMap.exec, which runs a function value\n    // directly (no fnMap registration needed) — see FigureOne index.js.\n    function wirePad(name, ctrl, onMove) {\n        if (ctrl == null)\n            return; // omitted pad group (pads.end/center: false).\n        ctrl.move.setTransformCallback = function (transform) {\n            if (suppressPad)\n                return;\n            var t = transform.t();\n            if (t == null)\n                return;\n            onMove(Fig.getPoint([t.x, t.y]));\n            updateLine();\n        };\n        element.notificationHelper.add(ctrl.move, 'startBeingMoved', function () {\n            // Re-grabbing mid-glide cancels any in-flight soft-snap settle (and clears the\n            // flag) so the drag and the settle animation don't fight over the endpoints.\n            if (element.custom.settling) {\n                element.stop('freeze');\n                element.custom.settling = false;\n            }\n            // Bring the grabbed line above its siblings so a line being dragged always\n            // draws on top of any line(s) it crosses (otherwise draw order is fixed and\n            // the last-defined line is permanently on top).\n            if (element.parent != null) {\n                element.parent.toFront(element);\n            }\n        });\n        element.notificationHelper.add(ctrl.move, 'stopBeingMoved', function () {\n            // Guard re-entrancy: the soft-snap settle below calls element.stop(), which\n            // FigureOne answers by RE-PUBLISHING 'stopBeingMoved' (it is tearing down the\n            // move state). `settling` is already true by then, so bail on that echo —\n            // otherwise it re-enters snapLineForRelease -> animateToLine -> stop -> ... and\n            // overflows the stack.\n            if (element.custom.settling)\n                return;\n            // On release: commit a soft snap to the nearest node, then re-place every pad\n            // from the snapped endpoints. The latter re-aligns the (invisible) grab target\n            // with the visible handle — during a drag the move pad tracks the pointer, so\n            // without this the line can look un-grabbable after a snap.\n            var commit = function () {\n                element.custom.state = element.custom.getState();\n                fig.answerChanged();\n            };\n            if (snapEnabled) {\n                // A soft snap animates onto its node; defer pads/state/answerChanged until the\n                // settle finishes so the committed answer is the final (snapped) pose.\n                var settling = snapLineForRelease(name, function () {\n                    element.custom.settling = false;\n                    updatePadsFromLine();\n                    commit();\n                    // Tell consumers wired to this line (e.g. a splittable_shape's declarative\n                    // splitLines) that the geometry finished changing, so they re-split at the\n                    // snapped pose — same signal a rotate uses. This is the ONLY re-split for a\n                    // soft snap (the release re-split is skipped while settling).\n                    element.notifications.publish('rotated');\n                });\n                if (settling)\n                    return;\n                updatePadsFromLine();\n            }\n            commit();\n        });\n    }\n    // --- SNAP -----------------------------------------------------------------\n    // The whole line snaps to ONE grid by default — the shape it overlaps (or\n    // snap.to) — while a pad may opt out (false) or opt into its OWN nearest grid\n    // ({ grid: 'nearest' }). Grids are consumed in figure space, so the line never\n    // learns a shape's coordinate frame. (resolveSplittable / isSplittable are\n    // defined further down; these helpers only call them at drag time, by which\n    // point they are assigned.)\n    // Resolve a grid from `snap.to`, which the content layer may hand over as a\n    // string path, a live element, OR an element-definition object — writing\n    // `to: S1` in YAML evaluates `S1` to its definition dict (carrying `name`), not\n    // the string \"S1\" — so fall back to resolving by `name`.\n    function snapGridOf(arg) {\n        if (arg == null)\n            return null;\n        var s = arg;\n        if (typeof arg === 'string')\n            s = fig.get(arg);\n        else if (arg.custom == null && typeof arg.name === 'string')\n            s = fig.get(arg.name);\n        return s != null && s.custom != null ? s.custom.snapGrid : null;\n    }\n    function primarySnapGrid(figurePt) {\n        if (o.snap && o.snap.to != null) {\n            var g = snapGridOf(o.snap.to);\n            if (g != null)\n                return g;\n        }\n        // The overlapped shape's grid, else the nearest grid in play — so snapping\n        // keeps working when the line is dragged off the shape.\n        var overlap = snapGridOf(resolveSplittable(null));\n        return overlap != null ? overlap : nearestSnapGrid(figurePt);\n    }\n    function nearestSnapGrid(figurePt) {\n        var all = fig.elements.getAllElements();\n        var best = null;\n        var bestD = Infinity;\n        for (var i = 0; i < all.length; i += 1) {\n            var s = all[i];\n            if (!isSplittable(s) || s.custom == null || s.custom.snapGrid == null)\n                continue;\n            var d = s.custom.snapGrid.nodeDistanceFigure(figurePt);\n            if (d < bestD) {\n                bestD = d;\n                best = s.custom.snapGrid;\n            }\n        }\n        return best;\n    }\n    function gridForPad(name, figurePt) {\n        if (!snapEnabled)\n            return null;\n        var cfg = snapPads[name];\n        if (cfg === false)\n            return null;\n        if (cfg && typeof cfg === 'object' && cfg.grid === 'nearest') {\n            return nearestSnapGrid(figurePt);\n        }\n        return primarySnapGrid(figurePt);\n    }\n    // Snap a point in the line's local (container/draw) space: lift to figure space,\n    // snap against the pad's grid, drop back. No-op when the pad's snapping is off or\n    // no grid resolves. During a drag (force=false) a SOFT grid (hard: false) moves\n    // freely — it snaps only on release (force=true); a HARD grid snaps every frame.\n    function snapLocal(name, local, force) {\n        if (force === void 0) { force = false; }\n        if (!snapEnabled)\n            return local;\n        var figurePt = lineEl.pointFromSpaceToSpace(local, 'draw', 'figure');\n        var grid = gridForPad(name, figurePt);\n        if (grid == null)\n            return local;\n        if (!force && !grid.hard)\n            return local; // soft: free until release\n        var snapped = grid.snapFigure(figurePt);\n        return lineEl.pointFromSpaceToSpace(snapped, 'figure', 'draw');\n    }\n    // Is the pad's resolved grid a SOFT one (hard: false)? A soft grid moves freely\n    // during the drag and only commits on release, so its release commit is animated;\n    // a hard grid already sits on a node every frame, so its release is instant.\n    function padGridIsSoft(name, local) {\n        var figurePt = lineEl.pointFromSpaceToSpace(local, 'draw', 'figure');\n        var grid = gridForPad(name, figurePt);\n        return grid != null && !grid.hard;\n    }\n    // Seconds a soft snap takes to glide onto its node on release (a gentle settle\n    // rather than an instant jump).\n    var SNAP_SETTLE_DURATION = 0.2;\n    // Force-snap the line to the grid for the just-released pad (the soft-snap commit;\n    // a no-op for a hard grid, already on a node). End pads snap their endpoint\n    // (re-clamped to minWidth); the centre snaps the midpoint and translates rigidly.\n    // For a SOFT grid the line glides to the snapped pose over SNAP_SETTLE_DURATION and\n    // this returns true (the caller defers its state/answerChanged commit to `done`,\n    // run when the glide finishes); otherwise it commits instantly and returns false.\n    function snapLineForRelease(name, done) {\n        if (!snapEnabled)\n            return false;\n        var targetP1 = lineP1;\n        var targetP2 = lineP2;\n        var refLocal = lineP1; // point used to resolve the pad's grid (+ its hardness)\n        if (name === 'center') {\n            var m = midpoint();\n            // Snap, then hold the snapped midpoint inside the figure (a node near the edge\n            // could otherwise place the line partly outside).\n            var snapped = clampCenterIntoFigure(snapLocal('center', m, true));\n            var dx = snapped.x - m.x;\n            var dy = snapped.y - m.y;\n            if (dx === 0 && dy === 0)\n                return false;\n            targetP1 = Fig.getPoint([lineP1.x + dx, lineP1.y + dy]);\n            targetP2 = Fig.getPoint([lineP2.x + dx, lineP2.y + dy]);\n            refLocal = m;\n        }\n        else if (name === 'end1') {\n            targetP1 = clampMinWidth(clampPointIntoFigure(snapLocal('end1', lineP1, true)), lineP2);\n            refLocal = lineP1;\n        }\n        else if (name === 'end2') {\n            targetP2 = clampMinWidth(clampPointIntoFigure(snapLocal('end2', lineP2, true)), lineP1);\n            refLocal = lineP2;\n        }\n        var moved = targetP1.x !== lineP1.x || targetP1.y !== lineP1.y\n            || targetP2.x !== lineP2.x || targetP2.y !== lineP2.y;\n        if (moved && padGridIsSoft(name, refLocal)) {\n            // Mark the line as settling so consumers (e.g. a splittable_shape's release\n            // re-split) hold off until the glide lands; cleared in the done callback.\n            element.custom.settling = true;\n            element.custom.animateToLine(targetP1, targetP2, SNAP_SETTLE_DURATION, done);\n            return true;\n        }\n        lineP1 = targetP1;\n        lineP2 = targetP2;\n        updateLine();\n        return false;\n    }\n    // --- FIGURE BOUNDS --------------------------------------------------------\n    // Keep the line inside the figure's scene rect (the same rect `boundMove` uses;\n    // gated on it, default on). The line moves via its pads — not `element.move` — so\n    // the generic setMoveBounds() (which bounds element.move) never constrains it;\n    // these clamp the pad-driven poses instead. Coordinates convert through lineEl,\n    // the frame lineP1/lineP2 live in. All are no-ops when boundMove is false or there\n    // is no parent (nothing to measure the scene against).\n    // Clamp a single endpoint (local draw) into the scene — used by end-pad drags,\n    // which reshape the line, so only the moved end is constrained.\n    function clampPointIntoFigure(pLocal) {\n        if (!o.boundMove || element.parent == null)\n            return pLocal;\n        var scene = element.parent.getScene();\n        var f = lineEl.pointFromSpaceToSpace(pLocal, 'draw', 'figure');\n        var cx = Math.min(Math.max(f.x, scene.left), scene.right);\n        var cy = Math.min(Math.max(f.y, scene.bottom), scene.top);\n        if (cx === f.x && cy === f.y)\n            return pLocal;\n        return lineEl.pointFromSpaceToSpace(Fig.getPoint([cx, cy]), 'figure', 'draw');\n    }\n    // Clamp a candidate MIDPOINT (local draw) so translating the rigid line there keeps\n    // it inside. A rotatable line (has a rotate button) is held a half-LENGTH from every\n    // edge, so it stays inside at any angle it can rotate to; a fixed line is only held\n    // inside for its current orientation (half its figure extent per axis). If the line\n    // is larger than the scene on an axis it cannot fit, so it is centred on that axis.\n    function clampCenterIntoFigure(mLocal) {\n        if (!o.boundMove || element.parent == null)\n            return mLocal;\n        var scene = element.parent.getScene();\n        var mFig = lineEl.pointFromSpaceToSpace(mLocal, 'draw', 'figure');\n        var f1 = lineEl.pointFromSpaceToSpace(lineP1, 'draw', 'figure');\n        var f2 = lineEl.pointFromSpaceToSpace(lineP2, 'draw', 'figure');\n        var insetX;\n        var insetY;\n        if (o.rotateButton) {\n            var lx = f2.x - f1.x;\n            var ly = f2.y - f1.y;\n            insetX = Math.sqrt(lx * lx + ly * ly) / 2; // swept-circle radius\n            insetY = insetX;\n        }\n        else {\n            insetX = Math.abs(f2.x - f1.x) / 2;\n            insetY = Math.abs(f2.y - f1.y) / 2;\n        }\n        var clampAxis = function (v, lo, hi, ins) {\n            var a = lo + ins;\n            var b = hi - ins;\n            return a <= b ? Math.min(Math.max(v, a), b) : (lo + hi) / 2;\n        };\n        var cx = clampAxis(mFig.x, scene.left, scene.right, insetX);\n        var cy = clampAxis(mFig.y, scene.bottom, scene.top, insetY);\n        if (cx === mFig.x && cy === mFig.y)\n            return mLocal;\n        return lineEl.pointFromSpaceToSpace(Fig.getPoint([cx, cy]), 'figure', 'draw');\n    }\n    // End controls move just their own endpoint. The dragged pad position is\n    // mapped back through the inset to the true endpoint, clamped to minWidth, then\n    // every control is re-placed: the other end's inset position and all rectangle\n    // rotations depend on the new line angle, so both ends and the centre update.\n    // The dragged pad's move element is only snapped (includeMove) when clamped —\n    // otherwise FigureOne owns it and it already sits where the pointer is. Skipped\n    // when the ends are inert (pads.end.movable: false) or omitted (pads.end: false).\n    if (endEnabled && endMovable) {\n        wirePad('end1', end1Control, function (pos) {\n            var snappedEnd = snapLocal('end1', endFromPad(pos, lineP2));\n            var rawEnd = clampPointIntoFigure(snappedEnd);\n            var figClamped = rawEnd.x !== snappedEnd.x || rawEnd.y !== snappedEnd.y;\n            var dx = rawEnd.x - lineP2.x;\n            var dy = rawEnd.y - lineP2.y;\n            var clamped = minWidth > 0 && Math.sqrt(dx * dx + dy * dy) < minWidth - 1e-9;\n            lineP1 = clamped ? clampMinWidth(rawEnd, lineP2) : rawEnd;\n            placeControl(end1Control, endPadPos(lineP1, lineP2), clamped || figClamped);\n            placeControl(end2Control, endPadPos(lineP2, lineP1));\n            placeControl(centerControl, midpoint());\n            alignControls();\n            placeAnchoredButtons();\n        });\n        wirePad('end2', end2Control, function (pos) {\n            var snappedEnd = snapLocal('end2', endFromPad(pos, lineP1));\n            var rawEnd = clampPointIntoFigure(snappedEnd);\n            var figClamped = rawEnd.x !== snappedEnd.x || rawEnd.y !== snappedEnd.y;\n            var dx = rawEnd.x - lineP1.x;\n            var dy = rawEnd.y - lineP1.y;\n            var clamped = minWidth > 0 && Math.sqrt(dx * dx + dy * dy) < minWidth - 1e-9;\n            lineP2 = clamped ? clampMinWidth(rawEnd, lineP1) : rawEnd;\n            placeControl(end2Control, endPadPos(lineP2, lineP1), clamped || figClamped);\n            placeControl(end1Control, endPadPos(lineP1, lineP2));\n            placeControl(centerControl, midpoint());\n            alignControls();\n            placeAnchoredButtons();\n        });\n    }\n    // The centre control translates the whole line by the delta from the old\n    // midpoint; the end controls follow. The angle is unchanged by a translation,\n    // so the rectangle rotations stay put.\n    wirePad('center', centerControl, function (pos) {\n        var target = clampCenterIntoFigure(snapLocal('center', pos));\n        var m = midpoint();\n        var dx = target.x - m.x;\n        var dy = target.y - m.y;\n        lineP1 = Fig.getPoint([lineP1.x + dx, lineP1.y + dy]);\n        lineP2 = Fig.getPoint([lineP2.x + dx, lineP2.y + dy]);\n        placeControl(centerControl, target, false);\n        placeControl(end1Control, endPadPos(lineP1, lineP2));\n        placeControl(end2Control, endPadPos(lineP2, lineP1));\n        placeAnchoredButtons();\n    });\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    // (element.notificationHelper is created up in the STRUCTURE section, since\n    // the pad wiring above already uses it.)\n    setupManipulative(element, null, o);\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    element.custom.getState = function () {\n        var p = element.getPosition();\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        return {\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            l: [\n                [Fig.round(lineP1.x, 3), Fig.round(lineP1.y, 3)],\n                [Fig.round(lineP2.x, 3), Fig.round(lineP2.y, 3)],\n            ],\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        if (stats.l != null) {\n            lineP1 = Fig.getPoint(stats.l[0]);\n            lineP2 = Fig.getPoint(stats.l[1]);\n            updateLine();\n            updatePadsFromLine();\n        }\n        element.custom.moved = true;\n    };\n    element.custom.state = element.custom.getState();\n    // Is the line currently resting ON its snap grid? A consumer (e.g. a\n    // splittable_shape) can gate on this so only snapped cut lines contribute to a\n    // split. True whenever snapping is off or the grid has no pull radius (`threshold`)\n    // — then a release always lands on a node, so a line is \"snapped\" by construction.\n    // With a threshold set, a line dropped beyond the pull radius sits off-lattice and\n    // reports false. The reference point is the CENTRE (the whole-line anchor — what a\n    // rotate_splitter drags and rotates about); if the centre doesn't snap, fall back\n    // to requiring both ENDS to be snapped. Stateless (reads the live pose), so it\n    // survives a snapshot restore for free.\n    element.custom.isSnapped = function () {\n        if (!snapEnabled)\n            return true;\n        var nodeWithin = function (name, local) {\n            var figurePt = lineEl.pointFromSpaceToSpace(local, 'draw', 'figure');\n            var grid = gridForPad(name, figurePt);\n            if (grid == null)\n                return null; // this pad does not snap\n            if (grid.threshold == null)\n                return true; // no pull radius: always on a node\n            return grid.nodeDistanceFigure(figurePt) <= grid.threshold + 1e-6;\n        };\n        var centre = centerControl != null ? nodeWithin('center', midpoint()) : null;\n        if (centre != null)\n            return centre;\n        var e1 = nodeWithin('end1', lineP1);\n        var e2 = nodeWithin('end2', lineP2);\n        if (e1 == null && e2 == null)\n            return true; // nothing snaps -> not gated\n        return e1 !== false && e2 !== false;\n    };\n    element.isSnapped = element.custom.isSnapped;\n    // The line's endpoints, exposed for other manipulatives (e.g. splittable_shape\n    // uses these as a cut). `getLinePoints` returns the local-space endpoints;\n    // `getFigureLine` converts them to figure space — the common frame a consumer\n    // in a different coordinate system needs. (lineEl's draw space is where the\n    // endpoints are defined, so the conversion accounts for yOffset, the\n    // manipulative's position, and any host-equation transform.)\n    element.custom.getLinePoints = function () { return [\n        [lineP1.x, lineP1.y],\n        [lineP2.x, lineP2.y],\n    ]; };\n    element.custom.getFigureLine = function () { return [\n        lineEl.pointFromSpaceToSpace(Fig.getPoint([lineP1.x, lineP1.y]), 'draw', 'figure'),\n        lineEl.pointFromSpaceToSpace(Fig.getPoint([lineP2.x, lineP2.y]), 'draw', 'figure'),\n    ]; };\n    element.getFigureLine = element.custom.getFigureLine;\n    // Drive the line programmatically (animation / guides / tests). Endpoints are\n    // in local coordinates, like p1/p2.\n    element.custom.setLine = function (p1, p2) {\n        lineP1 = Fig.getPoint(p1);\n        lineP2 = Fig.getPoint(p2);\n        updateLine();\n        updatePadsFromLine();\n        element.custom.state = element.custom.getState();\n    };\n    element.setLine = element.custom.setLine;\n    // Animate the endpoints from their current pose to (p1, p2) over `duration`\n    // seconds (local coords, like setLine), easing in/out. Used by show-answer to\n    // glide a line into place — a line already at the target barely moves. `done`\n    // runs when the glide finishes. duration <= 0 is an instant set.\n    element.custom.animateToLine = function (p1, p2, duration, done) {\n        if (duration === void 0) { duration = 0.8; }\n        var startP1 = lineP1;\n        var startP2 = lineP2;\n        var endP1 = Fig.getPoint(p1);\n        var endP2 = Fig.getPoint(p2);\n        var ease = function (t) { return (1 - Math.cos(Math.PI * t)) / 2; };\n        var apply = function (t) {\n            lineP1 = Fig.getPoint([startP1.x + (endP1.x - startP1.x) * t, startP1.y + (endP1.y - startP1.y) * t]);\n            lineP2 = Fig.getPoint([startP2.x + (endP2.x - startP2.x) * t, startP2.y + (endP2.y - startP2.y) * t]);\n            updateLine();\n            updatePadsFromLine();\n        };\n        var finish = function () {\n            apply(1);\n            element.custom.moved = true;\n            element.custom.state = element.custom.getState();\n            if (done != null)\n                done();\n        };\n        element.stop('complete');\n        if (duration > 0) {\n            // Register the per-frame + completion callbacks by NAME (fnMap) rather than as\n            // inline closures so the animation is SERIALIZABLE. figure.getState()/setState —\n            // which speech pause/resume relies on — can only capture custom/trigger steps whose\n            // callback is an fnMap string; a step with an inline closure is silently dropped\n            // from the state snapshot, so a pause mid-glide leaves the line frozen mid-move on\n            // resume. The closures still hold this call's start/end points: pause/resume is\n            // same-context, so they survive in memory and are re-resolved by name on restore.\n            // (Mirrors clock.ts goToTime.) Re-registered per call — a line animates only one\n            // glide at a time (stop('complete') above) and fnMap is element-scoped, so the\n            // fixed names never collide across lines.\n            element.fnMap.add('animateToLineCallback', function (t) { return apply(ease(t)); });\n            element.fnMap.add('animateToLineFinished', function () { return finish(); });\n            element.animations\n                .new()\n                .custom({ callback: 'animateToLineCallback', duration: duration })\n                .trigger({ callback: 'animateToLineFinished' })\n                .start();\n        }\n        else {\n            finish();\n        }\n    };\n    element.animateToLine = element.custom.animateToLine;\n    // Resolve the target splittable_shape for splitShape(): an explicit element or\n    // element path, else the first splittable_shape whose bounding box the\n    // (infinite) cut line crosses. Overlap is the side-of-line test on the shape's\n    // figure-space bounding-box corners — if some are on each side, the line passes\n    // through the box. Side-effect-free (it does not mutate any shape).\n    var isSplittable = function (e) {\n        return e != null && e.custom != null\n            && (e.custom.manipulativeType === 'splittable_shape'\n                || e.custom.manipulativeType === 'splittableShapeSlot');\n    };\n    var resolveSplittable = function (shapeArg) {\n        if (shapeArg != null) {\n            return typeof shapeArg === 'string' ? fig.get(shapeArg) : shapeArg;\n        }\n        var _a = element.custom.getFigureLine(), p1 = _a[0], p2 = _a[1];\n        var all = fig.elements.getAllElements();\n        for (var i = 0; i < all.length; i += 1) {\n            var s = all[i];\n            if (!isSplittable(s) || typeof s.getBoundingRect !== 'function')\n                continue;\n            var r = s.getBoundingRect('figure');\n            var corners = [\n                [r.left, r.bottom], [r.right, r.bottom],\n                [r.right, r.top], [r.left, r.top],\n            ];\n            var pos = false;\n            var neg = false;\n            for (var c = 0; c < 4; c += 1) {\n                var d = (p2.x - p1.x) * (corners[c][1] - p1.y)\n                    - (p2.y - p1.y) * (corners[c][0] - p1.x);\n                if (d > 1e-9)\n                    pos = true;\n                else if (d < -1e-9)\n                    neg = true;\n            }\n            if (pos && neg)\n                return s;\n        }\n        return null;\n    };\n    // Convenience from the line side: cut a splittable_shape with THIS line, then\n    // animate the reflection of one of the resulting pieces. `opts` is splittable\n    // shape's animateReflect options (mode/duration/pause/ambient/backColor/\n    // perspective) plus `shape` — the target shape (element or path). With no\n    // `shape`, the first splittable_shape the cut line overlaps is used. Returns\n    // the shape that was split, or null if none matched.\n    element.custom.splitShape = function (pieceIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        var shape = resolveSplittable(opts.shape);\n        if (shape == null || typeof shape.splitByLine !== 'function')\n            return null;\n        shape.splitByLine(element);\n        if (typeof shape.animateReflect === 'function') {\n            shape.animateReflect(pieceIndex, opts);\n        }\n        return shape;\n    };\n    element.splitShape = element.custom.splitShape;\n    // Optional cut button: a touchable polygon that runs splitShape with this line.\n    if (o.cutButton) {\n        var cb = o.cutButton;\n        var btnPieceIndex_1 = cb.pieceIndex != null ? cb.pieceIndex : 1;\n        // splitShape options — the splitShape/animateReflect defaults (duration 3,\n        // pause 1) made overridable; undefined keys fall through to animateReflect's\n        // own defaults.\n        var splitOpts_1 = {\n            shape: cb.shape,\n            mode: cb.mode,\n            duration: cb.duration != null ? cb.duration : 3,\n            pause: cb.pause != null ? cb.pause : 1,\n            ambient: cb.ambient,\n            backColor: cb.backColor,\n            perspective: cb.perspective,\n        };\n        // How long the fold animation runs, so the lock is released when it ends.\n        // bounce = two folds plus the hold; otherwise a single fold. Small buffer so\n        // re-enable lands just after the animation completes.\n        var foldMode = splitOpts_1.mode || 'bounce';\n        var lockSeconds_1 = (foldMode === 'bounce'\n            ? splitOpts_1.duration + splitOpts_1.pause + splitOpts_1.duration\n            : splitOpts_1.duration) + 0.1;\n        // The button is a small collection: an invisible touch disc (the reliable\n        // tap target, like the move pads) plus the icon — a fold (two parallelograms)\n        // and a curved arrow. The icon parts are inert; the disc handles the touch.\n        var iconColor = cb.color || [0.5, 0.5, 0.5, 1];\n        var iconScale = cb.radius != null ? cb.radius : 0.15;\n        cutBtn = container.add({ name: 'cutButton', make: 'collection' });\n        var cutTouch = cutBtn.add({\n            name: 'touch',\n            make: 'polygon',\n            sides: 20,\n            radius: iconScale * 1.15,\n            color: o.debug ? [0, 0.7, 0, 0.3] : [0, 0, 0, 0],\n        });\n        addCutIcon(cutBtn, iconColor, iconScale);\n        cutTouch.setTouchable();\n        // Anchor along the line (percent of p1->p2) plus an offset; placeAnchoredButtons\n        // keeps it there as the line moves. Added to `container` so it shares the line's\n        // coordinate frame.\n        var off = cb.offset != null ? Fig.getPoint(cb.offset) : Fig.getPoint([0, 0]);\n        anchoredButtons.push({\n            el: cutBtn, percent: cb.percent != null ? cb.percent : 0.5, offX: off.x, offY: off.y,\n        });\n        placeAnchoredButtons(); // initial placement on the line.\n        var cutBusy_1 = false;\n        element.notificationHelper.add(cutTouch, 'onClick', function () {\n            window.clickHandled = true;\n            if (cutBusy_1)\n                return;\n            var shape = element.custom.splitShape(btnPieceIndex_1, splitOpts_1);\n            if (shape == null)\n                return; // nothing to cut — leave everything pressable.\n            // Lock the whole manipulative (line drag + button) for the fold, then\n            // restore. hasTouchableElements gates touch recursion into the pads and the\n            // button; dimming just the button icon's opacity makes it read as disabled\n            // while the fold plays. The timer rides FigureOne's animation loop (no raw\n            // setTimeout).\n            cutBusy_1 = true;\n            element.hasTouchableElements = false;\n            cutBtn.setOpacity(0.4);\n            element.animations\n                .new()\n                .delay(lockSeconds_1)\n                .trigger(function () {\n                cutBusy_1 = false;\n                element.hasTouchableElements = o.isTouchable !== false;\n                cutBtn.setOpacity(1);\n            })\n                .start();\n        });\n    }\n    // Optional rotate button: a circular-arrow icon that spins the whole line about\n    // its centre (midpoint) by a fixed number of degrees per press. The rotation is\n    // animated and the line stays where it lands; mirrors the cut button's placement\n    // and lock-during-animation.\n    if (o.rotateButton) {\n        var rb = o.rotateButton;\n        var rotRad_1 = ((rb.degrees != null ? rb.degrees : 90) * Math.PI) / 180;\n        var rotDuration_1 = rb.duration != null ? rb.duration : 0.5;\n        var iconColor = rb.color || [0.5, 0.5, 0.5, 1];\n        var iconScale = rb.radius != null ? rb.radius : 0.15;\n        var rotBtn_1 = container.add({ name: 'rotateButton', make: 'collection' });\n        var rotTouch = rotBtn_1.add({\n            name: 'touch',\n            make: 'polygon',\n            sides: 20,\n            radius: iconScale * 1.15,\n            color: o.debug ? [0, 0.7, 0, 0.3] : [0, 0, 0, 0],\n        });\n        addRotateIcon(rotBtn_1, iconColor, iconScale, rotRad_1 >= 0);\n        rotTouch.setTouchable();\n        var roff = rb.offset != null ? Fig.getPoint(rb.offset) : Fig.getPoint([0, 0]);\n        anchoredButtons.push({\n            el: rotBtn_1, percent: rb.percent != null ? rb.percent : 0.5, offX: roff.x, offY: roff.y,\n        });\n        placeAnchoredButtons();\n        // Hide / show the rotate icon. The button's touch target is invisible, so this\n        // effectively just removes (or restores) the visible circular-arrow icon (and\n        // stops the button being pressable while hidden). With a duration it dissolves,\n        // otherwise it toggles instantly. Used e.g. by a demonstrate guide to clear the\n        // rotate icons before animating the pieces. Exposed on `element` (not just\n        // element.custom) because the speech `exec` dispatch calls element[method].\n        element.custom.hideRotateButton = function (duration) {\n            if (duration != null && duration > 0) {\n                rotBtn_1.animations.new().dissolveOut(duration).start();\n            }\n            else {\n                rotBtn_1.hide();\n            }\n        };\n        element.custom.showRotateButton = function (duration) {\n            if (duration != null && duration > 0) {\n                rotBtn_1.animations.new().dissolveIn(duration).start();\n            }\n            else {\n                rotBtn_1.show();\n            }\n        };\n        element.hideRotateButton = element.custom.hideRotateButton;\n        element.showRotateButton = element.custom.showRotateButton;\n        // Rotate a point rigidly about `center` by `ang` radians.\n        var rotateAbout_1 = function (p, center, ang) {\n            var dx = p.x - center.x;\n            var dy = p.y - center.y;\n            var ca = Math.cos(ang);\n            var sa = Math.sin(ang);\n            return Fig.getPoint([center.x + dx * ca - dy * sa, center.y + dx * sa + dy * ca]);\n        };\n        var rotBusy_1 = false;\n        element.notificationHelper.add(rotTouch, 'onClick', function () {\n            window.clickHandled = true;\n            if (rotBusy_1)\n                return;\n            rotBusy_1 = true;\n            element.hasTouchableElements = false;\n            rotBtn_1.setOpacity(0.4);\n            // Snapshot the endpoints + the (fixed) centre at the start; each frame rotates\n            // the snapshot about the centre by the eased fraction of the target angle, then\n            // redraws the line and re-places the pads/buttons.\n            var startP1 = lineP1;\n            var startP2 = lineP2;\n            var center = midpoint();\n            var ease = function (p) { return (1 - Math.cos(Math.PI * p)) / 2; }; // smooth 0->1\n            var apply = function (ang) {\n                lineP1 = rotateAbout_1(startP1, center, ang);\n                lineP2 = rotateAbout_1(startP2, center, ang);\n                updateLine();\n                updatePadsFromLine();\n            };\n            // Finalize the rotation: land exactly on the target angle, commit the answer,\n            // notify consumers, and re-enable the button. This MUST run whenever the\n            // animation ends — not only on natural completion — so it lives in the\n            // builder's whenFinished (fired on both completion and cancellation) rather\n            // than a trailing .trigger() step. A speech vpulse calls element.stop('cancel'),\n            // which recurses into this manipulative and cancels the in-flight rotation; a\n            // cancel freezes the active custom step and SKIPS any not-yet-started trigger\n            // step, so a finalize placed in a .trigger() would never run and the button\n            // would be left permanently disabled at a partial angle. The guard makes it\n            // idempotent (whenFinished fires once, but keep it defensive).\n            var finalized = false;\n            var finalize = function () {\n                if (finalized)\n                    return;\n                finalized = true;\n                apply(rotRad_1); // land exactly on the target angle.\n                element.custom.moved = true;\n                element.custom.state = element.custom.getState();\n                fig.answerChanged();\n                // Tell any consumer wired to this line (e.g. a splittable_shape's\n                // declarative splitLines) that the geometry changed, so it can re-split.\n                // A button rotation never fires a pad's stopBeingMoved, so this is the\n                // only signal those consumers get from a rotate.\n                element.notifications.publish('rotated');\n                rotBusy_1 = false;\n                element.hasTouchableElements = o.isTouchable !== false;\n                rotBtn_1.setOpacity(1);\n            };\n            element.animations\n                .new()\n                .custom({ callback: function (p) { return apply(rotRad_1 * ease(p)); }, duration: rotDuration_1 })\n                .whenFinished(finalize)\n                .start();\n        });\n    }\n    // On relayout (e.g. font loading) the equation repositions children; restore\n    // the learner's position if they've moved the element.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    // Called generically by the answer-input \"show answer\" flow (answerInput.ts)\n    // to freeze every manipulative once the answer is revealed.\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    // Register for answer processing. MUST be snake_case and match the YAML.\n    element.custom.manipulativeType = 'line_manipulative';\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    else {\n        // Move pads handle their own move; leave the container untouchable so native\n        // touch recurses into the pads.\n        element.hasTouchableElements = true;\n    }\n    return element;\n};\nexport { lineManipulative, };\n","import { setupManipulative, outlineVertices } from './tools';\nimport { makeSnapGrid } from './snapGrid';\nimport { NotificationHelper } from '../tools/notifications';\n// Small tolerance for \"is this vertex on the line\" tests so a vertex sitting\n// exactly on the cut isn't double-counted / dropped by floating-point noise.\nvar EPS = 1e-9;\n// A cut only divides a piece when BOTH sides hold at least this fraction of the\n// piece's area. Below it, one side is a numerical sliver (e.g. near-concurrent cuts\n// grazing the shared centre) rather than a real region, so the piece passes through\n// undivided. Legitimate bisections leave each side a large fraction of the parent, so\n// this sits well below any real split yet safely above floating-point slivers.\nvar SLIVER_AREA_FRAC = 0.01;\n// Decimal places each cut endpoint is snapped to (in the shape's local frame) before\n// clipping, so the same visual line placement splits identically every time. 5 dp is\n// far finer than anything visible (1e-5 of the shape) yet coarser than the ~1e-6\n// coordinate-round-trip jitter it exists to absorb.\nvar CUT_PRECISION = 5;\n// The standard manipulative fill colours (hex ÷255, alpha 1). These are the default\n// palette for split pieces.\nvar MANIPULATIVE_COLS = [\n    [0.443, 0.541, 0.749, 0.8], // #718ABF\n    [0.749, 0.447, 0.443, 0.8], // #BF7271\n    [0.608, 0.443, 0.749, 0.8], // #9B71BF\n    [0.584, 0.725, 0.698, 0.8], // #95B9B2\n    [0.565, 0.682, 0.51, 0.8], // #90AE82\n    [0.808, 0.525, 0.306, 0.8], // #CE864E\n    [0.969, 0.843, 0.502, 0.8], // #F7D780\n];\n// Fill colours for the regions a multi-line split makes, used after the two\n// splitColors run out. Cycled, so more pieces than colours just repeat — adjacent\n// regions still read apart in practice for a handful of cuts. Defaults to the\n// remaining MANIPULATIVE_COLS (the first two are the default splitColors below).\nvar EXTRA_PIECE_COLORS = MANIPULATIVE_COLS.slice(2);\nvar splittableShape = function (eqn_name, options, fig) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        color: [0.4, 0.4, 0.4, 1],\n        fill: [0.4, 0.4, 0.4, 0.25],\n        lineWidth: 0.005,\n        dash: [], // solid outline by default\n        // Default two-tone for a single cut = first two MANIPULATIVE_COLS. With the\n        // extra palette above (the remaining MANIPULATIVE_COLS), the full default\n        // piece palette is exactly MANIPULATIVE_COLS in order.\n        splitColors: [MANIPULATIVE_COLS[0], MANIPULATIVE_COLS[1]],\n        maxPieces: 16,\n        reportIgnoreAreaFrac: 0,\n        yOffset: 0,\n        isTouchable: false,\n        boundMove: true,\n        debug: false,\n    }, options);\n    // The fixed polygon's vertices (the single source of truth for the shape):\n    // the traced `outline` edge-walk if one is given, else the explicit `points`.\n    var shapePoints = o.outline != null\n        ? outlineVertices(o.outline, o.start)\n        : (o.points || []).map(function (p) { return Fig.getPoint(p); });\n    // --- GEOMETRY HELPERS (polygon split) -----------------------------------\n    // Signed area×2 of (b-a)×(p-a): >0 means p is left of the directed line a->b,\n    // <0 right of it, ~0 on it. Drives the half-plane test for clipping.\n    function sideOf(p, a, b) {\n        return (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);\n    }\n    // Intersection of segment p->q with the INFINITE line a->b. Only called when\n    // p and q straddle the line, so the denominator is non-zero.\n    function segLineIntersect(p, q, a, b) {\n        var rx = q.x - p.x;\n        var ry = q.y - p.y;\n        var sx = b.x - a.x;\n        var sy = b.y - a.y;\n        var denom = rx * sy - ry * sx;\n        var t = ((a.x - p.x) * sy - (a.y - p.y) * sx) / denom;\n        return Fig.getPoint([p.x + t * rx, p.y + t * ry]);\n    }\n    // Sutherland–Hodgman clip of `poly` against one half-plane of the line a->b.\n    // `side` is +1 (keep the left half) or -1 (keep the right half). Vertices on\n    // the line are kept by both halves, so the two results share the cut edge.\n    function clipHalfPlane(poly, a, b, side) {\n        var out = [];\n        var n = poly.length;\n        for (var i = 0; i < n; i += 1) {\n            var cur = poly[i];\n            var nxt = poly[(i + 1) % n];\n            var dCur = sideOf(cur, a, b) * side;\n            var dNxt = sideOf(nxt, a, b) * side;\n            var curIn = dCur >= -EPS;\n            if (curIn)\n                out.push(cur);\n            // Crossing the line (strictly, ignoring on-line endpoints) adds the\n            // intersection point so the sub-shape is closed along the cut.\n            if ((dCur > EPS && dNxt < -EPS) || (dCur < -EPS && dNxt > EPS)) {\n                out.push(segLineIntersect(cur, nxt, a, b));\n            }\n        }\n        return out;\n    }\n    // Ear-clipping triangulation of `poly`'s interior — a flat list of points in\n    // groups of three (one triangle each) to feed a TRIANGLES generic. Fills\n    // concave simple polygons too, so a concave sub-shape renders correctly.\n    function triangulate(poly) {\n        var n = poly.length;\n        if (n < 3)\n            return [];\n        var area2 = 0;\n        for (var i = 0; i < n; i += 1) {\n            var a = poly[i];\n            var b = poly[(i + 1) % n];\n            area2 += a.x * b.y - b.x * a.y;\n        }\n        var ring = [];\n        for (var i = 0; i < n; i += 1)\n            ring.push(i);\n        if (area2 < 0)\n            ring.reverse(); // force CCW so the \"left turn\" test is consistent.\n        var cross = function (a, b, c) {\n            return (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x);\n        };\n        var inTriangle = function (p, a, b, c) {\n            var d1 = cross(a, b, p);\n            var d2 = cross(b, c, p);\n            var d3 = cross(c, a, p);\n            var hasNeg = d1 < 0 || d2 < 0 || d3 < 0;\n            var hasPos = d1 > 0 || d2 > 0 || d3 > 0;\n            return !(hasNeg && hasPos);\n        };\n        var tris = [];\n        var guard = 0;\n        while (ring.length > 3 && guard < n * n) {\n            guard += 1;\n            var clipped = false;\n            for (var k = 0; k < ring.length; k += 1) {\n                var iPrev = ring[(k - 1 + ring.length) % ring.length];\n                var iCur = ring[k];\n                var iNext = ring[(k + 1) % ring.length];\n                var a = poly[iPrev];\n                var b = poly[iCur];\n                var c = poly[iNext];\n                if (cross(a, b, c) <= 0)\n                    continue; // reflex/collinear tip -> not an ear.\n                var contains = false;\n                for (var m = 0; m < ring.length; m += 1) {\n                    var idx = ring[m];\n                    if (idx === iPrev || idx === iCur || idx === iNext)\n                        continue;\n                    if (inTriangle(poly[idx], a, b, c)) {\n                        contains = true;\n                        break;\n                    }\n                }\n                if (contains)\n                    continue;\n                tris.push(a, b, c);\n                ring.splice(k, 1);\n                clipped = true;\n                break;\n            }\n            if (!clipped)\n                break;\n        }\n        if (ring.length === 3) {\n            tris.push(poly[ring[0]], poly[ring[1]], poly[ring[2]]);\n        }\n        return tris;\n    }\n    // Remove duplicate and collinear vertices from a polygon so clipped pieces are\n    // minimal. A cut through an existing vertex otherwise leaves redundant on-line\n    // points, which inflate vertex counts and break the angle-sequence match in\n    // rigidMap. Returns the cleaned ring (>= 3 vertices, else the input unchanged).\n    function cleanPolygon(poly) {\n        var n = poly.length;\n        if (n < 3)\n            return poly;\n        // Scale-relative merge tolerance: a cut through an existing vertex leaves an\n        // intersection point a few ULPs off the real vertex (well above EPS), so dedup\n        // loosely — still far below any real feature size (the shape's bbox diagonal).\n        var minX = Infinity;\n        var minY = Infinity;\n        var maxX = -Infinity;\n        var maxY = -Infinity;\n        for (var i = 0; i < n; i += 1) {\n            if (poly[i].x < minX)\n                minX = poly[i].x;\n            if (poly[i].x > maxX)\n                maxX = poly[i].x;\n            if (poly[i].y < minY)\n                minY = poly[i].y;\n            if (poly[i].y > maxY)\n                maxY = poly[i].y;\n        }\n        var diag = Math.sqrt((maxX - minX) * (maxX - minX) + (maxY - minY) * (maxY - minY));\n        var tol = Math.max(EPS, 1e-6 * diag);\n        // Drop consecutive (and wrap-around) duplicate points.\n        var pts = [];\n        for (var i = 0; i < n; i += 1) {\n            var p = poly[i];\n            var prev = pts[pts.length - 1];\n            if (prev == null || Math.abs(prev.x - p.x) > tol || Math.abs(prev.y - p.y) > tol) {\n                pts.push(p);\n            }\n        }\n        if (pts.length > 1) {\n            var a = pts[0];\n            var b = pts[pts.length - 1];\n            if (Math.abs(a.x - b.x) < tol && Math.abs(a.y - b.y) < tol)\n                pts.pop();\n        }\n        var m = pts.length;\n        if (m < 3)\n            return pts;\n        // Drop vertices whose two adjacent edges are collinear (|sin(turn)| ~ 0).\n        var out = [];\n        for (var i = 0; i < m; i += 1) {\n            var prev = pts[(i - 1 + m) % m];\n            var cur = pts[i];\n            var nxt = pts[(i + 1) % m];\n            var e1x = cur.x - prev.x;\n            var e1y = cur.y - prev.y;\n            var e2x = nxt.x - cur.x;\n            var e2y = nxt.y - cur.y;\n            var l1 = Math.sqrt(e1x * e1x + e1y * e1y);\n            var l2 = Math.sqrt(e2x * e2x + e2y * e2y);\n            if (l1 < tol || l2 < tol)\n                continue;\n            var cross = e1x * e2y - e1y * e2x;\n            if (Math.abs(cross) > 1e-7 * l1 * l2)\n                out.push(cur);\n        }\n        return out.length >= 3 ? out : pts;\n    }\n    // Area-weighted centroid of a simple polygon (local coords). Falls back to the\n    // plain vertex average for a degenerate (near-zero-area) ring.\n    function polyCentroid(poly) {\n        var n = poly.length;\n        var a = 0;\n        var cx = 0;\n        var cy = 0;\n        for (var i = 0; i < n; i += 1) {\n            var p = poly[i];\n            var q = poly[(i + 1) % n];\n            var cross = p.x * q.y - q.x * p.y;\n            a += cross;\n            cx += (p.x + q.x) * cross;\n            cy += (p.y + q.y) * cross;\n        }\n        if (Math.abs(a) < EPS) {\n            var sx = 0;\n            var sy = 0;\n            for (var i = 0; i < n; i += 1) {\n                sx += poly[i].x;\n                sy += poly[i].y;\n            }\n            return Fig.getPoint(n > 0 ? [sx / n, sy / n] : [0, 0]);\n        }\n        return Fig.getPoint([cx / (3 * a), cy / (3 * a)]);\n    }\n    // --- STRUCTURE ----------------------------------------------------------\n    // `element` is the top-level collection; `container` holds the three sub-\n    // element groups. Draw order (bottom -> top): full shape, then the two splits\n    // (drawn over it, shown only after a cut).\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    element.notificationHelper = new NotificationHelper();\n    // Build one filled + outlined polyline group (a sub-element). `pts` seeds it;\n    // the fill is a triangulated generic, the outline a closed polyline.\n    function buildGroup(name, pts, fillColor) {\n        var group = container.add({ name: name, make: 'collection' });\n        var fillEl = group.add({\n            name: 'fill',\n            make: 'generic',\n            points: triangulate(pts),\n            drawType: 'TRIANGLES',\n            color: fillColor,\n        });\n        fillEl.isTouchable = false;\n        var outlineEl = group.add({\n            name: 'outline',\n            make: 'polyline',\n            points: pts,\n            close: true,\n            width: o.lineWidth,\n            color: o.color,\n            // dash persists across updatePoints (the primitive merges its stored\n            // options), so the split sub-shape outlines stay dashed after a cut.\n            dash: o.dash,\n        });\n        outlineEl.isTouchable = false;\n        return group;\n    }\n    // The full shape (shown), plus a fixed pool of piece groups (hidden) that the\n    // split routines drive — two for a single cut, more once several cut lines carve\n    // additional regions. FigureOne elements are built up front, so the pool is\n    // sized once here at `maxPieces`; piece i is named `split<i>` (keeping `_split0`/\n    // `_split1` for the single-cut case and animateReflect/RotateOnto).\n    var fullGroup = buildGroup('full', shapePoints, o.fill);\n    var maxPieces = Math.max(2, Math.round(o.maxPieces));\n    // Region palette: the two splitColors first (so a single cut keeps its familiar\n    // two-tone look), then the extra hues, then any caller-supplied pieceColors win.\n    var palette = (o.pieceColors != null && o.pieceColors.length > 0)\n        ? o.pieceColors\n        : [o.splitColors[0], o.splitColors[1]].concat(EXTRA_PIECE_COLORS);\n    var pieceColorAt = function (i) { return palette[i % palette.length]; };\n    var pieceGroups = [];\n    for (var i = 0; i < maxPieces; i += 1) {\n        var g = buildGroup('split' + i, shapePoints, pieceColorAt(i));\n        g.hide();\n        pieceGroups.push(g);\n    }\n    var splitsShown = false;\n    // Optional snap grid, anchored to the full shape's outline frame (the frame the\n    // polygon vertices are defined in — the same frame lineToLocal() converts cuts\n    // into). The grid extent defaults to the shape's bounding box, derived directly\n    // from shapePoints so it is unambiguous in the outline draw space. Published\n    // below on element.custom for a consumer to find.\n    var snapGrid = null;\n    if (o.snapGrid != null && shapePoints.length > 0) {\n        var minX = Infinity;\n        var minY = Infinity;\n        var maxX = -Infinity;\n        var maxY = -Infinity;\n        for (var i = 0; i < shapePoints.length; i += 1) {\n            var v = shapePoints[i];\n            if (v.x < minX)\n                minX = v.x;\n            if (v.x > maxX)\n                maxX = v.x;\n            if (v.y < minY)\n                minY = v.y;\n            if (v.y > maxY)\n                maxY = v.y;\n        }\n        snapGrid = makeSnapGrid(fullGroup._outline, o.snapGrid, {\n            left: minX, bottom: minY, right: maxX, top: maxY,\n        });\n        if (o.debug)\n            snapGrid.debugRender(container);\n    }\n    // The cut line in local (draw) coordinates, kept from the last successful\n    // split so animateReflect() can reflect a piece across it, and animateRotateOnto()\n    // can spin a piece about the cut chord. Null when no split is currently shown.\n    var lastCut = null;\n    // The two sub-shape polygons (local coords) from the last successful split,\n    // kept so animateRotateOnto() can find each piece's chord endpoints. Null when\n    // no split is currently shown.\n    var lastHalves = null;\n    // ALL region polygons (local coords) from the last successful split, kept so\n    // animateRotateOntoPiece() can map one piece onto another. Null when no split\n    // is currently shown.\n    var lastPieces = null;\n    // The cut lines (local coords) from the last split — for debug logging only.\n    var lastCutLines = null;\n    // The live cut-line elements wired by the declarative `splitLines` option. Kept so\n    // getSplitLines()/showEqualSplit() can drive them without the question naming them.\n    var resolvedSplitLines = [];\n    // Read the cut line as two points in THIS shape's local (draw) coordinates.\n    // `line` is either a line_manipulative element (endpoints read in figure space\n    // via getFigureLine, then converted into the full shape's draw space) or a raw\n    // pair of figure-space points. The full shape's outline element is the frame\n    // the polygon vertices are defined in, so converting into its draw space lines\n    // the cut up with `shapePoints` regardless of either manipulative's position.\n    function lineToLocal(line) {\n        var figurePts;\n        if (line != null && line.custom != null && typeof line.custom.getFigureLine === 'function') {\n            figurePts = line.custom.getFigureLine();\n        }\n        else if (typeof line === 'function' || (line != null && typeof line.getFigureLine === 'function')) {\n            figurePts = (line.getFigureLine || line)();\n        }\n        else if (Array.isArray(line) && line.length === 2) {\n            figurePts = [Fig.getPoint(line[0]), Fig.getPoint(line[1])];\n        }\n        else {\n            return null;\n        }\n        var outline = fullGroup._outline;\n        return [\n            outline.pointFromSpaceToSpace(figurePts[0], 'figure', 'draw'),\n            outline.pointFromSpaceToSpace(figurePts[1], 'figure', 'draw'),\n        ];\n    }\n    // --- SPLIT --------------------------------------------------------------\n    // Drive the piece pool from a list of region polygons (local coords): show one\n    // pool piece per region (cycling the palette), hide the rest, and swap away from\n    // the full shape when `worthy` (more than one region). Publishes the regions\n    // rounded on element.custom.splitShapes for answer checks / tests and returns\n    // them.\n    function drivePieces(pieces, worthy) {\n        var result = [];\n        for (var i = 0; i < pieceGroups.length; i += 1) {\n            var group = pieceGroups[i];\n            if (worthy && i < pieces.length) {\n                var sub = pieces[i];\n                group._fill.custom.updatePoints({ points: triangulate(sub) });\n                group._outline.custom.updatePoints({ points: sub, close: true });\n                // Clear any fold/spin a prior animateReflect/RotateOnto left so a fresh\n                // split shows the piece flat in its own colour.\n                group.stop('complete');\n                group.setTransform(new Fig.Transform());\n                group._fill.setColor(pieceColorAt(i));\n                group.show();\n                result.push(sub.map(function (q) { return [\n                    Fig.round(q.x, 4), Fig.round(q.y, 4),\n                ]; }));\n            }\n            else {\n                group.hide();\n            }\n        }\n        if (worthy) {\n            fullGroup.hide();\n            splitsShown = true;\n            lastPieces = pieces.slice(0, pieceGroups.length);\n        }\n        else {\n            fullGroup.show();\n            splitsShown = false;\n            lastPieces = null;\n        }\n        element.custom.splitShapes = result;\n        element.custom.state = element.custom.getState();\n        return result;\n    }\n    // Divide the fixed polygon by EVERY given cut line at once. Each line is clipped\n    // against both its half-planes, applied successively to every piece so far, so K\n    // lines yield the arrangement of regions they carve (capped at maxPieces). `lines`\n    // entries are line_manipulative elements or raw figure-space point pairs (see\n    // lineToLocal); lines that miss the shape are ignored. The split is exact for a\n    // convex shape; for a concave one each line should make a single chord per piece.\n    function splitByLines(lines) {\n        var cuts = [];\n        for (var i = 0; i < lines.length; i += 1) {\n            // Only snapped lines cut (when snapping is in use). A line_manipulative reports\n            // isSnapped() === false when it was released beyond its grid's pull radius\n            // (`threshold`); such a line rests off-lattice and must not carve the shape.\n            // Lines without the method, or with snapping off / no threshold, always return\n            // true, so this is a no-op for every existing question.\n            var ln = lines[i];\n            if (ln != null && ln.custom != null\n                && typeof ln.custom.isSnapped === 'function' && ln.custom.isSnapped() === false) {\n                continue;\n            }\n            var local = lineToLocal(lines[i]);\n            if (local == null)\n                continue;\n            // Canonicalize each cut endpoint to a fixed precision. Mapping a line back to\n            // local space round-trips through several transforms and leaves ~1e-6 jitter, so\n            // the SAME visual placement can yield subtly different cut coords from run to run.\n            // Snapping to CUT_PRECISION makes identical placements produce byte-identical clip\n            // inputs, so the split is deterministic. (The SLIVER_AREA_FRAC guard below is what\n            // actually drops degenerate slivers; this only removes run-to-run wobble.)\n            cuts.push([\n                Fig.getPoint([Fig.round(local[0].x, CUT_PRECISION), Fig.round(local[0].y, CUT_PRECISION)]),\n                Fig.getPoint([Fig.round(local[1].x, CUT_PRECISION), Fig.round(local[1].y, CUT_PRECISION)]),\n            ]);\n        }\n        lastCutLines = cuts.length > 0 ? cuts : null;\n        // Start from the whole shape and bisect every piece by each cut in turn. A cut\n        // that leaves a piece wholly on one side passes that piece through unchanged.\n        var pieces = [shapePoints];\n        for (var c = 0; c < cuts.length; c += 1) {\n            var a = cuts[c][0];\n            var b = cuts[c][1];\n            var next = [];\n            for (var p = 0; p < pieces.length; p += 1) {\n                var left = clipHalfPlane(pieces[p], a, b, 1);\n                var right = clipHalfPlane(pieces[p], a, b, -1);\n                // Only treat the cut as dividing this piece when BOTH sides are real regions.\n                // A cut that only grazes a piece (e.g. three near-but-not-exactly-concurrent\n                // diameters meeting at the centre) can otherwise shave off a degenerate\n                // near-zero-area sliver, inflating the piece count (6 wedges -> 7 with a\n                // pinwheel triangle in the middle). Require each side to hold a non-trivial\n                // fraction of the parent's area (scale-invariant); else pass it through whole.\n                var divides = left.length >= 3 && right.length >= 3\n                    && Math.min(polyArea(left), polyArea(right)) > SLIVER_AREA_FRAC * polyArea(pieces[p]);\n                if (divides) {\n                    next.push(left);\n                    next.push(right);\n                }\n                else {\n                    next.push(pieces[p]);\n                }\n            }\n            pieces = next;\n        }\n        // Drop redundant collinear/duplicate vertices (e.g. from a cut through an\n        // existing vertex) so congruent pieces share an identical vertex count/shape.\n        pieces = pieces.map(cleanPolygon).filter(function (p) { return p.length >= 3; });\n        // The pool is finite; if the lines carve more regions than it can show, the\n        // extra regions are dropped (no piece is shown for them).\n        if (pieces.length > maxPieces)\n            pieces = pieces.slice(0, maxPieces);\n        var worthy = cuts.length > 0 && pieces.length > 1;\n        var result = drivePieces(pieces, worthy);\n        // animateReflect/RotateOnto only make sense for a single straight cut into two\n        // pieces; record that case so they can run, and clear it otherwise.\n        if (cuts.length === 1 && pieces.length === 2) {\n            lastCut = cuts[0];\n            lastHalves = [pieces[0], pieces[1]];\n        }\n        else {\n            lastCut = null;\n            lastHalves = null;\n        }\n        return result;\n    }\n    // Single-line convenience wrapper (back-compat): cut the shape into the two\n    // half-planes of one line. Used by lineManipulative.splitShape().\n    function splitByLine(line) {\n        return splitByLines([line]);\n    }\n    // Swap back to the whole shape (undo a split).\n    function clearSplit() {\n        for (var i = 0; i < pieceGroups.length; i += 1)\n            pieceGroups[i].hide();\n        fullGroup.show();\n        splitsShown = false;\n        lastCut = null;\n        lastHalves = null;\n        lastPieces = null;\n        lastCutLines = null;\n        element.custom.splitShapes = [];\n        element.custom.state = element.custom.getState();\n    }\n    // Animate a piece folding over the cut line as a real 3D rotation, with a\n    // perspective divide and faked directional shading. The piece is rotated about\n    // the cut axis (an in-plane axis) by phi, lifting it out of the plane toward the\n    // viewer; a perspective transform then enlarges the lifted part (closer =\n    // bigger). At phi = pi the piece lands on its mirror image. Perspective strength\n    // is opts.perspective (0 = a flat orthographic fold).\n    //\n    // FigureOne's 2D primitives carry no normals/lighting, so the shading is faked\n    // per frame. The flat face's normal tilts with the fold, so the component\n    // facing the viewer is cos(phi): brightness ~ |cos(phi)| darkens the piece\n    // toward edge-on, and the fill swaps to a back-face colour once the underside\n    // turns toward us (cos(phi) < 0). That shading is the cue that distinguishes\n    // folding toward vs. away from the viewer (a bare rotation looks identical\n    // either way). Depth occlusion is painter's-order in a 2D scene, which is fine\n    // for one flap folding over the base shape.\n    //\n    // opts.mode selects the motion (a \"fold\" is one direction, taking opts.duration):\n    //   'to'     — fold from flat to fully reflected and STAY reflected.\n    //   'from'   — start reflected, fold back to flat and STAY flat.\n    //   'bounce' — (default) fold to reflected, hold opts.pause seconds, fold back.\n    // opts.duration seconds per fold; opts.pause seconds held at the reflected state\n    // (bounce only); opts.ambient in [0, 1] floors the brightness at edge-on;\n    // opts.backColor overrides the underside colour (default: darkened front colour);\n    // opts.perspective in [0, 1) is the perspective strength (default 0.4; 0 = flat).\n    function animateReflect(pieceIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastCut == null)\n            return;\n        if (pieceIndex !== 0 && pieceIndex !== 1)\n            return;\n        var group = pieceGroups[pieceIndex];\n        // A fold lifts this piece toward the viewer, but that lift is only a\n        // perspective scale — not real depth. So the piece must draw on top of the\n        // other pieces, or it folds behind whichever piece was added later (or was\n        // toFront'd by an earlier fold, which permanently reorders the container).\n        // Own the z-order here so every caller (cut button, question glue) is correct\n        // and draw order can't get stuck from a prior fold of the other piece.\n        if (group.parent != null && typeof group.parent.toFront === 'function') {\n            group.parent.toFront(group);\n        }\n        var a = lastCut[0];\n        var b = lastCut[1];\n        var theta = Math.atan2(b.y - a.y, b.x - a.x);\n        var axisX = Math.cos(theta); // unit in-plane rotation axis (the cut line).\n        var axisY = Math.sin(theta);\n        var mode = opts.mode || 'bounce';\n        var duration = opts.duration != null ? opts.duration : 1;\n        var pause = opts.pause != null ? opts.pause : 0;\n        var ambient = opts.ambient != null ? opts.ambient : 0.3;\n        var strength = opts.perspective != null ? opts.perspective : 0.4;\n        var front = o.splitColors[pieceIndex];\n        var back = opts.backColor || [\n            front[0] * 0.5, front[1] * 0.5, front[2] * 0.5, front[3],\n        ];\n        // Piece 0 is left of the cut (a->b), piece 1 right; rotating by sigma*phi\n        // lifts whichever piece toward the viewer (+z), so it grows as it rises. maxR\n        // (farthest shape vertex from the pivot) bounds the lift so the perspective w\n        // stays > 0 (>= 1 - strength).\n        var sigma = pieceIndex === 0 ? 1 : -1;\n        var maxR = 0;\n        for (var i = 0; i < shapePoints.length; i += 1) {\n            var dx = shapePoints[i].x - a.x;\n            var dy = shapePoints[i].y - a.y;\n            maxR = Math.max(maxR, Math.sqrt(dx * dx + dy * dy));\n        }\n        // Camera inverse-distance for the perspective divide w = 1 - z * camZ (z is\n        // the out-of-plane lift). 0 disables perspective (a plain orthographic fold).\n        var camZ = strength > 0 && maxR > 1e-9 ? strength / maxR : 0;\n        // Place the piece at one fold angle: rotate about the cut axis (pivoting on a\n        // point of the cut), apply a perspective divide so the lifted part enlarges\n        // (closer = bigger), and shade it for that angle. The 'c' component sets a\n        // homogeneous w = 1 - z*camZ in the pivot frame; FigureOne carries the full\n        // matrix to gl_Position and the GPU divides, so the 2D orthographic scene\n        // shows true perspective without needing a perspective scene.\n        var applyFold = function (phi) {\n            var components = [\n                ['t', -a.x, -a.y, 0],\n                ['r', sigma * phi, axisX, axisY, 0],\n            ];\n            if (camZ > 0) {\n                // Row-major 4x4: identity on x/y/z; w-row = [0, 0, -camZ, 1].\n                components.push([\n                    'c',\n                    1, 0, 0, 0,\n                    0, 1, 0, 0,\n                    0, 0, 1, 0,\n                    0, 0, -camZ, 1,\n                ]);\n            }\n            components.push(['t', a.x, a.y, 0]);\n            group.setTransform(new Fig.Transform(components));\n            var cosPhi = Math.cos(phi);\n            var bright = ambient + (1 - ambient) * Math.abs(cosPhi);\n            var base = cosPhi >= 0 ? front : back;\n            group._fill.setColor([\n                base[0] * bright,\n                base[1] * bright,\n                base[2] * bright,\n                base[3],\n            ]);\n        };\n        var ease = function (p) { return (1 - Math.cos(Math.PI * p)) / 2; }; // smooth 0->1\n        var foldTo = function (p) { return applyFold(Math.PI * ease(p)); }; // flat -> reflected\n        var foldFrom = function (p) { return applyFold(Math.PI * (1 - ease(p))); }; // reflected -> flat\n        // Name the per-frame callbacks via fnMap so the animation is SERIALIZABLE and thus\n        // survives speech pause/resume: figure.getState()/setState (used by pause/resume) drop\n        // any step whose callback is an inline closure, so a pause mid-animation would freeze\n        // the piece and never resume. fnMap is group-scoped and each group animates one thing\n        // at a time (stop('complete') below), so fixed names never collide across pieces.\n        // (Same pattern as lineManipulative.animateToLine / clock.ts goToTime.)\n        group.fnMap.add('srFoldTo', foldTo);\n        group.fnMap.add('srFoldFrom', foldFrom);\n        group.stop('complete'); // settle any in-flight fold before re-starting.\n        if (mode === 'to') {\n            group.animations.new().custom({ callback: 'srFoldTo', duration: duration }).start();\n        }\n        else if (mode === 'from') {\n            applyFold(Math.PI); // lock the reflected start so there is no flash.\n            group.animations.new().custom({ callback: 'srFoldFrom', duration: duration }).start();\n        }\n        else {\n            var anim = group.animations.new().custom({ callback: 'srFoldTo', duration: duration });\n            if (pause > 0)\n                anim = anim.delay(pause);\n            anim.custom({ callback: 'srFoldFrom', duration: duration }).start();\n        }\n    }\n    // Animate a piece rotating 180° in-plane to land on top of the other piece —\n    // the rotational-symmetry counterpart to animateReflect's line-symmetry fold.\n    //\n    // For a single straight cut the two pieces share the cut chord: the two points\n    // where the line crosses the polygon boundary, which are vertices of BOTH\n    // pieces. The only proper rigid motion that can carry one piece onto the other\n    // swaps those two chord endpoints — a 180° rotation about the chord midpoint M.\n    // That lands the piece exactly on the other one iff the shape has 2-fold\n    // rotational (point) symmetry about M; otherwise it just shows where a half-turn\n    // takes the piece. Unlike animateReflect this is a flat in-plane spin — the face\n    // stays toward the viewer — so there is no fold, perspective divide, or\n    // back-face shading.\n    //\n    // opts.mode selects the motion (same vocabulary as animateReflect):\n    //   'to'     — spin from flat to fully rotated and STAY rotated (on the other piece).\n    //   'from'   — start rotated, spin back to flat and STAY flat.\n    //   'bounce' — (default) spin onto the other piece, hold opts.pause seconds, spin back.\n    // opts.duration seconds per half-turn; opts.pause seconds held (bounce only);\n    // opts.direction 'ccw' (default) or 'cw' picks which way it sweeps — both land in\n    // the same place, only the arc differs.\n    function animateRotateOnto(pieceIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastCut == null || lastHalves == null)\n            return;\n        if (pieceIndex !== 0 && pieceIndex !== 1)\n            return;\n        var group = pieceGroups[pieceIndex];\n        var a = lastCut[0];\n        var b = lastCut[1];\n        var dx = b.x - a.x;\n        var dy = b.y - a.y;\n        var len = Math.sqrt(dx * dx + dy * dy);\n        if (len < EPS)\n            return;\n        // The chord endpoints are the piece's vertices lying on the cut line (signed\n        // distance ~0). Pick the two farthest apart so an original polygon vertex that\n        // also happens to sit on the line can't shrink the chord, then rotate about\n        // their midpoint.\n        var onLine = lastHalves[pieceIndex].filter(function (v) { return Math.abs(sideOf(v, a, b)) / len < 1e-6; });\n        if (onLine.length < 2)\n            return;\n        var p = onLine[0];\n        var q = onLine[1];\n        var best = -1;\n        for (var i = 0; i < onLine.length; i += 1) {\n            for (var j = i + 1; j < onLine.length; j += 1) {\n                var ex = onLine[i].x - onLine[j].x;\n                var ey = onLine[i].y - onLine[j].y;\n                var d = ex * ex + ey * ey;\n                if (d > best) {\n                    best = d;\n                    p = onLine[i];\n                    q = onLine[j];\n                }\n            }\n        }\n        var mx = (p.x + q.x) / 2;\n        var my = (p.y + q.y) / 2;\n        var dir = opts.direction === 'cw' ? -1 : 1;\n        var mode = opts.mode || 'bounce';\n        var duration = opts.duration != null ? opts.duration : 1;\n        var pause = opts.pause != null ? opts.pause : 0;\n        // Clear any shading/fold a prior animateReflect may have left on this piece so\n        // it spins in its own flat colour.\n        group._fill.setColor(o.splitColors[pieceIndex]);\n        // Pivot in-plane about the chord midpoint: translate the midpoint to the\n        // origin, rotate about the z axis, translate back. At phi = pi the piece has\n        // swapped the chord endpoints and sits on the other piece's footprint.\n        var applyRot = function (phi) {\n            group.setTransform(new Fig.Transform([\n                ['t', -mx, -my, 0],\n                ['r', dir * phi, 0, 0, 1],\n                ['t', mx, my, 0],\n            ]));\n        };\n        var ease = function (pr) { return (1 - Math.cos(Math.PI * pr)) / 2; }; // smooth 0->1\n        var spinTo = function (pr) { return applyRot(Math.PI * ease(pr)); }; // flat -> rotated\n        var spinFrom = function (pr) { return applyRot(Math.PI * (1 - ease(pr))); }; // rotated -> flat\n        // fnMap-named callbacks so the spin survives speech pause/resume (see animateReflect).\n        group.fnMap.add('srSpinTo', spinTo);\n        group.fnMap.add('srSpinFrom', spinFrom);\n        group.stop('complete'); // settle any in-flight spin before re-starting.\n        if (mode === 'to') {\n            group.animations.new().custom({ callback: 'srSpinTo', duration: duration }).start();\n        }\n        else if (mode === 'from') {\n            applyRot(Math.PI); // lock the rotated start so there is no flash.\n            group.animations.new().custom({ callback: 'srSpinFrom', duration: duration }).start();\n        }\n        else {\n            var anim = group.animations.new().custom({ callback: 'srSpinTo', duration: duration });\n            if (pause > 0)\n                anim = anim.delay(pause);\n            anim.custom({ callback: 'srSpinFrom', duration: duration }).start();\n        }\n    }\n    // --- PIECE-TO-PIECE RIGID MAP (multi-split rotation) --------------------\n    // Interior angle (in (0, 2pi)) at each vertex of a CCW polygon. Angles are\n    // invariant under any rigid motion, so equal angles mark corresponding vertices.\n    function polyAngles(poly) {\n        var n = poly.length;\n        var angs = [];\n        for (var i = 0; i < n; i += 1) {\n            var prev = poly[(i - 1 + n) % n];\n            var cur = poly[i];\n            var nxt = poly[(i + 1) % n];\n            var aPrev = Math.atan2(prev.y - cur.y, prev.x - cur.x);\n            var aNext = Math.atan2(nxt.y - cur.y, nxt.x - cur.x);\n            var d = aPrev - aNext;\n            while (d < 0)\n                d += 2 * Math.PI;\n            while (d >= 2 * Math.PI)\n                d -= 2 * Math.PI;\n            angs.push(d);\n        }\n        return angs;\n    }\n    // Length of the edge leaving each vertex (vertex i -> i+1).\n    function polyEdges(poly) {\n        var n = poly.length;\n        var lens = [];\n        for (var i = 0; i < n; i += 1) {\n            var dx = poly[(i + 1) % n].x - poly[i].x;\n            var dy = poly[(i + 1) % n].y - poly[i].y;\n            lens.push(Math.sqrt(dx * dx + dy * dy));\n        }\n        return lens;\n    }\n    // Wrapped absolute difference of two angles, in [0, pi].\n    function angleDiff(a, b) {\n        var d = Math.abs(a - b);\n        if (d > Math.PI)\n            d = 2 * Math.PI - d;\n        return d;\n    }\n    // Build a rigid motion mapping point (ax, ay) -> (bx, by) with rotation phi,\n    // expressed as a pure rotation about a centre (or a translation when phi ~ 0).\n    // A planar rotation + translation is a pure rotation by phi about the centre\n    // C = (I - R)^-1 t, with det(I - R) = 2(1 - cos phi).\n    function makeRigid(phi, ax, ay, bx, by) {\n        var cos = Math.cos(phi);\n        var sin = Math.sin(phi);\n        var tx = bx - (cos * ax - sin * ay);\n        var ty = by - (sin * ax + cos * ay);\n        if (Math.abs(phi) < 1e-6)\n            return { kind: 'trans', tx: tx, ty: ty, phi: 0 };\n        var det = 2 * (1 - cos);\n        return {\n            kind: 'rot',\n            cx: ((1 - cos) * tx - sin * ty) / det,\n            cy: (sin * tx + (1 - cos) * ty) / det,\n            phi: phi,\n        };\n    }\n    // Corner-align: rotate so A's vertex i sits on B's vertex j, with A's LONGER\n    // adjacent edge there pointing along B's corresponding (same-side) edge. Aligning\n    // the longer edge sets the rotation from a straight feature — a chord/radius from a\n    // cut, not a short arc segment — so on a circle the chords/radii line up rather\n    // than the redundant arc. Both rings wind CCW; congruent pieces still coincide\n    // exactly (the correspondence guarantees same-side edges correspond).\n    function cornerAlign(A, B, i, j) {\n        var nA = A.length;\n        var nB = B.length;\n        var a0 = A[i];\n        var b0 = B[j];\n        var aNext = A[(i + 1) % nA];\n        var aPrev = A[(i - 1 + nA) % nA];\n        var bNext = B[(j + 1) % nB];\n        var bPrev = B[(j - 1 + nB) % nB];\n        var outDx = aNext.x - a0.x;\n        var outDy = aNext.y - a0.y;\n        var inDx = a0.x - aPrev.x;\n        var inDy = a0.y - aPrev.y;\n        var aDir;\n        var bDir;\n        if (outDx * outDx + outDy * outDy >= inDx * inDx + inDy * inDy) {\n            aDir = Math.atan2(outDy, outDx);\n            bDir = Math.atan2(bNext.y - b0.y, bNext.x - b0.x);\n        }\n        else {\n            aDir = Math.atan2(inDy, inDx);\n            bDir = Math.atan2(b0.y - bPrev.y, b0.x - bPrev.x);\n        }\n        var phi = bDir - aDir;\n        return makeRigid(phi, a0.x, a0.y, b0.x, b0.y);\n    }\n    // Find a rigid motion (rotation + translation, no reflection) mapping polygon A\n    // onto polygon B by lining up an angle (pinning a corner). The CORRESPONDENCE\n    // (which vertex of A pairs with which of B) is chosen to minimise the difference\n    // of corresponding angles AND corresponding sides, each normalised to a\n    // comparable scale (angles by pi, sides by the mean side length) so they weigh\n    // equally. Each vertex's contribution is further weighted by its \"cornerness\"\n    // (turn from straight): on a many-sided shape (a circle approximated by a 50/100-\n    // gon) the dozens of near-straight arc vertices are redundant, so they barely\n    // count, and the few distinctive corners (where cuts meet the boundary) drive\n    // both the match and the pinned corner — without this, accumulated noise over the\n    // redundant vertices could swamp the corner signal. The rotation then pins the\n    // most distinctive well-matching corner, so an equal angle lands on an equal\n    // angle and congruent pieces coincide exactly. Always returns a motion (never\n    // null for valid polygons). `exact` flags a congruent fit; `err` the match cost.\n    // PROPER only (rotation + translation, no reflection); rigidMap() wraps this to\n    // also try the mirror image.\n    function matchProper(A, B) {\n        if (A.length < 3 || B.length < 3)\n            return null;\n        var angA = polyAngles(A);\n        var angB = polyAngles(B);\n        var lenA = polyEdges(A);\n        var lenB = polyEdges(B);\n        var perimA = 0;\n        var perimB = 0;\n        for (var i = 0; i < lenA.length; i += 1)\n            perimA += lenA[i];\n        for (var i = 0; i < lenB.length; i += 1)\n            perimB += lenB[i];\n        // Characteristic side length normalises a side difference to ~[0, 1], matching\n        // the angle term (divided by pi), so angles and sides carry equal weight.\n        var charLen = Math.max(EPS, (perimA / A.length + perimB / B.length) / 2);\n        // Cornerness weight per vertex, in [0, 2]: 0 at a straight (interior pi) vertex,\n        // rising for sharp/reflex corners. Down-weights redundant smooth arc vertices.\n        var wA = angA.map(function (a) { return 1 + Math.cos(a); });\n        var wB = angB.map(function (a) { return 1 + Math.cos(a); });\n        // Normalised cost of pairing corner A[i] with B[j]: angle mismatch (/pi) plus\n        // outgoing-side mismatch (/charLen).\n        var pairCost = function (i, j) {\n            return angleDiff(angA[i], angB[j]) / Math.PI\n                + Math.abs(lenA[i] - lenB[j]) / charLen;\n        };\n        if (A.length === B.length) {\n            var n = A.length;\n            // Pick the cyclic correspondence A[i] <-> B[(i+k)%n] minimising the\n            // cornerness-WEIGHTED mean of the normalised (angle + side) difference.\n            var bestK = 0;\n            var bestCost = Infinity;\n            for (var k = 0; k < n; k += 1) {\n                var num = 0;\n                var den = 0;\n                for (var i = 0; i < n; i += 1) {\n                    var j = (i + k) % n;\n                    var w = Math.max(wA[i], wB[j]);\n                    num += w * pairCost(i, j);\n                    den += w;\n                }\n                var cost = den > EPS ? num / den : 0;\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestK = k;\n                }\n            }\n            // Within that correspondence, pin the corner with the longest adjacent edges\n            // — one made of the straight cut edges (chords/radii), not short arc segments:\n            // the apex of two cuts beats a chord/arc junction, which beats a mid-arc\n            // vertex. (cutSum/charLen dominates on a circle, where cuts are far longer\n            // than arc steps; match quality breaks ties on near-uniform shapes.)\n            var bestI = 0;\n            var bestScore = Infinity;\n            for (var i = 0; i < n; i += 1) {\n                var cutSum = lenA[(i - 1 + n) % n] + lenA[i];\n                var score = pairCost(i, (i + bestK) % n) - cutSum / charLen;\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestI = i;\n                }\n            }\n            var map_1 = cornerAlign(A, B, bestI, (bestI + bestK) % n);\n            map_1.exact = bestCost < 1e-2; // every corresponding pair matches => congruent.\n            map_1.err = bestCost;\n            // Debug fields: which corner was pinned and its adjacent edge lengths (two\n            // long => apex of two cuts; one long => chord/arc junction; both short => arc).\n            map_1.pinA = bestI;\n            map_1.pinB = (bestI + bestK) % n;\n            map_1.pinEdges = [lenA[(bestI - 1 + n) % n], lenA[bestI]];\n            return map_1;\n        }\n        // Different vertex counts: no full correspondence. Pin each piece's APEX — the\n        // corner of its two longest edges (where the cut lines meet) — independently, so\n        // the cut corner registers regardless of how the arcs / vertex counts differ. A\n        // cost-based search would otherwise let a perfectly-matching arc vertex win on a\n        // small piece (where arc steps rival the cut arms) and align the arc. (A chord +\n        // arc segment with no two-cut apex pins its chord/arc junction — its longest-\n        // edged corner.)\n        var apexOf = function (len) {\n            var idx = 0;\n            var best = -Infinity;\n            var m = len.length;\n            for (var i = 0; i < m; i += 1) {\n                var cut = len[(i - 1 + m) % m] + len[i];\n                if (cut > best) {\n                    best = cut;\n                    idx = i;\n                }\n            }\n            return idx;\n        };\n        var bi = apexOf(lenA);\n        var bj = apexOf(lenB);\n        var map = cornerAlign(A, B, bi, bj);\n        map.exact = false;\n        map.err = pairCost(bi, bj);\n        map.pinA = bi;\n        map.pinB = bj;\n        map.pinEdges = [lenA[(bi - 1 + A.length) % A.length], lenA[bi]];\n        return map;\n    }\n    // Find the best isometry (rotation+translation OR reflection) mapping A onto B.\n    // Tries the proper match and the match of A's MIRROR image; if the mirror fits\n    // better (A is ~a reflection of B, which no rotation can align), returns an\n    // improper isometry decomposed into a fold line + glide so it can be animated as\n    // a flip. `reflected` flags that case. Otherwise returns the proper match.\n    function rigidMap(A, B) {\n        var proper = matchProper(A, B);\n        // Mirror A across the x-axis AND reverse its order (reflection flips winding;\n        // reversing restores CCW so the proper matcher applies). Aref is the mirror of A.\n        var n = A.length;\n        var aRef = [];\n        for (var k = 0; k < n; k += 1) {\n            var p = A[(n - 1 - k) % n];\n            aRef.push(Fig.getPoint([p.x, -p.y]));\n        }\n        var refl = matchProper(aRef, B);\n        // Strongly prefer the proper (rotation) match. Only flip when rotation genuinely\n        // FAILS and the mirror clearly succeeds — i.e. the mirror is better by a wide\n        // margin. Pieces alignable by rotation (incl. near-congruent ones whose err is\n        // small discretisation noise) keep rotating; only true mirror pieces flip.\n        if (refl == null || proper == null || proper.err - refl.err <= 0.5)\n            return proper;\n        // Build the improper isometry on the ORIGINAL A: T(p) = Proper(S p), S = reflect\n        // across x-axis. Proper(q) = R(phi) q + tp (rotation about centre, or translation).\n        var phi = refl.phi != null ? refl.phi : 0;\n        var cosp = Math.cos(phi);\n        var sinp = Math.sin(phi);\n        var tpx;\n        var tpy;\n        if (refl.kind === 'trans') {\n            cosp = 1;\n            sinp = 0;\n            tpx = refl.tx;\n            tpy = refl.ty;\n        }\n        else {\n            tpx = refl.cx - (cosp * refl.cx - sinp * refl.cy); // C - R C\n            tpy = refl.cy - (sinp * refl.cx + cosp * refl.cy);\n        }\n        // M = R·S = [[cosp, sinp],[sinp, -cosp]] is a reflection; decompose T into a\n        // glide reflection: fold line through P0 at direction u, plus a glide g along u.\n        var beta = Math.atan2(sinp, cosp) / 2; // reflection-axis angle (2*beta = phi)\n        var ux = Math.cos(beta);\n        var uy = Math.sin(beta);\n        var glide = tpx * ux + tpy * uy;\n        var gx = glide * ux;\n        var gy = glide * uy;\n        var p0x = (tpx - gx) / 2; // the fold line passes through the perpendicular midpoint\n        var p0y = (tpy - gy) / 2;\n        return {\n            kind: 'reflect',\n            reflected: true,\n            p0x: p0x,\n            p0y: p0y,\n            ux: ux,\n            uy: uy,\n            gx: gx,\n            gy: gy,\n            exact: refl.exact,\n            err: refl.err,\n            phi: phi, // debug: the proper-part angle behind the reflection\n            pinA: refl.pinA,\n            pinB: refl.pinB,\n            pinEdges: refl.pinEdges,\n        };\n    }\n    // Rotate/transpose one piece onto another. `fromIndex` is the piece that moves;\n    // `toIndex` is the target piece (pass null/undefined to auto-pick the piece it is\n    // congruent to — the rigid-map match with the least error among an EXACT fit).\n    // With an explicit target it always animates the best-fit motion even if the\n    // pieces aren't perfectly congruent (\"closest angles\" fallback). opts mirror\n    // animateRotateOnto: mode 'to'|'from'|'bounce' (default bounce), duration, pause.\n    // Returns the resolved target index, or null if no motion was animated.\n    function animateRotateOntoPiece(fromIndex, toIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastPieces == null)\n            return null;\n        var A = lastPieces[fromIndex];\n        if (A == null)\n            return null;\n        var target = toIndex == null ? -1 : toIndex;\n        if (target < 0) {\n            // Auto-pick: the congruent piece (exact match) with the least error.\n            var bestErr = Infinity;\n            for (var j = 0; j < lastPieces.length; j += 1) {\n                if (j === fromIndex)\n                    continue;\n                var m = rigidMap(A, lastPieces[j]);\n                if (m != null && m.exact && m.err < bestErr) {\n                    bestErr = m.err;\n                    target = j;\n                }\n            }\n            if (target < 0)\n                return null; // nothing congruent to land on.\n        }\n        if (target === fromIndex || lastPieces[target] == null)\n            return null;\n        var map = rigidMap(A, lastPieces[target]);\n        if (map == null)\n            return null;\n        // Take the SHORTEST sweep by default. rigidMap's phi is bDir - aDir (a difference\n        // of two atan2 angles), so it lands in (-2pi, 2pi) and can send a piece the long\n        // way round (e.g. +240 deg instead of the equivalent -120). phi and phi -/+ 2pi are\n        // the same rotation about the same pivot (cos/sin are periodic -> identical\n        // endpoint), so wrapping a rotation to (-pi, pi] only changes the path, not where\n        // the piece lands.\n        if (map.kind === 'rot') {\n            while (map.phi > Math.PI)\n                map.phi -= 2 * Math.PI;\n            while (map.phi <= -Math.PI)\n                map.phi += 2 * Math.PI;\n        }\n        // Force the sweep direction if asked: taking the explement (phi -/+ 2pi) lands the\n        // piece in the same place the other way round. Only meaningful for a pure rotation.\n        if (opts.direction != null && map.kind === 'rot') {\n            if (opts.direction === 'ccw' && map.phi < 0)\n                map.phi += 2 * Math.PI;\n            else if (opts.direction === 'cw' && map.phi > 0)\n                map.phi -= 2 * Math.PI;\n        }\n        if (o.debug) {\n            var r3 = function (x) { return Math.round(x * 1000) / 1000; };\n            // eslint-disable-next-line no-console\n            console.log(\"[splittableShape \".concat(o.name, \"] rotate piece \").concat(fromIndex, \" -> \").concat(target, \":\"), {\n                kind: map.kind,\n                reflected: map.reflected === true, // true => flipped (mirror piece)\n                phiDeg: r3((map.phi * 180) / Math.PI),\n                exact: map.exact,\n                err: r3(map.err),\n                pinFrom: map.pinA, // vertex index of the moving piece that gets pinned\n                pinTo: map.pinB, // vertex index of the target it pins onto\n                pinEdges: (map.pinEdges || []).map(r3), // [incoming, outgoing] edge lengths\n                pivot: map.kind === 'rot' ? [r3(map.cx), r3(map.cy)] : null,\n                foldLine: map.kind === 'reflect' // [point, direction] of the flip axis\n                    ? { p0: [r3(map.p0x), r3(map.p0y)], dir: [r3(map.ux), r3(map.uy)] } : null,\n            });\n        }\n        var group = pieceGroups[fromIndex];\n        var mode = opts.mode || 'bounce';\n        var duration = opts.duration != null ? opts.duration : 1;\n        var pause = opts.pause != null ? opts.pause : 0;\n        var startDelay = opts.startDelay != null ? opts.startDelay : 0;\n        var hold = opts.hold != null ? opts.hold : pause; // bounce: gap before returning.\n        // Clear any shading/transform a prior animation left so the piece moves flat in\n        // its own colour.\n        var fillFront = pieceColorAt(fromIndex);\n        group._fill.setColor(fillFront);\n        // For a flip, set up a real 3D fold: perspective divide (closer = bigger) and\n        // faked directional shading (darkens edge-on, back-face colour once flipped) —\n        // the same treatment as animateReflect, so the flip reads as a physical turn.\n        var foldBack = [fillFront[0] * 0.5, fillFront[1] * 0.5, fillFront[2] * 0.5, fillFront[3]];\n        var foldAmbient = 0.3;\n        var foldCamZ = 0;\n        if (map.kind === 'reflect') {\n            var maxR = 0;\n            for (var i = 0; i < A.length; i += 1) {\n                var dx = A[i].x - map.p0x;\n                var dy = A[i].y - map.p0y;\n                maxR = Math.max(maxR, Math.sqrt(dx * dx + dy * dy));\n            }\n            var strength = 0.4; // perspective strength (0 = flat orthographic fold)\n            foldCamZ = maxR > 1e-9 ? strength / maxR : 0;\n        }\n        // Place the piece at fraction s in [0, 1] of the full motion.\n        var apply = function (s) {\n            if (map.kind === 'trans') {\n                group.setTransform(new Fig.Transform([['t', s * map.tx, s * map.ty, 0]]));\n            }\n            else if (map.kind === 'reflect') {\n                // Flip: fold 180° about the in-plane fold line (point p0, direction u) plus\n                // a glide along it. At s = 1 the piece is reflected across the line and\n                // glided — the improper isometry that lands the mirror piece on the target.\n                var phiFold = Math.PI * s;\n                var components = [\n                    ['t', -map.p0x, -map.p0y, 0],\n                    ['r', phiFold, map.ux, map.uy, 0],\n                ];\n                if (foldCamZ > 0) {\n                    // Perspective divide w = 1 - z*camZ in the fold frame (lifted part grows).\n                    components.push([\n                        'c', 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -foldCamZ, 1,\n                    ]);\n                }\n                components.push(['t', map.p0x, map.p0y, 0]);\n                components.push(['t', map.gx * s, map.gy * s, 0]);\n                group.setTransform(new Fig.Transform(components));\n                // Shade for the fold angle: darken toward edge-on, swap to the back-face\n                // colour once the underside turns toward us (cos < 0).\n                var cosF = Math.cos(phiFold);\n                var bright = foldAmbient + (1 - foldAmbient) * Math.abs(cosF);\n                var base = cosF >= 0 ? fillFront : foldBack;\n                group._fill.setColor([base[0] * bright, base[1] * bright, base[2] * bright, base[3]]);\n            }\n            else {\n                group.setTransform(new Fig.Transform([\n                    ['t', -map.cx, -map.cy, 0],\n                    ['r', s * map.phi, 0, 0, 1],\n                    ['t', map.cx, map.cy, 0],\n                ]));\n            }\n        };\n        var ease = function (p) { return (1 - Math.cos(Math.PI * p)) / 2; }; // smooth 0->1\n        var moveTo = function (p) { return apply(ease(p)); }; // start -> landed\n        var moveFrom = function (p) { return apply(1 - ease(p)); }; // landed -> start\n        // fnMap-named callbacks so the move survives speech pause/resume (see animateReflect).\n        group.fnMap.add('srMoveTo', moveTo);\n        group.fnMap.add('srMoveFrom', moveFrom);\n        group.stop('complete'); // settle any in-flight motion before re-starting.\n        if (mode === 'from')\n            apply(1); // lock the landed start so there is no flash.\n        var anim = group.animations.new();\n        if (startDelay > 0)\n            anim = anim.delay(startDelay); // stagger for ...PieceAll.\n        if (mode === 'to') {\n            anim.custom({ callback: 'srMoveTo', duration: duration }).start();\n        }\n        else if (mode === 'from') {\n            anim.custom({ callback: 'srMoveFrom', duration: duration }).start();\n        }\n        else {\n            anim = anim.custom({ callback: 'srMoveTo', duration: duration });\n            if (hold > 0)\n                anim = anim.delay(hold);\n            anim.custom({ callback: 'srMoveFrom', duration: duration }).start();\n        }\n        return target;\n    }\n    // Rotate/transpose EVERY other piece onto the piece at toIndex, in piece-index\n    // order (skipping toIndex). Two INDEPENDENT stagger gaps (seconds):\n    //   - delayTo:   gap between successive pieces STARTING their move onto the target\n    //                (0 => all set off together; d => one piece every d seconds).\n    //   - delayFrom: gap between successive pieces STARTING their RETURN (bounce only;\n    //                0 => they all snap back together).\n    // `delay` sets both at once (back-compat). Every return begins only after the last\n    // piece has arrived and held opts.pause, so the onto and return phases never\n    // overlap — e.g. delayTo > 0, delayFrom = 0 fans the pieces in one at a time then\n    // sends them all back together. Other opts (mode/duration/pause) forward to\n    // animateRotateOntoPiece. Returns the indices animated, in start order.\n    function animateRotateOntoPieceAll(toIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastPieces == null)\n            return [];\n        if (o.debug) {\n            var r3_1 = function (x) { return Math.round(x * 1000) / 1000; };\n            // eslint-disable-next-line no-console\n            console.log(\"[splittableShape \".concat(o.name, \"] animateRotateOntoPieceAll onto \").concat(toIndex, \" \\u2014\"), 'cut lines (local):', (lastCutLines || []).map(function (c) { return [[r3_1(c[0].x), r3_1(c[0].y)], [r3_1(c[1].x), r3_1(c[1].y)]]; }), '| pieces (vertices):', lastPieces.map(function (p) { return p.length; }));\n        }\n        var mode = opts.mode || 'bounce';\n        var duration = opts.duration != null ? opts.duration : 1;\n        var pause = opts.pause != null ? opts.pause : 0;\n        var fallback = opts.delay != null ? opts.delay : 0;\n        var delayTo = opts.delayTo != null ? opts.delayTo : fallback;\n        var delayFrom = opts.delayFrom != null ? opts.delayFrom : fallback;\n        // Pieces that will animate (valid polygons, excluding the target), in order.\n        var eligible = [];\n        for (var i = 0; i < lastPieces.length; i += 1) {\n            if (i === toIndex)\n                continue;\n            if (lastPieces[i] != null && lastPieces[i].length >= 3)\n                eligible.push(i);\n        }\n        var n = eligible.length;\n        // All returns begin at this common time (after the last arrival + pause), then\n        // are themselves staggered by delayFrom.\n        var fromStart = (n - 1) * delayTo + duration + pause;\n        var animated = [];\n        for (var idx = 0; idx < n; idx += 1) {\n            var i = eligible[idx];\n            // 'from' has only a return phase (staggered by delayFrom); 'to'/'bounce' stagger\n            // the onto phase by delayTo.\n            var startDelay = (mode === 'from' ? delayFrom : delayTo) * idx;\n            // Bounce hold: keep each piece at the target until its scheduled return, so the\n            // return starts at fromStart + idx*delayFrom regardless of when it arrived.\n            var hold = fromStart + idx * delayFrom - (idx * delayTo + duration);\n            var t = animateRotateOntoPiece(i, toIndex, Fig.joinObjects({}, opts, { startDelay: startDelay, hold: hold }));\n            if (t != null)\n                animated.push(i);\n        }\n        return animated;\n    }\n    // Slide pieces radially outward from the shape's centre (an \"exploded\" look), by\n    // `space` units (default 0.05) plus an optional fixed `offset`. The outward\n    // direction is the shape centroid -> piece centroid, computed per piece; a piece\n    // centred on the shape (no clear outward direction) moves by `offset` only. mode\n    // mirrors the other animators: 'to' slides out and stays, 'from' starts out and\n    // returns to place, 'bounce' (default) slides out, holds `pause` seconds, returns.\n    // `splitIndexes` is one piece index or a list of them; every listed shown piece\n    // separates together. Returns the indexes actually separated.\n    function separateSplit(splitIndexes, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastPieces == null)\n            return [];\n        var space = opts.space != null ? opts.space : 0.05;\n        var offset = Fig.getPoint(opts.offset != null ? opts.offset : [0, 0]);\n        var duration = opts.duration != null ? opts.duration : 1;\n        var pause = opts.pause != null ? opts.pause : 0;\n        var mode = opts.mode || 'bounce';\n        // A fixed slide direction, when `angle` is given (overrides the radial default).\n        var fixedDir = opts.angle != null\n            ? { x: Math.cos(opts.angle * (Math.PI / 180)), y: Math.sin(opts.angle * (Math.PI / 180)) }\n            : null;\n        var c = polyCentroid(shapePoints);\n        // Slide one piece outward; returns true if that piece exists and is shown.\n        var separateOne = function (splitIndex) {\n            var piece = lastPieces == null ? null : lastPieces[splitIndex];\n            var group = pieceGroups[splitIndex];\n            if (piece == null || piece.length < 3 || group == null)\n                return false;\n            var dx;\n            var dy;\n            if (fixedDir != null) {\n                // Caller-forced direction: same fixed angle for every piece.\n                dx = fixedDir.x;\n                dy = fixedDir.y;\n            }\n            else {\n                // Default: outward along the centroid -> piece-centroid ray.\n                var pc = polyCentroid(piece);\n                dx = pc.x - c.x;\n                dy = pc.y - c.y;\n                var len = Math.sqrt(dx * dx + dy * dy);\n                if (len > EPS) {\n                    dx /= len;\n                    dy /= len;\n                }\n                else {\n                    dx = 0;\n                    dy = 0;\n                }\n            }\n            var tx = dx * space + offset.x;\n            var ty = dy * space + offset.y;\n            // Translate the piece group by the full delta at fraction s of the motion.\n            var at = function (s) {\n                group.setTransform(new Fig.Transform([['t', tx * s, ty * s, 0]]));\n            };\n            var ease = function (p) { return (1 - Math.cos(Math.PI * p)) / 2; };\n            var slideTo = function (p) { return at(ease(p)); };\n            var slideFrom = function (p) { return at(1 - ease(p)); };\n            // fnMap-named callbacks so the slide survives speech pause/resume (see\n            // animateReflect). Each piece has its own group (own fnMap), so the fixed names\n            // stay independent even though separateSplit slides several pieces at once.\n            group.fnMap.add('srSlideTo', slideTo);\n            group.fnMap.add('srSlideFrom', slideFrom);\n            group.stop('complete');\n            if (mode === 'to') {\n                group.animations.new().custom({ callback: 'srSlideTo', duration: duration }).start();\n            }\n            else if (mode === 'from') {\n                at(1); // lock the separated start so there is no flash.\n                group.animations.new().custom({ callback: 'srSlideFrom', duration: duration }).start();\n            }\n            else {\n                var anim = group.animations.new().custom({ callback: 'srSlideTo', duration: duration });\n                if (pause > 0)\n                    anim = anim.delay(pause);\n                anim.custom({ callback: 'srSlideFrom', duration: duration }).start();\n            }\n            return true;\n        };\n        var indexes = Array.isArray(splitIndexes) ? splitIndexes : [splitIndexes];\n        var separated = [];\n        for (var i = 0; i < indexes.length; i += 1) {\n            if (separateOne(indexes[i]))\n                separated.push(indexes[i]);\n        }\n        return separated;\n    }\n    // Animate every piece in congruence group `congruentIndex` (an index into\n    // getSplitReport().congruentGroups) onto the FIRST piece of that group. The group's\n    // pieces are mutually congruent, so each lands exactly on the first. Successive\n    // pieces are staggered by `delay` seconds in group order; mode/duration/pause/\n    // direction forward to animateRotateOntoPiece. Returns the piece indices animated.\n    function animateCongruent(congruentIndex, opts) {\n        if (opts === void 0) { opts = {}; }\n        if (!splitsShown || lastPieces == null)\n            return [];\n        var groups = congruenceGroups(lastPieces);\n        var group = groups[congruentIndex];\n        if (group == null || group.length < 2)\n            return [];\n        var target = group[0];\n        var delay = opts.delay != null ? opts.delay : 0;\n        var animated = [];\n        for (var k = 1; k < group.length; k += 1) {\n            var t = animateRotateOntoPiece(group[k], target, Fig.joinObjects({}, opts, { startDelay: (k - 1) * delay }));\n            if (t != null)\n                animated.push(group[k]);\n        }\n        return animated;\n    }\n    // Fade pieces down to a dim alpha (so the rest stand out) or back to full. dim()\n    // sets the fill + outline alpha to DIM_ALPHA; highlight() restores each piece to\n    // its full assigned colour. `indexOrIndexes` is one piece index or a list;\n    // `duration` is the fade seconds (default 0.3; 0 = instant). The colour the\n    // animation interpolates FROM is the element's current colour, so dim<->highlight\n    // cross-fades cleanly; the target alpha is the only thing that changes (rgb stays\n    // the piece's own). Both return the indexes acted on (those with a shown piece).\n    var DIM_ALPHA = 0.2;\n    function setPieceDim(splitIndex, dimmed, duration) {\n        var group = pieceGroups[splitIndex];\n        if (group == null)\n            return false;\n        var fillBase = pieceColorAt(splitIndex);\n        var outBase = o.color;\n        var fillTarget = dimmed\n            ? [fillBase[0], fillBase[1], fillBase[2], DIM_ALPHA]\n            : fillBase.slice();\n        var outTarget = dimmed\n            ? [outBase[0], outBase[1], outBase[2], DIM_ALPHA]\n            : outBase.slice();\n        if (duration > 0) {\n            group._fill.animations.new().color({ target: fillTarget, duration: duration }).start();\n            group._outline.animations.new().color({ target: outTarget, duration: duration }).start();\n        }\n        else {\n            group._fill.setColor(fillTarget);\n            group._outline.setColor(outTarget);\n        }\n        return true;\n    }\n    function dim(indexOrIndexes, duration) {\n        if (duration === void 0) { duration = 0.3; }\n        var idxs = Array.isArray(indexOrIndexes) ? indexOrIndexes : [indexOrIndexes];\n        var done = [];\n        for (var i = 0; i < idxs.length; i += 1) {\n            if (setPieceDim(idxs[i], true, duration))\n                done.push(idxs[i]);\n        }\n        return done;\n    }\n    function highlight(indexOrIndexes, duration) {\n        if (duration === void 0) { duration = 0.3; }\n        var idxs = Array.isArray(indexOrIndexes) ? indexOrIndexes : [indexOrIndexes];\n        var done = [];\n        for (var i = 0; i < idxs.length; i += 1) {\n            if (setPieceDim(idxs[i], false, duration))\n                done.push(idxs[i]);\n        }\n        return done;\n    }\n    // Show-answer: glide the declarative `splitLines` into the configuration that\n    // carves EQUAL sectors — `count` concurrent diameters through the shape centre,\n    // evenly spaced in angle — while moving each line the LEAST. The answer is a\n    // PATTERN, not per-line: the global rotation is free, so it is fitted to the\n    // lines' current angles (the circular mean of their phases mod `spacing`). A line\n    // already sitting on a correct diameter barely moves; each line is matched to the\n    // nearest distinct target (a cyclic-shift bijection — optimal for equally spaced\n    // targets under free rotation). Re-splits when the glide finishes so the equal\n    // pieces show. opts: { lines?: number of diameters (default = #cut lines),\n    // spacing?: degrees between them (default 180/lines), center?, duration?, done? }.\n    function showEqualSplit(opts) {\n        if (opts === void 0) { opts = {}; }\n        var cutLines = resolvedSplitLines;\n        if (cutLines == null || cutLines.length === 0)\n            return false;\n        var L = opts.lines != null ? opts.lines : cutLines.length;\n        var spacing = opts.spacing != null ? opts.spacing : 180 / L;\n        var duration = opts.duration != null ? opts.duration : 0.8;\n        var center = opts.center != null ? Fig.getPoint(opts.center) : polyCentroid(shapePoints);\n        // Diameter half-length: overshoot the shape so each cut spans it fully.\n        var minX = Infinity;\n        var minY = Infinity;\n        var maxX = -Infinity;\n        var maxY = -Infinity;\n        for (var i = 0; i < shapePoints.length; i += 1) {\n            var v = shapePoints[i];\n            if (v.x < minX)\n                minX = v.x;\n            if (v.x > maxX)\n                maxX = v.x;\n            if (v.y < minY)\n                minY = v.y;\n            if (v.y > maxY)\n                maxY = v.y;\n        }\n        var half = Math.max(maxX - minX, maxY - minY) * 0.7;\n        var outlineEl = fullGroup._outline;\n        var norm180 = function (a) { return ((a % 180) + 180) % 180; };\n        // Current angle (deg, mod 180) of each cut line, in the shape's local frame.\n        var angles = cutLines.map(function (ln) {\n            var fp = ln.custom.getFigureLine();\n            var a = outlineEl.pointFromSpaceToSpace(fp[0], 'figure', 'draw');\n            var b = outlineEl.pointFromSpaceToSpace(fp[1], 'figure', 'draw');\n            return norm180(Math.atan2(b.y - a.y, b.x - a.x) * 180 / Math.PI);\n        });\n        // Fit the free global rotation: circular mean of the phases (angle mod spacing).\n        var sx = 0;\n        var sy = 0;\n        for (var i = 0; i < angles.length; i += 1) {\n            var t = (angles[i] % spacing) / spacing * 2 * Math.PI;\n            sx += Math.cos(t);\n            sy += Math.sin(t);\n        }\n        var mean = Math.atan2(sy, sx);\n        if (mean < 0)\n            mean += 2 * Math.PI;\n        var phi = mean / (2 * Math.PI) * spacing;\n        var targets = [];\n        for (var k = 0; k < cutLines.length; k += 1)\n            targets.push(norm180(phi + k * spacing));\n        // Min-movement bijection line -> target. Both sorted by angle; equally spaced\n        // targets + free rotation => a cyclic-shift assignment is optimal. Try all shifts.\n        var N = cutLines.length;\n        var angDist = function (a, b) {\n            var d = Math.abs(a - b) % 180;\n            return Math.min(d, 180 - d);\n        };\n        var lineOrder = angles.map(function (_, i) { return i; }).sort(function (p, q) { return angles[p] - angles[q]; });\n        var sortedTargets = targets.slice().sort(function (p, q) { return p - q; });\n        var bestShift = 0;\n        var bestCost = Infinity;\n        for (var s = 0; s < N; s += 1) {\n            var cost = 0;\n            for (var j = 0; j < N; j += 1)\n                cost += angDist(angles[lineOrder[j]], sortedTargets[(j + s) % N]);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestShift = s;\n            }\n        }\n        // Glide each line to its assigned diameter; re-split once the last one lands.\n        var pending = N;\n        var finish = function () {\n            pending -= 1;\n            if (pending === 0) {\n                splitByLines(cutLines);\n                if (opts.done != null)\n                    opts.done();\n            }\n        };\n        var _loop_1 = function (j) {\n            var ln = cutLines[lineOrder[j]];\n            var ang = sortedTargets[(j + bestShift) % N] * Math.PI / 180;\n            var dx = Math.cos(ang) * half;\n            var dy = Math.sin(ang) * half;\n            // shape-local -> figure -> the line's own draw space (matches placeLine).\n            var toLineDraw = function (lp) {\n                var figPt = outlineEl.pointFromSpaceToSpace(Fig.getPoint(lp), 'draw', 'figure');\n                return ln.pointFromSpaceToSpace(figPt, 'figure', 'draw');\n            };\n            var p1 = toLineDraw([center.x - dx, center.y - dy]);\n            var p2 = toLineDraw([center.x + dx, center.y + dy]);\n            if (ln.custom != null && typeof ln.custom.animateToLine === 'function') {\n                ln.custom.animateToLine(p1, p2, duration, finish);\n            }\n            else if (ln.custom != null && typeof ln.custom.setLine === 'function') {\n                ln.custom.setLine(p1, p2);\n                finish();\n            }\n            else {\n                finish();\n            }\n        };\n        for (var j = 0; j < N; j += 1) {\n            _loop_1(j);\n        }\n        return true;\n    }\n    // Resolve one `answerLines` spec to a [p1, p2] pair in this shape's local coords —\n    // endpoints, or point + angle° + length (align 'center'|'end'). Mirrors splitLines.\n    function answerSpecPoints(spec) {\n        if (spec == null || typeof spec !== 'object')\n            return null;\n        if (spec.p1 != null && spec.p2 != null)\n            return [spec.p1, spec.p2];\n        if (spec.point != null && spec.length != null) {\n            var c = Fig.getPoint(spec.point);\n            var ang = (spec.angle != null ? spec.angle : 0) * (Math.PI / 180);\n            var dx = Math.cos(ang) * spec.length;\n            var dy = Math.sin(ang) * spec.length;\n            if (spec.align === 'end')\n                return [[c.x, c.y], [c.x + dx, c.y + dy]];\n            return [[c.x - dx / 2, c.y - dy / 2], [c.x + dx / 2, c.y + dy / 2]];\n        }\n        return null;\n    }\n    // The authored answer as target endpoint pairs (shape-local) + the freeRotation flag.\n    function resolveAnswerTargets() {\n        var al = o.answerLines;\n        if (al == null)\n            return { targets: [], freeRotation: false };\n        var list = Array.isArray(al) ? al : (Array.isArray(al.lines) ? al.lines : []);\n        var freeRotation = !Array.isArray(al) && al.freeRotation === true;\n        var targets = [];\n        for (var i = 0; i < list.length; i += 1) {\n            var pts = answerSpecPoints(list[i]);\n            if (pts != null)\n                targets.push([Fig.getPoint(pts[0]), Fig.getPoint(pts[1])]);\n        }\n        return { targets: targets, freeRotation: freeRotation };\n    }\n    // Match the live cut lines to a set of ANONYMOUS target line pairs (shape-local)\n    // with least total endpoint movement, then glide each there and re-split. The\n    // match is a min-cost bijection on endpoint distance (each line takes whichever\n    // target orientation is nearer, so it never needlessly flips). When `freeRotation`\n    // is set the whole target set is rotated about the shape centre to best fit the\n    // learner's lines (fitted by a fine angle sweep) — so a rotationally-symmetric\n    // answer leaves an already-correct line in place. Returns false if nothing to do.\n    function glideToTargets(targetPairs, freeRotation, duration, done) {\n        var cutLines = resolvedSplitLines;\n        if (cutLines == null || cutLines.length === 0 || targetPairs.length === 0) {\n            if (done != null)\n                done();\n            return false;\n        }\n        var outlineEl = fullGroup._outline;\n        var cur = cutLines.map(function (ln) {\n            var fp = ln.custom.getFigureLine();\n            return [\n                outlineEl.pointFromSpaceToSpace(fp[0], 'figure', 'draw'),\n                outlineEl.pointFromSpaceToSpace(fp[1], 'figure', 'draw'),\n            ];\n        });\n        var centre = polyCentroid(shapePoints);\n        var N = Math.min(cur.length, targetPairs.length);\n        var dist = function (a, b) {\n            return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));\n        };\n        // Cost + orientation of matching current line `ci` to target pair `t`.\n        var pairCost = function (ci, t) {\n            var straight = dist(ci[0], t[0]) + dist(ci[1], t[1]);\n            var flipped = dist(ci[0], t[1]) + dist(ci[1], t[0]);\n            return straight <= flipped ? { cost: straight, flip: false } : { cost: flipped, flip: true };\n        };\n        var rotAbout = function (p, ang) {\n            var s = Math.sin(ang);\n            var co = Math.cos(ang);\n            var dx = p.x - centre.x;\n            var dy = p.y - centre.y;\n            return Fig.getPoint([centre.x + dx * co - dy * s, centre.y + dx * s + dy * co]);\n        };\n        // Candidate global rotations: just 0, or a 2° sweep over [0,180) if freeRotation.\n        var phis = [];\n        if (freeRotation) {\n            for (var deg = 0; deg < 180; deg += 2)\n                phis.push(deg * Math.PI / 180);\n        }\n        else {\n            phis.push(0);\n        }\n        // All permutations of [0..N-1] (min-cost bijection); greedy fallback if N is big.\n        var perms = [];\n        if (N <= 7) {\n            var build_1 = function (chosen) {\n                if (chosen.length === N) {\n                    perms.push(chosen.slice());\n                    return;\n                }\n                for (var i = 0; i < N; i += 1) {\n                    if (chosen.indexOf(i) > -1)\n                        continue;\n                    chosen.push(i);\n                    build_1(chosen);\n                    chosen.pop();\n                }\n            };\n            build_1([]);\n        }\n        var best = null;\n        var _loop_2 = function (pi) {\n            var rt = targetPairs.map(function (t) { return [rotAbout(t[0], phis[pi]), rotAbout(t[1], phis[pi])]; });\n            if (perms.length > 0) {\n                for (var p = 0; p < perms.length; p += 1) {\n                    var total = 0;\n                    var assign = [];\n                    for (var i = 0; i < N; i += 1) {\n                        var pc = pairCost(cur[i], rt[perms[p][i]]);\n                        total += pc.cost;\n                        assign.push({ line: i, target: perms[p][i], flip: pc.flip });\n                    }\n                    if (best == null || total < best.total)\n                        best = { total: total, assign: assign, targets: rt };\n                }\n            }\n            else {\n                // Greedy nearest-target assignment (only for N > 7).\n                var usedT = new Array(targetPairs.length).fill(false);\n                var total = 0;\n                var assign = [];\n                for (var i = 0; i < N; i += 1) {\n                    var bt = -1;\n                    var bc = Infinity;\n                    var bf = false;\n                    for (var k = 0; k < targetPairs.length; k += 1) {\n                        if (usedT[k])\n                            continue;\n                        var pc = pairCost(cur[i], rt[k]);\n                        if (pc.cost < bc) {\n                            bc = pc.cost;\n                            bt = k;\n                            bf = pc.flip;\n                        }\n                    }\n                    if (bt > -1) {\n                        usedT[bt] = true;\n                        total += bc;\n                        assign.push({ line: i, target: bt, flip: bf });\n                    }\n                }\n                if (best == null || total < best.total)\n                    best = { total: total, assign: assign, targets: rt };\n            }\n        };\n        for (var pi = 0; pi < phis.length; pi += 1) {\n            _loop_2(pi);\n        }\n        if (best == null || best.assign.length === 0) {\n            if (done != null)\n                done();\n            return false;\n        }\n        var pending = best.assign.length;\n        var finish = function () {\n            pending -= 1;\n            if (pending === 0) {\n                splitByLines(cutLines);\n                if (done != null)\n                    done();\n            }\n        };\n        var _loop_3 = function (a) {\n            var asn = best.assign[a];\n            var ln = cutLines[asn.line];\n            var t = best.targets[asn.target];\n            var tp1 = asn.flip ? t[1] : t[0];\n            var tp2 = asn.flip ? t[0] : t[1];\n            var toLineDraw = function (lp) {\n                var figPt = outlineEl.pointFromSpaceToSpace(Fig.getPoint([lp.x, lp.y]), 'draw', 'figure');\n                return ln.pointFromSpaceToSpace(figPt, 'figure', 'draw');\n            };\n            var p1 = toLineDraw(tp1);\n            var p2 = toLineDraw(tp2);\n            if (ln.custom != null && typeof ln.custom.animateToLine === 'function') {\n                ln.custom.animateToLine(p1, p2, duration, finish);\n            }\n            else if (ln.custom != null && typeof ln.custom.setLine === 'function') {\n                ln.custom.setLine(p1, p2);\n                finish();\n            }\n            else {\n                finish();\n            }\n        };\n        for (var a = 0; a < best.assign.length; a += 1) {\n            _loop_3(a);\n        }\n        return true;\n    }\n    // Show-answer entry point: glide the cut lines to the authored `answerLines`.\n    function showAnswerLines(opts) {\n        if (opts === void 0) { opts = {}; }\n        var resolved = resolveAnswerTargets();\n        if (resolved.targets.length === 0)\n            return false;\n        var duration = opts.duration != null ? opts.duration : 0.8;\n        return glideToTargets(resolved.targets, resolved.freeRotation, duration, opts.done);\n    }\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    // (element.notificationHelper is created up in the STRUCTURE section.)\n    setupManipulative(element, null, o);\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    element.custom.getState = function (isSlot) {\n        // As an answer slot (isSlot), report the current split so an answer check reads\n        // it via get_manipulative_slots()[name] — same {full, partial} shape as any\n        // combined slot. Otherwise return the reload snapshot (position + split shown).\n        if (isSlot === true) {\n            return { full: element.custom.getSplitReport(), partial: [] };\n        }\n        var p = element.getPosition();\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        return {\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            split: splitsShown,\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        // The full shape always exists on restore; the split is re-driven by the\n        // caller (it needs the line). Just restore the full/clear display here.\n        if (stats.split !== true)\n            clearSplit();\n        element.custom.moved = true;\n    };\n    element.custom.state = element.custom.getState();\n    // Exposed so guides / answer-checks / tests can drive the split directly.\n    element.custom.splitByLine = splitByLine;\n    element.splitByLine = splitByLine;\n    element.custom.splitByLines = splitByLines;\n    element.splitByLines = splitByLines;\n    element.custom.clearSplit = clearSplit;\n    element.clearSplit = clearSplit;\n    element.custom.animateReflect = animateReflect;\n    element.animateReflect = animateReflect;\n    element.custom.animateRotateOnto = animateRotateOnto;\n    element.animateRotateOnto = animateRotateOnto;\n    element.custom.animateRotateOntoPiece = animateRotateOntoPiece;\n    element.animateRotateOntoPiece = animateRotateOntoPiece;\n    element.custom.animateRotateOntoPieceAll = animateRotateOntoPieceAll;\n    element.animateRotateOntoPieceAll = animateRotateOntoPieceAll;\n    element.custom.separateSplit = separateSplit;\n    element.separateSplit = separateSplit;\n    element.custom.animateCongruent = animateCongruent;\n    element.animateCongruent = animateCongruent;\n    element.custom.dim = dim;\n    element.dim = dim;\n    element.custom.highlight = highlight;\n    element.highlight = highlight;\n    element.custom.getSplitLines = function () { return resolvedSplitLines; };\n    element.getSplitLines = element.custom.getSplitLines;\n    element.custom.showEqualSplit = showEqualSplit;\n    element.showEqualSplit = showEqualSplit;\n    element.custom.showAnswerLines = showAnswerLines;\n    element.showAnswerLines = showAnswerLines;\n    // --- SPLIT REPORT (for answer checks / guides) --------------------------\n    // Describe the CURRENT split by area and congruence so an answer check can ask\n    // \"did the learner cut this into equal pieces?\". Key fields:\n    //   - areas:  a dict { pieceIndex: area } — one entry per shown piece.\n    //   - congruentGroups:  a list of lists of piece indices, partitioning the pieces\n    //     into congruence classes. Each inner list is a set of pieces that are exact\n    //     rigid images (rotation OR reflection, via rigidMap) of one another. All\n    //     pieces congruent => a single group [[0,1,2,...]]; all distinct => singletons\n    //     [[0],[1],...]. (Congruence is an equivalence relation, so grouping by a class\n    //     representative is well defined.)\n    //   - equalArea: every piece has the same area to within EQUAL_AREA_TOL (a \"fair\n    //     share\" / same-amount test; tolerant of the arc discretisation that makes a\n    //     circle's equal sectors differ by a hair). This is the RELIABLE equality test\n    //     for a discretised circle — whose equal sectors have slightly different vertex\n    //     counts, so they are equal in AREA without being congruent POLYGONS.\n    //   - congruent: convenience flag, true iff there is a single congruence group.\n    // Areas are in the shape's own (local/draw) units. With nothing split (count < 2)\n    // areas is the (≤1) piece dict, congruentGroups is empty, both flags false.\n    // Shoelace area; |·| so winding doesn't matter.\n    var EQUAL_AREA_TOL = 0.02; // <=2% area spread reads as \"equal\" (arc noise).\n    var polyArea = function (poly) {\n        var a2 = 0;\n        for (var i = 0; i < poly.length; i += 1) {\n            var p = poly[i];\n            var q = poly[(i + 1) % poly.length];\n            a2 += p.x * q.y - q.x * p.y;\n        }\n        return Math.abs(a2) / 2;\n    };\n    // Partition the pieces into congruence classes. Greedy: each unplaced piece opens\n    // a new group, then every later unplaced piece exact-matching the group's\n    // representative joins it. O(n^2) rigidMaps, fine for the small piece pool.\n    function congruenceGroups(pieces) {\n        var groups = [];\n        var placed = new Array(pieces.length).fill(false);\n        for (var i = 0; i < pieces.length; i += 1) {\n            if (placed[i])\n                continue;\n            var group = [i];\n            placed[i] = true;\n            for (var j = i + 1; j < pieces.length; j += 1) {\n                if (placed[j])\n                    continue;\n                var m = rigidMap(pieces[i], pieces[j]);\n                if (m != null && m.exact === true) {\n                    group.push(j);\n                    placed[j] = true;\n                }\n            }\n            groups.push(group);\n        }\n        return groups;\n    }\n    // Graded congruence: the WORST rigidMap error of any given piece against the\n    // largest one (the reference — a sliver makes a poor reference, so pick the best-\n    // formed piece). 0 = all identical; ~< 0.01 reads as congruent (the same threshold\n    // matchProper uses for its `exact` flag); it climbs smoothly as the pieces diverge,\n    // so a question can accept \"within a few %\" instead of demanding exact congruence.\n    // < 2 pieces => 0 (nothing to compare). rigidMap tries reflection too, so a mirror-\n    // image piece scores as congruent.\n    function maxCongruenceError(pieces) {\n        if (pieces.length < 2)\n            return 0;\n        var ref = 0;\n        var refArea = -Infinity;\n        for (var i = 0; i < pieces.length; i += 1) {\n            var a = polyArea(pieces[i]);\n            if (a > refArea) {\n                refArea = a;\n                ref = i;\n            }\n        }\n        var worst = 0;\n        for (var i = 0; i < pieces.length; i += 1) {\n            if (i === ref)\n                continue;\n            var m = rigidMap(pieces[ref], pieces[i]);\n            var err = m != null && typeof m.err === 'number' ? m.err : Infinity;\n            if (err > worst)\n                worst = err;\n        }\n        return worst;\n    }\n    // Orientation (degrees, folded to [0, 180) since a cut is undirected) of each live\n    // cut line, in the shape's local frame — the same frame splitLines' `angle` uses, so\n    // a guide can compare against a line's authored initial angle (e.g. detect that no\n    // line has been rotated). One entry per cut line, in `splitLines` declaration order\n    // (resolvedSplitLines), with any line whose lineToLocal is null skipped — the SAME\n    // order and skip that answerPointDistances() uses, so lineAngles[k] and each\n    // pointDistances[name][k] refer to the same cut line. NOT sorted by angle.\n    var cutLineAnglesDeg = function () {\n        var out = [];\n        var lines = resolvedSplitLines || [];\n        for (var i = 0; i < lines.length; i += 1) {\n            var loc = lineToLocal(lines[i]);\n            if (loc == null)\n                continue;\n            var deg = Math.atan2(loc[1].y - loc[0].y, loc[1].x - loc[0].x) * (180 / Math.PI);\n            out.push(Fig.round(((deg % 180) + 180) % 180, 2)); // fold to [0, 180)\n        }\n        return out;\n    };\n    // Perpendicular distance from every cut line to each named answer point (see the\n    // `answerPoints` option). Both live in the shape's local frame (lineToLocal converts\n    // a cut line into it), so Fig.Line(p1, p2).distanceToPoint(point) is the perpendicular\n    // distance to the INFINITE cut line — how far the cut passes from the point, ignoring\n    // the segment's ends. Per-point distances are ordered like lineAngles (same\n    // resolvedSplitLines iteration + null skip). {} when no answerPoints are configured.\n    var answerPointDistances = function () {\n        var out = {};\n        var pts = o.answerPoints;\n        if (pts == null)\n            return out;\n        var lines = resolvedSplitLines || [];\n        var localLines = [];\n        for (var i = 0; i < lines.length; i += 1) {\n            var loc = lineToLocal(lines[i]);\n            if (loc != null)\n                localLines.push(loc);\n        }\n        var names = Object.keys(pts);\n        for (var k = 0; k < names.length; k += 1) {\n            var p = Fig.getPoint(pts[names[k]]);\n            var dists = [];\n            for (var i = 0; i < localLines.length; i += 1) {\n                var fl = new Fig.Line(localLines[i][0], localLines[i][1]);\n                dists.push(Fig.round(fl.distanceToPoint(p), 5));\n            }\n            out[names[k]] = dists;\n        }\n        return out;\n    };\n    element.custom.getSplitReport = function (opts) {\n        var ignoreAreaFrac = opts != null && opts.ignoreAreaFrac != null\n            ? opts.ignoreAreaFrac : o.reportIgnoreAreaFrac;\n        // Negligible-area cutoff: the absolute cap wins when set, else the fraction of total\n        // (resolved against `total` below). opts override either for direct JS callers.\n        var maxNegArea = opts != null && opts.maxNegligibleArea != null\n            ? opts.maxNegligibleArea : o.maxNegligibleArea;\n        var pieces = lastPieces;\n        if (pieces == null || pieces.length < 2) {\n            var areas_1 = {};\n            var total0 = 0;\n            if (pieces != null) {\n                for (var i = 0; i < pieces.length; i += 1) {\n                    var a = polyArea(pieces[i]);\n                    areas_1[i] = Fig.round(a, 5);\n                    total0 += a;\n                }\n            }\n            return {\n                count: pieces == null ? 0 : pieces.length,\n                areas: areas_1,\n                equalArea: false,\n                congruentGroups: pieces != null && pieces.length === 1 ? [[0]] : [],\n                congruent: false,\n                lineAngles: cutLineAnglesDeg(),\n                total: Fig.round(total0, 5),\n                minAreaFrac: 0, // a single piece is the whole shape; there is no \"tiny\" piece\n                negligibleCount: 0,\n                mainCount: pieces == null ? 0 : pieces.length,\n                areaSpread: 0,\n                congruenceError: 0,\n                pointDistances: answerPointDistances(),\n            };\n        }\n        var areaList = pieces.map(polyArea);\n        var areas = {};\n        var min = Infinity;\n        var max = -Infinity;\n        var total = 0;\n        for (var i = 0; i < areaList.length; i += 1) {\n            areas[i] = Fig.round(areaList[i], 5);\n            total += areaList[i];\n            if (areaList[i] < min)\n                min = areaList[i];\n            if (areaList[i] > max)\n                max = areaList[i];\n        }\n        var mean = total / areaList.length;\n        var spread = mean > EPS ? (max - min) / mean : 0;\n        var groups = congruenceGroups(pieces);\n        // Set aside pieces below the negligible-area threshold, then measure equal-area /\n        // congruence over the MAIN pieces only — so a hairline central polygon doesn't\n        // wreck the graded numbers the question checks. The threshold is the absolute\n        // maxNegligibleArea when set, else ignoreAreaFrac of the total. With neither set\n        // it is 0, so mainCount === count and the graded fields mirror the all-piece values.\n        var threshold = maxNegArea != null ? maxNegArea : ignoreAreaFrac * total;\n        var mainPieces = [];\n        var mainMin = Infinity;\n        var mainMax = -Infinity;\n        var mainTotal = 0;\n        for (var i = 0; i < pieces.length; i += 1) {\n            if (areaList[i] < threshold)\n                continue;\n            mainPieces.push(pieces[i]);\n            mainTotal += areaList[i];\n            if (areaList[i] < mainMin)\n                mainMin = areaList[i];\n            if (areaList[i] > mainMax)\n                mainMax = areaList[i];\n        }\n        var mainMean = mainPieces.length > 0 ? mainTotal / mainPieces.length : 0;\n        var mainSpread = mainMean > EPS ? (mainMax - mainMin) / mainMean : 0;\n        return {\n            count: pieces.length,\n            areas: areas,\n            equalArea: spread <= EQUAL_AREA_TOL,\n            congruentGroups: groups,\n            congruent: groups.length === 1,\n            lineAngles: cutLineAnglesDeg(),\n            total: Fig.round(total, 5),\n            minAreaFrac: total > EPS ? Fig.round(min / total, 5) : 0,\n            negligibleCount: pieces.length - mainPieces.length,\n            mainCount: mainPieces.length,\n            areaSpread: Fig.round(mainSpread, 5),\n            congruenceError: Fig.round(maxCongruenceError(mainPieces), 5),\n            pointDistances: answerPointDistances(),\n        };\n    };\n    element.getSplitReport = element.custom.getSplitReport;\n    // The snap grid (if any), for consumers that snap to this shape. snapFigurePoint\n    // is the figure-space facade the line calls; snapGrid carries the lattice and\n    // nodeDistanceFigure (used to pick the nearest grid when several shapes have one).\n    element.custom.snapGrid = snapGrid;\n    if (snapGrid != null) {\n        element.custom.snapFigurePoint = snapGrid.snapFigure;\n    }\n    // On relayout (e.g. font loading) the equation repositions children; restore\n    // the learner's position if they've moved the element.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    // Whole-shape drag is opt-in (isTouchable: true).\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n        element.custom.state.p = element.getPosition().toArray(2);\n    });\n    element.notificationHelper.add(element._container, 'onClick', function () {\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n    });\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        element.custom.state.p = element.getPosition().toArray(2);\n        fig.answerChanged();\n    });\n    // Declarative auto-split (`splitLines`): resolve the given cut lines, optionally\n    // place them, split once, and re-split whenever a line is released. Replaces the\n    // per-question glue JS (find lines -> splitByLines -> wire stopBeingMoved).\n    if (Array.isArray(o.splitLines) && o.splitLines.length > 0) {\n        var specs_1 = o.splitLines;\n        // Lines are siblings nested under the host equation, not children of this shape,\n        // so resolve a leaf name by walking the figure (same as the old glue JS did).\n        var findByName_1 = function (name) {\n            var found = null;\n            var walk = function (el) {\n                if (found != null || el == null || el.elements == null)\n                    return;\n                var keys = Object.keys(el.elements);\n                for (var i = 0; i < keys.length; i += 1) {\n                    if (found != null)\n                        return;\n                    if (keys[i] === name) {\n                        found = el.elements[keys[i]];\n                        return;\n                    }\n                    walk(el.elements[keys[i]]);\n                }\n            };\n            walk(fig.elements);\n            return found;\n        };\n        var resolve_1 = function (spec) {\n            var ref = (spec != null && spec.line != null) ? spec.line : spec;\n            return typeof ref === 'string' ? findByName_1(ref) : ref;\n        };\n        // The cut endpoints a spec asks for, in this shape's local coords: either p1/p2\n        // directly, or derived from point + angle° + length (align 'center'|'end' — same\n        // as the line_manipulative). Null when the spec only references a line (no place).\n        var specPoints_1 = function (spec) {\n            if (spec == null || typeof spec !== 'object')\n                return null;\n            if (spec.p1 != null && spec.p2 != null)\n                return [spec.p1, spec.p2];\n            if (spec.point != null && spec.length != null) {\n                var c = Fig.getPoint(spec.point);\n                var ang = (spec.angle != null ? spec.angle : 0) * (Math.PI / 180);\n                var dx = Math.cos(ang) * spec.length;\n                var dy = Math.sin(ang) * spec.length;\n                if (spec.align === 'end') {\n                    return [[c.x, c.y], [c.x + dx, c.y + dy]];\n                }\n                return [[c.x - dx / 2, c.y - dy / 2], [c.x + dx / 2, c.y + dy / 2]];\n            }\n            return null;\n        };\n        // Position a line at p1->p2 given in this shape's local (outline draw) coords:\n        // local -> figure -> the line's own draw space, then setLine (matches the frame\n        // lineToLocal reads the cut back from, so the cut lands exactly where authored).\n        var outline_1 = fullGroup._outline;\n        var placeLine_1 = function (line, p1, p2) {\n            if (line == null || line.custom == null\n                || typeof line.custom.setLine !== 'function')\n                return;\n            var toLineDraw = function (lp) {\n                var figPt = outline_1.pointFromSpaceToSpace(Fig.getPoint(lp), 'draw', 'figure');\n                return line.pointFromSpaceToSpace(figPt, 'figure', 'draw');\n            };\n            line.custom.setLine(toLineDraw(p1), toLineDraw(p2));\n        };\n        var wired_1 = false;\n        var wireAndSplit = function () {\n            // Resolve + (optionally) place each spec, collecting the live line elements.\n            var lines = [];\n            for (var i = 0; i < specs_1.length; i += 1) {\n                var spec = specs_1[i];\n                var line = resolve_1(spec);\n                if (line == null)\n                    continue;\n                var pts = specPoints_1(spec);\n                if (pts != null)\n                    placeLine_1(line, pts[0], pts[1]);\n                lines.push(line);\n            }\n            if (lines.length === 0)\n                return;\n            resolvedSplitLines = lines; // publish for getSplitLines()/showEqualSplit().\n            splitByLines(lines);\n            if (wired_1)\n                return; // wire the release re-split exactly once.\n            wired_1 = true;\n            var resplit = function () { splitByLines(lines); };\n            var padNames = ['end1Move', 'centerMove', 'end2Move'];\n            var _loop_4 = function (i) {\n                var line = lines[i];\n                // On a pad release, re-split immediately UNLESS the line is gliding onto a\n                // soft-snap node (line.custom.settling). While settling we skip the re-split\n                // — cutting at the pre-snap pose then again at the snapped pose would flash —\n                // and let the line's 'rotated' signal (published when the glide lands) do the\n                // single re-split at the final pose.\n                var resplitOnRelease = function () {\n                    if (line.custom != null && line.custom.settling)\n                        return;\n                    splitByLines(lines);\n                };\n                for (var j = 0; j < padNames.length; j += 1) {\n                    var pad = typeof line.getElement === 'function'\n                        ? line.getElement('container.pads.' + padNames[j]) : null;\n                    if (pad != null && pad.notifications != null) {\n                        pad.notifications.add('stopBeingMoved', resplitOnRelease);\n                    }\n                }\n                // A rotateButton rotation, or a completed soft-snap settle, publishes\n                // 'rotated' without firing any pad's stopBeingMoved — re-split unconditionally\n                // then, so the cut always lands on the line's final pose.\n                if (line.notifications != null) {\n                    line.notifications.add('rotated', resplit);\n                }\n            };\n            for (var i = 0; i < lines.length; i += 1) {\n                _loop_4(i);\n            }\n        };\n        // By 'ready' the equation has laid out its children, so the lines exist and their\n        // transforms are set (needed for the local->figure->line coordinate conversion).\n        element.notificationHelper.add(fig, 'ready', wireAndSplit);\n    }\n    // Called generically by the answer-input \"show answer\" flow (answerInput.ts)\n    // to freeze every manipulative once the answer is revealed.\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    // As an answer slot (`slot: True`) the shape is a first-class combined slot (like\n    // rekenrekSlot/customSlot): a distinct manipulativeType so getManipulativeSlots()\n    // discovers it, plus the slot hooks answerInput.ts calls. showAnswer glides the\n    // cut lines to the authored `answerLines`. Otherwise it stays a plain display\n    // shape (snake_case type, for answer-processing registration) driven by its lines.\n    if (o.slot === true) {\n        element.custom.manipulativeType = 'splittableShapeSlot';\n        element.custom.showAnswer = function (payload, showOptions) {\n            var duration = showOptions != null && showOptions.duration != null ? showOptions.duration : 0.8;\n            showAnswerLines({ duration: duration });\n        };\n        element.showAnswer = function () {\n            var _a;\n            var args = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                args[_i] = arguments[_i];\n            }\n            return (_a = element.custom).showAnswer.apply(_a, args);\n        };\n        // Stubs for the generic slot surface (guarded callers, but be explicit).\n        if (element.custom.showCorrectness == null)\n            element.custom.showCorrectness = function () { };\n        element.custom.unhighlight = element.custom.unhighlight || (function () { });\n        element.unhighlight = function () { return element.custom.unhighlight(); };\n    }\n    else {\n        // Register for answer processing. MUST be snake_case and match the YAML.\n        element.custom.manipulativeType = 'splittable_shape';\n    }\n    if (o.isTouchable === true) {\n        container.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    else {\n        // Default: the shape is inert (the line is the mover).\n        element.hasTouchableElements = false;\n    }\n    return element;\n};\nexport { splittableShape, };\n","var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n        if (ar || !(i in from)) {\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n            ar[i] = from[i];\n        }\n    }\n    return to.concat(ar || Array.prototype.slice.call(from));\n};\nimport { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\n// Defaults shared by every solid. Wrappers merge these with their own geometry\n// defaults before calling makeSolid3d().\nvar SOLID3D_BASE_DEFAULTS = {\n    color: [0.2, 0.45, 0.95, 1],\n    cameraPosition: [1.4, 1.1, 2],\n    isRotatable: false,\n    autoRotate: false,\n    layoutBox: null, // null = size the box to the real footprint\n    yOffset: 0,\n    isTouchable: true,\n    sensitivity: 5,\n    edgeColor: [0, 0, 0, 1],\n    edgeWidth: 0,\n    edgeSides: 4,\n    hiddenLine: false,\n    silhouette: false,\n    annotationColor: null,\n    annotationFaceColor: null,\n    annotationEdgeColor: null,\n    annotationVertexColor: null,\n    annotationEdgeWidth: 0.02,\n    annotationEdgeOvershoot: null,\n    annotationVertexRadius: 0.03,\n    debug: false,\n};\n// The real scene camera is fixed straight-on so the equation's horizontal\n// layout projects without diagonal skew (see cameraPosition above).\nvar REAL_CAMERA = [0, 0, 2];\nvar LOOK_AT = [0, 0, 0];\nvar UP = [0, 1, 0];\n// The fixed orthographic view volume (half-extents) every solid is drawn in.\n// Used to build each solid's scene AND to project its silhouette for layout.\n// The larger half-extent maps to the edge of the solid's 2D space, so its\n// reciprocal is the world->local scale (aspect-preserving, which keeps a sphere\n// round).\nvar SCENE_HALF_W = 1.5;\nvar SCENE_HALF_H = 1;\nvar PROJ_SCALE = 1 / Math.max(SCENE_HALF_W, SCENE_HALF_H);\n// The 2D footprint a solid actually occupies on screen, in its collection's\n// local units — i.e. what the equation SHOULD measure it by. A 3D GL primitive\n// can't be measured (getBoundingRect throws), but its silhouette is fully\n// determined by its geometry + the fixed camera, so we compute it: bound the\n// solid by a vertical cylinder (radius R about the spin axis, half-height H),\n// project that cylinder's top/bottom rings through the resting view orientation,\n// and take the 2D extent. Bounding by a cylinder makes the footprint rotation-\n// invariant, so an auto-spinning solid never outgrows it and the layout never\n// reflows. `modelMatrix` is the resting orientation, viewToMatrix(cameraPosition).\nfunction projectedFootprint(o, modelMatrix, type) {\n    var margin = 1.08;\n    // A sphere projects to a circle of its radius at any orientation, centred.\n    if (type === 'sphere') {\n        var d = 2 * (o.radius != null ? o.radius : 0.3) * PROJ_SCALE * margin;\n        return { w: d, h: d, cx: 0, cy: 0 };\n    }\n    // Vertical bounding cylinder (radius R about the spin axis, half-height H).\n    var R;\n    var H;\n    var outline = type === 'prism' ? prismOutline(o) : null;\n    if (outline) {\n        // Polygon prism: bound by the circumscribed circle (the farthest corner from\n        // the axis) — rotation-invariant, matching how the cube is bounded.\n        R = 0;\n        outline.forEach(function (c) { R = Math.max(R, Math.hypot(c.x, c.z)); });\n        H = (o.length != null ? o.length : 0.6) / 2;\n    }\n    else if (o.side != null) {\n        // Cube: the far corner sits side * sqrt(2) / 2 from the vertical axis.\n        R = o.side * Math.SQRT1_2;\n        H = o.side / 2;\n    }\n    else if (o.radius != null && o.length != null) {\n        R = o.radius; // cylinder / cone / pyramid base radius\n        H = o.length / 2;\n    }\n    else {\n        R = 0.3;\n        H = 0.3;\n    }\n    // Cone and pyramid taper to a single apex at the top — no material at radius R\n    // up there — so sample the base ring + apex point only. Prisms (cube, cylinder)\n    // have a full top ring. Using the true silhouette (and centring the box on it,\n    // below) keeps the shape vertically centred instead of sitting low.\n    var tapers = type === 'cone' || type === 'pyramid';\n    var pts = [];\n    var N = 32;\n    for (var i = 0; i < N; i += 1) {\n        var a = (i / N) * 2 * Math.PI;\n        var x = R * Math.cos(a);\n        var z = R * Math.sin(a);\n        pts.push(new Fig.Point(x, -H, z)); // base ring (always)\n        if (!tapers) {\n            pts.push(new Fig.Point(x, H, z)); // top ring (prisms only)\n        }\n    }\n    if (tapers) {\n        pts.push(new Fig.Point(0, H, 0)); // apex point\n    }\n    var minX = Infinity;\n    var maxX = -Infinity;\n    var minY = Infinity;\n    var maxY = -Infinity;\n    for (var i = 0; i < pts.length; i += 1) {\n        var p = pts[i].transformBy(modelMatrix);\n        // Straight-on orthographic camera: the projected position is just (x, y).\n        if (p.x < minX) {\n            minX = p.x;\n        }\n        if (p.x > maxX) {\n            maxX = p.x;\n        }\n        if (p.y < minY) {\n            minY = p.y;\n        }\n        if (p.y > maxY) {\n            maxY = p.y;\n        }\n    }\n    // World extent + centre -> local units (margin inflates the size about the\n    // centre; the centre itself is not scaled by the margin).\n    return {\n        w: (maxX - minX) * PROJ_SCALE * margin,\n        h: (maxY - minY) * PROJ_SCALE * margin,\n        cx: ((minX + maxX) / 2) * PROJ_SCALE,\n        cy: ((minY + maxY) / 2) * PROJ_SCALE,\n    };\n}\n// Edges are pushed very slightly outward (radially, in the shape's local frame,\n// so it stays rotation-invariant) so they sit just proud of the surface and\n// don't z-fight with the faces they trace. Kept tiny: a larger value makes a\n// dark edge visibly overhang the silhouette. 0.3% clears z-fighting without a\n// perceptible overhang.\nvar EDGE_SCALE = 1.003;\n// DEPTH LAYERING (prototype, Option 3). Every solid renders into its own\n// orthographic scene, but all scenes share ONE WebGL depth buffer (FigureOne\n// clears it once per frame). Because every solid is centred on the origin under\n// the same camera, two overlapping solids occupy the same depth band and\n// depth-fight — the back solid punches holes in the front one. To avoid that we\n// push each solid's scene camera back along its view axis by (stacking rank ×\n// LAYER_SEP), so a tile drawn later (on top) gets a strictly NEARER depth band\n// than the tiles beneath it. Under an orthographic projection a shift along the\n// view axis changes ONLY depth — not size, screen position, orientation or\n// lighting — so this is invisible except for fixing the occlusion. LAYER_SEP\n// must exceed a solid's depth extent (its bounding-sphere diameter, ~0.67 for\n// the largest solid here) so adjacent layers' bands never overlap. 1.0 clears\n// that with ~0.3 of margin. NOTE: keep the total push small — pushing the camera\n// far back (e.g. a long row of co-located solids) moves a solid deep into the\n// [near, far] range where orthographic depth precision is too coarse to separate\n// its own front/back faces, so it z-fights and reads as broken-transparent.\nvar LAYER_SEP = 1.0;\n// Hidden-line mode pushes the translucent FACE fill this far back along the view\n// axis (−z, away from the camera) while leaving the edges at the origin, so every\n// edge fragment is nearer than every face fragment and the wireframe always draws\n// over the fill (the faces write depth and would otherwise occlude the dashed\n// hidden edges). Must exceed the solid's full depth extent — a cube of side s has\n// space diagonal s·√3 ≈ 1.07 at s = 0.62 — so 1.5 clears it with margin, and the\n// faces (pushed to z ≈ −2) stay well inside the scene's far plane.\nvar HL_FACE_PUSH = 1.5;\n// Cylinder hidden-line optimisation. The cylinder spins about its own (fixed,\n// camera-tilted) axis under autoRotate, so its silhouette is invariant — only the\n// surface turns. We exploit that: the dashed rim geometry is uploaded ONCE and\n// merely rotated each frame (the dashes sweep round with the surface), while the\n// \"front is solid\" part is a separate camera-fixed SOLID ARC over the near half.\n// That arc depends only on the (slowly-changing) axis direction, so it's rebuilt\n// only when the axis moves more than HL_AXIS_TOL — i.e. never during the spin,\n// just on a tilt/drag. The arc samples the rim this finely (boundary precision),\n// and sits HL_ARC_BIAS nearer than the dashed rim so it cleanly covers the front\n// dashes.\nvar HL_ARC_SAMPLES = 96;\nvar HL_ARC_BIAS = 0.01;\nvar HL_AXIS_TOL = 1e-3;\n// Push the raw edge vertices just proud of the surface (see EDGE_SCALE).\nfunction scaleEdgePoints(points) {\n    return points.map(function (p) {\n        var x = p.x === undefined ? p[0] : p.x;\n        var y = p.y === undefined ? p[1] : p.y;\n        var z = p.z === undefined ? p[2] : p.z;\n        return [x * EDGE_SCALE, y * EDGE_SCALE, z * EDGE_SCALE];\n    });\n}\n// Thicken edge segments into geometry. Each vertex PAIR becomes a capped prism\n// of radius `width` with `sides` faces around it (Fig.line3 revolves a\n// rectangular profile about the segment, so the ends are closed).\n//\n// A prism is used rather than a screen-facing ribbon because these solids\n// ROTATE: a solid tube subtends the same thickness from every angle and\n// occludes correctly against the faces it traces, whereas a billboarded ribbon\n// would have to be rebuilt every frame and still shear at the corners.\n//\n// By default each tube overshoots its segment by one radius at both ends so the\n// tubes meeting at a corner overlap and the joint reads as one continuous stroke\n// instead of leaving a wedge-shaped gap on the outside of the corner. That\n// overlap is invisible only because a continuous edge is drawn unlit in ONE flat\n// colour — so `overshoot` can be dropped to 0 where neighbouring segments differ\n// in colour. The hidden-line wireframe does exactly that: its dashes are\n// alternating inked and TRANSPARENT segments, and an overshooting inked tube\n// would interpenetrate its transparent neighbours as two coaxial, equal-radius\n// surfaces, which z-fight (and so flicker as the solid turns) as well as eating\n// the gap the dash pattern depends on.\n//\n// Vertex count is a constant `sides`-dependent multiple of the segment count,\n// including for degenerate (zero-length) segments — a cone's collapsed apex\n// ring, say — which become a small blob of the same thickness rather than being\n// dropped. That matters because grow() rewrites these vertices in place.\nfunction edgeTubePoints(points, width, sides, overshoot) {\n    var over = overshoot === undefined ? width : overshoot;\n    var out = [];\n    for (var i = 0; i + 1 < points.length; i += 2) {\n        var p0 = Fig.getPoint(points[i]);\n        var p1 = Fig.getPoint(points[i + 1]);\n        if (p1.sub(p0).distance() < 1e-9) {\n            p1 = p0.add(1e-6, 0, 0); // degenerate: keep the vertex count, draw a blob\n        }\n        var d = p1.sub(p0);\n        var ext = d.scale(over / d.distance()); // overshoot per end (0 = butt end)\n        var tubePoints = Fig.line3({\n            p1: p0.sub(ext),\n            p2: p1.add(ext),\n            width: width,\n            sides: sides,\n            normals: 'flat',\n        })[0];\n        tubePoints.forEach(function (p) { return out.push(p); });\n    }\n    return out;\n}\n// Add structural edges as a constant-colour, unlit primitive into the solid's\n// scene. `points` are vertex PAIRS (each consecutive two = one segment), as\n// [x,y,z] arrays or Fig.Points.\n//\n// `o.edgeWidth` picks the rendering: 0 (default) draws GL LINES — a hairline,\n// because WebGL implementations ignore lineWidth and there is no way to\n// thicken a LINES primitive — while any value above 0 draws prism tubes of\n// that radius with `o.edgeSides` faces each (see edgeTubePoints).\n//\n// The returned element carries custom.setEdgePoints(rawPairs), which re-scales\n// and (if thickened) re-tubes a new set of segment pairs and uploads them —\n// used by grow() to keep the outline tracking the sweeping cross-section.\nfunction addLineEdges(scene, name, points, color, o) {\n    var width = (o && o.edgeWidth) || 0;\n    var sides = (o && o.edgeSides) || 4;\n    var build = function (raw) { return (width > 0\n        ? edgeTubePoints(scaleEdgePoints(raw), width, sides)\n        : scaleEdgePoints(raw)); };\n    var element = scene.add({\n        name: name,\n        make: 'generic3',\n        glPrimitive: width > 0 ? 'TRIANGLES' : 'LINES',\n        light: null,\n        points: build(points),\n        color: color,\n    });\n    element.custom.setEdgePoints = function (raw) {\n        element.custom.updateGeneric3({ points: build(raw) });\n    };\n    return element;\n}\n// Vertex pairs tracing a circle of `radius` at height `y` (in the x-z plane) —\n// used for cone/cylinder rims. Returns LINES (consecutive pairs).\nfunction circleEdges(radius, y, sides) {\n    var pts = [];\n    for (var i = 0; i < sides; i += 1) {\n        var a0 = (i / sides) * 2 * Math.PI;\n        var a1 = ((i + 1) / sides) * 2 * Math.PI;\n        pts.push([radius * Math.cos(a0), y, radius * Math.sin(a0)]);\n        pts.push([radius * Math.cos(a1), y, radius * Math.sin(a1)]);\n    }\n    return pts;\n}\n// A prism's cross-section corners, as absolute {x, z} points in the shape's\n// local frame, or null when the prism is a plain regular n-gon (built from\n// radius/sides/rotation instead). Two ways to give a polygon, in precedence:\n//   - `width` and/or `height`: a rectangular footprint, `width` along x and\n//     `height` along z (either defaults if the other is given). The quick path\n//     for a box.\n//   - `points`: an author-supplied list of [x, z] pairs — an arbitrary CONVEX\n//     polygon, ordered around the outline.\n// Either way `length` still extrudes it vertically. We recentre the corners on\n// their vertex centroid so the extrusion axis runs through the middle: that\n// keeps the prism spinning about its own centre (like every regular solid here,\n// which is axis-centred) and keeps the projected footprint symmetric. When a\n// polygon outline is in play the profile radius is used as a 0/1 SCALE (1 = full\n// outline, 0 = the collapsed axis point) rather than a literal radius, so grow()\n// still sweeps a flat cut face up through the extrusion exactly as it does for\n// the n-gon prism. Convexity / ordering is the author's responsibility; fewer\n// than 3 corners falls back to the regular prism.\nfunction prismOutline(o) {\n    var c;\n    if (o.width != null || o.height != null) {\n        var w = (o.width != null ? o.width : 0.6) / 2; // half-extent along x\n        var h = (o.height != null ? o.height : 0.4) / 2; // half-extent along z\n        c = [[-w, -h], [w, -h], [w, h], [-w, h]];\n    }\n    else {\n        c = o.points;\n    }\n    if (!Array.isArray(c) || c.length < 3) {\n        return null;\n    }\n    var pts = c.map(function (p) { return ({\n        x: p.x === undefined ? p[0] : p.x,\n        z: p.z === undefined ? (p[1] === undefined ? p.y : p[1]) : p.z,\n    }); });\n    var cx = 0;\n    var cz = 0;\n    pts.forEach(function (p) { cx += p.x; cz += p.z; });\n    cx /= pts.length;\n    cz /= pts.length;\n    return pts.map(function (p) { return ({ x: p.x - cx, z: p.z - cz }); });\n}\n// Revolve `profile` about the Y axis with `sides` segments into a flat triangle\n// list. EVERY quad emits two triangles even when degenerate (zero radius/height),\n// so the vertex count is CONSTANT for any profile of the same length — that is\n// what lets grow() rewrite positions each frame without changing topology, so\n// the per-vertex colour buffer and face mapping stay valid. Normals are analytic\n// and always outward (FigureOne doesn't cull, so winding is irrelevant):\n//   'flat'   — one normal per quad (square prism faces, pyramid faces, caps);\n//   'smooth' — radial, per-vertex angle (round cylinder/cone walls);\n//   'sphere' — normalized position (a sphere centred at the origin).\n// `rotation` offsets the angular start (square prism / pyramid corners).\n// `outline`, when given, replaces the regular n-gon cross-section with an\n// arbitrary set of corner DIRECTIONS {x, z} (one per side): corner j sits at\n// profile[i].r · outline[j] instead of profile[i].r · (cos, sin) of an even\n// angle. Passing no outline reproduces the regular-polygon behaviour exactly.\nfunction latheMesh(profile, segMode, sides, rotation, outline) {\n    var points = [];\n    var normals = [];\n    var ang = function (j) { return rotation + (j / sides) * 2 * Math.PI; };\n    // Cross-section corner direction j (wrapping): the given outline, or the even\n    // n-gon corner. Only the 'flat'/'sphere' segment modes are used with an\n    // outline; 'smooth' (cylinder/cone walls) always run without one, so its\n    // per-vertex angle normals below stay correct.\n    var dir = outline\n        ? function (j) { return outline[((j % sides) + sides) % sides]; }\n        : function (j) { return ({ x: Math.cos(ang(j)), z: Math.sin(ang(j)) }); };\n    var pos = function (i, j) {\n        var d = dir(j);\n        return new Fig.Point(profile[i].r * d.x, profile[i].y, profile[i].r * d.z);\n    };\n    var _loop_1 = function (s) {\n        var mode = segMode[s];\n        var dy = profile[s + 1].y - profile[s].y;\n        var dr = profile[s + 1].r - profile[s].r;\n        // 2D outward profile normal (ny, nr) for 'smooth' walls.\n        var sl = Math.hypot(dr, dy) || 1;\n        var ny = -dr / sl;\n        var nr = dy / sl;\n        var horizontal = Math.abs(dy) < 1e-9; // a cap ring\n        var capSign = s === 0 ? -1 : 1; // base cap faces -Y, a top/cut cap +Y\n        for (var j = 0; j < sides; j += 1) {\n            var aj = ang(j);\n            var aj1 = ang(j + 1);\n            var B0 = pos(s, j);\n            var B1 = pos(s, j + 1);\n            var T0 = pos(s + 1, j);\n            var T1 = pos(s + 1, j + 1);\n            var tri = [B0, B1, T1, B0, T1, T0];\n            var nrm = void 0;\n            if (mode === 'sphere') {\n                nrm = tri.map(function (p) { return p.normalize(); });\n            }\n            else if (mode === 'smooth') {\n                var nA = function (a) { return new Fig.Point(nr * Math.cos(a), ny, nr * Math.sin(a)); };\n                var nj = nA(aj);\n                var nj1 = nA(aj1);\n                nrm = [nj, nj1, nj1, nj, nj1, nj];\n            }\n            else if (horizontal) {\n                var n = new Fig.Point(0, capSign, 0);\n                nrm = [n, n, n, n, n, n];\n            }\n            else {\n                // Flat slanted/vertical face: face normal, flipped to point away from\n                // the origin (which is inside these roughly-convex solids).\n                var n = B1.sub(B0).crossProduct(T0.sub(B0));\n                var cx = (B0.x + B1.x + T0.x + T1.x) / 4;\n                var cy = (B0.y + B1.y + T0.y + T1.y) / 4;\n                var cz = (B0.z + B1.z + T0.z + T1.z) / 4;\n                if (n.x * cx + n.y * cy + n.z * cz < 0) {\n                    n = new Fig.Point(-n.x, -n.y, -n.z);\n                }\n                n = n.normalize();\n                nrm = [n, n, n, n, n, n];\n            }\n            for (var k = 0; k < 6; k += 1) {\n                points.push(tri[k]);\n                normals.push(nrm[k]);\n            }\n        }\n    };\n    for (var s = 0; s < profile.length - 1; s += 1) {\n        _loop_1(s);\n    }\n    return { points: points, normals: normals };\n}\n// The [points, normals] for a solid grown to height-fraction `t` in [0, 1]:\n//   t = 1 is the full solid; t = 0 is its flat base cross-section; in between a\n//   flat cut face sweeps up. Topology (vertex count) is identical for every t.\n// `type` is the manipulativeType; `o` the merged options.\nfunction solidGeometryAt(type, o, t) {\n    if (type === 'sphere') {\n        var R_1 = o.radius != null ? o.radius : 0.35;\n        var n = Math.max(3, o.sides != null ? o.sides : 20); // arc samples\n        var aCut = Math.PI * t; // polar angle from bottom pole (0) to top (π)\n        var profile_1 = [];\n        var segMode = [];\n        for (var i = 0; i < n; i += 1) {\n            var a = aCut * (i / (n - 1));\n            profile_1.push({ y: -R_1 * Math.cos(a), r: R_1 * Math.sin(a) });\n            if (i < n - 1) {\n                segMode.push('sphere');\n            }\n        }\n        profile_1.push({ y: profile_1[profile_1.length - 1].y, r: 0 }); // flat cut cap\n        segMode.push('flat');\n        return latheMesh(profile_1, segMode, n, 0);\n    }\n    // Revolved prism / cone family. The cube is a 4-sided square prism; a `prism`\n    // is an n-gon prism whose cross-section is spun by its own `rotation`.\n    var isFaceted = type === 'pyramid' || type === 'cube';\n    var sides = isFaceted ? 4 : (o.sides != null ? o.sides : 20);\n    var rotation = isFaceted\n        ? Math.PI / 4\n        : (type === 'prism' ? (o.rotation != null ? o.rotation : Math.PI / 6) : 0);\n    // An arbitrary convex-polygon prism (o.corners) uses the outline directly and\n    // a 0/1 profile SCALE (R = 1) in place of a radius; every other solid keeps\n    // its literal radius and even n-gon corners.\n    var outline = type === 'prism' ? prismOutline(o) : null;\n    var R;\n    var L;\n    if (type === 'cube') {\n        var S = o.side != null ? o.side : 0.5;\n        R = S * Math.SQRT1_2; // corner radius so the square has side S\n        L = S;\n    }\n    else if (outline) {\n        R = 1; // profile scale for the (absolute) outline corners\n        L = o.length != null ? o.length : 0.6;\n    }\n    else {\n        R = o.radius != null ? o.radius : 0.3;\n        L = o.length != null ? o.length : 0.6;\n    }\n    var baseY = -L / 2;\n    var topY = baseY + L * t;\n    var topR = (type === 'cone' || type === 'pyramid') ? R * (1 - t) : R;\n    var profile = [\n        { y: baseY, r: 0 }, // base centre\n        { y: baseY, r: R }, // base rim\n        { y: topY, r: topR }, // cut rim\n        { y: topY, r: 0 }, // cut centre\n    ];\n    var wall = (type === 'cylinder' || type === 'cone') ? 'smooth' : 'flat';\n    return latheMesh(profile, ['flat', wall, 'flat'], outline ? outline.length : sides, outline ? 0 : rotation, outline);\n}\n// The structural edge line-segments (vertex PAIRS, for a LINES primitive) of a\n// solid grown to fraction t — the white lines that trace the form: the base\n// outline, the moving CROSS-SECTION outline at the current height, and (for the\n// faceted cube/pyramid) the corner edges joining them. Returns a CONSTANT number\n// of segments for a given type (rings that collapse become zero-length, hence\n// invisible), so it can be pushed via updateGeneric3 during grow without\n// changing topology. At t=1 it equals the finished solid's edges: cube → 12 box\n// edges; cylinder → top+bottom rims; cone → base rim (cut ring collapsed);\n// pyramid → base + 4 slants; sphere → nothing (both rings collapsed).\n// `outline` (as in latheMesh) swaps the even n-gon corners for arbitrary corner\n// directions; `r` still scales them (a 0/1 grow scale for a polygon prism).\nfunction ringSegments(y, r, sides, rotation, out, outline) {\n    var dir = outline\n        ? function (j) { return outline[((j % sides) + sides) % sides]; }\n        : function (j) { return ({ x: Math.cos(rotation + (j / sides) * 2 * Math.PI),\n            z: Math.sin(rotation + (j / sides) * 2 * Math.PI) }); };\n    for (var j = 0; j < sides; j += 1) {\n        var d0 = dir(j);\n        var d1 = dir(j + 1);\n        out.push([r * d0.x, y, r * d0.z]);\n        out.push([r * d1.x, y, r * d1.z]);\n    }\n}\nfunction solidEdgesAt(type, o, t) {\n    var out = [];\n    if (type === 'sphere') {\n        var R_2 = o.radius != null ? o.radius : 0.35;\n        var sides_1 = Math.max(3, o.sides != null ? o.sides : 20);\n        var aCut = Math.PI * t;\n        // Just the cross-section circle (no base ring — the sphere's base is a\n        // point); collapses to a point at t=1, so the finished sphere has no edges.\n        ringSegments(-R_2 * Math.cos(aCut), R_2 * Math.sin(aCut), sides_1, 0, out);\n        return out;\n    }\n    var isFaceted = type === 'pyramid' || type === 'cube';\n    var sides = isFaceted ? 4 : (o.sides != null ? o.sides : 20);\n    var rotation = isFaceted\n        ? Math.PI / 4\n        : (type === 'prism' ? (o.rotation != null ? o.rotation : Math.PI / 6) : 0);\n    var outline = type === 'prism' ? prismOutline(o) : null;\n    var R;\n    var L;\n    if (type === 'cube') {\n        var S = o.side != null ? o.side : 0.5;\n        R = S * Math.SQRT1_2;\n        L = S;\n    }\n    else if (outline) {\n        R = 1; // profile scale for the (absolute) outline corners\n        L = o.length != null ? o.length : 0.6;\n    }\n    else {\n        R = o.radius != null ? o.radius : 0.3;\n        L = o.length != null ? o.length : 0.6;\n    }\n    var baseY = -L / 2;\n    var topY = baseY + L * t;\n    var topR = (type === 'cone' || type === 'pyramid') ? R * (1 - t) : R;\n    var nSides = outline ? outline.length : sides;\n    var rot = outline ? 0 : rotation;\n    ringSegments(baseY, R, nSides, rot, out, outline); // base outline\n    ringSegments(topY, topR, nSides, rot, out, outline); // cross-section outline\n    if (isFaceted || type === 'prism') {\n        // Corner edges joining each base corner to its cross-section corner\n        // (vertical for the cube/prism, slanted-to-apex for the pyramid).\n        for (var j = 0; j < nSides; j += 1) {\n            var d = outline\n                ? outline[j]\n                : { x: Math.cos(rotation + (j / sides) * 2 * Math.PI),\n                    z: Math.sin(rotation + (j / sides) * 2 * Math.PI) };\n            out.push([R * d.x, baseY, R * d.z]);\n            out.push([topR * d.x, topY, topR * d.z]);\n        }\n    }\n    return out;\n}\n// The structural edges for hidden-line mode (faces off, edges split solid/dashed\n// by visibility), each tagged with the outward normals of the two faces it\n// borders so the core can classify it, and — for curved rims passed as many\n// short segments — a cumulative arc-length `s0` so the dashes run continuously.\n// Mirrors solidEdgesAt's geometry but only the finished solid (t = 1):\n//   cube / prism → n base + n top + n vertical edges (flat-walled n-gon prism);\n//   pyramid      → 4 base + 4 slant-to-apex edges;\n//   cylinder     → top + bottom rim segments (no verticals — the wall is smooth);\n//   cone         → base rim segments only.\n// Returns [] for the sphere (no flat structural edges).\nfunction solidHiddenLineEdges(type, o) {\n    var out = [];\n    if (type === 'sphere') {\n        return out;\n    }\n    var isFaceted = type === 'pyramid' || type === 'cube';\n    var sides = isFaceted ? 4 : (o.sides != null ? o.sides : 20);\n    var rotation = isFaceted\n        ? Math.PI / 4\n        : (type === 'prism' ? (o.rotation != null ? o.rotation : Math.PI / 6) : 0);\n    var R;\n    var L;\n    if (type === 'cube') {\n        var S = o.side != null ? o.side : 0.5;\n        R = S * Math.SQRT1_2;\n        L = S;\n    }\n    else {\n        R = o.radius != null ? o.radius : 0.3;\n        L = o.length != null ? o.length : 0.6;\n    }\n    var baseY = -L / 2;\n    var topY = L / 2;\n    var topCap = [0, 1, 0];\n    var botCap = [0, -1, 0];\n    var ang = function (j) { return rotation + (j / sides) * 2 * Math.PI; };\n    var mid = function (j) { return rotation + ((j + 0.5) / sides) * 2 * Math.PI; };\n    var ringPt = function (j, y) { return [R * Math.cos(ang(j)), y, R * Math.sin(ang(j))]; };\n    // Rim segment length for the curved solids, as the CHORD not the arc: the\n    // dashes are drawn along these chords, so measuring the run in chord space\n    // keeps s0 exactly in step with the geometry (an arc-length s0 drifts ~0.1%\n    // per segment against it, which is enough to nudge a cut onto the wrong side\n    // of a dash boundary). segTotal closes the loop — see HiddenLineEdge.sTotal.\n    var segLen = 2 * R * Math.sin(Math.PI / sides);\n    var segTotal = segLen * sides;\n    var outline = type === 'prism' ? prismOutline(o) : null;\n    if (outline) {\n        // Arbitrary convex-polygon prism: n base + n top + n vertical edges, exactly\n        // like the regular prism below but with the outline corners and per-EDGE wall\n        // normals (each side face's outward normal is the perpendicular of its edge\n        // in the x-z plane, not an even mid-angle).\n        var n_1 = outline.length;\n        var corner_1 = function (j) { return outline[((j % n_1) + n_1) % n_1]; };\n        var pAt = function (j, y) { var c = corner_1(j); return [c.x, y, c.z]; };\n        var wall_1 = function (j) {\n            var a = corner_1(j);\n            var b = corner_1(j + 1);\n            var nx = b.z - a.z;\n            var nz = -(b.x - a.x);\n            // Flip to point outward (away from the axis) using the edge midpoint.\n            if (nx * (a.x + b.x) + nz * (a.z + b.z) < 0) {\n                nx = -nx;\n                nz = -nz;\n            }\n            var m = Math.hypot(nx, nz) || 1;\n            return [nx / m, 0, nz / m];\n        };\n        for (var j = 0; j < n_1; j += 1) {\n            out.push({ p0: pAt(j, baseY), p1: pAt(j + 1, baseY), n0: botCap, n1: wall_1(j) });\n            out.push({ p0: pAt(j, topY), p1: pAt(j + 1, topY), n0: topCap, n1: wall_1(j) });\n            out.push({\n                p0: pAt(j, baseY), p1: pAt(j, topY), n0: wall_1((j - 1 + n_1) % n_1), n1: wall_1(j),\n            });\n        }\n        return out;\n    }\n    if (type === 'cone') {\n        // Base rim only; each segment borders the base cap and the slanted wall. The\n        // wall's outward normal tilts up by the cone's slope (profile normal R..L).\n        var slope = Math.hypot(L, R);\n        for (var j = 0; j < sides; j += 1) {\n            var wall_2 = [(L / slope) * Math.cos(mid(j)), R / slope, (L / slope) * Math.sin(mid(j))];\n            out.push({\n                p0: ringPt(j, baseY), p1: ringPt(j + 1, baseY), n0: botCap, n1: wall_2,\n                s0: j * segLen, sTotal: segTotal,\n            });\n        }\n        return out;\n    }\n    if (type === 'cylinder') {\n        // Top + bottom rims; each segment borders its cap and the radial wall.\n        for (var j = 0; j < sides; j += 1) {\n            var wall_3 = [Math.cos(mid(j)), 0, Math.sin(mid(j))];\n            out.push({\n                p0: ringPt(j, baseY), p1: ringPt(j + 1, baseY), n0: botCap, n1: wall_3,\n                s0: j * segLen, sTotal: segTotal,\n            });\n            out.push({\n                p0: ringPt(j, topY), p1: ringPt(j + 1, topY), n0: topCap, n1: wall_3,\n                s0: j * segLen, sTotal: segTotal,\n            });\n        }\n        return out;\n    }\n    if (type === 'pyramid') {\n        var apex = [0, topY, 0];\n        // Outward unit normal of slant face j (base corners j, j+1 and the apex).\n        var slantN = [];\n        for (var j = 0; j < sides; j += 1) {\n            var a = ringPt(j, baseY);\n            var b = ringPt(j + 1, baseY);\n            var v1 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];\n            var v2 = [apex[0] - a[0], apex[1] - a[1], apex[2] - a[2]];\n            var n = [\n                v1[1] * v2[2] - v1[2] * v2[1],\n                v1[2] * v2[0] - v1[0] * v2[2],\n                v1[0] * v2[1] - v1[1] * v2[0],\n            ];\n            // Flip to point away from the axis (outward) using the face centroid's xz.\n            var cx = (a[0] + b[0] + apex[0]) / 3;\n            var cz = (a[2] + b[2] + apex[2]) / 3;\n            if (n[0] * cx + n[2] * cz < 0) {\n                n = [-n[0], -n[1], -n[2]];\n            }\n            var mag = Math.hypot(n[0], n[1], n[2]) || 1;\n            slantN.push([n[0] / mag, n[1] / mag, n[2] / mag]);\n        }\n        for (var j = 0; j < sides; j += 1) {\n            out.push({ p0: ringPt(j, baseY), p1: ringPt(j + 1, baseY), n0: botCap, n1: slantN[j] });\n            out.push({\n                p0: ringPt(j, baseY), p1: apex, n0: slantN[(j - 1 + sides) % sides], n1: slantN[j],\n            });\n        }\n        return out;\n    }\n    // cube / prism: flat-walled n-gon prism — n base, n top and n vertical edges.\n    // Wall j (between corners j and j+1) has a radial normal at its mid-angle.\n    var wall = function (j) { return [Math.cos(mid(j)), 0, Math.sin(mid(j))]; };\n    for (var j = 0; j < sides; j += 1) {\n        out.push({ p0: ringPt(j, baseY), p1: ringPt(j + 1, baseY), n0: botCap, n1: wall(j) });\n        out.push({ p0: ringPt(j, topY), p1: ringPt(j + 1, topY), n0: topCap, n1: wall(j) });\n        out.push({\n            p0: ringPt(j, baseY), p1: ringPt(j, topY), n0: wall((j - 1 + sides) % sides), n1: wall(j),\n        });\n    }\n    return out;\n}\n// Split one structural edge into the dash cells that draw it. A cell is one\n// whole dash UNIT — all ink or all gap, never part of each — which is what makes\n// the dashes come out even, and it is why the cuts below land on unit boundaries\n// rather than on fixed fractions of the edge.\n//\n// The unit length is fitted per RUN so a whole number of units spans the run\n// exactly. A run is the closed loop for a cone/cylinder rim (e.sTotal, chained\n// across the many short segments it is passed as) or the edge itself for a\n// straight structural edge. Fitting is what stops a run ending mid-unit; it is\n// also why parity is counted in units of the FITTED length and not of `dash`.\n//\n// Counting parity in `dash` while cutting on something else is the bug this\n// replaces: a 50-sided cone rim has segments (0.0502) LONGER than the 0.04 dash,\n// so the old code gave each segment exactly one cell while the parity kept\n// stepping by 0.04 — the two drifted apart and inked 1 or 2 segments at a time,\n// an irregular #..#.##.#..#.# instead of #.#.#.#.\nfunction hiddenLineDashCells(e, len, dash) {\n    var out = [];\n    if (!(len > 0) || !(dash > 0)) {\n        return out;\n    }\n    var unit;\n    if (e.sTotal == null) {\n        // Open edge: fit to the edge. Any count will do — there is no seam to close.\n        unit = len / Math.max(1, Math.round(len / dash));\n    }\n    else {\n        // Closed loop: the count must also be EVEN, or ink meets ink where the run\n        // wraps and the dash at the seam comes out double length.\n        unit = e.sTotal / (2 * Math.max(1, Math.round(e.sTotal / (2 * dash))));\n    }\n    var s0 = e.s0 || 0;\n    var EPS_T = 1e-9;\n    // Walk the edge unit by unit. `u` indexes the unit the current position sits\n    // in, so ink/gap follows straight from its parity — no rounding, no drift. A\n    // segment shorter than a unit just yields one part-cell and the next segment\n    // carries the same unit on, which is how a rim's short segments chain into one\n    // continuous run.\n    var u = Math.floor(s0 / unit + EPS_T);\n    var t0 = 0;\n    while (t0 < 1 - EPS_T) {\n        var t1 = Math.min(1, ((u + 1) * unit - s0) / len);\n        if (t1 > t0 + EPS_T) {\n            out.push({ t0: t0, t1: t1, ink: u % 2 === 0 });\n            t0 = t1;\n        }\n        u += 1;\n    }\n    return out;\n}\n// The solids with a smooth wall, and so the only ones `silhouette` applies to.\nvar SILHOUETTE_TYPES = ['cylinder', 'cone', 'sphere'];\n// Whether hidden-line mode is actually ACTIVE for a solid — which is not simply\n// `o.hiddenLine`. The sphere has no structural edges, so on its own the flag has\n// nothing to draw and stays ignored; `silhouette` is what gives it an outline and\n// so what switches the mode on there. Every wrapper's addShape needs this to pick\n// its lighting (hidden-line's fill is a flat unlit tint, never directionally lit),\n// so it lives here as the single definition makeSolid3d itself gates on.\nfunction solidHiddenLineOn(type, o) {\n    if (!o.hiddenLine) {\n        return false;\n    }\n    return type !== 'sphere' || !!o.silhouette;\n}\n// How finely the sphere's silhouette circle is sampled. It is a full-size smooth\n// curve, so it needs the same boundary precision as the cylinder's front arc.\nvar SIL_CIRCLE_SAMPLES = HL_ARC_SAMPLES;\n// Below this the axis points close enough to the camera that a cylinder/cone has\n// no usable side line. rho is exactly the foreshortening of a side line (a\n// cylinder's runs the full length L along A, projecting to L.rho), so this bounds\n// the on-screen length of what we drop to well under a pixel — and it also keeps\n// atan2 away from the 0/0 corner where the angle would jitter.\nvar SIL_AXIS_EPS = 1e-3;\nfunction solidSilhouetteSegments(type, o, A) {\n    var segments = [];\n    if (type === 'sphere') {\n        // Orientation-independent: the great circle in the plane z = 0.\n        var R_3 = o.radius != null ? o.radius : 0.35;\n        var step = (2 * Math.PI) / SIL_CIRCLE_SAMPLES;\n        for (var k = 0; k < SIL_CIRCLE_SAMPLES; k += 1) {\n            segments.push([R_3 * Math.cos(k * step), R_3 * Math.sin(k * step), 0]);\n            segments.push([R_3 * Math.cos((k + 1) * step), R_3 * Math.sin((k + 1) * step), 0]);\n        }\n        return { segments: segments, visible: true };\n    }\n    if (type !== 'cylinder' && type !== 'cone') {\n        return { segments: segments, visible: false };\n    }\n    var R = o.radius != null ? o.radius : 0.3;\n    var L = o.length != null ? o.length : 0.6;\n    var norm = function (v) {\n        var m = Math.hypot(v[0], v[1], v[2]) || 1;\n        return [v[0] / m, v[1] / m, v[2] / m];\n    };\n    var cross = function (a, b) { return [\n        a[1] * b[2] - a[2] * b[1],\n        a[2] * b[0] - a[0] * b[2],\n        a[0] * b[1] - a[1] * b[0],\n    ]; };\n    var e1 = cross(A, [0, 0, 1]);\n    if (Math.hypot(e1[0], e1[1], e1[2]) < 1e-4) {\n        e1 = cross(A, [1, 0, 0]);\n    }\n    e1 = norm(e1);\n    var e2 = norm(cross(A, e1));\n    var rho = Math.hypot(e1[2], e2[2]);\n    // The silhouette angles are phi +/- acos(target / rho). Both degenerate cases\n    // still produce geometry — the placeholder — so the vertex count never changes:\n    // an axis-on solid falls back to phi = 0, and a cone past its slant clamps to\n    // the limiting angle, where its two lines have converged into one.\n    var degenerate = rho < SIL_AXIS_EPS;\n    var phi = degenerate ? 0 : Math.atan2(e2[2], e1[2]);\n    var target = type === 'cone' ? (-R * A[2]) / L : 0;\n    var c = degenerate ? 0 : target / rho;\n    var d = Math.acos(Math.max(-1, Math.min(1, c)));\n    var radial = function (t) { return [\n        e1[0] * Math.cos(t) + e2[0] * Math.sin(t),\n        e1[1] * Math.cos(t) + e2[1] * Math.sin(t),\n        e1[2] * Math.cos(t) + e2[2] * Math.sin(t),\n    ]; };\n    var along = function (s) { return [A[0] * s, A[1] * s, A[2] * s]; };\n    var base = along(-L / 2);\n    var top = along(L / 2);\n    [phi - d, phi + d].forEach(function (t) {\n        var r = radial(t);\n        segments.push([base[0] + R * r[0], base[1] + R * r[1], base[2] + R * r[2]]);\n        segments.push(type === 'cone'\n            ? top.slice()\n            : [top[0] + R * r[0], top[1] + R * r[1], top[2] + R * r[2]]);\n    });\n    return { segments: segments, visible: !degenerate && c >= -1 && c <= 1 };\n}\n// --- COUNTABLE FEATURE GEOMETRY -----------------------------------------\n// The corner points and structural edges of a solid, enumerated as discrete,\n// indexable features so the annotation layer can highlight one face / edge /\n// vertex at a time (see element.showEdge / showVertex). Mirrors solidEdgesAt's\n// geometry but groups it into LOGICAL features (one edge per box edge, one\n// polyline per curved rim) rather than the flat LINES list, and only ever for\n// the finished solid (t = 1). Both share this resolved geometry.\nfunction solidFeatureParams(type, o) {\n    var isFaceted = type === 'pyramid' || type === 'cube';\n    var sides = isFaceted ? 4 : (o.sides != null ? o.sides : 20);\n    var rotation = isFaceted\n        ? Math.PI / 4\n        : (type === 'prism' ? (o.rotation != null ? o.rotation : Math.PI / 6) : 0);\n    var outline = type === 'prism' ? prismOutline(o) : null;\n    var R;\n    var L;\n    if (type === 'cube') {\n        var S = o.side != null ? o.side : 0.5;\n        R = S * Math.SQRT1_2;\n        L = S;\n    }\n    else if (outline) {\n        R = 1; // profile scale for the (absolute) outline corners\n        L = o.length != null ? o.length : 0.6;\n    }\n    else {\n        R = o.radius != null ? o.radius : 0.3;\n        L = o.length != null ? o.length : 0.6;\n    }\n    var nSides = outline ? outline.length : sides;\n    var rot = outline ? 0 : rotation;\n    // Corner direction j (wrapping): the outline corner, or the even n-gon corner.\n    var dir = outline\n        ? function (j) { return outline[((j % nSides) + nSides) % nSides]; }\n        : function (j) { return ({\n            x: Math.cos(rot + (j / nSides) * 2 * Math.PI),\n            z: Math.sin(rot + (j / nSides) * 2 * Math.PI),\n        }); };\n    return { nSides: nSides, R: R, baseY: -L / 2, topY: L / 2, dir: dir };\n}\n// Unique corner vertices of a solid (local frame), in a stable order:\n//   cube / prism → all base corners (0..n-1) then all top corners (n..2n-1);\n//   pyramid      → the 4 base corners (0..3) then the apex (4);\n//   cone         → the apex only (0);\n//   cylinder / sphere → none (no corners).\nfunction solidFeatureVertices(type, o) {\n    if (type === 'sphere' || type === 'cylinder') {\n        return [];\n    }\n    var g = solidFeatureParams(type, o);\n    if (type === 'cone') {\n        return [[0, g.topY, 0]];\n    }\n    var out = [];\n    for (var j = 0; j < g.nSides; j += 1) {\n        var d = g.dir(j);\n        out.push([g.R * d.x, g.baseY, g.R * d.z]); // base corners\n    }\n    if (type === 'pyramid') {\n        out.push([0, g.topY, 0]); // apex\n    }\n    else {\n        for (var j = 0; j < g.nSides; j += 1) {\n            var d = g.dir(j);\n            out.push([g.R * d.x, g.topY, g.R * d.z]); // top corners\n        }\n    }\n    return out;\n}\n// The wall's dimensions and its outward profile normal (nR radial, nY up): the\n// lathe's 'smooth' wall normal for a wall from (R, -L/2) up to (topR, L/2).\nfunction sweepWall(type, o) {\n    var R = o.radius;\n    var L = o.length;\n    var topR = type === 'cone' ? 0 : R;\n    var sl = Math.hypot(topR - R, L) || 1;\n    return { R: R, L: L, topR: topR, nR: L / sl, nY: -(topR - R) / sl };\n}\n// The point on the wall at angle `a`, on the bottom rim or (top) the top rim /\n// apex, pushed `proud` out along the wall normal so a fill drawn there sits\n// just above the surface instead of z-fighting it.\nfunction sweepWallPoint(w, a, top, proud) {\n    if (proud === void 0) { proud = 0; }\n    var r = top ? w.topR : w.R;\n    var y = top ? w.L / 2 : -w.L / 2;\n    var c = Math.cos(a);\n    var s = Math.sin(a);\n    return [r * c + w.nR * c * proud, y + w.nY * proud, r * s + w.nR * s * proud];\n}\n// Where the sweep starts and which way it turns, for the current view.\n// `toView` maps a local direction [x, y, z, 0] into view space, where +x is\n// screen-right and +z points at the camera. The start `a0` is the wall angle\n// whose normal points furthest screen-LEFT (the left silhouette); `dir` (±1) is\n// the way round that turns the wall toward the camera, so the sweep crosses\n// the front first.\nfunction sweepStart(w, toView, samples) {\n    if (samples === void 0) { samples = 360; }\n    var viewN = function (a) { return toView([w.nR * Math.cos(a), w.nY, w.nR * Math.sin(a), 0]); };\n    var a0 = 0;\n    var minX = Infinity;\n    for (var j = 0; j < samples; j += 1) {\n        var a = (j / samples) * 2 * Math.PI;\n        var x = viewN(a)[0];\n        if (x < minX) {\n            minX = x;\n            a0 = a;\n        }\n    }\n    var dir = viewN(a0 + 0.1)[2] >= viewN(a0 - 0.1)[2] ? 1 : -1;\n    return { a0: a0, dir: dir };\n}\n// The shaded part of the wall at sweep progress `p` in [0, 1]: `segs` quads (two\n// triangles, 6 vertices each) spanning the swept arc from a0 to a0 + dir·p·2π.\n// The vertex count is the same for every p, so the fill can be rewritten in\n// place each frame.\nfunction sweepFillPoints(w, a0, dir, p, segs, proud) {\n    if (proud === void 0) { proud = 0; }\n    var pts = [];\n    var span = dir * p * 2 * Math.PI;\n    for (var j = 0; j < segs; j += 1) {\n        var aj = a0 + (span * j) / segs;\n        var aj1 = a0 + (span * (j + 1)) / segs;\n        var B0 = sweepWallPoint(w, aj, false, proud);\n        var B1 = sweepWallPoint(w, aj1, false, proud);\n        var T0 = sweepWallPoint(w, aj, true, proud);\n        var T1 = sweepWallPoint(w, aj1, true, proud);\n        pts.push(B0, B1, T1, B0, T1, T0);\n    }\n    return pts;\n}\n// The sweep line's two ends at progress `p`: bottom rim to top rim / apex.\nfunction sweepLineEnds(w, a0, dir, p) {\n    var a = a0 + dir * p * 2 * Math.PI;\n    return [sweepWallPoint(w, a, false), sweepWallPoint(w, a, true)];\n}\n// Structural edges of a solid as LOGICAL features, each a polyline (a list of\n// points): a straight edge is two points; a curved rim is the ring of points\n// around it. Stable order:\n//   cube / prism → n base edges (0..n-1), n top edges (n..2n-1), n vertical\n//                  edges (2n..3n-1);\n//   pyramid      → n base edges (0..n-1), n slant-to-apex edges (n..2n-1);\n//   cylinder     → the bottom rim (0) then the top rim (1);\n//   cone         → the base rim (0);\n//   sphere       → none.\nfunction solidFeatureEdges(type, o) {\n    if (type === 'sphere') {\n        return [];\n    }\n    var g = solidFeatureParams(type, o);\n    var corner = function (j, y) {\n        var d = g.dir(j);\n        return [g.R * d.x, y, g.R * d.z];\n    };\n    // A closed ring of points around a circle at height y (for a curved rim).\n    var ring = function (y) {\n        var pts = [];\n        for (var j = 0; j <= g.nSides; j += 1) {\n            pts.push(corner(j, y));\n        }\n        return pts;\n    };\n    if (type === 'cylinder') {\n        return [ring(g.baseY), ring(g.topY)];\n    }\n    if (type === 'cone') {\n        return [ring(g.baseY)];\n    }\n    var out = [];\n    for (var j = 0; j < g.nSides; j += 1) { // base edges\n        out.push([corner(j, g.baseY), corner(j + 1, g.baseY)]);\n    }\n    if (type === 'pyramid') {\n        for (var j = 0; j < g.nSides; j += 1) { // slant edges to the apex\n            out.push([corner(j, g.baseY), [0, g.topY, 0]]);\n        }\n    }\n    else {\n        for (var j = 0; j < g.nSides; j += 1) { // top edges\n            out.push([corner(j, g.topY), corner(j + 1, g.topY)]);\n        }\n        for (var j = 0; j < g.nSides; j += 1) { // vertical corner edges\n            out.push([corner(j, g.baseY), corner(j, g.topY)]);\n        }\n    }\n    return out;\n}\n// Build a solid as a `generic3` primitive that carries a PER-VERTEX colour\n// buffer, and attach `shape.custom.colorFace(faceIndex, color)` to recolour\n// every vertex the classifier assigns to that face. This is exactly what\n// make:'cube'/'cylinder'/... do internally (one colour expanded across every\n// vertex) — we just keep the per-vertex buffer so individual faces can be\n// repainted later. The per-vertex normals still drive directional shading, so a\n// uniformly-coloured solid is visually identical to the single-colour\n// primitive. `points`/`normals` are the [points, normals] a Fig.* generator\n// returns. `color` is an [r,g,b,a] array.\nfunction addColorableShape(scene, name, points, normals, color, classify, \n// Optional: regenerates [points, normals] for a grow fraction t in [0, 1]\n// (t=1 must equal the geometry passed above). Stored for grow(); see makeSolid3d.\ngeometryAt, \n// Lighting model for the faces. 'directional' (default) shades each face by\n// its angle to the scene light, giving the solid 3D form. null draws every\n// face a flat, uniform colour — used by hidden-line mode, whose translucent\n// fill must not pick up per-face brightness differences.\nlight) {\n    if (light === void 0) { light = 'directional'; }\n    var colors = points.map(function () { return color.slice(); });\n    var faceOf = points.map(function (p, i) { return classify(p, normals[i], i); });\n    // A representative outward unit normal per face = the (normalised) average of\n    // its vertices' normals. Well-defined for flat faces (cube faces, the cube /\n    // cylinder caps, the cone base, the pyramid's triangular sides). For a face\n    // that wraps all the way around the solid (a cylinder's curved wall, a\n    // sphere) the averaged normal cancels to ~zero — left undefined, since such a\n    // face has no single \"head-on\" direction to orient toward.\n    var faceSum = {};\n    for (var i = 0; i < faceOf.length; i += 1) {\n        var n = normals[i];\n        var nx = n.x === undefined ? n[0] : n.x;\n        var ny = n.y === undefined ? n[1] : n.y;\n        var nz = n.z === undefined ? n[2] : n.z;\n        var f = faceOf[i];\n        if (faceSum[f] === undefined) {\n            faceSum[f] = [0, 0, 0];\n        }\n        faceSum[f][0] += nx;\n        faceSum[f][1] += ny;\n        faceSum[f][2] += nz;\n    }\n    var faceNormals = {};\n    Object.keys(faceSum).forEach(function (key) {\n        var f = Number(key);\n        var s = faceSum[f];\n        var mag = Math.sqrt(s[0] * s[0] + s[1] * s[1] + s[2] * s[2]);\n        if (mag > 1e-3) {\n            faceNormals[f] = [s[0] / mag, s[1] / mag, s[2] / mag];\n        }\n    });\n    var shape = scene.add({\n        name: name,\n        make: 'generic3',\n        light: light,\n        points: points,\n        normals: normals,\n        colors: colors,\n    });\n    // Recolour every vertex assigned to `faceIndex`. A faceIndex that matches no\n    // vertex is a no-op (so out-of-range indices are simply ignored). `color` is\n    // an [r,g,b,a] array.\n    shape.custom.colorFace = function (faceIndex, faceColor) {\n        var changed = false;\n        for (var i = 0; i < faceOf.length; i += 1) {\n            if (faceOf[i] === faceIndex) {\n                colors[i] = faceColor.slice();\n                changed = true;\n            }\n        }\n        if (changed) {\n            shape.custom.updateGeneric3({ colors: colors });\n        }\n    };\n    // Back-face cull for hidden-line mode's translucent fill: paint every vertex\n    // whose (oriented) normal faces the camera `frontColor`, the rest `backColor`,\n    // in one buffer upload. Working per VERTEX — not per classified face — means it\n    // culls a smooth wall (cylinder/cone) correctly too, where the wall is one\n    // wrap-around face with no single normal but each quad has its own. `m` is the\n    // current orientation matrix; the camera looks down +z, so normal.z > 0 faces\n    // it. (Uses the t = 1 normals captured here, so don't combine with grow.)\n    shape.custom.cullToFront = function (m, frontColor, backColor) {\n        // Recolour by orientation, but only re-upload if a vertex actually flipped.\n        // A faceted solid's front-face set is constant between silhouette crossings,\n        // so this skips the buffer upload on the vast majority of spin frames.\n        var changed = false;\n        for (var i = 0; i < colors.length; i += 1) {\n            var n = normals[i];\n            var nx = n.x === undefined ? n[0] : n.x;\n            var ny = n.y === undefined ? n[1] : n.y;\n            var nz = n.z === undefined ? n[2] : n.z;\n            var w = Fig.m3.transformVector(m, [nx, ny, nz, 0]);\n            var target = (w[2] > 1e-4 ? frontColor : backColor);\n            var c = colors[i];\n            if (c[0] !== target[0] || c[1] !== target[1] || c[2] !== target[2] || c[3] !== target[3]) {\n                colors[i] = target.slice();\n                changed = true;\n            }\n        }\n        if (changed) {\n            shape.custom.updateGeneric3({ colors: colors });\n        }\n    };\n    // Repaint every vertex back to the solid's original base colour, undoing any\n    // colorFace/highlightFace recolouring.\n    shape.custom.resetColors = function () {\n        for (var i = 0; i < colors.length; i += 1) {\n            colors[i] = color.slice();\n        }\n        shape.custom.updateGeneric3({ colors: colors });\n    };\n    // Representative outward unit normal of a face in the solid's local frame, or\n    // null for a wrap-around face with no single facing direction (see above).\n    // Used by highlightFace to turn that face toward the viewer.\n    shape.custom.faceNormal = function (faceIndex) {\n        return faceNormals[faceIndex] || null;\n    };\n    // The distinct face indices this solid exposes (every value the classifier\n    // returned, excluding the -1 \"belongs to no face\" sentinel), ascending. Lets\n    // the annotation layer iterate faces (showFaces) and report a face count.\n    shape.custom.faceIndices = Array.from(new Set(faceOf.filter(function (f) { return f >= 0; })))\n        .sort(function (a, b) { return a - b; });\n    // The (t = 1) triangle geometry of a single face — the vertices the classifier\n    // assigned to `faceIndex`, with their outward normals. Used to build a fill\n    // overlay that highlights just that face (see element.showFace). Returns empty\n    // arrays for a face index nothing matches.\n    shape.custom.faceTriangles = function (faceIndex) {\n        var pts = [];\n        var nrm = [];\n        for (var i = 0; i < faceOf.length; i += 1) {\n            if (faceOf[i] === faceIndex) {\n                pts.push(points[i]);\n                nrm.push(normals[i]);\n            }\n        }\n        return { points: pts, normals: nrm };\n    };\n    // Stored for grow(): rewrites this shape's vertices to the geometry at fraction\n    // t (constant topology, so `colors`/`faceOf` stay valid).\n    if (geometryAt) {\n        shape.custom.geometryAt = geometryAt;\n    }\n    return shape;\n}\nfunction makeSolid3d(eqn_name, o, fig, config) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    // --- STRUCTURE ----------------------------------------------------------\n    // `element` is the top-level collection. `container` holds the visuals at the\n    // y-offset so the manipulative's anchor stays at the baseline.\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    // The model transform that orients the solid into its resting 3/4 view —\n    // needed both to size the layout box (below) and to pose the solid (applyView).\n    var cameraMatrix0 = Fig.m3.lookAt(REAL_CAMERA, LOOK_AT, UP);\n    // `up` is normally world-up, but flips to (0,-1,0) when the view tips OVER a\n    // pole (elevation past ±90°) so the solid keeps tipping the same way (a smooth\n    // roll-over) instead of the image flipping back (a \"bounce\"). See animateView.\n    var viewToMatrix = function (cam, up) {\n        if (up === void 0) { up = UP; }\n        return Fig.m3.mul(cameraMatrix0, Fig.m3.inverse(Fig.m3.lookAt(cam, LOOK_AT, up)));\n    };\n    // --- VISUALS ------------------------------------------------------------\n    // The equation lays each element out by its 2D bounding box, but a 3D GL\n    // primitive can't be measured (getBoundingRect throws), so the equation sizes\n    // the solid by an invisible 2D layout box we add here. By default the box is\n    // the solid's TRUE projected footprint, centred on the shape, so it lays out\n    // exactly like any 2D element — no surplus, even spacing, correct row height.\n    // An explicit `layoutBox` overrides this with a fixed left-anchored square\n    // (legacy behaviour) for callers that tuned spacing by hand.\n    var boxW;\n    var boxH;\n    var boxXAlign;\n    var boxX; // box position (its centre, or left edge when left-aligned)\n    var boxY;\n    var sceneX; // solidScene x position\n    var handleX; // drag handle position (covers the rendered shape)\n    var handleY;\n    if (o.layoutBox != null) {\n        // Legacy override: fixed left-anchored square; shape shifted to its centre.\n        boxW = o.layoutBox;\n        boxH = o.layoutBox;\n        boxXAlign = 'left';\n        boxX = 0;\n        boxY = 0;\n        sceneX = o.layoutBox / 2;\n        handleX = o.layoutBox / 2;\n        handleY = 0;\n    }\n    else {\n        // Default: box = the solid's true projected footprint, centred on the\n        // shape's projected centre so the shape sits centred — not low or biased to\n        // one side (a cone/pyramid's centre is below the origin; a cube's is at it).\n        var fp = projectedFootprint(o, viewToMatrix(o.cameraPosition), config.manipulativeType);\n        boxW = fp.w;\n        boxH = fp.h;\n        boxXAlign = 'center';\n        boxX = fp.cx;\n        boxY = fp.cy;\n        sceneX = 0;\n        handleX = fp.cx;\n        handleY = fp.cy;\n    }\n    // The invisible drag handle covers the shape; capped so a tiny solid still\n    // gets a grabbable target.\n    var HANDLE_SIZE = Math.max(0.18, Math.min(0.8, Math.max(boxW, boxH)));\n    container.add({\n        name: 'layoutBox',\n        make: 'rectangle',\n        xAlign: boxXAlign,\n        position: [boxX, boxY],\n        width: boxW,\n        height: boxH,\n        // Tinted when debugging so the computed footprint can be eyeballed; else\n        // effectively invisible and never touchable.\n        color: o.debug ? [1, 0, 0, 0.12] : [0, 0, 0, 0.001],\n    });\n    // The solid needs an orthographic scene, so give a sub-collection its own.\n    // Light is fixed; the solid itself rotates (see INTERACTION). The camera sits\n    // straight-on but its z is nudged per stacking layer (see DEPTH LAYERING) so\n    // overlapping solids land in disjoint depth bands. `far` is widened from the\n    // default 10 to leave room for those layers (each pushes the camera back by\n    // LAYER_SEP, up to ~one per co-located solid).\n    var scene = new Fig.Scene({\n        style: 'orthographic',\n        camera: { position: REAL_CAMERA, lookAt: LOOK_AT, up: UP },\n        left: -SCENE_HALF_W,\n        right: SCENE_HALF_W,\n        top: SCENE_HALF_H,\n        bottom: -SCENE_HALF_H,\n        near: 0.1,\n        far: 20,\n        light: { directional: [0.5, 0.7, 1], ambient: 0.5 },\n    });\n    var solidScene = container.add({\n        name: 'solidScene',\n        make: 'collection',\n        position: [sceneX, 0],\n        scene: scene,\n    });\n    var shape = config.addShape(solidScene, o);\n    // Optional structural edges (cube edges, cone/cylinder rims). They live in the\n    // same scene and are transformed in lockstep with the shape (see applyView).\n    // Skipped in hidden-line mode, which draws its own solid/dashed edge set below.\n    var hiddenLineOn = solidHiddenLineOn(config.manipulativeType, o);\n    var hlInput = hiddenLineOn\n        ? solidHiddenLineEdges(config.manipulativeType, o)\n        : [];\n    // The curved solids can additionally draw their view-dependent outline (see\n    // solidSilhouetteSegments). For the SPHERE that outline is the only line work\n    // there is, which is why solidHiddenLineOn gates the whole mode on it.\n    var silhouetteOn = hiddenLineOn && !!o.silhouette\n        && SILHOUETTE_TYPES.indexOf(config.manipulativeType) !== -1;\n    var edges = !hiddenLineOn && config.addEdges && o.edgeColor != null\n        ? config.addEdges(solidScene, o)\n        : null;\n    // --- HIDDEN-LINE WIREFRAME (optional) -----------------------------------\n    // Draw the solid as a wireframe over a flat translucent fill. Each frame the\n    // FACES are back-face culled (the unlit fill painted only on its camera-facing\n    // surface, so the tint is one even layer), and the EDGES are split into VISIBLE\n    // (solid) and HIDDEN (dashed). For a convex solid the edge split is exact: an\n    // edge is visible iff at least one of the two faces it borders points toward\n    // the (fixed, straight-on) camera, i.e. that face's world-space outward normal\n    // has a positive z. Each edge is pre-chopped into fixed-length dash CELLS\n    // (constant geometry); only each cell's COLOUR changes (inked when solid or on\n    // a dash, transparent on a gap). The fill is pushed back (HL_FACE_PUSH, in\n    // applyView) so the wireframe always draws over it.\n    //\n    // Per-frame uploads are avoided wherever possible:\n    //   - The CYLINDER (see HL_ARC_* constants) uploads its dashed rim ONCE and only\n    //     rotates it; a camera-fixed solid arc covers the front, rebuilt on a tilt.\n    //   - The CONE, also a body of revolution (spin-invariant silhouette), FREEZES\n    //     its unlit fill the same way the cylinder does — re-culled only on a tilt.\n    //   - The faceted CUBE/PRISM/PYRAMID can't freeze (their silhouette turns), so\n    //     their fill rotates each frame, but the edge recolour and the fill cull are\n    //     diff-and-skipped: re-uploaded only when a face crosses the silhouette.\n    var isCylinderHL = config.manipulativeType === 'cylinder';\n    var isConeHL = config.manipulativeType === 'cone';\n    var isSphereHL = config.manipulativeType === 'sphere';\n    // Bodies of revolution: silhouette invariant under spin, so the unlit fill can\n    // be frozen (re-oriented + re-culled only on a tilt) instead of every frame.\n    // The sphere rides along on the same gate — it re-culls on a tilt exactly like\n    // the cone, and never during a spin about its own axis. For a sphere that work\n    // is redundant rather than necessary (its outline is the same circle at every\n    // orientation, so any cull is as good as any other), but it costs nothing:\n    // cullToFront only uploads when a vertex actually flips.\n    var freezeFill = isCylinderHL || isConeHL || isSphereHL;\n    var hlEdges = null;\n    var hlSolidArc = null;\n    var hlSilhouette = null;\n    var updateHiddenLine = null;\n    var updateSilhouette = null;\n    // OPAQUE TWIN (built only in hidden-line mode; see DUAL REPRESENTATION below).\n    // A second, fully-opaque directionally-lit fill + solid edge set, hidden at\n    // rest, that setWireframe() cross-fades to/from the wireframe.\n    var opaqueFill = null;\n    var opaqueEdges = null;\n    // The intended representation: true = wireframe (opaque twin hidden), false =\n    // opaque solid. setWireframe() updates it; the beforeDraw reveal guard re-asserts\n    // it, since showing the parent collection recursively shows every child (which\n    // would otherwise un-hide the opaque twin — see the guard below). wireAnimating\n    // is true only while a setWireframe cross-fade is mid-flight, so the guard leaves\n    // that animation alone.\n    var wireframeOn = true;\n    var wireAnimating = false;\n    if (hiddenLineOn && o.edgeColor != null) {\n        var ec_1 = o.edgeColor.slice();\n        var TRANSPARENT_1 = [0, 0, 0, 0];\n        var EPS_1 = 1e-4; // normal-z above this counts as facing the camera\n        // The flat translucent fill colour (the solid's colour + author's low alpha).\n        var FACE_TINT_1 = o.color.slice();\n        // edgeWidth thickens the wireframe as well: each dash CELL (and each segment\n        // of the cylinder's solid arc) becomes a prism tube instead of a GL line, so\n        // a cell owns `vpc` vertices rather than 2. Everything that recolours a cell\n        // — the per-frame visible/hidden split, the baked cylinder dashes, the arc\n        // builder — indexes by that stride, which is constant for a given edgeSides.\n        var hlWidth_1 = o.edgeWidth || 0;\n        var hlSides_1 = o.edgeSides || 4;\n        var hlThick_1 = hlWidth_1 > 0;\n        // Butt-ended (overshoot 0): a cell abuts cells of a DIFFERENT colour — the\n        // gaps of the dash run — so the usual corner overshoot would z-fight and eat\n        // the gaps (see edgeTubePoints). Within one straight edge the cells are\n        // collinear, so butting them reads as one unbroken tube when the whole edge\n        // inks. Where the run TURNS, butting instead leaves a notch of w*tan(t/2)\n        // for a turn t, on the outside of the joint:\n        //   - Along a curved rim (cylinder/cone), t is one segment's share of the\n        //     circle, so the notch stays a fixed ~2-5% of the stroke width however\n        //     thick the edges are — invisible.\n        //   - At a VERTEX, where two structural edges meet at ~90 degrees, it is a\n        //     full radius. Sub-pixel at the small edgeWidths used so far, but it\n        //     scales with edgeWidth and would show on a thick wireframe. Closing it\n        //     needs the joint inked on BOTH sides before the tubes may overlap\n        //     again — see the note on end-cell parity below.\n        var cellPoints_1 = function (a, b) { return (hlThick_1 ? edgeTubePoints([a, b], hlWidth_1, hlSides_1, 0) : [a, b]); };\n        var vpc_1 = cellPoints_1([0, 0, 0], [1, 0, 0]).length;\n        // Dash/gap cell length, local units. A butt-ended cell is exactly this long\n        // and 2*edgeWidth thick, so a fixed 0.04 would render a thick wireframe's\n        // dashes as squares; hold them to at least 1.5x their own thickness. The\n        // hairline default (edgeWidth 0) keeps the 0.04 that has always been used.\n        var DASH_1 = Math.max(0.04, 3 * hlWidth_1);\n        // Push one cell's worth of vertices and its (uniform) colour.\n        var pushCell_1 = function (pts, cols, a, b, col) {\n            cellPoints_1(a, b).forEach(function (p) { return pts.push(p); });\n            for (var j = 0; j < vpc_1; j += 1) {\n                cols.push(col.slice());\n            }\n        };\n        var input = hlInput;\n        var points_1 = [];\n        var colors_1 = [];\n        var cellEdge_1 = []; // each cell's parent-edge index\n        var cellInk_1 = []; // is this cell an \"ink\" cell of the dash run\n        var edgeN0_1 = [];\n        var edgeN1_1 = [];\n        input.forEach(function (e, ei) {\n            edgeN0_1.push(e.n0);\n            edgeN1_1.push(e.n1);\n            var p0 = Fig.getPoint(e.p0);\n            var p1 = Fig.getPoint(e.p1);\n            var len = p1.sub(p0).distance();\n            var at = function (t) { return [\n                p0.x + (p1.x - p0.x) * t,\n                p0.y + (p1.y - p0.y) * t,\n                p0.z + (p1.z - p0.z) * t,\n            ]; };\n            hiddenLineDashCells(e, len, DASH_1).forEach(function (cell) {\n                cellEdge_1.push(ei);\n                cellInk_1.push(cell.ink);\n                // The cylinder rim is permanently dashed (its front is covered by the\n                // solid arc), so bake the dash pattern in now and never recolour it.\n                // Every other solid starts solid and is recoloured per frame.\n                var c0 = isCylinderHL ? (cell.ink ? ec_1 : TRANSPARENT_1) : ec_1;\n                pushCell_1(points_1, colors_1, at(cell.t0), at(cell.t1), c0);\n            });\n        });\n        // A sphere reaches here with no structural edges at all (it is in hidden-line\n        // mode purely for its silhouette), so there may be nothing to build.\n        hlEdges = points_1.length > 0\n            ? solidScene.add({\n                name: 'hiddenLineEdges',\n                make: 'generic3',\n                glPrimitive: hlThick_1 ? 'TRIANGLES' : 'LINES',\n                light: null,\n                points: points_1,\n                colors: colors_1,\n            })\n            : null;\n        // axisOf(m) — the solid's axis (local +y) in scene space. Both the cylinder's\n        // solid arc and the cone/cylinder fill-freeze gate on how much it has moved.\n        var norm3_1 = function (v) {\n            var n = Math.hypot(v[0], v[1], v[2]) || 1;\n            return [v[0] / n, v[1] / n, v[2] / n];\n        };\n        var cross3_1 = function (a, b) { return [\n            a[1] * b[2] - a[2] * b[1],\n            a[2] * b[0] - a[0] * b[2],\n            a[0] * b[1] - a[1] * b[0],\n        ]; };\n        var axisOf_1 = function (m) {\n            var av = Fig.m3.transformVector(m, [0, 1, 0, 0]);\n            return norm3_1([av[0], av[1], av[2]]);\n        };\n        // axisStill(a, b) — true when the axis has barely moved (autoRotate), so a\n        // frozen fill / camera-fixed arc is still correct and needn't be rebuilt.\n        var axisStill_1 = function (a, b) { return a != null\n            && Math.abs(a[0] - b[0]) < HL_AXIS_TOL\n            && Math.abs(a[1] - b[1]) < HL_AXIS_TOL\n            && Math.abs(a[2] - b[2]) < HL_AXIS_TOL; };\n        // Re-orient + re-cull the frozen fill to pose m (used by the cone/cylinder).\n        var reorientFill_1 = function (m) {\n            shape.setTransform(new Fig.Transform([__spreadArray(['c'], m, true), ['t', 0, 0, -HL_FACE_PUSH]]));\n            if (shape.custom.cullToFront) {\n                shape.custom.cullToFront(m, FACE_TINT_1, TRANSPARENT_1);\n            }\n        };\n        if (isCylinderHL) {\n            // --- Camera-fixed solid front arc (the cylinder optimisation) ---------\n            // A full pair of rim circles whose CAMERA-FACING segments are inked and the\n            // rest transparent, baked in scene space from the axis direction so it's\n            // independent of the surface spin. Rebuilt only when the axis tilts.\n            var Rc_1 = o.radius != null ? o.radius : 0.3;\n            var Lc_1 = o.length != null ? o.length : 0.6;\n            var TWO_PI_1 = 2 * Math.PI;\n            // The solid arc's points+colours for axis direction A. A rim segment is\n            // inked when its cap faces the camera (whole rim visible) or its own outward\n            // radial does (the near half); otherwise transparent (the dashed rim shows).\n            var buildArc_1 = function (A) {\n                var e1 = cross3_1(A, [0, 0, 1]);\n                if (Math.hypot(e1[0], e1[1], e1[2]) < 1e-4) {\n                    e1 = cross3_1(A, [1, 0, 0]);\n                }\n                e1 = norm3_1(e1);\n                var e2 = norm3_1(cross3_1(A, e1));\n                var rims = [\n                    { cy: Lc_1 / 2, capFront: A[2] > EPS_1 },\n                    { cy: -Lc_1 / 2, capFront: A[2] < -EPS_1 },\n                ];\n                var aPoints = [];\n                var aColors = [];\n                var radial = function (ang) { return [\n                    e1[0] * Math.cos(ang) + e2[0] * Math.sin(ang),\n                    e1[1] * Math.cos(ang) + e2[1] * Math.sin(ang),\n                    e1[2] * Math.cos(ang) + e2[2] * Math.sin(ang),\n                ]; };\n                rims.forEach(function (rim) {\n                    var C = [A[0] * rim.cy, A[1] * rim.cy, A[2] * rim.cy];\n                    for (var k = 0; k < HL_ARC_SAMPLES; k += 1) {\n                        var r0 = radial((k / HL_ARC_SAMPLES) * TWO_PI_1);\n                        var r1 = radial(((k + 1) / HL_ARC_SAMPLES) * TWO_PI_1);\n                        var rm = radial(((k + 0.5) / HL_ARC_SAMPLES) * TWO_PI_1);\n                        var col = (rim.capFront || rm[2] > EPS_1) ? ec_1 : TRANSPARENT_1;\n                        pushCell_1(aPoints, aColors, [C[0] + Rc_1 * r0[0], C[1] + Rc_1 * r0[1], C[2] + Rc_1 * r0[2]], [C[0] + Rc_1 * r1[0], C[1] + Rc_1 * r1[1], C[2] + Rc_1 * r1[2]], col);\n                    }\n                });\n                return { points: aPoints, colors: aColors };\n            };\n            var restA = axisOf_1(viewToMatrix(o.cameraPosition));\n            var arc0 = buildArc_1(restA);\n            var arcEl_1 = solidScene.add({\n                name: 'hiddenLineSolidArc',\n                make: 'generic3',\n                glPrimitive: hlThick_1 ? 'TRIANGLES' : 'LINES',\n                light: null,\n                points: arc0.points,\n                colors: arc0.colors,\n            });\n            hlSolidArc = arcEl_1; // hoist out so setWireframe can fade it with the rim\n            // Held a hair nearer than the dashed rim so it cleanly covers the front\n            // dashes; never rotated (it's camera-fixed — applyView only turns hlEdges).\n            // Thickened, the arc and the rim are coincident tubes rather than\n            // coincident lines, so the bias has to clear a full diameter for the arc\n            // to hide the dashes underneath it instead of z-fighting them.\n            arcEl_1.setTransform(new Fig.Transform([\n                ['t', 0, 0, HL_ARC_BIAS + 2 * hlWidth_1],\n            ]));\n            // Nothing here re-uploads while the cylinder merely spins: the dashed rim is\n            // only rotated (applyView), and the fill + solid arc are rebuilt solely when\n            // the axis tilts. The fill is even frozen in place — it's an unlit uniform\n            // tint, so keeping its azimuth fixed between tilts is invisible; only the\n            // (spin-invariant) silhouette matters, so one cull holds until the next tilt.\n            var lastArcA_1 = null;\n            updateHiddenLine = function (m) {\n                var A = axisOf_1(m);\n                if (axisStill_1(lastArcA_1, A)) {\n                    return; // silhouette unchanged (autoRotate) — fill + arc already correct\n                }\n                lastArcA_1 = A;\n                reorientFill_1(m); // frozen fill: re-orient + re-cull only on a tilt\n                var arc = buildArc_1(A);\n                arcEl_1.custom.updateGeneric3({ points: arc.points, colors: arc.colors });\n            };\n        }\n        else {\n            // Cube / prism / pyramid / cone / sphere. The edges are recoloured\n            // solid/dashed and (for the faceted solids) the fill is culled — but both\n            // are diff-and-skipped: the visible-edge set and front-face set only change\n            // when a face (or rim segment) crosses the silhouette, so most spin frames\n            // upload nothing. The cone and sphere additionally FREEZE their fill (both\n            // bodies of revolution), like the cylinder; the faceted solids must keep\n            // rotating their fill each frame. The SPHERE has no structural edges at all,\n            // so for it this reduces to that one frozen fill cull — it is here purely\n            // because `silhouette` put it in hidden-line mode.\n            var lastVis_1 = null;\n            var lastFillA_1 = null;\n            updateHiddenLine = function (m) {\n                // Edge visibility (per edge, from its two bordering face normals), with a\n                // recolour+upload only when that set actually changes.\n                var vis = [];\n                var visChanged = lastVis_1 == null;\n                for (var i = 0; i < edgeN0_1.length; i += 1) {\n                    var a = Fig.m3.transformVector(m, [edgeN0_1[i][0], edgeN0_1[i][1], edgeN0_1[i][2], 0]);\n                    var b = Fig.m3.transformVector(m, [edgeN1_1[i][0], edgeN1_1[i][1], edgeN1_1[i][2], 0]);\n                    vis[i] = a[2] > EPS_1 || b[2] > EPS_1;\n                    if (lastVis_1 != null && lastVis_1[i] !== vis[i]) {\n                        visChanged = true;\n                    }\n                }\n                if (visChanged && hlEdges) {\n                    for (var c = 0; c < cellEdge_1.length; c += 1) {\n                        var inked = vis[cellEdge_1[c]] || cellInk_1[c]; // solid edge, or a dash\n                        var col = inked ? ec_1 : TRANSPARENT_1;\n                        for (var j = 0; j < vpc_1; j += 1) {\n                            colors_1[c * vpc_1 + j] = col.slice();\n                        }\n                    }\n                    hlEdges.custom.updateGeneric3({ colors: colors_1 });\n                    lastVis_1 = vis;\n                }\n                // Fill: the cone and sphere freeze it (re-cull only on a tilt); the\n                // faceted solids rotate it every frame (applyView) and cull with the\n                // cullToFront diff. (The cylinder took the other branch entirely.)\n                if (freezeFill) {\n                    var A = axisOf_1(m);\n                    if (!axisStill_1(lastFillA_1, A)) {\n                        lastFillA_1 = A;\n                        reorientFill_1(m);\n                    }\n                }\n                else if (shape.custom.cullToFront) {\n                    shape.custom.cullToFront(m, FACE_TINT_1, TRANSPARENT_1);\n                }\n            };\n        }\n        // --- VIEW-DEPENDENT SILHOUETTE (curved solids) ------------------------\n        // The line where a smooth wall turns away from the camera — see\n        // solidSilhouetteSegments for the geometry and for why only these three\n        // solids need it. Like the cylinder's solid arc it is built in SCENE space\n        // from the current pose and never rotated by applyView (there is no fixed\n        // curve on the surface to rotate — the outline slides across the surface as\n        // the solid turns), and like the arc it is rebuilt only when the AXIS moves,\n        // since a body of revolution's outline is invariant under its own spin. A\n        // silhouette is by definition the boundary between the front and back of the\n        // surface, so it is never occluded: it draws solid and is never dashed.\n        if (silhouetteOn) {\n            var buildSil_1 = function (A) {\n                var sil = solidSilhouetteSegments(config.manipulativeType, o, A);\n                var sPoints = [];\n                var sColors = [];\n                // A pose with no silhouette still yields its full complement of\n                // (placeholder) segments, drawn transparent — that keeps the vertex count\n                // fixed so this can be a buffer rewrite rather than a rebuild.\n                var col = sil.visible ? ec_1 : TRANSPARENT_1;\n                for (var i = 0; i + 1 < sil.segments.length; i += 2) {\n                    pushCell_1(sPoints, sColors, sil.segments[i], sil.segments[i + 1], col);\n                }\n                return { points: sPoints, colors: sColors };\n            };\n            var restSilA = axisOf_1(viewToMatrix(o.cameraPosition));\n            var sil0 = buildSil_1(restSilA);\n            var silEl_1 = solidScene.add({\n                name: 'hiddenLineSilhouette',\n                make: 'generic3',\n                glPrimitive: hlThick_1 ? 'TRIANGLES' : 'LINES',\n                light: null,\n                points: sil0.points,\n                colors: sil0.colors,\n            });\n            hlSilhouette = silEl_1; // hoist out so setWireframe fades it with the rest\n            // Held the same hair nearer than the rim as the cylinder's solid arc, so\n            // where a side line meets a rim it covers it rather than z-fighting it.\n            silEl_1.setTransform(new Fig.Transform([\n                ['t', 0, 0, HL_ARC_BIAS + 2 * hlWidth_1],\n            ]));\n            // Seeded with the resting axis, since applyView's first call below passes\n            // exactly that pose and would otherwise re-upload the geometry just built.\n            var lastSilA_1 = restSilA;\n            updateSilhouette = function (m) {\n                // A sphere's outline is the same circle whatever the pose, so it is built\n                // once and never touched again.\n                if (isSphereHL) {\n                    return;\n                }\n                var A = axisOf_1(m);\n                if (axisStill_1(lastSilA_1, A)) {\n                    return;\n                } // spin only — outline unchanged\n                lastSilA_1 = A;\n                var s = buildSil_1(A);\n                silEl_1.custom.updateGeneric3({ points: s.points, colors: s.colors });\n            };\n        }\n    }\n    // --- DUAL REPRESENTATION (opaque twin, hidden-line mode only) -----------\n    // Build a SECOND, fully-opaque representation of the same solid — a\n    // directionally-lit, alpha-1 fill + the solid all-round edges — so the solid\n    // can be CROSS-FADED between its opaque look and the hidden-line wireframe\n    // (element.setWireframe). Both representations live on this ONE element as\n    // siblings in the sub-scene; only their opacity differs. Built solely in\n    // hidden-line mode (a plain opaque solid already IS its opaque self), and\n    // hidden at rest so the default render is unchanged — the wireframe — until\n    // setWireframe(false) is called. The opaque fill sits at z = 0 (the wireframe\n    // fill is pushed back to −HL_FACE_PUSH), so when shown it cleanly covers the\n    // dashed edges. NOTE: grow()/colorFace() drive the wireframe fill only, so the\n    // twin isn't built for solids that also grow/recolour — not a combination the\n    // hidden-line solids use.\n    if (hiddenLineOn) {\n        var og = solidGeometryAt(config.manipulativeType, o, 1);\n        var opaqueColor = o.color.slice();\n        opaqueColor[3] = 1; // opaque, whatever translucent alpha the wireframe uses\n        // The twin needs no per-face recolouring (the wireframe owns colorFace), so\n        // classify every vertex to -1 (a face index nothing targets).\n        opaqueFill = addColorableShape(solidScene, 'opaqueFill', og.points, og.normals, opaqueColor, function () { return -1; }, undefined, 'directional');\n        if (config.addEdges && o.edgeColor != null) {\n            opaqueEdges = config.addEdges(solidScene, o); // solid all-round edges\n        }\n        // Hidden at rest: the solid renders as the wireframe until asked otherwise.\n        opaqueFill.hide();\n        if (opaqueEdges) {\n            opaqueEdges.hide();\n        }\n        // Cross-fade between the wireframe and the opaque twin. `wire` truthy → show\n        // the wireframe (dashed hidden edges over the translucent fill); falsy → show\n        // the opaque solid. Opacity is animated both ways over `duration` seconds\n        // (<= 0 jumps). Mid-fade the opaque fill is briefly translucent-and-lit (it\n        // still writes depth), so the dashed back edges only fully read once it has\n        // faded out — an acceptable, brief reveal. Exposed for speech, e.g.\n        // |e:NAME,setWireframe,0,0.5| to dissolve a solid open into its wireframe.\n        var wireEls_1 = [\n            shape, hlEdges, hlSolidArc, hlSilhouette,\n        ].filter(Boolean);\n        var solidEls_1 = [opaqueFill, opaqueEdges].filter(Boolean);\n        element.setWireframe = function (wire, duration) {\n            if (wire === void 0) { wire = true; }\n            if (duration === void 0) { duration = 0.5; }\n            wireframeOn = !!wire;\n            var showEls = wire ? wireEls_1 : solidEls_1;\n            var hideEls = wire ? solidEls_1 : wireEls_1;\n            element.animations.cancel('solid3dWire');\n            wireAnimating = false;\n            if (duration <= 0) {\n                showEls.forEach(function (e) { e.setOpacity(1); e.show(); });\n                hideEls.forEach(function (e) { e.setOpacity(0); e.hide(); });\n                fig.animateNextFrame();\n                return;\n            }\n            // A cross-fade is now in flight; the reveal guard must not snap the opaque\n            // twin hidden mid-fade (cleared in solid3dWireFinish).\n            wireAnimating = true;\n            showEls.forEach(function (e) { e.setOpacity(0); e.show(); }); // fade up from 0\n            hideEls.forEach(function (e) { e.show(); }); // keep drawable while fading out\n            // Name both callbacks via fnMap (owner = element) so a speech exec cue\n            // (|e:NAME,setWireframe,...|) survives pause/resume: inline .custom/.trigger\n            // are dropped from figure.getState(), so a pause mid-fade would freeze the\n            // cross-fade half-done. Cancelled-and-restarted each call, so stable names\n            // are safe (the closures re-capture the current show/hide sets).\n            element.fnMap.add('solid3dWireDraw', function (p) {\n                showEls.forEach(function (e) { e.setOpacity(p); });\n                hideEls.forEach(function (e) { e.setOpacity(1 - p); });\n            });\n            element.fnMap.add('solid3dWireFinish', function () {\n                showEls.forEach(function (e) { e.setOpacity(1); });\n                hideEls.forEach(function (e) { e.setOpacity(0); e.hide(); });\n                wireAnimating = false;\n            });\n            element.animations\n                .new('solid3dWire')\n                .custom({\n                duration: duration,\n                callback: 'solid3dWireDraw',\n            })\n                .trigger({ callback: 'solid3dWireFinish' })\n                .start();\n            fig.animateNextFrame();\n        };\n    }\n    // The colourable shape lives deep in the sub-scene (element._container.\n    // _solidScene.<shape>), with its recolour methods on shape.custom. Hoist them\n    // to the TOP-LEVEL element so callers can just do `element.colorFace(...)` /\n    // `element.resetColors()` without walking into the sub-scene.\n    if (shape.custom && shape.custom.colorFace) {\n        element.colorFace = function (faceIndex, color) {\n            return shape.custom.colorFace(faceIndex, color);\n        };\n        element.resetColors = function () { return shape.custom.resetColors(); };\n    }\n    // Orient the solid as if seen from the *virtual* camera (cameraPosition),\n    // while the real camera stays straight-on. This is exactly the transform\n    // rotateControl applies: M = cameraMatrix0 . inverse(view-at-virtual-camera),\n    // so the resting pose and a subsequent drag are continuous (no snap). The\n    // solid's own position stays at the origin (centred on lookAt). cameraMatrix0\n    // and viewToMatrix are defined above the layout box (also used to size it).\n    // cameraControl behaviour: the light is fixed in the orbited world, so the\n    // VISIBLE lit side sweeps across the solid as the viewpoint turns. That sweep\n    // is what reveals rotation on a body of revolution — a sphere/cone is\n    // symmetric, so turning it under a fixed light shows nothing, but moving the\n    // lit side across it does. In this fixed-(real-)camera setup that means\n    // rotating the scene light with the view; measured relative to the resting\n    // view, so at rest the light is exactly BASE_LIGHT and the resting look is\n    // unchanged. (Each face/point then keeps the brightness it would have under a\n    // world-fixed light viewed from an orbiting camera.)\n    var BASE_LIGHT = [0.5, 0.7, 1];\n    // Feature-highlight annotations (showFace / showEdge / showVertex) that must\n    // turn in lockstep with the solid. Each is re-transformed by applyView every\n    // frame, exactly like the edges. Built lazily below and pushed here.\n    var annElements = [];\n    var restMatrixInv = Fig.m3.inverse(viewToMatrix(o.cameraPosition));\n    // `viewUp` is the current up vector — UP normally, flipped over the poles.\n    // applyView remembers it so relayout/drag re-applies (which pass no `up`) keep\n    // the same orientation rather than snapping back.\n    var viewUp = UP;\n    var applyView = function (cam, up) {\n        if (up) {\n            viewUp = up;\n        }\n        element.custom.viewCam = cam;\n        element.custom.viewUp = viewUp;\n        var m = viewToMatrix(cam, viewUp);\n        // In hidden-line mode the FACE fill is pushed back along the view axis so the\n        // wireframe (kept at the origin) always draws over it; otherwise both sit at 0.\n        var faceZ = hiddenLineOn ? -HL_FACE_PUSH : 0;\n        var t = new Fig.Transform([__spreadArray(['c'], m, true), ['t', 0, 0, faceZ]]);\n        // A frozen-fill solid (cylinder, cone) re-orients its featureless fill inside\n        // updateHiddenLine only on a tilt — spinning it would change nothing but cost\n        // an upload — so don't turn it here. Every other solid's fill turns each frame.\n        if (!(freezeFill && hiddenLineOn)) {\n            shape.setTransform(t);\n        }\n        if (edges) {\n            edges.setTransform(t);\n        }\n        // The wireframe edges and the opaque twin (fill + edges) all sit at the\n        // origin (z = 0); only the translucent wireframe FILL is pushed back.\n        var t0 = new Fig.Transform([__spreadArray(['c'], m, true), ['t', 0, 0, 0]]);\n        if (hlEdges) {\n            hlEdges.setTransform(t0);\n        }\n        // Not gated on hlEdges: a sphere in hidden-line mode has no structural edges,\n        // but its (frozen) fill cull still runs through here.\n        if (updateHiddenLine) {\n            updateHiddenLine(m);\n        }\n        // The silhouette is REBUILT from the pose rather than transformed by it (it\n        // is camera-fixed geometry, like the cylinder's solid arc), so it deliberately\n        // gets no setTransform here.\n        if (updateSilhouette) {\n            updateSilhouette(m);\n        }\n        if (opaqueFill) {\n            opaqueFill.setTransform(t0);\n        }\n        if (opaqueEdges) {\n            opaqueEdges.setTransform(t0);\n        }\n        // Feature highlights sit at the origin (z = 0), so in hidden-line mode they\n        // draw in front of the pushed-back translucent fill and stay visible — the\n        // whole point of highlighting a feature from a fixed viewpoint.\n        for (var i = 0; i < annElements.length; i += 1) {\n            annElements[i].setTransform(t0);\n        }\n        var delta = Fig.m3.mul(m, restMatrixInv);\n        var l = Fig.m3.transformVector(delta, [\n            BASE_LIGHT[0],\n            BASE_LIGHT[1],\n            BASE_LIGHT[2],\n            0,\n        ]);\n        scene.setLight({ directional: [l[0], l[1], l[2]], ambient: 0.5 });\n    };\n    applyView(o.cameraPosition);\n    // --- COUNTABLE FEATURE ANNOTATIONS --------------------------------------\n    // Turn an individual face / edge / vertex into a standalone highlight the\n    // author can switch on and off, the 3D counterpart of poly.ts's per-side /\n    // per-angle marks. A face highlight is a flat fill of that face; an edge a\n    // capped tube along it; a vertex a small sphere at the corner. Built lazily\n    // (only the features actually highlighted allocate geometry) and cached, so a\n    // second showX for the same index just re-shows (and optionally recolours) the\n    // existing element. All are added straight to the sub-scene and registered in\n    // annElements so applyView turns them with the solid. Callable from speech,\n    // e.g. |e:NAME,showEdge,3,[1,0,0,1]| or |e:NAME,showFace,0|.\n    var featureVerts = solidFeatureVertices(config.manipulativeType, o);\n    var featureEdges = solidFeatureEdges(config.manipulativeType, o);\n    var faceIdx = (shape.custom && shape.custom.faceIndices) || [];\n    // How many of each feature this solid exposes — for \"count the edges\" style\n    // tasks and for the plural show/hide helpers below.\n    element.custom.counts = {\n        faces: faceIdx.length,\n        edges: featureEdges.length,\n        vertices: featureVerts.length,\n    };\n    // Per-index caches so an element is built once and toggled thereafter.\n    var faceAnn = {};\n    var edgeAnn = {};\n    var vertAnn = {};\n    // A face fill is nudged this far out along each vertex normal so it sits just\n    // proud of the real surface and doesn't z-fight it (the edge/vertex tubes reuse\n    // the existing EDGE_SCALE radial push instead).\n    var FACE_PROUD = 0.004;\n    // Per-kind colour fallbacks, layered: the kind-specific option wins, then the\n    // shared annotationColor, then the natural fallback (a face → the solid colour,\n    // an edge/vertex → the edge colour). So faces, edges and vertices can each be\n    // given their own default while annotationColor still sets any left unset.\n    var annColor = o.annotationColor;\n    var faceColorDefault = (o.annotationFaceColor\n        || annColor || o.color || [0.4, 0.4, 0.4, 1]);\n    var edgeColorDefault = (o.annotationEdgeColor\n        || annColor || o.edgeColor || [0, 0, 0, 1]);\n    var vertColorDefault = (o.annotationVertexColor\n        || annColor || o.edgeColor || [0, 0, 0, 1]);\n    // Give a freshly-built annotation the current view transform and enrol it for\n    // future applyView updates.\n    var registerAnn = function (el) {\n        var m = viewToMatrix(element.custom.viewCam, element.custom.viewUp || UP);\n        el.setTransform(new Fig.Transform([__spreadArray(['c'], m, true), ['t', 0, 0, 0]]));\n        annElements.push(el);\n    };\n    // showFace(index, color?, opacity?) — highlight face `index` (see each solid's\n    // colorFace doc for the indices) with a flat fill. `color` defaults to the\n    // solid colour (or annotationColor); `opacity` (default 1) overrides its alpha.\n    if (shape.custom && shape.custom.faceTriangles) {\n        element.showFace = function (index, color, opacity) {\n            if (color === void 0) { color = null; }\n            if (opacity === void 0) { opacity = null; }\n            var el = faceAnn[index];\n            var col = (color || faceColorDefault).slice();\n            if (opacity != null) {\n                col[3] = opacity;\n            }\n            if (!el) {\n                var f_1 = shape.custom.faceTriangles(index);\n                if (f_1.points.length === 0) {\n                    return;\n                } // no such face (e.g. a bad index)\n                // Push each vertex out along its own normal so the fill floats just above\n                // the face it traces.\n                var pts = f_1.points.map(function (p, i) {\n                    var n = f_1.normals[i];\n                    var px = p.x === undefined ? p[0] : p.x;\n                    var py = p.y === undefined ? p[1] : p.y;\n                    var pz = p.z === undefined ? p[2] : p.z;\n                    var nx = n.x === undefined ? n[0] : n.x;\n                    var ny = n.y === undefined ? n[1] : n.y;\n                    var nz = n.z === undefined ? n[2] : n.z;\n                    return [px + nx * FACE_PROUD, py + ny * FACE_PROUD, pz + nz * FACE_PROUD];\n                });\n                el = solidScene.add({\n                    name: \"annFace\".concat(index),\n                    make: 'generic3',\n                    light: null, // \"just a fill\" — a flat, orientation-independent colour\n                    points: pts,\n                    color: col,\n                });\n                faceAnn[index] = el;\n                registerAnn(el);\n            }\n            else if (color != null || opacity != null) {\n                el.setColor(col);\n            }\n            el.show();\n            fig.animateNextFrame();\n        };\n        element.hideFace = function (index) {\n            if (faceAnn[index]) {\n                faceAnn[index].hide();\n                fig.animateNextFrame();\n            }\n            if (index === 0) {\n                hideSweep();\n            }\n        };\n    }\n    // sweepFace(index, color?, duration?, lineColor?, lineWidth?) — progressively\n    // shade a CYLINDER or CONE's curved wall (face 0): a line on the wall (bottom\n    // rim → top rim for a cylinder, base rim → apex for a cone) sweeps once round\n    // the axis over `duration` seconds (default 2.5), shading the wall behind it as\n    // it goes. It starts at the silhouette on the viewer's LEFT and moves right\n    // across the front, so the first half of the sweep is in plain view; the\n    // second half runs round the back, seen through the wireframe. When it ends\n    // the line goes and the whole wall stays shaded until hideFace(0) /\n    // hideAnnotations. `color` defaults to the showFace fill colour, `lineColor`\n    // to the showEdge colour, `lineWidth` (tube radius) to the solid's edgeWidth\n    // (or 0.003 for a hairline solid), so the line is as thin as the edges.\n    // The fill is rebuilt each frame as `SWEEP_SEGS` quads spanning the swept\n    // arc (constant vertex count), so it tracks the line exactly. Any other solid\n    // or face index falls back to showFace.\n    var SWEEP_SEGS = 96;\n    var sweepFill = null;\n    var sweepLine = null;\n    function hideSweep() {\n        element.animations.cancel('solid3dSweep');\n        if (sweepFill) {\n            sweepFill.hide();\n        }\n        if (sweepLine) {\n            sweepLine.hide();\n        }\n        fig.animateNextFrame();\n    }\n    var sweepable = config.manipulativeType === 'cylinder' || config.manipulativeType === 'cone';\n    element.sweepFace = function (index, color, duration, lineColor, lineWidth) {\n        if (color === void 0) { color = null; }\n        if (duration === void 0) { duration = 2.5; }\n        if (lineColor === void 0) { lineColor = null; }\n        if (lineWidth === void 0) { lineWidth = null; }\n        if (!sweepable || index !== 0) {\n            if (element.showFace) {\n                element.showFace(index, color);\n            }\n            return;\n        }\n        hideSweep();\n        var wall = sweepWall(config.manipulativeType, {\n            radius: o.radius, length: o.length,\n        });\n        // Start on the left silhouette, heading toward the front (see sweepStart).\n        var m = viewToMatrix(element.custom.viewCam, element.custom.viewUp || UP);\n        var _a = sweepStart(wall, function (v) { return Fig.m3.transformVector(m, v); }), a0 = _a.a0, dir = _a.dir;\n        var fillPoints = function (p) { return sweepFillPoints(wall, a0, dir, p, SWEEP_SEGS, FACE_PROUD); };\n        // Thin by default: the solid's own edge width (a hairline edgeWidth of 0\n        // can't be a tube, so it falls back to a thin 0.003 radius).\n        var edgeW = o.edgeWidth;\n        var w = lineWidth != null ? lineWidth : (edgeW > 0 ? edgeW : 0.003);\n        var linePoints = function (p) {\n            return edgeTubePoints(scaleEdgePoints(sweepLineEnds(wall, a0, dir, p)), w, 8, 0);\n        };\n        var fillCol = (color || faceColorDefault).slice();\n        var lineCol = (lineColor || edgeColorDefault).slice();\n        if (!sweepFill) {\n            sweepFill = solidScene.add({\n                name: 'annSweepFill',\n                make: 'generic3',\n                light: null,\n                points: fillPoints(0),\n                color: fillCol,\n            });\n            registerAnn(sweepFill);\n        }\n        if (!sweepLine) {\n            sweepLine = solidScene.add({\n                name: 'annSweepLine',\n                make: 'generic3',\n                glPrimitive: 'TRIANGLES',\n                light: null,\n                points: linePoints(0),\n                color: lineCol,\n            });\n            registerAnn(sweepLine);\n        }\n        var fillEl = sweepFill;\n        var lineEl = sweepLine;\n        fillEl.setColor(fillCol);\n        lineEl.setColor(lineCol);\n        var step = function (p) {\n            fillEl.custom.updateGeneric3({ points: fillPoints(p) });\n            lineEl.custom.updateGeneric3({ points: linePoints(p) });\n        };\n        step(0);\n        fillEl.show();\n        lineEl.show();\n        // Named callbacks (fnMap) so the animation survives speech pause/resume —\n        // the same reason animateView registers its legs by name.\n        element.fnMap.add('solid3dSweepStep', step);\n        element.fnMap.add('solid3dSweepDone', function () {\n            step(1);\n            lineEl.hide();\n            fig.animateNextFrame();\n        });\n        element.animations.new('solid3dSweep')\n            .custom({ duration: duration, callback: 'solid3dSweepStep' })\n            .trigger({ callback: 'solid3dSweepDone' })\n            .start();\n        fig.animateNextFrame();\n    };\n    // showEdge(index, color?, width?, sides?, overshoot?) — highlight structural\n    // edge `index` (see solidFeatureEdges' order) as a capped tube. `width` is the\n    // tube radius (default annotationEdgeWidth), `sides` the faces around it, and\n    // `overshoot` how far the tube runs past each endpoint (default\n    // annotationEdgeOvershoot; null there = one tube radius). The tube is built\n    // through edgeTubePoints (Fig.line3), so its ends are closed surfaces — it\n    // reads as a solid bar even when the face behind it is hidden.\n    element.showEdge = function (index, color, width, sides, overshoot) {\n        if (color === void 0) { color = null; }\n        if (width === void 0) { width = null; }\n        if (sides === void 0) { sides = null; }\n        if (overshoot === void 0) { overshoot = null; }\n        var el = edgeAnn[index];\n        var col = (color || edgeColorDefault).slice();\n        if (!el) {\n            var poly = featureEdges[index];\n            if (poly == null) {\n                return;\n            } // no such edge\n            var w = width != null ? width : o.annotationEdgeWidth;\n            var sd = sides != null ? sides : Math.max(o.edgeSides || 4, 6);\n            // Per-call overshoot wins; else the global annotationEdgeOvershoot; else\n            // (both null) one tube radius, edgeTubePoints' own default for a joined look.\n            var globalOver = o.annotationEdgeOvershoot;\n            var ov = overshoot != null ? overshoot : (globalOver != null ? globalOver : w);\n            // The polyline as consecutive vertex PAIRS (each pair = one tube segment).\n            var pairs = [];\n            for (var i = 0; i + 1 < poly.length; i += 1) {\n                pairs.push(poly[i], poly[i + 1]);\n            }\n            el = solidScene.add({\n                name: \"annEdge\".concat(index),\n                make: 'generic3',\n                glPrimitive: 'TRIANGLES',\n                light: null,\n                points: edgeTubePoints(scaleEdgePoints(pairs), w, sd, ov),\n                color: col,\n            });\n            edgeAnn[index] = el;\n            registerAnn(el);\n        }\n        else if (color != null) {\n            el.setColor(col);\n        }\n        el.show();\n        fig.animateNextFrame();\n    };\n    element.hideEdge = function (index) {\n        if (edgeAnn[index]) {\n            edgeAnn[index].hide();\n            fig.animateNextFrame();\n        }\n    };\n    // showVertex(index, color?, radius?, sides?) — highlight corner `index` (see\n    // solidFeatureVertices' order) with a low-poly sphere marker. `radius` defaults\n    // to annotationVertexRadius; `sides` (default 8) sets its facet count.\n    element.showVertex = function (index, color, radius, sides) {\n        if (color === void 0) { color = null; }\n        if (radius === void 0) { radius = null; }\n        if (sides === void 0) { sides = null; }\n        var el = vertAnn[index];\n        var col = (color || vertColorDefault).slice();\n        if (!el) {\n            var v_1 = featureVerts[index];\n            if (v_1 == null) {\n                return;\n            } // no such vertex\n            var r = radius != null ? radius : o.annotationVertexRadius;\n            var spherePts = Fig.sphere({ radius: r, sides: sides != null ? sides : 8 })[0];\n            var pts = spherePts.map(function (p) {\n                var px = p.x === undefined ? p[0] : p.x;\n                var py = p.y === undefined ? p[1] : p.y;\n                var pz = p.z === undefined ? p[2] : p.z;\n                return [px + v_1[0], py + v_1[1], pz + v_1[2]];\n            });\n            el = solidScene.add({\n                name: \"annVertex\".concat(index),\n                make: 'generic3',\n                light: null,\n                points: pts,\n                color: col,\n            });\n            vertAnn[index] = el;\n            registerAnn(el);\n        }\n        else if (color != null) {\n            el.setColor(col);\n        }\n        el.show();\n        fig.animateNextFrame();\n    };\n    element.hideVertex = function (index) {\n        if (vertAnn[index]) {\n            vertAnn[index].hide();\n            fig.animateNextFrame();\n        }\n    };\n    // Plural helpers: light up EVERY face / edge / vertex at once (handy for a\n    // \"count the edges\" demo), and hide them all. Each forwards its per-call style\n    // to the singular method above.\n    element.showFaces = function (color, opacity) {\n        if (color === void 0) { color = null; }\n        if (opacity === void 0) { opacity = null; }\n        if (element.showFace) {\n            faceIdx.forEach(function (i) { return element.showFace(i, color, opacity); });\n        }\n    };\n    element.showEdges = function (color, width, sides, overshoot) {\n        if (color === void 0) { color = null; }\n        if (width === void 0) { width = null; }\n        if (sides === void 0) { sides = null; }\n        if (overshoot === void 0) { overshoot = null; }\n        for (var i = 0; i < featureEdges.length; i += 1) {\n            element.showEdge(i, color, width, sides, overshoot);\n        }\n    };\n    element.showVertices = function (color, radius, sides) {\n        if (color === void 0) { color = null; }\n        if (radius === void 0) { radius = null; }\n        if (sides === void 0) { sides = null; }\n        for (var i = 0; i < featureVerts.length; i += 1) {\n            element.showVertex(i, color, radius, sides);\n        }\n    };\n    // Hide every annotation (faces, edges and vertices) in one call.\n    element.hideAnnotations = function () {\n        Object.keys(faceAnn).forEach(function (k) { return faceAnn[Number(k)].hide(); });\n        Object.keys(edgeAnn).forEach(function (k) { return edgeAnn[Number(k)].hide(); });\n        Object.keys(vertAnn).forEach(function (k) { return vertAnn[Number(k)].hide(); });\n        hideSweep();\n    };\n    // --- VIEW ANIMATION -----------------------------------------------------\n    // Animate the virtual camera to a target orientation, in TURNTABLE coords —\n    // azimuth about world up + elevation above the horizon — exactly the\n    // parameterisation the drag (rotateView) uses. This keeps world-up projecting\n    // to screen-up, so the solid never rolls or skews mid-turn, and lets us avoid\n    // the two ways the fixed-camera view breaks down:\n    //   - the POLES (elevation ≡ 90° mod 180°): lookAt()'s forward becomes\n    //     parallel to up and the view matrix is undefined. We don't forbid the\n    //     poles (viewFrom may sweep elevation past 90° to tip up and OVER the\n    //     top); instead camAt nudges any single frame that lands within POLE_EPS\n    //     of a pole a hair to the side it's on — skipping the exact singularity\n    //     (which NaNs within ~1e-5 of it) with a sub-tenth-degree, invisible jump.\n    //     Faces clamp their TARGET to EL_MAX (just shy of 90°) so a top/bottom\n    //     face settles dead-on rather than tipping over the back.\n    //   - a near-zero-but-nonzero camera x (~1e-16): FigureOne's m3.inverse shears\n    //     the view there. This is what a face whose normal lies in the y-z plane\n    //     produces (azimuth 0 or π — e.g. a cube's front/back face, a pyramid's\n    //     ±z side): the normal's x is floating-point dust, so the camera x comes\n    //     out as dust too. m3.inverse is EXACT and clean at x === 0, so we snap\n    //     dust x to zero (in camAt). A nonzero azimuth offset also moves clear.\n    var L = Fig.getPoint(LOOK_AT);\n    var EL_MAX = Math.PI / 2 - 1e-3; // face target clamp — just shy of the pole\n    var POLE_EPS = 8e-4; // a frame this close to a pole is nudged off it\n    var X_EPS = 1e-6; // |camera x| below this is dust → snap to exactly 0\n    var azOf = function (p) { return Math.atan2(p.x, p.z); };\n    var elOf = function (p) { return Math.asin(Math.max(-1, Math.min(1, p.y))); };\n    var DEG = Math.PI / 180; // the public view API takes degrees; the turntable radians\n    var clampEl = function (el) { return Math.max(-EL_MAX, Math.min(EL_MAX, el)); };\n    var animateThrough = function (stops, duration, pause, onFinish) {\n        if (stops.length === 0) {\n            if (onFinish) {\n                onFinish();\n            }\n            return;\n        }\n        var start = Fig.getPoint(element.custom.viewCam);\n        var dist = start.sub(L).distance() || 1;\n        var camAt = function (az, el) {\n            // Nudge a frame that lands on a pole (el ≡ 90° mod 180°, cos el = 0, where\n            // lookAt is singular) a hair to the side it's already on, so an over-the-\n            // top sweep crosses the pole without a NaN frame.\n            var e = el;\n            var pole = Math.PI / 2 + Math.round((e - Math.PI / 2) / Math.PI) * Math.PI;\n            if (Math.abs(e - pole) < POLE_EPS) {\n                e = pole + (e < pole ? -POLE_EPS : POLE_EPS);\n            }\n            var cx = Math.cos(e) * Math.sin(az) * dist;\n            if (Math.abs(cx) < X_EPS) {\n                cx = 0;\n            }\n            return [cx, Math.sin(e) * dist, Math.cos(e) * Math.cos(az) * dist];\n        };\n        // World-up flips each time elevation crosses a pole, so a sweep that tips\n        // past ±90° keeps rolling the same way (over the top) instead of bouncing.\n        var upForEl = function (el) {\n            var crossings = Math.floor((el + Math.PI / 2) / Math.PI);\n            return [0, ((crossings % 2) + 2) % 2 === 0 ? 1 : -1, 0];\n        };\n        element.custom.moved = true; // keep this pose across relayout\n        element.animations.cancel('solid3dView');\n        if (duration <= 0) {\n            var last = stops[stops.length - 1];\n            stops.forEach(function (s) { if (s.onArrive) {\n                s.onArrive();\n            } });\n            applyView(camAt(last.az, last.el), upForEl(last.el));\n            if (onFinish) {\n                onFinish();\n            }\n            fig.animateNextFrame(); // draw the jump\n            return;\n        }\n        var startDir = start.sub(L).normalize();\n        var fromAz = azOf(startDir);\n        var fromEl = elOf(startDir);\n        // azOf/elOf fold the angles back to az ∈ (-π, π], el ∈ [-π/2, π/2]. If the\n        // current view is already tipped over a pole (up flipped), unwrap to the\n        // real over-the-top angles so the next sweep continues smoothly.\n        if (element.custom.viewUp && element.custom.viewUp[1] < 0) {\n            fromEl = Math.PI - fromEl;\n            fromAz -= Math.PI;\n        }\n        var anim = element.animations.new('solid3dView');\n        stops.forEach(function (s, i) {\n            var a0 = fromAz;\n            var e0 = fromEl;\n            var tEl = s.el; // already clamped per-caller (faces) or intentional (viewFrom)\n            var dAz = s.az - a0;\n            dAz = Math.atan2(Math.sin(dAz), Math.cos(dAz)); // shortest way round\n            var dEl = tEl - e0;\n            var legDur = s.duration != null ? s.duration : duration;\n            var legPause = s.pause != null ? s.pause : pause;\n            // Register each leg's callbacks by NAME (fnMap) so the whole tour is SERIALIZABLE\n            // and survives speech pause/resume: figure.getState()/setState drop steps whose\n            // callback is an inline closure, so a pause mid-turn would freeze the solid. fnMap\n            // is element-scoped and only one 'solid3dView' animation runs at a time, so the\n            // per-leg indexed names never collide; the closures survive in memory (same-context\n            // pause) so per-leg angles are preserved on resume. (Same pattern as clock.ts.)\n            if (s.onArrive) {\n                element.fnMap.add(\"solid3dViewArrive\".concat(i), function () { return s.onArrive(); });\n                anim = anim.trigger({ callback: \"solid3dViewArrive\".concat(i) });\n            }\n            element.fnMap.add(\"solid3dViewLand\".concat(i), function () { return applyView(camAt(s.az, tEl), upForEl(tEl)); });\n            if (legDur <= 0) {\n                anim = anim.trigger({ callback: \"solid3dViewLand\".concat(i) });\n            }\n            else {\n                element.fnMap.add(\"solid3dViewCb\".concat(i), function (p) {\n                    var el = e0 + dEl * p;\n                    applyView(camAt(a0 + dAz * p, el), upForEl(el));\n                });\n                anim = anim\n                    .custom({ duration: legDur, callback: \"solid3dViewCb\".concat(i) })\n                    .trigger({ callback: \"solid3dViewLand\".concat(i) }); // land on stop\n            }\n            if (i < stops.length - 1 && legPause > 0) {\n                anim = anim.delay(legPause);\n            }\n            fromAz = s.az;\n            fromEl = tEl;\n        });\n        if (onFinish) {\n            element.fnMap.add('solid3dViewFinish', function () { return onFinish(); });\n            anim = anim.trigger({ callback: 'solid3dViewFinish' });\n        }\n        anim.start();\n        fig.animateNextFrame(); // kick the render loop so the animation actually plays\n    };\n    // Turn the solid to an absolute viewpoint, animated. Angles are in DEGREES:\n    // azimuth swings about world up (0 = front/+z, 90 = right/+x), elevation rises\n    // above the horizon (0 = level, +90 = top-down, -90 = bottom-up). Elevation is\n    // NOT clamped — e.g. 120 tips up to the top then 30° OVER it (rolling past the\n    // pole), rather than stopping at 90. Two forms:\n    //   viewFrom(azimuth, elevation, duration?)        — a single viewpoint\n    //   viewFrom([[az, el, duration?, pause?], ...])   — a tour of viewpoints,\n    //       each leg using its own duration (default 1; <= 0 jumps) and pausing\n    //       its own `pause` (default 0.1) before the next.\n    // Exposed by all 3D solids.\n    element.viewFrom = function (azimuth, elevation, duration) {\n        if (elevation === void 0) { elevation = 0; }\n        if (duration === void 0) { duration = 1; }\n        element.custom.spinPaused = true; // hold auto-rotation during the move\n        if (Array.isArray(azimuth)) {\n            var stops = azimuth.map(function (t) { return ({\n                az: t[0] * DEG,\n                el: t[1] * DEG,\n                duration: t[2], // undefined → shared default below\n                pause: t[3],\n            }); });\n            animateThrough(stops, 1, 0.1);\n            return;\n        }\n        animateThrough([{ az: azimuth * DEG, el: elevation * DEG }], duration, 0);\n    };\n    // Return the solid to its starting orientation (the resting cameraPosition).\n    // `duration` is the animation seconds (default 1; <= 0 jumps). If\n    // `resumeAutoRotate` is true, auto-rotation resumes once it lands (only has an\n    // effect if the solid was created with autoRotate and is not disabled).\n    element.resetOrientation = function (duration, resumeAutoRotate) {\n        if (duration === void 0) { duration = 1; }\n        if (resumeAutoRotate === void 0) { resumeAutoRotate = false; }\n        // elOf needs a unit direction (cameraPosition is not normalised).\n        var rest = Fig.getPoint(o.cameraPosition).sub(L).normalize();\n        element.custom.spinPaused = true; // hold auto-rotation during the move\n        animateThrough([{ az: azOf(rest), el: elOf(rest) }], duration, 0, function () {\n            if (resumeAutoRotate) {\n                element.custom.spinPaused = false;\n            }\n        });\n    };\n    // Turn the solid so a face faces the viewer (animated), optionally recolouring\n    // it.\n    //   index:    a face index, or an ARRAY of faces to tour in order — turning to\n    //             each in turn (each leg takes `duration`, with `pause` held on\n    //             each). An array entry may be a plain index (uses the `offset`\n    //             below) or a per-face [index, azimuth, elevation] triple whose\n    //             azimuth/elevation (DEGREES) is that face's own offset, e.g.\n    //             [[0, 0, 0], [1, 10, 20]] = face 0 dead-on, then face 1 offset\n    //             10°/20°. See each solid's colorFace doc for the indices.\n    //   color:    [r,g,b,a] to paint the face(s), or null (default) to leave the\n    //             colour(s) unchanged and only orient. With an array, each face is\n    //             painted as it is reached (cumulative — use resetColors to clear).\n    //   offset:   how to orient a plain (non-triple) index. `0` (default) means\n    //             DON'T rotate — just colour the face in place. An [azimuth,\n    //             elevation] pair in DEGREES turns the solid so the face faces the\n    //             viewer at that angle away from dead-on ([0, 0] = dead-on; a\n    //             small offset shows it at a 3/4 angle, reading 3D).\n    //   duration: per-face animation seconds (default 1). <= 0 jumps immediately.\n    //   pause:    seconds held on each face when touring an array (default 0.1).\n    // Faces with no single facing direction (a cylinder's curved wall, a sphere)\n    // are recoloured (if a colour is given) but not reoriented. Defined only when\n    // the shape is colourable.\n    if (shape.custom && shape.custom.colorFace) {\n        element.highlightFace = function (index, color, offset, duration, pause) {\n            if (color === void 0) { color = null; }\n            if (offset === void 0) { offset = 0; }\n            if (duration === void 0) { duration = 1; }\n            if (pause === void 0) { pause = 0.1; }\n            var entries = Array.isArray(index) ? index : [index];\n            var stops = [];\n            entries.forEach(function (entry) {\n                // An [index, az, el] triple always rotates to its own offset (degrees).\n                // A plain index rotates only when the shared `offset` is an [az, el]\n                // pair; a scalar `offset` (i.e. 0) means colour in place, no rotation.\n                var idx = Array.isArray(entry) ? entry[0] : entry;\n                var rot = Array.isArray(entry)\n                    ? [entry[1] || 0, entry[2] || 0]\n                    : (Array.isArray(offset) ? offset : null);\n                var faceN = shape.custom.faceNormal(idx);\n                // No rotation requested (or a wrap-around face with no facing direction)\n                // → just colour the face where it is.\n                if (rot === null || !faceN) {\n                    if (color) {\n                        shape.custom.colorFace(idx, color);\n                    }\n                    fig.animateNextFrame();\n                    return;\n                }\n                var fp = Fig.getPoint(faceN);\n                stops.push({\n                    az: azOf(fp) + rot[0] * DEG,\n                    // Clamp so a top/bottom face settles dead-on, never tipping over the\n                    // back (unlike viewFrom, which may sweep past the pole on purpose).\n                    el: clampEl(elOf(fp) + rot[1] * DEG),\n                    onArrive: color ? function () { return shape.custom.colorFace(idx, color); } : undefined,\n                });\n            });\n            if (stops.length === 0) {\n                return;\n            }\n            element.custom.spinPaused = true; // hold any auto-rotation during the move\n            animateThrough(stops, duration, pause);\n        };\n    }\n    // Grow == sweeping the solid from its flat 2D base up into the full 3D shape:\n    // a cross-section plane rising base→top with the solid extruding behind it,\n    // built by revolving a profile truncated at height-fraction t (0 = base cross-\n    // section, 1 = finished). Topology is constant, so we just rewrite vertices.\n    // The structural edges are rewritten in lockstep (edgesAt, set in addEdges) so\n    // the white outline traces the base, the moving cross-section, and the corner\n    // edges throughout — they're never hidden.\n    if (shape.custom && shape.custom.geometryAt) {\n        var geometryAt_1 = shape.custom.geometryAt;\n        // Set the growth instantly to fraction `t` in [0, 1] (no animation).\n        element.setGrowth = function (t) {\n            var tc = Math.max(0, Math.min(1, t));\n            var g = geometryAt_1(tc);\n            shape.custom.updateGeneric3({ points: g.points, normals: g.normals });\n            if (edges && edges.custom && edges.custom.edgesAt) {\n                // setEdgePoints re-scales and (when edgeWidth > 0) re-tubes the segments.\n                edges.custom.setEdgePoints(edges.custom.edgesAt(tc));\n            }\n            fig.animateNextFrame();\n        };\n        // Animate the growth from `start` to `stop` (fractions in [0, 1]) over\n        // `duration` seconds (<= 0 jumps straight to `stop`). Defaults sweep the\n        // full 0 → 1.\n        element.grow = function (start, stop, duration) {\n            if (start === void 0) { start = 0; }\n            if (stop === void 0) { stop = 1; }\n            if (duration === void 0) { duration = 1; }\n            element.animations.cancel('solid3dGrow');\n            if (duration <= 0) {\n                element.setGrowth(stop);\n                return;\n            }\n            element.setGrowth(start);\n            // fnMap-named callback so the grow survives speech pause/resume (see animateThrough).\n            element.fnMap.add('solid3dGrowCb', function (p) { return element.setGrowth(start + (stop - start) * p); });\n            element.animations\n                .new('solid3dGrow')\n                .custom({ duration: duration, callback: 'solid3dGrowCb' })\n                .start();\n            fig.animateNextFrame();\n        };\n    }\n    // Project a point given in the solid's LOCAL 3D geometry space (e.g. the cone\n    // tip at [0, length/2, 0]) into the host expression's 2D coordinates: through\n    // the shape's current orientation + the orthographic projection (FigureOne's\n    // 'draw'→'figure'), then back into the expression's child space. Lets content\n    // anchor a 2D arrow/label to a feature of the 3D solid. Returns [x, y] in\n    // expression coordinates — recompute after reorienting, as it moves with the\n    // view.\n    element.custom.localPointToExpression = function (p3d) {\n        var f = shape.pointFromSpaceToSpace(Fig.getPoint(p3d), 'draw', 'figure');\n        var e = toAdd.pointFromSpaceToSpace(f, 'figure', 'draw');\n        return [e.x, e.y];\n    };\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    element.notificationHelper = new NotificationHelper();\n    // setupManipulative wires the shared helpers: trash(), setMoveBounds(),\n    // bounds shadow, preserveChildColor. Pass `null` for selectBorder unless this\n    // is a select-style (click-to-select) manipulative.\n    setupManipulative(element, null, o);\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    // These solids intentionally define NO getState/setState. Their orientation is\n    // not persisted: the save/restore layer (getManipulativesState/setManipulatives\n    // in manage.ts) skips any manipulative without a getState, so a solid adds\n    // nothing to the answer payload and is never restored from a snapshot.\n    var isInteractive = o.isRotatable && o.isTouchable !== false;\n    // On relayout (e.g. font loading) the equation repositions children; restore\n    // the learner's orientation if they've moved (rotated) the solid.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            applyView(element.custom.viewCam);\n        }\n    });\n    // HIDDEN-LINE REVEAL GUARD. Showing the parent collection (e.g. showForm\n    // revealing this solid from a form that had it hidden) recursively shows every\n    // child, which un-hides the opaque directionally-lit twin built for hidden-line\n    // mode — it then paints over the wireframe and the solid looks lit. There is no\n    // reliable \"was just shown\" notification (layoutForms does not fire on a plain\n    // showForm), so enforce the invariant each draw instead: while the wireframe is\n    // the intended representation and no setWireframe cross-fade is mid-flight, the\n    // opaque twin must stay hidden. Cheap (a couple of boolean checks) and only acts\n    // when the invariant is actually violated. No-op when the twin was never built.\n    if (opaqueFill) {\n        element.notificationHelper.add(fig, 'beforeDraw', function () {\n            if (wireframeOn && !wireAnimating && opaqueFill && opaqueFill.isShown) {\n                opaqueFill.hide();\n                if (opaqueEdges) {\n                    opaqueEdges.hide();\n                }\n            }\n        });\n    }\n    // --- INTERACTION --------------------------------------------------------\n    // Each solid gets its own invisible touch handle inside its container. The\n    // handle is parented with the solid, so FigureOne hit-tests it per-solid with\n    // no overlap — unlike FigureOne's `rotateControl`, whose canvas-relative hit\n    // region can't be scoped to one of several solids in a shared figure (all the\n    // controls collapse to a single hit area, so only one would respond).\n    //\n    // A drag is turned into a rotation of the VIRTUAL camera — azimuth about the\n    // up axis, elevation about the side axis — then the solid is re-oriented (and\n    // the light swept) via applyView(). This is the motion `cameraControl`\n    // produces (viewpoint orbits a world-fixed light), so the lit side moves\n    // across the solid — which is what makes a sphere/cone read as rotating.\n    if (isInteractive) {\n        var rotateView_1 = function (dx, dy) {\n            var P = Fig.getPoint(element.custom.viewCam);\n            var L = Fig.getPoint(LOOK_AT);\n            var U = Fig.getPoint(UP);\n            var deltaAz = -dx * o.sensitivity;\n            var deltaEl = dy * o.sensitivity;\n            var panAxis = U;\n            var tiltAxis = U.crossProduct(P.sub(L)).normalize();\n            // Clamp elevation so the view never tips past the poles (and flips).\n            var toPole = Math.abs(Math.acos(P.sub(L).normalize().dotProduct(L.add(U).normalize())));\n            if (deltaEl < 0) {\n                deltaEl = Math.max(deltaEl, -toPole + 0.05);\n            }\n            else if (deltaEl > 0) {\n                deltaEl = Math.min(deltaEl, Math.PI - toPole - 0.05);\n            }\n            var t = [\n                ['r', deltaEl, tiltAxis.x, tiltAxis.y, tiltAxis.z],\n                ['r', deltaAz, panAxis.x, panAxis.y, panAxis.z],\n            ];\n            var Pn = P.transformBy(Fig.getTransform(t).matrix());\n            element.custom.viewCam = [Pn.x, Pn.y, Pn.z];\n            applyView(element.custom.viewCam);\n        };\n        var handle_1 = container.add({\n            name: 'handle',\n            make: 'rectangle',\n            position: [handleX, handleY], // centre on the shape\n            width: HANDLE_SIZE,\n            height: HANDLE_SIZE,\n            color: o.debug ? [0, 0, 1, 0.15] : [0, 0, 0, 0.001], // touchable, ~invisible\n            move: { type: 'translation', freely: false },\n        });\n        element.custom.handle = handle_1;\n        handle_1.custom.moving = false;\n        // 'beforeMove' fires before each pointer-move applies; capture the pre-move\n        // position so 'setTransform' can diff against it for the drag increment.\n        element.notificationHelper.add(handle_1, 'beforeMove', function () {\n            handle_1.custom.position = handle_1.getPosition();\n            handle_1.custom.moving = true;\n            element.custom.spinPaused = true; // pause autoRotate while the learner drags\n        });\n        element.notificationHelper.add(handle_1, 'setTransform', function () {\n            if (!handle_1.custom.moving) {\n                return;\n            }\n            var delta = handle_1.getPosition().sub(handle_1.custom.position);\n            rotateView_1(delta.x, delta.y);\n            element.custom.moved = true;\n            // Snap the handle back so it tracks the (stationary) solid, never wanders.\n            handle_1.transform.updateTranslation(handle_1.custom.position);\n            handle_1.custom.moving = false;\n        });\n        // When the drag finishes, flag that the answer may have changed. Orientation\n        // is not persisted (no getState/setState), so nothing is recorded here.\n        element.notificationHelper.add(handle_1, 'stopBeingMoved', function () {\n            element.custom.spinPaused = false; // resume autoRotate from the new pose\n            fig.answerChanged();\n        });\n        // Enlarge the touch target a little so the solid is easy to grab.\n        handle_1.custom.secondaryTouchBounds = 0.1;\n    }\n    // --- AUTO-ROTATION ------------------------------------------------------\n    // Optionally spin the solid slowly about world up, on its own. We orbit the\n    // VIRTUAL camera (same path drag uses) so the lit side sweeps across the body\n    // — that sweep is what reads as rotation on a sphere/cone, which would look\n    // static under a turning-but-symmetric silhouette alone. The loop is a\n    // beforeDraw handler that advances by real elapsed time and re-requests the\n    // next frame; registering it through notificationHelper means teardown\n    // (loadQuestion.ts) removes it and the loop stops requesting frames.\n    if (o.autoRotate) {\n        var speed_1 = typeof o.autoRotate === 'number' ? o.autoRotate : 0.35;\n        var U_1 = Fig.getPoint(UP);\n        var L_1 = Fig.getPoint(LOOK_AT);\n        element.custom.spinPaused = false;\n        var last_1 = performance.now();\n        var orbitAzimuth_1 = function (angle) {\n            var P = Fig.getPoint(element.custom.viewCam);\n            var t = [['r', angle, U_1.x, U_1.y, U_1.z]];\n            var Pn = P.transformBy(Fig.getTransform(t).matrix());\n            element.custom.viewCam = [Pn.x, Pn.y, Pn.z];\n            applyView(element.custom.viewCam);\n        };\n        // --- TILT REVEAL (show the base) --------------------------------------\n        // A one-shot tilt about the horizontal (side) axis: ease up to `angle`\n        // degrees, hold, then ease back to exactly the resting pose — used to tip\n        // the solid back and reveal its base while it's being described. While a tilt\n        // is active it owns the orientation (the azimuth branch is skipped), and the\n        // whole arc is computed from a FIXED resting camera + axis captured at the\n        // start, so it returns exactly to rest; it deliberately leaves spinPaused\n        // alone, so whatever the caller's spin policy is (e.g. the play's focusSpin /\n        // spinNone) simply resumes afterwards. Sign flips the tilt direction (which\n        // way reveals the base reads best is tuned in content).\n        var BASE_REVEAL_SIGN_1 = 1;\n        // Smooth, symmetric in/out easing on [0, 1].\n        var ease_1 = function (x) {\n            var c = x < 0 ? 0 : x > 1 ? 1 : x;\n            return 0.5 - 0.5 * Math.cos(Math.PI * c);\n        };\n        var advanceTilt_1 = function (now) {\n            var s = element.custom.tilt;\n            var t = now - s.start;\n            var frac;\n            if (t < s.rise) {\n                frac = ease_1(t / s.rise); // tip up\n            }\n            else if (t < s.rise + s.hold) {\n                frac = 1; // hold at the top\n            }\n            else if (t < 2 * s.rise + s.hold) {\n                frac = ease_1(1 - (t - s.rise - s.hold) / s.rise); // tip back\n            }\n            else {\n                frac = 0; // done — exactly at rest\n            }\n            var rot = [['r', s.maxEl * frac, s.axis.x, s.axis.y, s.axis.z]];\n            var Pn = Fig.getPoint(s.restCam).transformBy(Fig.getTransform(rot).matrix());\n            element.custom.viewCam = [Pn.x, Pn.y, Pn.z];\n            applyView(element.custom.viewCam);\n            if (t >= 2 * s.rise + s.hold) {\n                element.custom.tilt = null; // done — spinPaused is left as the caller set it\n            }\n        };\n        // angleDeg/holdSec/riseSec are optional; called with no usable args (e.g. via\n        // the speech directive |e:NAME,tiltReveal|) it uses the defaults below.\n        element.tiltReveal = function (angleDeg, holdSec, riseSec) {\n            if (element.custom.tilt || element.custom.spinStopped) {\n                return; // already tilting, or the solid is frozen (answer shown)\n            }\n            var deg = typeof angleDeg === 'number' ? angleDeg : 90;\n            var hold = typeof holdSec === 'number' ? holdSec : 1.5;\n            var rise = typeof riseSec === 'number' ? riseSec : 1.2;\n            var restCam = element.custom.viewCam.slice();\n            // Horizontal axis perpendicular to the up axis and the view direction.\n            var axis = U_1.crossProduct(Fig.getPoint(restCam).sub(L_1)).normalize();\n            element.custom.tilt = {\n                start: performance.now(),\n                restCam: restCam,\n                axis: axis,\n                maxEl: (BASE_REVEAL_SIGN_1 * deg * Math.PI) / 180,\n                hold: hold * 1000,\n                rise: rise * 1000,\n            };\n        };\n        var spin = function () {\n            var now = performance.now();\n            var dt = (now - last_1) / 1000;\n            last_1 = now;\n            if (element.custom.spinStopped) {\n                return; // frozen — stop requesting frames\n            }\n            if (element.custom.tilt) {\n                advanceTilt_1(now); // a reveal is in progress (azimuth is paused)\n            }\n            else if (!element.custom.spinPaused && dt < 0.25) {\n                // Skip huge dt (tab was backgrounded) so the solid doesn't jump on return.\n                orbitAzimuth_1(speed_1 * dt);\n            }\n            fig.animateNextFrame();\n        };\n        element.notificationHelper.add(fig, 'beforeDraw', spin);\n        fig.animateNextFrame(); // kick off the loop\n    }\n    // --- DEPTH LAYERING -----------------------------------------------------\n    // Bias this solid's scene-camera z by its stacking rank so overlapping solids\n    // occupy disjoint depth bands (see LAYER_SEP). Only meaningful when the solid\n    // sits inside a draggable wrapper (a manipulative_tile) that shares a parent\n    // with other such wrappers — `element.parent` is the tile, `holder` is the\n    // collection whose drawOrder the tile is reordered within on grab\n    // (tile.ts calls `tile.parent.toFront(tile)`). Solids placed directly in the\n    // equation (no tile) just skip this — they're laid out in a non-overlapping row\n    // (so they never share a depth band) and pushing their cameras back would only\n    // cost depth precision (see LAYER_SEP note: a far push z-fights the faces).\n    var tile = element.parent;\n    var holder = tile != null ? tile.parent : null;\n    if (holder != null && holder.drawOrder != null) {\n        // Mark the tile so sibling solids can recognise it when ranking.\n        tile.custom.solid3dStack = true;\n        element.custom.depthOffset = -1; // force the first updateDepth() to apply\n        var updateDepth = function () {\n            var order = holder.drawOrder; // child names; later in the list = on top\n            var myIdx = order.indexOf(tile.name);\n            if (myIdx < 0) {\n                return;\n            }\n            // Count solid-bearing tiles drawn AFTER me — those are visually in front,\n            // so I sit that many layers further back.\n            var inFront = 0;\n            for (var i = myIdx + 1; i < order.length; i += 1) {\n                var sib = holder.elements[order[i]];\n                if (sib != null && sib.custom != null && sib.custom.solid3dStack) {\n                    inFront += 1;\n                }\n            }\n            var offset = inFront * LAYER_SEP;\n            if (offset !== element.custom.depthOffset) {\n                element.custom.depthOffset = offset;\n                scene.setCamera({\n                    position: [REAL_CAMERA[0], REAL_CAMERA[1], REAL_CAMERA[2] + offset],\n                });\n            }\n        };\n        // Recompute on every redraw — stacking only changes via interaction (drag /\n        // toFront / snap), which already drives redraws — plus once now.\n        element.notificationHelper.add(fig, 'beforeDraw', updateDepth);\n        updateDepth();\n    }\n    // Called generically by the answer-input \"show answer\" flow (answerInput.ts)\n    // to freeze every manipulative once the answer is revealed.\n    element.disable = function () {\n        element.hasTouchableElements = false;\n        element.custom.spinStopped = true; // halt autoRotate when the answer is shown\n        if (element.custom.handle) {\n            element.custom.handle.isTouchable = false;\n        }\n    };\n    // Register for answer processing. MUST be snake_case and match the YAML.\n    element.custom.manipulativeType = config.manipulativeType;\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    return element;\n}\nexport { makeSolid3d, addLineEdges, edgeTubePoints, circleEdges, addColorableShape, solidGeometryAt, solidEdgesAt, solidHiddenLineOn, solidSilhouetteSegments, solidHiddenLineEdges, hiddenLineDashCells, solidFeatureVertices, solidFeatureEdges, sweepWall, sweepWallPoint, sweepStart, sweepFillPoints, sweepLineEnds, prismOutline, SOLID3D_BASE_DEFAULTS, };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// colorFace(faceIndex, color) — the cube's 6 faces, keyed by their outward\n// normal direction:\n//   0 = +z (front)   1 = +x (right)   2 = +y (top)\n//   3 = -z (back)    4 = -x (left)    5 = -y (bottom)\nvar cubeFaceOf = function (_p, n) {\n    if (n.z > 0.5) {\n        return 0;\n    }\n    if (n.x > 0.5) {\n        return 1;\n    }\n    if (n.y > 0.5) {\n        return 2;\n    }\n    if (n.z < -0.5) {\n        return 3;\n    }\n    if (n.x < -0.5) {\n        return 4;\n    }\n    return 5;\n};\nvar cube = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { side: 0.5 }, options);\n    return makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'cube',\n        // Built as a generic3 square prism (a 4-sided revolve) via the shared\n        // profile geometry, so it carries a per-vertex colour buffer (faces keyed by\n        // normal) AND can grow() from its flat base. classify by normal → 6 faces.\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('cube', opts, t); };\n            var g = geometryAt(1);\n            // Hidden-line mode draws the faces as a flat, unlit translucent fill; the\n            // normal cube is directionally lit so its faces read as 3D.\n            var faceLight = solidHiddenLineOn('cube', opts) ? null : 'directional';\n            return addColorableShape(scene, 'cube', g.points, g.normals, opts.color, cubeFaceOf, geometryAt, faceLight);\n        },\n        // The 12 box edges, generated from the same profile so they can track grow().\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('cube', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('cube', opts, t); };\n            return e;\n        },\n    });\n};\nexport { cube };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// colorFace(faceIndex, color) — the cylinder's 3 faces, keyed by normal:\n//   0 = lateral (curved side wall)   1 = top cap   2 = bottom cap\n// The caps' normals point along the axis (±y); the side wall's are radial.\nvar cylinderFaceOf = function (_p, n) {\n    if (n.y > 0.5) {\n        return 1;\n    }\n    if (n.y < -0.5) {\n        return 2;\n    }\n    return 0;\n};\nvar cylinder = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { radius: 0.3, length: 0.6, sides: 20 }, options);\n    return makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'cylinder',\n        // Built as a generic3 (what make:'cylinder' is internally) so it carries a\n        // per-vertex colour buffer and faces can be recoloured via colorFace. `line`\n        // orients + centers the cylinder vertically about the origin so it sits in\n        // the camera's lookAt and rotates about its own centre.\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('cylinder', opts, t); };\n            var g = geometryAt(1);\n            // Hidden-line mode draws the faces as a flat, unlit translucent fill.\n            var faceLight = solidHiddenLineOn('cylinder', opts) ? null : 'directional';\n            return addColorableShape(scene, 'cylinder', g.points, g.normals, opts.color, cylinderFaceOf, geometryAt, faceLight);\n        },\n        // The top and bottom rim circles (and, during grow, the moving cross-section\n        // circle); generated from the profile so they track grow().\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('cylinder', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('cylinder', opts, t); };\n            return e;\n        },\n    });\n};\nexport { cylinder };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// colorFace(faceIndex, color) — the cone's 2 faces, keyed by normal:\n//   0 = lateral (curved slant surface)   1 = base cap\n// The base cap's normal points straight down the axis (-y); the slant surface's\n// normals point outward and up.\nvar coneFaceOf = function (_p, n) { return (n.y < -0.5 ? 1 : 0); };\nvar cone = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { radius: 0.3, length: 0.6, sides: 20 }, options);\n    var element = makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'cone',\n        // Built as a generic3 (what make:'cone' is internally) so it carries a\n        // per-vertex colour buffer and faces can be recoloured via colorFace. `line`\n        // is [base, tip]: base below the origin, tip above, so the cone is centred\n        // vertically about the camera's lookAt and rotates about its centre.\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('cone', opts, t); };\n            var g = geometryAt(1);\n            // Hidden-line mode draws the faces as a flat, unlit translucent fill.\n            var faceLight = solidHiddenLineOn('cone', opts) ? null : 'directional';\n            return addColorableShape(scene, 'cone', g.points, g.normals, opts.color, coneFaceOf, geometryAt, faceLight);\n        },\n        // The base rim circle (and, during grow, the shrinking cross-section circle);\n        // generated from the profile so they track grow().\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('cone', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('cone', opts, t); };\n            return e;\n        },\n    });\n    // The cone's tip (apex, local [0, length/2, 0]) in EXPRESSION coordinates [x, y]\n    // — for pointing an arrow/label at it. Reflects the current orientation, so\n    // recompute after reorienting (viewFrom / drag / spin).\n    element.coneTip = function () { return element.custom.localPointToExpression([0, o.length / 2, 0]); };\n    return element;\n};\nexport { cone };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// A sphere is one continuous surface with no natural faces, so colorFace\n// exposes a single face: colorFace(0, color) recolours the whole sphere.\nvar sphereFaceOf = function () { return 0; };\nvar sphere = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { radius: 0.35, sides: 20 }, options);\n    return makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'sphere',\n        // Built as a generic3 revolved semicircle (so it can grow() from a point at\n        // the bottom up through the equator to the full sphere). colorFace(0, color)\n        // recolours the whole surface.\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('sphere', opts, t); };\n            var g = geometryAt(1);\n            // Unlit in hidden-line mode, where the fill is a flat tint behind the\n            // outline rather than a shaded surface. Note the sphere only enters that\n            // mode when `silhouette` is set too — hiddenLine alone has nothing to draw\n            // on an edgeless solid — which is exactly what solidHiddenLineOn encodes.\n            var faceLight = solidHiddenLineOn('sphere', opts) ? null : 'directional';\n            return addColorableShape(scene, 'sphere', g.points, g.normals, opts.color, sphereFaceOf, geometryAt, faceLight);\n        },\n        // The sphere has no edges at rest, but during grow() the cross-section is a\n        // circle — draw it (collapses to a point, so invisible, at t=1).\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('sphere', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('sphere', opts, t); };\n            return e;\n        },\n    });\n};\nexport { sphere };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// SIDES is fixed at 4 — that's what makes it a pyramid (a 4-sided cone).\nvar SIDES = 4;\n// colorFace(faceIndex, color) — the pyramid's 5 faces, keyed by normal:\n//   0..3 = the four triangular side faces, in azimuth order (atan2(z, x));\n//   4    = the square base (its flat normal points straight down, -y).\n// The flat normals (one per triangular face) sit at azimuths 0/90/180/270 for\n// the default rotation; the +PI/4 shift centres each in its 90° bin so a face's\n// vertices always classify together, robust to floating-point wobble.\nvar pyramidFaceOf = function (_p, n) {\n    if (n.y < -0.5) {\n        return 4;\n    } // base (faces straight down)\n    // The grow geometry carries a top \"cap\" that degenerates to the apex at full\n    // height; its leftover up-facing (+y) verts belong to no side face — exclude\n    // them (-1) so they don't drag a side's orientation toward vertical.\n    if (n.y > 0.5) {\n        return -1;\n    }\n    var a = Math.atan2(n.z, n.x);\n    if (a < 0) {\n        a += 2 * Math.PI;\n    }\n    return Math.floor((a + Math.PI / 4) / (Math.PI / 2)) % SIDES;\n};\nvar pyramid = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { radius: 0.4, length: 0.6, rotation: Math.PI / 4 }, options);\n    var element = makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'pyramid',\n        // A 4-sided cone IS a square pyramid. Built as a generic3 (what make:'cone'\n        // is internally) so it carries a per-vertex colour buffer and faces can be\n        // recoloured via colorFace. `line` centres it vertically about the origin\n        // (base below, apex above) so it rotates about its own centre, and flat\n        // normals give it four distinct triangular faces.\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('pyramid', opts, t); };\n            var g = geometryAt(1);\n            // Hidden-line mode draws the faces as a flat, unlit translucent fill.\n            var faceLight = solidHiddenLineOn('pyramid', opts) ? null : 'directional';\n            return addColorableShape(scene, 'pyramid', g.points, g.normals, opts.color, pyramidFaceOf, geometryAt, faceLight);\n        },\n        // The base square plus the four slant edges to the apex (and, during grow,\n        // the shrinking cross-section square); generated from the profile so they\n        // track grow().\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('pyramid', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('pyramid', opts, t); };\n            return e;\n        },\n    });\n    // The pyramid's tip (apex, local [0, length/2, 0]) in EXPRESSION coordinates\n    // [x, y] — for pointing an arrow/label at it. Reflects the current orientation,\n    // so recompute after reorienting (viewFrom / drag / spin).\n    element.pyramidTip = function () { return element.custom.localPointToExpression([0, o.length / 2, 0]); };\n    return element;\n};\nexport { pyramid };\n","import { makeSolid3d, addLineEdges, addColorableShape, solidGeometryAt, solidHiddenLineOn, solidEdgesAt, prismOutline, SOLID3D_BASE_DEFAULTS, } from './solid3d';\n// colorFace(faceIndex, color) — keyed by each face's flat normal:\n//   0..sides-1 = the rectangular side faces, in azimuth order (atan2(z, x));\n//   sides      = the top end face   (normal +y)\n//   sides + 1  = the bottom end face (normal -y)\n// Side face i's outward normal sits at azimuth rotation + (i + 0.5)/sides·2π;\n// subtracting rotation and binning by 1/sides of a turn classifies each face's\n// vertices together, robust to floating-point wobble.\nfunction prismFaceOf(sides, rotation) {\n    var TWO_PI = 2 * Math.PI;\n    return function (_p, n) {\n        var ny = n.y === undefined ? n[1] : n.y;\n        if (ny > 0.5) {\n            return sides;\n        }\n        if (ny < -0.5) {\n            return sides + 1;\n        }\n        var nx = n.x === undefined ? n[0] : n.x;\n        var nz = n.z === undefined ? n[2] : n.z;\n        var rel = Math.atan2(nz, nx) - rotation;\n        rel = ((rel % TWO_PI) + TWO_PI) % TWO_PI;\n        return Math.floor(rel / (TWO_PI / sides)) % sides;\n    };\n}\n// The arbitrary-polygon counterpart of prismFaceOf. Side faces aren't evenly\n// spaced in azimuth, so we can't bin by angle; instead we precompute each side\n// face's outward-normal azimuth (the perpendicular of edge j→j+1, pointing away\n// from the axis) and classify a vertex to the face whose azimuth is nearest.\n// Face indices match the regular prism: 0..n-1 = the side faces in corner order,\n// n = top end face (+y), n + 1 = bottom end face (−y). `corners` are the same\n// centred {x, z} outline the geometry uses (from prismOutline).\nfunction prismPolygonFaceOf(corners) {\n    var n = corners.length;\n    var TWO_PI = 2 * Math.PI;\n    var faceAz = [];\n    for (var i = 0; i < n; i += 1) {\n        var a = corners[i];\n        var b = corners[(i + 1) % n];\n        var nx = b.z - a.z;\n        var nz = -(b.x - a.x);\n        if (nx * (a.x + b.x) + nz * (a.z + b.z) < 0) {\n            nx = -nx;\n            nz = -nz;\n        }\n        faceAz.push(Math.atan2(nz, nx));\n    }\n    return function (_p, nrm) {\n        var ny = nrm.y === undefined ? nrm[1] : nrm.y;\n        if (ny > 0.5) {\n            return n;\n        }\n        if (ny < -0.5) {\n            return n + 1;\n        }\n        var nx = nrm.x === undefined ? nrm[0] : nrm.x;\n        var nz = nrm.z === undefined ? nrm[2] : nrm.z;\n        var az = Math.atan2(nz, nx);\n        var best = 0;\n        var bestD = Infinity;\n        for (var i = 0; i < n; i += 1) {\n            var d = Math.abs(az - faceAz[i]);\n            if (d > Math.PI) {\n                d = TWO_PI - d;\n            }\n            if (d < bestD) {\n                bestD = d;\n                best = i;\n            }\n        }\n        return best;\n    };\n}\nvar prism = function (eqn_name, options, fig) {\n    var o = Fig.joinObjects({}, SOLID3D_BASE_DEFAULTS, { radius: 0.34, length: 0.6, sides: 3, rotation: Math.PI / 6 }, options);\n    return makeSolid3d(eqn_name, o, fig, {\n        manipulativeType: 'prism',\n        // Built through the shared profile→revolve machinery (solidGeometryAt) — a\n        // prism is an n-gon cross-section extruded along its axis, i.e. a flat-walled\n        // surface of revolution — so it carries a per-vertex colour buffer (faces\n        // keyed by normal via prismFaceOf) AND can grow() from its flat base. The\n        // cross-section is spun by `rotation` to present a face (or a corner).\n        addShape: function (scene, opts) {\n            var geometryAt = function (t) { return solidGeometryAt('prism', opts, t); };\n            var g = geometryAt(1);\n            // Hidden-line mode draws the faces as a flat, unlit translucent fill.\n            var faceLight = solidHiddenLineOn('prism', opts) ? null : 'directional';\n            // A polygon prism keys faces off its (centred) outline; a regular prism\n            // keys them off the even n-gon azimuths. Both index side faces 0..n-1 then\n            // top (n) and bottom (n+1), so colorFace/highlightFace read the same way.\n            var outline = prismOutline(opts);\n            var classify = outline\n                ? prismPolygonFaceOf(outline)\n                : prismFaceOf(opts.sides, opts.rotation);\n            return addColorableShape(scene, 'prism', g.points, g.normals, opts.color, classify, geometryAt, faceLight);\n        },\n        // The two end rings plus the vertical corner edges, generated from the same\n        // profile so they track grow().\n        addEdges: function (scene, opts) {\n            var e = addLineEdges(scene, 'edges', solidEdgesAt('prism', opts, 1), opts.edgeColor, opts);\n            e.custom.edgesAt = function (t) { return solidEdgesAt('prism', opts, t); };\n            return e;\n        },\n    });\n};\nexport { prism, prismFaceOf, prismPolygonFaceOf, };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\n// --- SHAPE CATALOG ------------------------------------------------------\n// Unit-edge vertex lists (CCW) + the classic pattern-block colour. The regular\n// shapes are generated; the rhombi and trapezoid are explicit. SQRT3_2 = sin60.\nvar SQRT3_2 = Math.sqrt(3) / 2;\n// Regular n-gon with edge length 1, oriented flat-bottom (matches poly's\n// defaultRegularRotation: first vertex half a step past straight down).\nfunction regularUnitEdge(n) {\n    var radius = 1 / (2 * Math.sin(Math.PI / n)); // edge 1 -> circumradius.\n    var rot = -Math.PI / 2 + Math.PI / n;\n    var out = [];\n    for (var i = 0; i < n; i += 1) {\n        var a = rot + (i * Math.PI * 2) / n;\n        out.push([radius * Math.cos(a), radius * Math.sin(a)]);\n    }\n    return out;\n}\nvar CLASSIC = {\n    triangle: { verts: regularUnitEdge(3), color: [0.30, 0.69, 0.31, 1] }, // green\n    square: { verts: regularUnitEdge(4), color: [1.00, 0.60, 0.00, 1] }, // orange\n    hexagon: { verts: regularUnitEdge(6), color: [1.00, 0.84, 0.00, 1] }, // yellow\n    blueRhombus: {\n        verts: [[0, 0], [1, 0], [1.5, SQRT3_2], [0.5, SQRT3_2]], // 60/120\n        color: [0.26, 0.45, 0.85, 1],\n    },\n    tanRhombus: {\n        verts: [[0, 0], [1, 0], [1 + SQRT3_2, 0.5], [SQRT3_2, 0.5]], // 30/150\n        color: [0.86, 0.72, 0.53, 1],\n    },\n    trapezoid: {\n        verts: [[0, 0], [2, 0], [1.5, SQRT3_2], [0.5, SQRT3_2]], // half-hexagon, long edge = 2\n        color: [0.90, 0.27, 0.27, 1],\n    },\n};\n// How many unit triangles each block decomposes into on the triangular lattice.\n// Only the 60°-family blocks tile that lattice; the square and tan rhombus are\n// geometrically incommensurate with it (see the file header) so they have no\n// integer triangle count and the slot's auto-solver can't place them.\nvar TRI_COUNT = {\n    triangle: 1,\n    blueRhombus: 2,\n    trapezoid: 3,\n    hexagon: 6,\n};\n// Rotational-symmetry angle (radians) per shape: rotating a block by this maps it\n// onto an identical polygon. The slot's show-answer reveal uses it to place a\n// block at the orientation-equivalent nearest its current pose, so a block that\n// is already correctly oriented isn't spun pointlessly — matters most for\n// rotateStep:0 (drag-only) questions, where the learner can't rotate at all so a\n// reveal spin shows a motion they could never make. Trapezoid has no rotational\n// symmetry (order 1) and is intentionally absent -> its orientation is honoured\n// exactly.\nvar SYMMETRY_ANGLE = {\n    triangle: (2 * Math.PI) / 3, // 120°\n    square: Math.PI / 2, // 90°\n    hexagon: Math.PI / 3, // 60°\n    blueRhombus: Math.PI, // 180°\n    tanRhombus: Math.PI, // 180°\n};\nvar deg2rad = function (d) { return (d * Math.PI) / 180; };\n// Wrap an angle to (-π, π] so rotation corrections take the short way round.\nfunction wrapAngle(a) {\n    var x = a;\n    while (x > Math.PI)\n        x -= Math.PI * 2;\n    while (x <= -Math.PI)\n        x += Math.PI * 2;\n    return x;\n}\nfunction rotatePoint(x, y, a) {\n    var c = Math.cos(a);\n    var s = Math.sin(a);\n    return { x: x * c - y * s, y: x * s + y * c };\n}\nfunction convexOverlap(a, b, eps) {\n    var polys = [a, b];\n    for (var pi = 0; pi < 2; pi += 1) {\n        var poly = polys[pi];\n        for (var i = 0; i < poly.length; i += 1) {\n            var p0 = poly[i];\n            var p1 = poly[(i + 1) % poly.length];\n            // Axis = edge normal.\n            var ax = -(p1.y - p0.y);\n            var ay = p1.x - p0.x;\n            var len = Math.hypot(ax, ay) || 1;\n            var nx = ax / len;\n            var ny = ay / len;\n            var aMin = Infinity;\n            var aMax = -Infinity;\n            var bMin = Infinity;\n            var bMax = -Infinity;\n            for (var k = 0; k < a.length; k += 1) {\n                var d = a[k].x * nx + a[k].y * ny;\n                if (d < aMin)\n                    aMin = d;\n                if (d > aMax)\n                    aMax = d;\n            }\n            for (var k = 0; k < b.length; k += 1) {\n                var d = b[k].x * nx + b[k].y * ny;\n                if (d < bMin)\n                    bMin = d;\n                if (d > bMax)\n                    bMax = d;\n            }\n            // Separation along this axis (positive = a gap). Touching ≈ 0.\n            var sep = Math.max(bMin - aMax, aMin - bMax);\n            if (sep >= -eps)\n                return false; // separated (or just touching) -> no overlap.\n        }\n    }\n    return true; // overlap deeper than eps on every axis.\n}\n// Best-effort copy of `text` to the clipboard (so getOutline(s) output pastes\n// with real newlines). Async Clipboard API where available, hidden-textarea\n// execCommand fallback otherwise. Never throws.\nfunction copyToClipboard(text) {\n    var fallback = function () {\n        try {\n            var ta = document.createElement('textarea');\n            ta.value = text;\n            ta.style.position = 'fixed';\n            ta.style.left = '-9999px';\n            document.body.appendChild(ta);\n            ta.select();\n            document.execCommand('copy');\n            document.body.removeChild(ta);\n        }\n        catch ( /* clipboard unavailable — ignore */_a) { /* clipboard unavailable — ignore */ }\n    };\n    try {\n        if (typeof navigator !== 'undefined' && navigator.clipboard\n            && navigator.clipboard.writeText) {\n            navigator.clipboard.writeText(text).catch(fallback);\n            return;\n        }\n    }\n    catch ( /* fall through to execCommand */_a) { /* fall through to execCommand */ }\n    fallback();\n}\nvar patternBlocks = function (eqn_name, options, fig) {\n    // Resolve where to attach the manipulative. `eqn_name` is usually a string\n    // path to the host equation; fall back to the figure's root elements.\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        shape: 'triangle',\n        size: 0.35,\n        borderWidth: 0.01,\n        rotation: 0,\n        yOffset: 0,\n        rotateStep: 30,\n        snap: true,\n        isTouchable: true,\n        boundMove: true,\n        debug: false,\n    }, options);\n    var shape = CLASSIC[o.shape] != null\n        ? o.shape\n        : 'triangle';\n    var def = CLASSIC[shape];\n    var fillColor = o.color != null ? o.color : def.color;\n    var borderColor = o.border != null\n        ? o.border\n        : [fillColor[0] * 0.6, fillColor[1] * 0.6, fillColor[2] * 0.6, 1];\n    // Centre on the vertex average so rotation pivots about the middle, then scale\n    // by `size`. `local` is the single source of truth for the block's geometry in\n    // container-local coordinates.\n    var cx = def.verts.reduce(function (s, v) { return s + v[0]; }, 0) / def.verts.length;\n    var cy = def.verts.reduce(function (s, v) { return s + v[1]; }, 0) / def.verts.length;\n    var local = def.verts.map(function (v) { return [\n        (v[0] - cx) * o.size,\n        (v[1] - cy) * o.size,\n    ]; });\n    // Snapping config.\n    var snapOn = o.snap !== false;\n    var snapCfg = typeof o.snap === 'object' && o.snap != null ? o.snap : {};\n    var posTol = snapCfg.tolerance != null ? snapCfg.tolerance : o.size * 0.6;\n    var angTol = deg2rad(snapCfg.angleTolerance != null ? snapCfg.angleTolerance : 16);\n    var rotateStep = deg2rad(o.rotateStep);\n    var initialRotation = deg2rad(o.rotation); // authored \"home\" orientation.\n    // Overlap slack: a shared edge (blocks merely touching) penetrates by ~0, so\n    // this much tolerance means \"touching is allowed, real covering is not\".\n    var eps = o.size * 0.06;\n    // --- STRUCTURE ----------------------------------------------------------\n    // `element` is the movable top-level collection (its position is the move\n    // anchor / answer position). `container` carries the y-offset AND the block's\n    // rotation, so moving and rotating are cleanly separated: element translates,\n    // container rotates about the centroid.\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    // Set the initial orientation via setRotation (a clean 2D rotation) rather\n    // than an explicit transform — passing `['r', a]` in a transform literal\n    // expands to a 3D rotation here, which makes getRotation() return NaN.\n    container.setRotation(deg2rad(o.rotation));\n    // --- VISUALS ------------------------------------------------------------\n    // Filled convex polygon as a triangle fan (v0,vi,vi+1), plus an outline.\n    // NB: pass *copies* of the local points to FigureOne — it parses a `points`\n    // array in place, replacing each [x, y] with a Point object. Sharing `local`\n    // would corrupt our numeric source of truth (v[0]/v[1] would become\n    // undefined), so the snapping math must keep its own clean arrays.\n    var copy = function (p) { return [p[0], p[1]]; };\n    var fan = [];\n    for (var i = 1; i < local.length - 1; i += 1) {\n        fan.push(copy(local[0]), copy(local[i]), copy(local[i + 1]));\n    }\n    container.add({\n        name: 'fill',\n        make: 'generic',\n        points: fan,\n        drawType: 'TRIANGLES',\n        color: fillColor,\n    });\n    container.add({\n        name: 'border',\n        make: 'polyline',\n        points: local.map(copy),\n        close: true,\n        width: o.borderWidth,\n        color: borderColor,\n        // Make the whole filled polygon grabbable (point-in-polygon), not just the\n        // thin stroke — otherwise narrow shapes (triangle, tan rhombus) are easy to\n        // miss, which reads as flaky tap-to-rotate.\n        touchBorder: local.map(copy),\n    });\n    // --- GEOMETRY HELPERS (world-space, in the shared parent frame) ---------\n    // The centroid (rotation pivot) in parent coordinates. element.getPosition()\n    // is the move anchor; the container's y-offset lifts the visuals off it.\n    function centroidWorld() {\n        var p = element.getPosition();\n        return { x: p.x, y: p.y + o.yOffset };\n    }\n    function getRotation() {\n        return container.getRotation();\n    }\n    // Block vertices for an arbitrary centroid + rotation (used to test where a\n    // candidate snap *would* place the block before committing to it).\n    function worldVertsAt(cx, cy, a) {\n        return local.map(function (v) {\n            var r = rotatePoint(v[0], v[1], a);\n            return { x: cx + r.x, y: cy + r.y };\n        });\n    }\n    // Block vertices in the shared parent frame: centroid + R(θ)·local.\n    element.custom.getWorldVertices = function () {\n        var c = centroidWorld();\n        return worldVertsAt(c.x, c.y, getRotation());\n    };\n    // Every edge as a run of unit segments (length-2 edges split into 2), each\n    // with midpoint + unit direction. This is what edge-mate matching consumes.\n    element.custom.getWorldSegments = function () {\n        var vs = element.custom.getWorldVertices();\n        var out = [];\n        for (var i = 0; i < vs.length; i += 1) {\n            var a = vs[i];\n            var b = vs[(i + 1) % vs.length];\n            var len = Math.hypot(b.x - a.x, b.y - a.y);\n            var n = Math.max(1, Math.round(len / o.size)); // unit segments per edge.\n            for (var k = 0; k < n; k += 1) {\n                var t0 = k / n;\n                var t1 = (k + 1) / n;\n                var p0 = { x: a.x + (b.x - a.x) * t0, y: a.y + (b.y - a.y) * t0 };\n                var p1 = { x: a.x + (b.x - a.x) * t1, y: a.y + (b.y - a.y) * t1 };\n                var sx = p1.x - p0.x;\n                var sy = p1.y - p0.y;\n                var m = Math.hypot(sx, sy) || 1;\n                out.push({\n                    mx: (p0.x + p1.x) / 2,\n                    my: (p0.y + p1.y) / 2,\n                    dx: sx / m,\n                    dy: sy / m,\n                });\n            }\n        }\n        return out;\n    };\n    // Sibling pattern blocks under the same parent (snap candidates AND the only\n    // overlap obstacles — a block may never come to rest covering another block).\n    function getOtherBlocks() {\n        var out = [];\n        var parent = element.parent;\n        if (parent == null || parent.elements == null)\n            return out;\n        Object.keys(parent.elements).forEach(function (k) {\n            var el = parent.elements[k];\n            if (el === element)\n                return;\n            if (el.custom != null && el.custom.manipulativeType === 'pattern_block') {\n                out.push(el);\n            }\n        });\n        return out;\n    }\n    // Sibling pattern-block slots. Their boundary is an extra snap target (a block\n    // snaps to a slot edge just like to another block) but NOT an overlap\n    // obstacle — blocks are meant to sit inside the slot. The slot already exposes\n    // its segments reversed so anti-parallel matching lands the block inside.\n    function getSnapSlots() {\n        var out = [];\n        var parent = element.parent;\n        if (parent == null || parent.elements == null)\n            return out;\n        Object.keys(parent.elements).forEach(function (k) {\n            var el = parent.elements[k];\n            if (el === element)\n                return;\n            if (el.custom != null && el.custom.isPatternSlot === true) {\n                out.push(el);\n            }\n        });\n        return out;\n    }\n    // --- EDGE-MATE SNAP -----------------------------------------------------\n    // Lay one of this block's unit segments anti-parallel and coincident onto a\n    // neighbour's. We gather every candidate mate within tolerance, sort by cost\n    // (translation + a little for rotation), then commit to the cheapest one whose\n    // resulting placement does NOT cover another block — so a block snaps to a\n    // free edge and skips edges that are already occupied. No global grid: each\n    // mate is local geometry, so every shape (incl. square + tan rhombus) snaps\n    // the same way.\n    // The cheapest non-covering mate for the block's *current* placement, as an\n    // absolute target { theta (rotation), cx/cy (centroid) }, or null if none is\n    // within tolerance. Pure — it doesn't move the block, so it can drive either an\n    // instant snap (drag) or an animated slide (after a rotation).\n    function bestMate() {\n        if (!snapOn)\n            return null;\n        var blocks = getOtherBlocks();\n        // Snap to other blocks' edges AND any slot's boundary edges. Obstacles for\n        // the no-cover test below are blocks only — a block is meant to sit inside\n        // a slot, so the slot is a snap target but never an overlap obstacle.\n        var sources = blocks.concat(getSnapSlots());\n        if (sources.length === 0)\n            return null;\n        var mySegs = element.custom.getWorldSegments();\n        var c = centroidWorld();\n        var theta = getRotation();\n        // Neighbour (block) polygons, cached once for the overlap test below.\n        var nbPolys = blocks.map(function (b) { return b.custom.getWorldVertices(); });\n        var candidates = [];\n        for (var oi = 0; oi < sources.length; oi += 1) {\n            var nbSegs = sources[oi].custom.getWorldSegments();\n            for (var i = 0; i < mySegs.length; i += 1) {\n                var s = mySegs[i];\n                for (var j = 0; j < nbSegs.length; j += 1) {\n                    var t = nbSegs[j];\n                    // Mating edge sits anti-parallel: my direction should become -t.dir.\n                    var aMine = Math.atan2(s.dy, s.dx);\n                    var aWant = Math.atan2(-t.dy, -t.dx);\n                    var dTheta = wrapAngle(aWant - aMine);\n                    if (Math.abs(dTheta) > angTol)\n                        continue;\n                    // Where my segment midpoint lands after rotating dTheta about centroid.\n                    var rel = rotatePoint(s.mx - c.x, s.my - c.y, dTheta);\n                    var rotMid = { x: c.x + rel.x, y: c.y + rel.y };\n                    var tx = t.mx - rotMid.x;\n                    var ty = t.my - rotMid.y;\n                    var dist = Math.hypot(tx, ty);\n                    if (dist > posTol)\n                        continue;\n                    candidates.push({ dTheta: dTheta, tx: tx, ty: ty, cost: dist + o.size * Math.abs(dTheta) });\n                }\n            }\n        }\n        candidates.sort(function (x, y) { return x.cost - y.cost; });\n        // The cheapest mate that doesn't cover another block. Allow up to a sliver of\n        // penetration (eps) so a shared edge counts as touching, not overlapping.\n        for (var k = 0; k < candidates.length; k += 1) {\n            var cand = candidates[k];\n            var newTheta = theta + cand.dTheta;\n            var newCx = c.x + cand.tx;\n            var newCy = c.y + cand.ty;\n            var myPoly = worldVertsAt(newCx, newCy, newTheta);\n            var covers = false;\n            for (var oi = 0; oi < nbPolys.length; oi += 1) {\n                if (convexOverlap(myPoly, nbPolys[oi], eps)) {\n                    covers = true;\n                    break;\n                }\n            }\n            if (covers)\n                continue;\n            return { theta: newTheta, cx: newCx, cy: newCy };\n        }\n        return null;\n    }\n    // Instant snap (used on drag release): apply the best mate immediately.\n    function snapToNeighbors() {\n        var m = bestMate();\n        if (m == null)\n            return false;\n        container.setRotation(m.theta);\n        element.setPosition(m.cx, m.cy - o.yOffset); // position is the move anchor.\n        return true;\n    }\n    function rotateByStep() {\n        container.setRotation(getRotation() + rotateStep);\n    }\n    // Neighbour blocks whose polygon the block currently overlaps (more than the\n    // touching slack `eps`). Used to revert/explain an invalid placement.\n    function overlappingNeighbors() {\n        var myPoly = element.custom.getWorldVertices();\n        return getOtherBlocks().filter(function (b) {\n            return convexOverlap(myPoly, b.custom.getWorldVertices(), eps);\n        });\n    }\n    // --- CLUSTER OUTLINE ----------------------------------------------------\n    // The outer outline of the connected group of blocks reachable from this one\n    // by shared edges — i.e. everything snapped to it directly or indirectly.\n    //\n    // Method: every block contributes its unit boundary segments, directed CCW so\n    // each block's interior is on its left. Where two blocks share an edge the two\n    // copies run in opposite directions and cancel; the segments left uncancelled\n    // are exactly the cluster's boundary. We chain those head-to-tail into loops,\n    // keep the largest (the outer ring; any holes are inner loops we drop), and\n    // remove collinear joints so only corners remain.\n    //\n    // Returns the corner ring in WORLD (draw) units, wound CCW, or [] if empty.\n    // Both getPoints (edge-unit vertices) and getOutline (edge-walk) build on it.\n    function clusterRing() {\n        var half = o.size / 2;\n        var q = o.size * 0.02; // quantisation for matching shared endpoints.\n        var kz = function (x, y) {\n            return \"\".concat(Math.round(x / q), \",\").concat(Math.round(y / q));\n        };\n        // Each block's unit segments as directed endpoints a -> b (interior left).\n        var segsOf = function (blk) {\n            return blk.custom.getWorldSegments().map(function (s) { return ({\n                ax: s.mx - s.dx * half,\n                ay: s.my - s.dy * half,\n                bx: s.mx + s.dx * half,\n                by: s.my + s.dy * half,\n            }); });\n        };\n        var blocks = getOtherBlocks().concat([element]);\n        var blockSegs = blocks.map(segsOf);\n        var selfIndex = blocks.length - 1;\n        // directed-segment key -> blocks that own it (adjacency + cancellation).\n        var owners = {};\n        for (var i = 0; i < blocks.length; i += 1) {\n            for (var j = 0; j < blockSegs[i].length; j += 1) {\n                var s = blockSegs[i][j];\n                var dk = \"\".concat(kz(s.ax, s.ay), \">\").concat(kz(s.bx, s.by));\n                (owners[dk] = owners[dk] || []).push(i);\n            }\n        }\n        // BFS the cluster: a neighbour owns the reverse of one of our segments.\n        var inCluster = new Array(blocks.length).fill(false);\n        inCluster[selfIndex] = true;\n        var queue = [selfIndex];\n        while (queue.length > 0) {\n            var bi = queue.shift();\n            for (var j = 0; j < blockSegs[bi].length; j += 1) {\n                var s = blockSegs[bi][j];\n                var rk = \"\".concat(kz(s.bx, s.by), \">\").concat(kz(s.ax, s.ay));\n                var nb = owners[rk];\n                if (nb == null)\n                    continue;\n                for (var n = 0; n < nb.length; n += 1) {\n                    if (!inCluster[nb[n]]) {\n                        inCluster[nb[n]] = true;\n                        queue.push(nb[n]);\n                    }\n                }\n            }\n        }\n        // Boundary = cluster segments whose reverse isn't owned by a cluster block.\n        var next = {};\n        var startKeys = [];\n        for (var i = 0; i < blocks.length; i += 1) {\n            if (!inCluster[i])\n                continue;\n            for (var j = 0; j < blockSegs[i].length; j += 1) {\n                var s = blockSegs[i][j];\n                var rev = owners[\"\".concat(kz(s.bx, s.by), \">\").concat(kz(s.ax, s.ay))];\n                if (rev != null && rev.some(function (idx) { return inCluster[idx]; }))\n                    continue; // interior.\n                var sk = kz(s.ax, s.ay);\n                next[sk] = { ax: s.ax, ay: s.ay, bx: s.bx, by: s.by };\n                startKeys.push(sk);\n            }\n        }\n        // Chain boundary segments into closed loops.\n        var areaOf = function (ring) {\n            var a = 0;\n            for (var i = 0; i < ring.length; i += 1) {\n                var p = ring[i];\n                var r = ring[(i + 1) % ring.length];\n                a += p[0] * r[1] - r[0] * p[1];\n            }\n            return a / 2;\n        };\n        var loops = [];\n        var visited = {};\n        for (var si = 0; si < startKeys.length; si += 1) {\n            var sk = startKeys[si];\n            if (visited[sk])\n                continue;\n            var loop = [];\n            var guard = 0;\n            while (next[sk] != null && !visited[sk] && guard < 10000) {\n                visited[sk] = true;\n                var seg = next[sk];\n                loop.push([seg.ax, seg.ay]);\n                sk = kz(seg.bx, seg.by);\n                guard += 1;\n            }\n            if (loop.length >= 3)\n                loops.push(loop);\n        }\n        if (loops.length === 0)\n            return [];\n        loops.sort(function (p, r) { return Math.abs(areaOf(r)) - Math.abs(areaOf(p)); });\n        var ring = loops[0];\n        if (areaOf(ring) < 0)\n            ring = ring.slice().reverse(); // canonical CCW.\n        // Drop collinear joints, keeping only corners (tolerance scaled by size to\n        // ignore the tiny mismatch where two blocks' shared corner is computed\n        // independently, while a real turn — min 30° — is far larger).\n        var cornerTol = o.size * o.size * 1e-3;\n        var corners = [];\n        for (var i = 0; i < ring.length; i += 1) {\n            var prev = ring[(i - 1 + ring.length) % ring.length];\n            var cur = ring[i];\n            var nxt = ring[(i + 1) % ring.length];\n            var cross = (cur[0] - prev[0]) * (nxt[1] - cur[1])\n                - (cur[1] - prev[1]) * (nxt[0] - cur[0]);\n            if (Math.abs(cross) > cornerTol)\n                corners.push(cur);\n        }\n        return corners;\n    }\n    // The cluster outline as a ring of vertices in EDGE-LENGTH units.\n    // opts.normalize (default true): translate so the min corner is at [0, 0] —\n    // a tidy, placement-independent shape. opts.round (default 4): decimal places.\n    // Suitable for a patternBlocksSlot `points`; for the preferred edge-walk form\n    // (and a copy-paste-ready string) use getOutline().\n    function getPoints(opts) {\n        var corners = clusterRing();\n        if (corners.length === 0)\n            return [];\n        var normalize = opts == null || opts.normalize !== false;\n        var decimals = opts != null && opts.round != null ? opts.round : 4;\n        var minX = Infinity;\n        var minY = Infinity;\n        corners.forEach(function (c) {\n            if (c[0] < minX)\n                minX = c[0];\n            if (c[1] < minY)\n                minY = c[1];\n        });\n        var f = Math.pow(10, decimals);\n        return corners.map(function (c) {\n            var x = (normalize ? c[0] - minX : c[0]) / o.size;\n            var y = (normalize ? c[1] - minY : c[1]) / o.size;\n            return [Math.round(x * f) / f, Math.round(y * f) / f];\n        });\n    }\n    // The cluster outline as an edge-walk, returned as a copy-paste-ready TS\n    // string for a patternBlocksSlot, e.g.\n    //   outline: [[0, 2], [120, 1], [60, 1], [180, 2], [300, 1], [240, 1]]\n    // Each move is [heading°, lengthInEdges]; the walk starts at the lowest-then-\n    // leftmost corner and runs CCW. Because every block edge is a whole number of\n    // edges at a multiple of 30°, the headings/lengths are snapped to exact\n    // integers — so this cleans up any float noise from the captured positions\n    // rather than propagating it (unlike raw points). Returns '' if no outline.\n    function getOutline() {\n        var corners = clusterRing();\n        if (corners.length < 3)\n            return '';\n        // Start at the lowest, then leftmost corner for a stable, readable result.\n        var s = 0;\n        for (var i = 1; i < corners.length; i += 1) {\n            if (corners[i][1] < corners[s][1] - 1e-9\n                || (Math.abs(corners[i][1] - corners[s][1]) < 1e-9 && corners[i][0] < corners[s][0])) {\n                s = i;\n            }\n        }\n        var n = corners.length;\n        var moves = [];\n        for (var k = 0; k < n; k += 1) {\n            var a = corners[(s + k) % n];\n            var b = corners[(s + k + 1) % n];\n            var dx = b[0] - a[0];\n            var dy = b[1] - a[1];\n            var heading = ((Math.round((Math.atan2(dy, dx) * 180) / Math.PI / 30) * 30) % 360 + 360) % 360;\n            var len = Math.max(1, Math.round(Math.hypot(dx, dy) / o.size));\n            moves.push([heading, len]);\n        }\n        var body = moves.map(function (m) { return \"[\".concat(m[0], \", \").concat(m[1], \"]\"); }).join(', ');\n        return \"outline: [\".concat(body, \"]\");\n    }\n    // All outline rings of the arrangement reachable from this block — one per\n    // EDGE-connected region. Regions that touch only at a vertex (or sit a little\n    // apart, within a buffer) are still gathered, so a multi-region shape such as\n    // a bow tie is captured whole from any of its blocks. Returns CCW corner rings\n    // in WORLD (draw) units. (getOutlines formats these for a slot's `outlines:`.)\n    function clusterOutlineRings() {\n        var half = o.size / 2;\n        var q = o.size * 0.02; // tight: shared-edge endpoint matching / cancellation.\n        var vq = o.size * 0.2; // buffer: group vertex-touching / nearly-touching regions.\n        var kz = function (x, y) { return \"\".concat(Math.round(x / q), \",\").concat(Math.round(y / q)); };\n        var vk = function (x, y) { return \"\".concat(Math.round(x / vq), \",\").concat(Math.round(y / vq)); };\n        var segsOf = function (blk) {\n            return blk.custom.getWorldSegments().map(function (s) { return ({\n                ax: s.mx - s.dx * half, ay: s.my - s.dy * half,\n                bx: s.mx + s.dx * half, by: s.my + s.dy * half,\n            }); });\n        };\n        var blocks = getOtherBlocks().concat([element]);\n        var segs = blocks.map(segsOf);\n        var selfIndex = blocks.length - 1;\n        // Reachability via shared (buffered) vertices — gathers vertex-touching lobes.\n        var vOwners = {};\n        var blockVKeys = blocks.map(function (_, i) {\n            var seen = {};\n            segs[i].forEach(function (s) { seen[vk(s.ax, s.ay)] = true; seen[vk(s.bx, s.by)] = true; });\n            var keys = Object.keys(seen);\n            keys.forEach(function (k) { return (vOwners[k] = vOwners[k] || []).push(i); });\n            return keys;\n        });\n        var reachable = new Array(blocks.length).fill(false);\n        reachable[selfIndex] = true;\n        var rq = [selfIndex];\n        while (rq.length > 0) {\n            var bi = rq.shift();\n            blockVKeys[bi].forEach(function (k) {\n                (vOwners[k] || []).forEach(function (nb) { if (!reachable[nb]) {\n                    reachable[nb] = true;\n                    rq.push(nb);\n                } });\n            });\n        }\n        // Directed-segment owners (tight) over reachable blocks: edge adjacency +\n        // boundary cancellation.\n        var owners = {};\n        for (var i = 0; i < blocks.length; i += 1) {\n            if (!reachable[i])\n                continue;\n            for (var j = 0; j < segs[i].length; j += 1) {\n                var s = segs[i][j];\n                var dk = \"\".concat(kz(s.ax, s.ay), \">\").concat(kz(s.bx, s.by));\n                (owners[dk] = owners[dk] || []).push(i);\n            }\n        }\n        // Edge-connected components among the reachable blocks (each a simple region).\n        var comp = new Array(blocks.length).fill(-1);\n        var nc = 0;\n        var _loop_1 = function (i) {\n            if (!reachable[i] || comp[i] >= 0)\n                return \"continue\";\n            comp[i] = nc;\n            var cq = [i];\n            while (cq.length > 0) {\n                var bi = cq.shift();\n                for (var j = 0; j < segs[bi].length; j += 1) {\n                    var s = segs[bi][j];\n                    var nb = owners[\"\".concat(kz(s.bx, s.by), \">\").concat(kz(s.ax, s.ay))];\n                    if (nb == null)\n                        continue;\n                    nb.forEach(function (m) { if (reachable[m] && comp[m] < 0) {\n                        comp[m] = nc;\n                        cq.push(m);\n                    } });\n                }\n            }\n            nc += 1;\n        };\n        for (var i = 0; i < blocks.length; i += 1) {\n            _loop_1(i);\n        }\n        var areaOf = function (ring) {\n            var a = 0;\n            for (var i = 0; i < ring.length; i += 1) {\n                var p = ring[i];\n                var r = ring[(i + 1) % ring.length];\n                a += p[0] * r[1] - r[0] * p[1];\n            }\n            return a / 2;\n        };\n        var cornerTol = o.size * o.size * 1e-3;\n        var rings = [];\n        var _loop_2 = function (c) {\n            // Boundary of this component = its segments whose reverse isn't owned by a\n            // same-component block.\n            var next = {};\n            var startKeys = [];\n            for (var i = 0; i < blocks.length; i += 1) {\n                if (comp[i] !== c)\n                    continue;\n                for (var j = 0; j < segs[i].length; j += 1) {\n                    var s = segs[i][j];\n                    var rev = owners[\"\".concat(kz(s.bx, s.by), \">\").concat(kz(s.ax, s.ay))];\n                    if (rev != null && rev.some(function (idx) { return comp[idx] === c; }))\n                        continue;\n                    var sk = kz(s.ax, s.ay);\n                    next[sk] = { ax: s.ax, ay: s.ay, bx: s.bx, by: s.by };\n                    startKeys.push(sk);\n                }\n            }\n            // Chain into loops, keep the largest, canonicalise CCW, drop collinear joints.\n            var loops = [];\n            var visited = {};\n            for (var si = 0; si < startKeys.length; si += 1) {\n                var sk = startKeys[si];\n                if (visited[sk])\n                    continue;\n                var loop = [];\n                var guard = 0;\n                while (next[sk] != null && !visited[sk] && guard < 10000) {\n                    visited[sk] = true;\n                    var seg = next[sk];\n                    loop.push([seg.ax, seg.ay]);\n                    sk = kz(seg.bx, seg.by);\n                    guard += 1;\n                }\n                if (loop.length >= 3)\n                    loops.push(loop);\n            }\n            if (loops.length === 0)\n                return \"continue\";\n            loops.sort(function (p, r) { return Math.abs(areaOf(r)) - Math.abs(areaOf(p)); });\n            var ring = loops[0];\n            if (areaOf(ring) < 0)\n                ring = ring.slice().reverse();\n            var corners = [];\n            for (var i = 0; i < ring.length; i += 1) {\n                var prev = ring[(i - 1 + ring.length) % ring.length];\n                var cur = ring[i];\n                var nxt = ring[(i + 1) % ring.length];\n                var cross = (cur[0] - prev[0]) * (nxt[1] - cur[1])\n                    - (cur[1] - prev[1]) * (nxt[0] - cur[0]);\n                if (Math.abs(cross) > cornerTol)\n                    corners.push(cur);\n            }\n            if (corners.length >= 3)\n                rings.push(corners);\n        };\n        for (var c = 0; c < nc; c += 1) {\n            _loop_2(c);\n        }\n        return rings;\n    }\n    // The whole arrangement as a paste-ready `outlines:` block for a\n    // patternBlocksSlot — one ring per region (regions touching at a vertex are\n    // captured together), each an edge-walk with a lattice-snapped `start` so the\n    // rings keep their relative positions and touch points coincide exactly.\n    // Copied to the clipboard. A single region yields a plain `outline:` (delegates\n    // to getOutline). Returns '' if there's nothing to capture.\n    function getOutlines() {\n        var rings = clusterOutlineRings().filter(function (r) { return r.length >= 3; });\n        if (rings.length === 0)\n            return '';\n        if (rings.length === 1) {\n            var s = getOutline();\n            copyToClipboard(s);\n            return s;\n        }\n        // Weld the rings together: shift each ring (rigidly) so its vertex nearest to\n        // an already-placed ring coincides EXACTLY with that vertex. The rings were\n        // grouped because they touch/nearly-touch, so this locks their touch points\n        // together. It's geometry-agnostic — unlike a fixed-lattice snap it handles\n        // squares, tan rhombi, and mixed triangle orientations (a \"fish\") that don't\n        // share one triangular lattice.\n        var weldTol = o.size * 0.5;\n        var placed = rings[0].slice();\n        var welded = [rings[0]];\n        var _loop_3 = function (i) {\n            var bestD = Infinity;\n            var sx = 0;\n            var sy = 0;\n            rings[i].forEach(function (v) {\n                placed.forEach(function (w) {\n                    var d = Math.hypot(v[0] - w[0], v[1] - w[1]);\n                    if (d < bestD && d <= weldTol) {\n                        bestD = d;\n                        sx = w[0] - v[0];\n                        sy = w[1] - v[1];\n                    }\n                });\n            });\n            var shifted = rings[i].map(function (c) { return [c[0] + sx, c[1] + sy]; });\n            welded.push(shifted);\n            shifted.forEach(function (c) { return placed.push(c); });\n        };\n        for (var i = 1; i < rings.length; i += 1) {\n            _loop_3(i);\n        }\n        // Normalise the whole welded shape (min corner -> origin) into edge units.\n        var minX = Infinity;\n        var minY = Infinity;\n        welded.forEach(function (r) { return r.forEach(function (c) {\n            if (c[0] < minX)\n                minX = c[0];\n            if (c[1] < minY)\n                minY = c[1];\n        }); });\n        var round4 = function (n) { return Math.round(n * 1e4) / 1e4; };\n        var lines = [];\n        welded.forEach(function (corners) {\n            var s = 0;\n            for (var i = 1; i < corners.length; i += 1) {\n                if (corners[i][1] < corners[s][1] - 1e-9\n                    || (Math.abs(corners[i][1] - corners[s][1]) < 1e-9 && corners[i][0] < corners[s][0])) {\n                    s = i;\n                }\n            }\n            var n = corners.length;\n            var moves = [];\n            for (var k = 0; k < n; k += 1) {\n                var a = corners[(s + k) % n];\n                var b = corners[(s + k + 1) % n];\n                var dx = b[0] - a[0];\n                var dy = b[1] - a[1];\n                var heading = ((Math.round((Math.atan2(dy, dx) * 180) / Math.PI / 30) * 30) % 360 + 360) % 360;\n                var len = Math.max(1, Math.round(Math.hypot(dx, dy) / o.size));\n                moves.push([heading, len]);\n            }\n            var startX = round4((corners[s][0] - minX) / o.size);\n            var startY = round4((corners[s][1] - minY) / o.size);\n            var body = moves.map(function (m) { return \"[\".concat(m[0], \", \").concat(m[1], \"]\"); }).join(', ');\n            // Block-style YAML (outline/start on their own lines, no flow braces).\n            lines.push(\"  - outline: [\".concat(body, \"]\\n    start: [\").concat(startX, \", \").concat(startY, \"]\"));\n        });\n        var out = \"outlines:\\n\".concat(lines.join('\\n'));\n        copyToClipboard(out);\n        return out;\n    }\n    // Brief \"you're in the way\" feedback: a scale bump plus a red colour flash\n    // that settles back to the block's own fill/border colours. Defined per block\n    // so an offending neighbour flashes itself (it owns its colours).\n    element.custom.flashBlocked = function () {\n        element.animations.new().pulse({ duration: 0.45, scale: 1.12 }).start();\n        var fillEl = container.getElement('fill');\n        var borderEl = container.getElement('border');\n        if (fillEl != null) {\n            fillEl.animations.new()\n                .color({ target: [0.95, 0.25, 0.25, 1], duration: 0.12 })\n                .color({ target: fillColor, duration: 0.45 })\n                .start();\n        }\n        if (borderEl != null) {\n            borderEl.animations.new()\n                .color({ target: [0.8, 0, 0, 1], duration: 0.12 })\n                .color({ target: borderColor, duration: 0.45 })\n                .start();\n        }\n    };\n    function pulseBlockers(blockers) {\n        blockers.forEach(function (b) {\n            if (b.custom != null && typeof b.custom.flashBlocked === 'function') {\n                b.custom.flashBlocked();\n            }\n        });\n    }\n    // Animate the block's move anchor back to (px, py) — used when a drop has no\n    // valid resting place (it would overlap), so the block returns to where it\n    // was picked up. State/answer update once the slide finishes.\n    function animateRevertTo(px, py) {\n        element.stopAnimating();\n        fig.elements.animations.new()\n            .position({ element: element, target: [px, py], duration: 0.25 })\n            .trigger(function () {\n            element.custom.state = element.custom.getState();\n            element.setMoveBounds();\n            fig.answerChanged();\n        })\n            .start();\n    }\n    // Tap-to-rotate. `rotTarget` is the logical committed angle (where the block\n    // *should* be), independent of the in-flight animation's interpolated value;\n    // `rotAnimating` says whether a turn is mid-flight. Together they let rapid\n    // taps queue cleanly: a new tap first settles the current turn instantly, then\n    // animates the next step from there — so two quick taps land a clean 60°, not\n    // some half-interpolated angle. The animation lives on `container.animations`\n    // so `container.stopAnimating()` actually cancels it.\n    var rotTarget = getRotation();\n    var rotAnimating = false;\n    // When a turn settles into a neighbour mate, the block slides to this target;\n    // tracked so an interrupting tap can finish the slide instantly.\n    var pendingMate = null;\n    function commitRotation() {\n        element.custom.state = element.custom.getState();\n        element.setMoveBounds();\n        fig.answerChanged();\n    }\n    // Finish any in-flight turn (or mate-slide) immediately, snapping to its target.\n    function settleRotation() {\n        if (!rotAnimating)\n            return;\n        container.stopAnimating();\n        element.stopAnimating();\n        if (pendingMate != null) {\n            container.setRotation(pendingMate.theta);\n            element.setPosition(pendingMate.cx, pendingMate.cy - o.yOffset);\n            rotTarget = pendingMate.theta;\n            pendingMate = null;\n        }\n        else {\n            container.setRotation(rotTarget);\n        }\n        rotAnimating = false;\n        commitRotation();\n    }\n    // After a turn settles, if the new orientation lines the block up with a\n    // neighbour edge (within tolerance), slide the rest of the way into the mate.\n    // A tiny anti-parallel angle correction (<= angTol) is applied instantly; the\n    // translation animates so it reads as \"clicking\" into place.\n    function snapSlideAfterRotate() {\n        var m = bestMate();\n        if (m == null) {\n            commitRotation();\n            return;\n        }\n        container.setRotation(m.theta);\n        rotTarget = m.theta;\n        pendingMate = m;\n        rotAnimating = true;\n        element.stopAnimating();\n        element.animations.new()\n            .position({ target: [m.cx, m.cy - o.yOffset], duration: 0.16, element: element })\n            .trigger(function () {\n            rotAnimating = false;\n            pendingMate = null;\n            commitRotation();\n        })\n            .start();\n    }\n    function rotateTap() {\n        settleRotation(); // complete a prior turn first so taps queue cleanly.\n        var start = rotTarget;\n        var target = start + rotateStep;\n        var c = centroidWorld();\n        var poly = worldVertsAt(c.x, c.y, target);\n        var blockers = getOtherBlocks().filter(function (b) {\n            return convexOverlap(poly, b.custom.getWorldVertices(), eps);\n        });\n        if (blockers.length > 0) {\n            // Blocked: bounce. Lean toward the next position, flash what's in the way\n            // at the apex, then return. rotTarget/state stay put — no net change.\n            rotAnimating = true;\n            container.animations.new()\n                .rotation({ target: target, duration: 0.13, element: container })\n                .trigger(function () { return pulseBlockers(blockers); })\n                .rotation({ target: start, duration: 0.19, element: container })\n                .trigger(function () { rotAnimating = false; })\n                .start();\n            return;\n        }\n        // Clear: rotate in place to the next position, then snap into a mate if the\n        // new orientation lines up with a neighbour (only on natural completion — a\n        // cancelled turn from rapid tapping never reaches this).\n        rotTarget = target;\n        element.custom.moved = true;\n        rotAnimating = true;\n        container.animations.new()\n            .rotation({ target: target, duration: 0.22, element: container })\n            .trigger(function () {\n            rotAnimating = false;\n            snapSlideAfterRotate();\n        })\n            .start();\n    }\n    // --- STATE & MANIPULATIVE PLUMBING --------------------------------------\n    element.notificationHelper = new NotificationHelper();\n    setupManipulative(element, null, o);\n    element.custom.patternYOffset = o.yOffset;\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    element.custom.getState = function () {\n        var p = element.getPosition();\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        return {\n            e: e_name,\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n            r: Fig.round(getRotation(), 5),\n            shape: shape,\n        };\n    };\n    element.custom.setState = function (stats) {\n        element.setPosition(Fig.parsePoint(stats.p));\n        if (stats.r != null)\n            container.setRotation(stats.r);\n        element.custom.moved = true;\n    };\n    element.custom.state = element.custom.getState();\n    // Exposed for animation / guides / tests.\n    element.custom.rotateByStep = rotateByStep;\n    element.custom.rotateTap = rotateTap;\n    element.custom.snapToNeighbors = snapToNeighbors;\n    element.custom.overlappingNeighbors = overlappingNeighbors;\n    element.custom.getPoints = getPoints;\n    element.custom.getOutline = getOutline;\n    element.custom.getOutlines = getOutlines;\n    // --- POSE / GEOMETRY API (used by patternBlocksSlot's show-answer solver) ---\n    // The block's shape, edge length, and triangle count let the solver reason\n    // about it without re-deriving geometry; worldVertsAt / centroidWorld / getRotation\n    // let it predict a candidate placement's polygon before committing.\n    element.custom.shape = shape;\n    element.custom.size = o.size;\n    element.custom.triCount = TRI_COUNT[shape] != null ? TRI_COUNT[shape] : null;\n    // 0 = no rotational symmetry (trapezoid): honour the placement's orientation.\n    element.custom.symmetryAngle = SYMMETRY_ANGLE[shape] != null ? SYMMETRY_ANGLE[shape] : 0;\n    element.custom.worldVertsAt = function (cx, cy, a) {\n        return worldVertsAt(cx, cy, a);\n    };\n    element.custom.centroidWorld = centroidWorld;\n    element.custom.getRotation = getRotation;\n    // Move/rotate the block so its centroid sits at (cx, cy) at orientation\n    // `theta` (radians). `theta` is normalised to the short way round from the\n    // current angle so an animated turn never spins the long way. With\n    // opts.animate the position and rotation tween (opts.duration / opts.delay);\n    // otherwise it snaps. State and move bounds update on settle.\n    element.custom.placeAt = function (cx, cy, theta, opts) {\n        if (opts === void 0) { opts = {}; }\n        var duration = opts.duration != null ? opts.duration : 0.4;\n        var delay = opts.delay != null ? opts.delay : 0;\n        var px = cx;\n        var py = cy - o.yOffset; // position is the move anchor; container holds yOffset.\n        var tgt = theta;\n        var cur = getRotation();\n        while (tgt - cur > Math.PI)\n            tgt -= Math.PI * 2;\n        while (tgt - cur < -Math.PI)\n            tgt += Math.PI * 2;\n        element.custom.moved = true;\n        if (opts.animate !== true) {\n            container.setRotation(tgt);\n            element.setPosition(px, py);\n            element.custom.state = element.custom.getState();\n            element.setMoveBounds();\n            return;\n        }\n        element.stopAnimating();\n        container.stopAnimating();\n        // Host the reveal tweens on the figure-root animation manager rather than on\n        // element/container. During show-answer the demonstrate guide's speech\n        // playback calls speechManager.stopFigure() -> _expression.stop('complete'),\n        // which force-completes every animation owned by _expression and its\n        // descendants. Pattern blocks live *inside* the expression equation, so an\n        // element/container-hosted reveal tween would be snapped straight to its end\n        // pose (no visible slide). Root-hosted tweens still move these child elements\n        // but aren't owned by _expression, so the reveal survives the speech\n        // teardown. (Mirrors animateRevertTo above; figure-level stops on teardown /\n        // question transitions still cancel them, so nothing leaks.)\n        fig.elements.animations.new()\n            .delay(delay)\n            .rotation({ target: tgt, duration: duration, element: container })\n            .start();\n        // Name the completion trigger via fnMap (owner = fig.elements, the root\n        // manager this reveal is hosted on) so the state-commit + setMoveBounds survive\n        // a speech pause/resume during show-answer: an inline .trigger is dropped from\n        // figure.getState(), so a pause mid-reveal would leave element.custom.state\n        // stale (the layoutForms restore reads it). Keyed per block — show-answer\n        // reveals many blocks concurrently.\n        var placeKey = \"pbPlaceAt:\".concat(element.name);\n        fig.elements.fnMap.add(placeKey, function () {\n            element.custom.state = element.custom.getState();\n            element.setMoveBounds();\n        });\n        fig.elements.animations.new()\n            .delay(delay)\n            .position({ target: [px, py], duration: duration, element: element })\n            .trigger({ callback: placeKey })\n            .start();\n    };\n    // Send the block back to where it was laid out (its authored home pose). Used\n    // by show-answer for blocks the solution doesn't need.\n    element.custom.returnHome = function (animate) {\n        var home = element.custom.initialPosition;\n        if (home == null)\n            return;\n        element.custom.placeAt(home.x, home.y + o.yOffset, initialRotation, { animate: animate });\n    };\n    // On relayout (e.g. font loading) the equation repositions children; restore\n    // the learner's position/rotation if they've moved the block.\n    element.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (element.custom.moved) {\n            element.setPosition(Fig.parsePoint(element.custom.state.p));\n            container.setRotation(element.custom.state.r);\n        }\n        element.setMoveBounds();\n    });\n    element.notificationHelper.add(fig, 'ready', function () {\n        element.custom.initialPosition = element.getPosition();\n        element.setMoveBounds();\n    });\n    // --- INTERACTION --------------------------------------------------------\n    // Drag to move, tap to rotate. We tell the two apart by how far the anchor\n    // travelled between grab and release: a tap barely moves, a drag does.\n    //\n    // Invariant: a block never comes to rest overlapping another. A drag either\n    // snaps to a free edge, lands in clear space, or — if it would overlap —\n    // slides back to where it was picked up while the blocking block(s) flash. A\n    // tap rotates in place (animated) only if the turn stays clear, else it flashes\n    // what's in the way. So every gesture ends valid; nothing is ever left covering.\n    //\n    // Event wiring (see FigureOne selectElement/touchUpHandler): on touch-DOWN\n    // FigureOne fires `onClick` and starts moving the *container* (the element\n    // with setMove), NOT `element`. So we must call `element.startBeingMoved()`\n    // ourselves here — exactly like poly — otherwise `element.state.isBeingMoved`\n    // stays false and `stopBeingMoved` never fires on `element`, making tap\n    // detection unreliable. We record the press position (and resync the rotation\n    // target) here, the only event guaranteed to fire on touch-down.\n    var pressPos = null;\n    var TAP_DIST = 0.03; // draw units; below this a press counts as a tap.\n    element.notificationHelper.add(element, 'moved', function () {\n        element.custom.moved = true;\n    });\n    element.notificationHelper.add(element._container, 'onClick', function () {\n        var p = element.getPosition();\n        pressPos = { x: p.x, y: p.y };\n        // Only resync the logical rotation target when at rest — mid-animation the\n        // live angle is interpolating and would corrupt the next step.\n        if (!rotAnimating)\n            rotTarget = getRotation();\n        element.startBeingMoved();\n        element.parent.toFront(element);\n        window.clickHandled = true;\n    });\n    element.notificationHelper.add(element, 'stopBeingMoved', function () {\n        settleRotation(); // finish any in-flight turn before handling this gesture.\n        var p = element.getPosition();\n        var travelled = pressPos != null\n            ? Math.hypot(p.x - pressPos.x, p.y - pressPos.y)\n            : Infinity;\n        if (travelled < TAP_DIST) {\n            // Tap: rotate in place. Undo any micro-drift from the press first so the\n            // block truly turns about its centre. rotateTap handles its own state /\n            // answerChanged (on the animation's finish) or flashes the blockers.\n            if (pressPos != null)\n                element.setPosition(pressPos.x, pressPos.y);\n            rotateTap();\n            return;\n        }\n        // Drag: snap to a free edge; otherwise if the drop overlaps, revert + flash.\n        element.custom.moved = true;\n        var snapped = snapToNeighbors();\n        if (!snapped) {\n            var blockers = overlappingNeighbors();\n            if (blockers.length > 0) {\n                pulseBlockers(blockers);\n                if (pressPos != null)\n                    animateRevertTo(pressPos.x, pressPos.y);\n                return; // animateRevertTo updates state/answer when the slide finishes.\n            }\n        }\n        element.custom.state = element.custom.getState();\n        fig.answerChanged();\n    });\n    // Freeze the block once the answer is revealed (answerInput.ts \"show answer\").\n    element.disable = function () {\n        element.hasTouchableElements = false;\n    };\n    // Register for answer processing. MUST be snake_case and match the YAML.\n    element.custom.manipulativeType = 'pattern_block';\n    element._container.custom.secondaryTouchBounds = 0.05;\n    if (o.isTouchable === false) {\n        element.hasTouchableElements = false;\n    }\n    else {\n        container.setMove({ freely: false, element: element });\n        element.move.freely = false;\n    }\n    return element;\n};\nexport { patternBlocks, };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\n// --- TRIANGULAR-LATTICE CONSTANTS (used by the show-answer solver) ---------\n// Every 60°-family block decomposes into unit equilateral triangles on a single\n// triangular lattice with axes e1 = (1,0), e2 = (1/2, √3/2). SHAPE_OFFSETS lists,\n// per shape, the centroids of those unit triangles in EDGE units relative to the\n// block's rotation pivot (its vertex-average) at rotation 0 — derived once from\n// the block geometry. Rotated by a multiple of 60° and translated, these land\n// exactly on lattice cell centroids, which is how the solver predicts (and the\n// blocks then realise) a placement. The square and tan rhombus aren't on this\n// lattice, so they have no entry and the solver never places them.\nvar SQRT3_2 = Math.sqrt(3) / 2;\nvar S6 = Math.sqrt(3) / 6; //  √3/6  ≈ 0.2887  (up/down centroid height)\nvar S3 = Math.sqrt(3) / 3; //  √3/3  ≈ 0.5774\nvar S12 = Math.sqrt(3) / 12; // √3/12 ≈ 0.1443\nvar SHAPE_OFFSETS = {\n    triangle: [[0, 0]],\n    hexagon: [[0.5, -S6], [0.5, S6], [0, S3], [-0.5, S6], [-0.5, -S6], [0, -S3]],\n    blueRhombus: [[-0.25, -S12], [0.25, S12]],\n    trapezoid: [[-0.5, -S12], [0, S12], [0.5, -S12]],\n};\nvar TRI_COUNT = {\n    triangle: 1, blueRhombus: 2, trapezoid: 3, hexagon: 6,\n};\n// Largest first: the solver prefers to fill each cell with the biggest block\n// that fits (a hexagon before six triangles), per the authoring intent.\nvar SHAPE_ORDER = ['hexagon', 'trapezoid', 'blueRhombus', 'triangle'];\nfunction rotPt(x, y, a) {\n    var c = Math.cos(a);\n    var s = Math.sin(a);\n    return { x: x * c - y * s, y: x * s + y * c };\n}\n// Wrap an angle to (-π, π] so a rotation cost is the short way round.\nfunction angDelta(a) {\n    var x = a;\n    while (x > Math.PI)\n        x -= Math.PI * 2;\n    while (x <= -Math.PI)\n        x += Math.PI * 2;\n    return x;\n}\n// Smallest angular distance between orientations `a` apart, modulo a shape's\n// rotational symmetry (`sym` <= 0 means no symmetry -> full circle). Used to rank\n// solver orientations by how close they are to a block's current pose.\nfunction symDist(a, sym) {\n    var m = sym > 0 ? sym : Math.PI * 2;\n    var x = a % m;\n    while (x > m / 2)\n        x -= m;\n    while (x <= -m / 2)\n        x += m;\n    return Math.abs(x);\n}\n// Current rotations of `list`, grouped by shape — the \"preferred\" orientations\n// the solver should try first so its tiling matches how the blocks are already\n// turned (see solveCells). Keeps asymmetric pieces (trapezoid) from being tiled\n// in a valid-but-rotated way the learner never made.\nfunction prefThetasByShape(list) {\n    var out = {};\n    list.forEach(function (b) {\n        var sh = b.custom.shape;\n        (out[sh] = out[sh] || []).push(b.custom.getRotation());\n    });\n    return out;\n}\n// The show-answer solver is rotation-blind: it tiles the slot at whatever 60°\n// orientation fits first, ignoring how the blocks are currently turned (and\n// `rotateStep`). Two helpers keep the reveal from spinning blocks needlessly.\n//\n// orientNearCurrent: rotate the solved `theta` into the member of the block's\n// rotational-symmetry class nearest its CURRENT orientation. The block polygon is\n// identical under its symmetry, so the tiling is preserved while a block that is\n// already correctly oriented is placed with zero rotation. A shape with no\n// symmetry (trapezoid, symmetryAngle 0) keeps `theta` exactly.\nfunction orientNearCurrent(b, theta) {\n    var sym = b.custom.symmetryAngle;\n    if (!sym)\n        return theta;\n    var cur = b.custom.getRotation();\n    return theta - Math.round((theta - cur) / sym) * sym;\n}\n// takeBestForTheta: remove and return the block from `list` that needs the least\n// rotation to reach `theta` (so the two triangles of a rhombus, etc., can't be\n// assigned into each other's cells and forced to spin). Mutates `list`.\nfunction takeBestForTheta(list, theta) {\n    if (list == null || list.length === 0)\n        return null;\n    var bestIdx = 0;\n    var bestCost = Infinity;\n    for (var k = 0; k < list.length; k += 1) {\n        var cost = Math.abs(angDelta(orientNearCurrent(list[k], theta) - list[k].custom.getRotation()));\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestIdx = k;\n        }\n    }\n    return list.splice(bestIdx, 1)[0];\n}\n// Author-facing warning (bad outline etc.) — visible in the browser console but\n// never throws, so a mistake is surfaced without breaking the page.\nfunction warn(msg) {\n    // eslint-disable-next-line no-console\n    if (typeof console !== 'undefined' && console.warn)\n        console.warn(msg);\n}\n// Best-effort copy of `text` to the clipboard (so getSolution() output pastes\n// with real newlines). Uses the async Clipboard API where available, falling\n// back to a hidden-textarea execCommand for contexts where it's blocked. Never\n// throws — copying is a convenience, not load-bearing.\nfunction copyToClipboard(text) {\n    var fallback = function () {\n        try {\n            var ta = document.createElement('textarea');\n            ta.value = text;\n            ta.style.position = 'fixed';\n            ta.style.left = '-9999px';\n            document.body.appendChild(ta);\n            ta.select();\n            document.execCommand('copy');\n            document.body.removeChild(ta);\n        }\n        catch ( /* clipboard unavailable — ignore */_a) { /* clipboard unavailable — ignore */ }\n    };\n    try {\n        if (typeof navigator !== 'undefined' && navigator.clipboard\n            && navigator.clipboard.writeText) {\n            navigator.clipboard.writeText(text).catch(fallback);\n            return;\n        }\n    }\n    catch ( /* fall through to execCommand */_a) { /* fall through to execCommand */ }\n    fallback();\n}\n// Signed area (shoelace) — positive when the ring is CCW.\nfunction signedArea(pts) {\n    var a = 0;\n    var get = function (p) {\n        return Array.isArray(p) ? [p[0], p[1]] : [p.x, p.y];\n    };\n    for (var i = 0; i < pts.length; i += 1) {\n        var _a = get(pts[i]), x0 = _a[0], y0 = _a[1];\n        var _b = get(pts[(i + 1) % pts.length]), x1 = _b[0], y1 = _b[1];\n        a += x0 * y1 - x1 * y0;\n    }\n    return a / 2;\n}\n// Build the closed outline (vertices in edge-length units) from the options.\n// Preferred: an edge-walk — a list of [heading°, length] moves traced from\n// `start` on a 30° compass. We validate the pattern-block invariants (headings\n// multiple of 30°, integer lengths, the walk closes) and warn (without\n// throwing) so authoring mistakes are visible but never break the page.\n// Falls back to raw `points`, then a default unit hexagon.\nfunction resolveOutline(o) {\n    if (Array.isArray(o.outline) && o.outline.length >= 3) {\n        var start = Array.isArray(o.start) ? o.start : [0, 0];\n        var verts = [[start[0], start[1]]];\n        var x = start[0];\n        var y = start[1];\n        for (var i = 0; i < o.outline.length; i += 1) {\n            var heading = o.outline[i][0];\n            var len = o.outline[i][1];\n            var onGrid = (((heading % 30) + 30) % 30);\n            if (onGrid > 1e-6 && onGrid < 30 - 1e-6) {\n                warn(\"[pattern_block_slot \".concat(o.name, \"] outline move \").concat(i, \": heading \").concat(heading, \"\\u00B0 \")\n                    + 'is not a multiple of 30° — blocks may not snap to this edge.');\n            }\n            if (Math.abs(len - Math.round(len)) > 1e-6) {\n                warn(\"[pattern_block_slot \".concat(o.name, \"] outline move \").concat(i, \": length \").concat(len, \" \")\n                    + 'is not an integer number of edges.');\n            }\n            var a = (heading * Math.PI) / 180;\n            x += len * Math.cos(a);\n            y += len * Math.sin(a);\n            verts.push([x, y]);\n        }\n        var last = verts[verts.length - 1];\n        var closeErr = Math.hypot(last[0] - start[0], last[1] - start[1]);\n        if (closeErr > 1e-4) {\n            warn(\"[pattern_block_slot \".concat(o.name, \"] outline walk does not close \")\n                + \"(off by \".concat(closeErr.toFixed(3), \" edges) \\u2014 check the headings/lengths.\"));\n        }\n        else {\n            verts.pop(); // drop the closure point (it duplicates the start).\n        }\n        return verts;\n    }\n    if (Array.isArray(o.points) && o.points.length >= 3) {\n        return o.points.map(function (p) { return [p[0], p[1]]; });\n    }\n    // Default: a unit hexagon (edge length 1).\n    return [\n        [0.5, -0.8660254], [1, 0], [0.5, 0.8660254],\n        [-0.5, 0.8660254], [-1, 0], [-0.5, -0.8660254],\n    ];\n}\n// Resolve the option(s) into a LIST of rings (each a vertex list in edge units).\n// `outlines` (a list of ring specs) gives a multi-region slot; otherwise a\n// single ring from `outline`/`points`. Each ring spec reuses resolveOutline, so\n// it may be an `{outline, start}` edge-walk, a `{points}` list, or a bare\n// edge-walk array.\nfunction resolveOutlines(o) {\n    if (Array.isArray(o.outlines) && o.outlines.length > 0) {\n        return o.outlines.map(function (spec, i) {\n            var ringSpec = Array.isArray(spec) ? { outline: spec } : spec;\n            return resolveOutline({\n                outline: ringSpec.outline,\n                start: ringSpec.start,\n                points: ringSpec.points,\n                name: \"\".concat(o.name, \"[\").concat(i, \"]\"),\n            });\n        });\n    }\n    return [resolveOutline(o)];\n}\n// Ray-casting point-in-polygon for a closed ring of {x, y} points.\nfunction pointInPolygon(pt, poly) {\n    var inside = false;\n    var j = poly.length - 1;\n    for (var i = 0; i < poly.length; i += 1) {\n        var xi = poly[i].x;\n        var yi = poly[i].y;\n        var xj = poly[j].x;\n        var yj = poly[j].y;\n        if ((yi > pt.y) !== (yj > pt.y) &&\n            pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi) + xi) {\n            inside = !inside;\n        }\n        j = i;\n    }\n    return inside;\n}\nvar patternBlocksSlot = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        size: 0.35,\n        color: [0.45, 0.45, 0.45, 1],\n        lineWidth: 0.012,\n        yOffset: 0,\n        correctColor: colors.COLOR_GROKKOLI_GREEN,\n        incorrectColor: colors.COLOR_GROKKOLI_ORANGE,\n        correctness: true,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        debug: false,\n    }, options);\n    // Resolve to one or more rings (each a simple closed polygon). Multiple rings\n    // (`outlines`) make a multi-region slot — e.g. a bow tie of two triangles that\n    // touch at a point — where each ring stays simple, so area, containment, and\n    // the solver are robust (no self-touching geometry to confuse ray-casting).\n    var rawRings = resolveOutlines(o);\n    // Canonicalise each ring to CCW (interior on the left — needed for the\n    // snap-segment reversal and containment) and scale into draw units.\n    var localRings = rawRings.map(function (raw) {\n        var ccw = signedArea(raw) >= 0 ? raw : raw.slice().reverse();\n        return ccw.map(function (p) { return [p[0] * o.size, p[1] * o.size]; });\n    });\n    // Anchor in the local frame per xAlign/yAlign (default left/bottom => the whole\n    // shape's left-most point at x=0, bottom-most at y=0). The shift is computed\n    // over the UNION of all rings and applied to every ring, so the rings keep\n    // their relative positions (a shared touch point is preserved) and the drawn\n    // outline + every geometry consumer (snap segments, containment, the lattice\n    // solver, solution `at` coords) share one consistent frame.\n    if (!(o.xAlign === 'absolute' && o.yAlign === 'absolute')) {\n        var minX_1 = Infinity;\n        var maxX_1 = -Infinity;\n        var minY_1 = Infinity;\n        var maxY_1 = -Infinity;\n        localRings.forEach(function (ring) { return ring.forEach(function (p) {\n            if (p[0] < minX_1)\n                minX_1 = p[0];\n            if (p[0] > maxX_1)\n                maxX_1 = p[0];\n            if (p[1] < minY_1)\n                minY_1 = p[1];\n            if (p[1] > maxY_1)\n                maxY_1 = p[1];\n        }); });\n        var dx_1 = 0;\n        if (o.xAlign === 'left')\n            dx_1 = -minX_1;\n        else if (o.xAlign === 'center')\n            dx_1 = -(minX_1 + maxX_1) / 2;\n        else if (o.xAlign === 'right')\n            dx_1 = -maxX_1;\n        var dy_1 = 0;\n        if (o.yAlign === 'bottom')\n            dy_1 = -minY_1;\n        else if (o.yAlign === 'middle')\n            dy_1 = -(minY_1 + maxY_1) / 2;\n        else if (o.yAlign === 'top')\n            dy_1 = -maxY_1;\n        localRings.forEach(function (ring) { return ring.forEach(function (p) { p[0] += dx_1; p[1] += dy_1; }); });\n    }\n    // Areas/gaps are measured against the unit triangle (the smallest block).\n    var unitTriArea = (o.size * o.size * Math.sqrt(3)) / 4;\n    var areaTol = unitTriArea * 0.5; // tolerate < half a small triangle of slop.\n    var nudge = o.size * 0.1; // inward nudge for the on-boundary containment test.\n    // --- STRUCTURE ----------------------------------------------------------\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = element.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    // --- VISUALS ------------------------------------------------------------\n    // Closed outline. Pass copies of the points — FigureOne parses a `points`\n    // array in place (replacing [x, y] with Point objects).\n    var copy = function (p) { return [p[0], p[1]]; };\n    // One closed polyline per ring. `borders` is recoloured together on feedback.\n    var borders = localRings.map(function (ring, idx) {\n        var borderOptions = {\n            name: \"border\".concat(idx),\n            make: 'polyline',\n            points: ring.map(copy),\n            close: true,\n            width: o.lineWidth,\n            color: o.color,\n        };\n        if (o.dash != null && o.dash.length > 0) {\n            borderOptions.dash = o.dash;\n        }\n        var b = container.add(borderOptions);\n        b.custom.initialColor = o.color.slice();\n        return b;\n    });\n    if (o.debug) {\n        localRings.forEach(function (ring, idx) {\n            container.add({\n                name: \"debugDot\".concat(idx),\n                make: 'polygon',\n                radius: o.size * 0.08,\n                sides: 12,\n                color: [1, 0, 0, 0.5],\n                position: copy(ring[0]),\n            });\n        });\n    }\n    // --- GEOMETRY (shared parent frame, matching the blocks) ----------------\n    // The slot never rotates, so a world vertex is just position + local offset.\n    // Each ring is reported separately; getWorldVertices returns the first ring for\n    // back-compat (single-ring slots).\n    function getWorldRings() {\n        var p = element.getPosition();\n        return localRings.map(function (ring) {\n            return ring.map(function (v) { return ({ x: p.x + v[0], y: p.y + o.yOffset + v[1] }); });\n        });\n    }\n    element.custom.getWorldRings = getWorldRings;\n    function getWorldVertices() {\n        var rings = getWorldRings();\n        return rings.length > 0 ? rings[0] : [];\n    }\n    element.custom.getWorldVertices = getWorldVertices;\n    // Boundary as unit segments (across ALL rings), each with its direction\n    // REVERSED from the CCW traversal (see file header) so a block's anti-parallel\n    // matcher snaps it INSIDE the slot. Same shape as a block's getWorldSegments.\n    element.custom.getWorldSegments = function () {\n        var out = [];\n        getWorldRings().forEach(function (vs) {\n            for (var i = 0; i < vs.length; i += 1) {\n                var a = vs[i];\n                var b = vs[(i + 1) % vs.length];\n                var len = Math.hypot(b.x - a.x, b.y - a.y);\n                var n = Math.max(1, Math.round(len / o.size));\n                for (var k = 0; k < n; k += 1) {\n                    var t0 = k / n;\n                    var t1 = (k + 1) / n;\n                    var p0 = { x: a.x + (b.x - a.x) * t0, y: a.y + (b.y - a.y) * t0 };\n                    var p1 = { x: a.x + (b.x - a.x) * t1, y: a.y + (b.y - a.y) * t1 };\n                    var sx = p1.x - p0.x;\n                    var sy = p1.y - p0.y;\n                    var m = Math.hypot(sx, sy) || 1;\n                    out.push({\n                        mx: (p0.x + p1.x) / 2,\n                        my: (p0.y + p1.y) / 2,\n                        dx: -sx / m, // reversed -> blocks snap to the interior side.\n                        dy: -sy / m,\n                    });\n                }\n            }\n        });\n        return out;\n    };\n    // Marker so a pattern block can pick the slot out as a snap source.\n    element.custom.isPatternSlot = true;\n    // Sibling pattern blocks (the things that fill the slot).\n    function getBlocks() {\n        var out = [];\n        var parent = element.parent;\n        if (parent == null || parent.elements == null)\n            return out;\n        Object.keys(parent.elements).forEach(function (k) {\n            var el = parent.elements[k];\n            if (el === element)\n                return;\n            if (el.custom != null && el.custom.manipulativeType === 'pattern_block') {\n                out.push(el);\n            }\n        });\n        return out;\n    }\n    // Is a (convex) block fully inside the slot? Test each block vertex nudged a\n    // little toward the block centroid: a contained block (even one resting with\n    // an edge exactly on the boundary) has every nudged point strictly inside; a\n    // block poking out has its outside vertex still outside after the nudge. With\n    // multiple rings the block must sit fully within ONE ring (it can't straddle\n    // two regions) — which also sidesteps the pinch ambiguity of a self-touching\n    // outline, since each ring is simple.\n    function blockInside(bverts) {\n        var cx = 0;\n        var cy = 0;\n        for (var i = 0; i < bverts.length; i += 1) {\n            cx += bverts[i].x;\n            cy += bverts[i].y;\n        }\n        cx /= bverts.length;\n        cy /= bverts.length;\n        var test = bverts.map(function (v) {\n            var dx = cx - v.x;\n            var dy = cy - v.y;\n            var d = Math.hypot(dx, dy) || 1;\n            return { x: v.x + (dx / d) * nudge, y: v.y + (dy / d) * nudge };\n        });\n        return getWorldRings().some(function (ring) { return test.every(function (t) { return pointInPolygon(t, ring); }); });\n    }\n    // The fill verdict: sum the areas of fully-contained blocks and compare to\n    // the slot area. Blocks can't overlap, so equal areas => exact tiling.\n    function computeFill() {\n        var area = getWorldRings()\n            .reduce(function (s, ring) { return s + Math.abs(signedArea(ring)); }, 0);\n        var covered = 0;\n        var contained = [];\n        var blocks = getBlocks();\n        for (var i = 0; i < blocks.length; i += 1) {\n            var bverts = blocks[i].custom.getWorldVertices();\n            if (bverts == null || bverts.length < 3)\n                continue;\n            if (blockInside(bverts)) {\n                covered += Math.abs(signedArea(bverts));\n                contained.push(blocks[i].name);\n            }\n        }\n        var filled = Math.abs(covered - area) < areaTol;\n        return { filled: filled, area: area, covered: covered, contained: contained };\n    }\n    element.custom.computeFill = computeFill;\n    // --- SHOW ANSWER: triangular-lattice tiling solver ----------------------\n    // Reveal a complete tiling. The strategy (chosen with the author):\n    //   1. Keep every block the learner has already placed validly inside, locking\n    //      the unit cells it covers (biased first-fit — disturb nothing that's\n    //      already right).\n    //   2. Tile the remaining cells with the still-unplaced blocks by exact cover,\n    //      trying the largest block that fits at each step (hexagon → trapezoid →\n    //      blue rhombus → triangle) but backtracking so it always completes when a\n    //      tiling exists.\n    //   3. If the locked placement leaves the rest unsolvable, fall back to solving\n    //      the whole slot from scratch (every block free to move). Off-lattice\n    //      slots (squares / tan rhombi) can't be auto-tiled — that's where an\n    //      authored solution would plug in.\n    // The blocks then animate into the chosen poses; unused blocks return home.\n    // Rasterise the slot interior into unit up/down triangle cells on the lattice\n    // anchored at slot vertex 0. Returns null if the slot isn't on the lattice\n    // (cell count doesn't match the slot area) so the caller can fall back.\n    function buildLattice() {\n        var rings = getWorldRings();\n        if (rings.length === 0 || rings[0].length === 0)\n            return null;\n        var O = rings[0][0]; // any ring vertex is a lattice point shared by all.\n        var e1 = { x: o.size, y: 0 };\n        var e2 = { x: o.size * 0.5, y: o.size * SQRT3_2 };\n        var base = function (a, b) { return ({\n            x: O.x + a * e1.x + b * e2.x,\n            y: O.y + a * e1.y + b * e2.y,\n        }); };\n        var centroid = function (a, b, u) {\n            var p = base(a, b);\n            var f = u === 0 ? 1 / 3 : 2 / 3;\n            return { x: p.x + (e1.x + e2.x) * f, y: p.y + (e1.y + e2.y) * f };\n        };\n        var cellCorners = function (cell) {\n            var a = cell.a, b = cell.b, u = cell.u;\n            if (u === 0)\n                return [base(a, b), base(a + 1, b), base(a, b + 1)];\n            return [base(a + 1, b), base(a, b + 1), base(a + 1, b + 1)];\n        };\n        // Slot bounding box in lattice (a, b) coords, to bound the scan.\n        var toAB = function (p) {\n            var b = (p.y - O.y) / (o.size * SQRT3_2);\n            var a = ((p.x - O.x) - 0.5 * o.size * b) / o.size;\n            return { a: a, b: b };\n        };\n        var amin = Infinity;\n        var amax = -Infinity;\n        var bmin = Infinity;\n        var bmax = -Infinity;\n        rings.forEach(function (ring) { return ring.forEach(function (v) {\n            var ab = toAB(v);\n            if (ab.a < amin)\n                amin = ab.a;\n            if (ab.a > amax)\n                amax = ab.a;\n            if (ab.b < bmin)\n                bmin = ab.b;\n            if (ab.b > bmax)\n                bmax = ab.b;\n        }); });\n        amin = Math.floor(amin) - 1;\n        amax = Math.ceil(amax) + 1;\n        bmin = Math.floor(bmin) - 1;\n        bmax = Math.ceil(bmax) + 1;\n        var q = o.size * 0.05;\n        var key = function (p) { return \"\".concat(Math.round(p.x / q), \",\").concat(Math.round(p.y / q)); };\n        var cells = [];\n        var keyToId = {};\n        for (var a = amin; a <= amax; a += 1) {\n            for (var b = bmin; b <= bmax; b += 1) {\n                var _loop_1 = function (u) {\n                    var c = centroid(a, b, u);\n                    // A cell belongs to the slot if its centroid is inside ANY ring.\n                    if (!rings.some(function (ring) { return pointInPolygon(c, ring); }))\n                        return \"continue\";\n                    var id = cells.length;\n                    cells.push({ id: id, a: a, b: b, u: u, c: c });\n                    keyToId[key(c)] = id;\n                };\n                for (var u = 0; u < 2; u += 1) {\n                    _loop_1(u);\n                }\n            }\n        }\n        if (cells.length === 0)\n            return null;\n        var expected = rings.reduce(function (s, r) { return s + Math.abs(signedArea(r)); }, 0) / unitTriArea;\n        if (Math.abs(expected - cells.length) > 0.5) {\n            warn(\"[pattern_block_slot \".concat(o.name, \"] show-answer: slot is not on the triangular \")\n                + \"lattice (got \".concat(cells.length, \" cells vs area \").concat(expected.toFixed(2), \") \\u2014 \")\n                + 'cannot auto-solve. Provide an authored solution for this slot.');\n            return null;\n        }\n        return { cells: cells, keyToId: keyToId, key: key, cellCorners: cellCorners };\n    }\n    // Try to seat `shape` (at orientation `theta`) so its sub-cell `si` covers\n    // `target`. Returns the block centroid + the covered cell ids, or null if any\n    // covered cell is off-board / already filled, or a geometric check fails (this\n    // is what disqualifies, e.g., an up-triangle proposed for a down cell).\n    function tryPlace(target, offs, si, rep, theta, empty, lat) {\n        var ros = offs.map(function (off) { return rotPt(off[0] * o.size, off[1] * o.size, theta); });\n        var pivot = { x: target.c.x - ros[si].x, y: target.c.y - ros[si].y };\n        var claimed = [];\n        for (var j = 0; j < ros.length; j += 1) {\n            var p = { x: pivot.x + ros[j].x, y: pivot.y + ros[j].y };\n            var id = lat.keyToId[lat.key(p)];\n            if (id == null || !empty[id])\n                return null;\n            if (claimed.indexOf(id) !== -1)\n                return null;\n            claimed.push(id);\n        }\n        // Geometric verify: the real block polygon at this pose must actually cover\n        // each claimed cell. Test points near each cell CORNER (85% of the way from\n        // the cell centroid to the corner). Closer-in points (e.g. the midpoint) sit\n        // in the hexagonal overlap of an up- and down-triangle and would wrongly\n        // accept a triangle of the opposite orientation; 0.85 is past that overlap\n        // (which ends at 0.5) yet safely inside a correctly-oriented block.\n        var F = 0.85;\n        var poly = rep.custom.worldVertsAt(pivot.x, pivot.y, theta);\n        for (var j = 0; j < claimed.length; j += 1) {\n            var cell = lat.cells[claimed[j]];\n            var corners = lat.cellCorners(cell);\n            for (var k = 0; k < corners.length; k += 1) {\n                var tp = {\n                    x: cell.c.x + F * (corners[k].x - cell.c.x),\n                    y: cell.c.y + F * (corners[k].y - cell.c.y),\n                };\n                if (!pointInPolygon(tp, poly))\n                    return null;\n            }\n        }\n        return { pivot: pivot, claimed: claimed };\n    }\n    // Exact-cover backtracking. Fills the lowest-then-leftmost empty cell first,\n    // trying the largest available shape first, and never reuses a block beyond\n    // its inventory count. Returns the chosen placements, or null if it can't tile.\n    function solveCells(lat, empty, inventory, repByShape, prefByShape) {\n        if (prefByShape === void 0) { prefByShape = {}; }\n        var thetas = [0, 1, 2, 3, 4, 5].map(function (k) { return (k * Math.PI) / 3; });\n        // Per shape, the order to try orientations in: those nearest the available\n        // blocks' current rotations first, so the first tiling found matches how the\n        // learner already turned the blocks (no needless reveal spin). Correctness is\n        // unaffected — every orientation is still tried, only the order changes.\n        var thetaOrder = {};\n        SHAPE_ORDER.forEach(function (shape) {\n            var prefs = prefByShape[shape] || [];\n            var rep = repByShape[shape];\n            var sym = rep != null && rep.custom.symmetryAngle ? rep.custom.symmetryAngle : 0;\n            var idx = thetas.map(function (_, i) { return i; });\n            if (prefs.length > 0) {\n                var nearestPref_1 = function (th) {\n                    return prefs.reduce(function (best, p) { return Math.min(best, symDist(th - p, sym)); }, Infinity);\n                };\n                idx.sort(function (a, b) { return nearestPref_1(thetas[a]) - nearestPref_1(thetas[b]); });\n            }\n            thetaOrder[shape] = idx;\n        });\n        var sortedIds = lat.cells.map(function (c) { return c.id; }).sort(function (i, j) {\n            var A = lat.cells[i];\n            var B = lat.cells[j];\n            if (Math.abs(A.c.y - B.c.y) > 1e-6)\n                return A.c.y - B.c.y;\n            return A.c.x - B.c.x;\n        });\n        var assignments = [];\n        var nodes = 0;\n        function recurse() {\n            var target = null;\n            for (var i = 0; i < sortedIds.length; i += 1) {\n                if (empty[sortedIds[i]]) {\n                    target = lat.cells[sortedIds[i]];\n                    break;\n                }\n            }\n            if (target == null)\n                return true; // every cell covered.\n            nodes += 1;\n            if (nodes > 200000)\n                return false; // runaway guard (boards are tiny).\n            var seen = {};\n            for (var s = 0; s < SHAPE_ORDER.length; s += 1) {\n                var shape = SHAPE_ORDER[s];\n                if ((inventory[shape] || 0) <= 0)\n                    continue;\n                var rep = repByShape[shape];\n                if (rep == null)\n                    continue;\n                var offs = SHAPE_OFFSETS[shape];\n                var order = thetaOrder[shape] || thetas.map(function (_, i) { return i; });\n                for (var ti = 0; ti < order.length; ti += 1) {\n                    var t = order[ti];\n                    for (var si = 0; si < offs.length; si += 1) {\n                        var placed = tryPlace(target, offs, si, rep, thetas[t], empty, lat);\n                        if (placed == null)\n                            continue;\n                        var sig = shape + ':' + placed.claimed.slice().sort(function (a, b) { return a - b; }).join(',');\n                        if (seen[sig])\n                            continue; // same piece-on-same-cells already tried.\n                        seen[sig] = true;\n                        inventory[shape] -= 1;\n                        for (var c = 0; c < placed.claimed.length; c += 1)\n                            empty[placed.claimed[c]] = false;\n                        assignments.push({ shape: shape, pivot: placed.pivot, theta: thetas[t], claimed: placed.claimed });\n                        if (recurse())\n                            return true;\n                        assignments.pop();\n                        for (var c = 0; c < placed.claimed.length; c += 1)\n                            empty[placed.claimed[c]] = true;\n                        inventory[shape] += 1;\n                    }\n                }\n            }\n            return false;\n        }\n        return recurse() ? assignments.slice() : null;\n    }\n    function buildInventory(list) {\n        var inv = {};\n        list.forEach(function (b) {\n            var sh = b.custom.shape;\n            if (TRI_COUNT[sh] != null)\n                inv[sh] = (inv[sh] || 0) + 1;\n        });\n        return inv;\n    }\n    // --- AUTHORED SOLUTIONS -------------------------------------------------\n    // Normalise the authored solution option(s) into a list of solutions, each a\n    // list of placements. Accepts `solutions` (many) and/or `solution` (one).\n    function resolveSolutions() {\n        var out = [];\n        if (Array.isArray(o.solutions)) {\n            o.solutions.forEach(function (sol) { if (Array.isArray(sol))\n                out.push(sol); });\n        }\n        if (Array.isArray(o.solution))\n            out.push(o.solution);\n        return out;\n    }\n    // A placement in world space: its centroid, rotation (rad), and the block\n    // polygon it implies (via a representative block of that shape). Returns null\n    // if no palette block of that shape exists (the placement can't be realised).\n    function placementWorld(p, repByShape) {\n        var rep = repByShape[p.shape];\n        if (rep == null || !Array.isArray(p.at))\n            return null;\n        var pos = element.getPosition();\n        var centroid = {\n            x: pos.x + p.at[0] * o.size,\n            y: pos.y + o.yOffset + p.at[1] * o.size,\n        };\n        var theta = ((p.rotation || 0) * Math.PI) / 180;\n        var verts = rep.custom.worldVertsAt(centroid.x, centroid.y, theta);\n        return { shape: p.shape, centroid: centroid, theta: theta, verts: verts };\n    }\n    // Do two polygons describe the same placement? Compare as unordered vertex\n    // sets (within tol) — congruence, so a block's rotational symmetry (a hexagon\n    // at 0° vs 60°) still counts as \"already placed there\".\n    function vertsMatch(a, b, tol) {\n        if (a.length !== b.length)\n            return false;\n        var used = new Array(b.length).fill(false);\n        for (var i = 0; i < a.length; i += 1) {\n            var found = -1;\n            for (var j = 0; j < b.length; j += 1) {\n                if (used[j])\n                    continue;\n                if (Math.hypot(a[i].x - b[j].x, a[i].y - b[j].y) <= tol) {\n                    found = j;\n                    break;\n                }\n            }\n            if (found === -1)\n                return false;\n            used[found] = true;\n        }\n        return true;\n    }\n    // Play the authored solution that disturbs the learner's current blocks least:\n    // for each solution count how many already-placed blocks sit exactly at one of\n    // its placements (kept), pick the one keeping the most, then move the rest into\n    // place and send unused blocks home. Returns false if none can be realised.\n    function playAuthoredSolution(solutions, blocks, repByShape) {\n        var tol = o.size * 0.18;\n        var inside = blocks.filter(function (b) {\n            var v = b.custom.getWorldVertices();\n            return v != null && v.length >= 3 && blockInside(v);\n        });\n        var best = null;\n        var _loop_2 = function (si) {\n            var placements = [];\n            var invalid = false;\n            solutions[si].forEach(function (p) {\n                var w = placementWorld(p, repByShape);\n                if (w == null)\n                    invalid = true;\n                else\n                    placements.push(w);\n            });\n            if (invalid || placements.length === 0)\n                return \"continue\"; // missing block shape.\n            var taken = new Array(placements.length).fill(false);\n            var matched = new Set();\n            inside.forEach(function (b) {\n                var bv = b.custom.getWorldVertices();\n                for (var pi = 0; pi < placements.length; pi += 1) {\n                    if (taken[pi] || placements[pi].shape !== b.custom.shape)\n                        continue;\n                    if (vertsMatch(bv, placements[pi].verts, tol)) {\n                        taken[pi] = true;\n                        matched.add(b);\n                        break;\n                    }\n                }\n            });\n            var cand = { placements: placements, taken: taken, matched: matched, kept: matched.size, size: placements.length };\n            if (best == null || cand.kept > best.kept\n                || (cand.kept === best.kept && cand.size < best.size)) {\n                best = cand;\n            }\n        };\n        for (var si = 0; si < solutions.length; si += 1) {\n            _loop_2(si);\n        }\n        if (best == null)\n            return false;\n        // Realise it: kept blocks stay; unsatisfied placements pull a free block of\n        // their shape; everything left over goes home.\n        var pools = {};\n        blocks.forEach(function (b) {\n            if (best.matched.has(b))\n                return;\n            (pools[b.custom.shape] = pools[b.custom.shape] || []).push(b);\n        });\n        var used = new Set(best.matched);\n        var i = 0;\n        best.placements.forEach(function (pl, pi) {\n            if (best.taken[pi]) {\n                i += 1;\n                return;\n            } // already satisfied by a kept block.\n            // Pick the same-shape block closest to this placement's orientation and\n            // place it at the symmetry-equivalent nearest its current pose (see helpers).\n            var b = takeBestForTheta(pools[pl.shape], pl.theta);\n            if (b == null) {\n                warn(\"[pattern_block_slot \".concat(o.name, \"] show-answer: no free '\").concat(pl.shape, \"' \")\n                    + 'block for the authored solution.');\n                return;\n            }\n            used.add(b);\n            b.custom.placeAt(pl.centroid.x, pl.centroid.y, orientNearCurrent(b, pl.theta), { animate: true, delay: i * 0.06 });\n            if (b.disable)\n                b.disable();\n            i += 1;\n        });\n        best.matched.forEach(function (b) { if (b.disable)\n            b.disable(); });\n        blocks.forEach(function (b) {\n            if (!used.has(b)) {\n                if (b.custom.returnHome)\n                    b.custom.returnHome(true);\n                if (b.disable)\n                    b.disable();\n            }\n        });\n        element.custom.showCorrectness(1);\n        return true;\n    }\n    // Capture the blocks currently inside the slot as a paste-ready authored\n    // solution, as a multi-line YAML block, e.g.\n    //   solution:\n    //     - {shape: hexagon, at: [-2.5, 0.866], rotation: 0}\n    //     - {shape: trapezoid, at: [-1, 0.433], rotation: 0}\n    // Calling it also copies the result to the clipboard (newlines intact), so you\n    // can paste straight into the YAML — logging the raw string just shows escaped\n    // \"\\n\"s. Re-indent to match where you paste it. For several alternatives,\n    // capture each and list them under\n    // `solutions:`, indenting each `- {...}` one level deeper beneath a `- ` item.\n    // Positions are in edge units from the outline origin; rotations in degrees.\n    function getSolution() {\n        var pos = element.getPosition();\n        var lines = [];\n        getBlocks().forEach(function (b) {\n            var v = b.custom.getWorldVertices();\n            if (v == null || v.length < 3 || !blockInside(v))\n                return;\n            var c = b.custom.centroidWorld();\n            var ax = Math.round(((c.x - pos.x) / o.size) * 1e4) / 1e4;\n            var ay = Math.round(((c.y - pos.y - o.yOffset) / o.size) * 1e4) / 1e4;\n            var deg = (b.custom.getRotation() * 180) / Math.PI;\n            deg = ((Math.round(deg) % 360) + 360) % 360;\n            lines.push(\"  - {shape: \".concat(b.custom.shape, \", at: [\").concat(ax, \", \").concat(ay, \"], rotation: \").concat(deg, \"}\"));\n        });\n        if (lines.length === 0)\n            return '';\n        var out = \"solution:\\n\".concat(lines.join('\\n'));\n        copyToClipboard(out); // also place it on the clipboard, newlines intact.\n        return out;\n    }\n    element.custom.getSolution = getSolution;\n    function solveAndShow() {\n        var blocks = getBlocks();\n        // One representative block per shape (geometry is identical within a shape)\n        // for placement prediction / verification.\n        var repByShape = {};\n        blocks.forEach(function (b) {\n            var sh = b.custom.shape;\n            if (sh != null && repByShape[sh] == null)\n                repByShape[sh] = b;\n        });\n        var authored = resolveSolutions();\n        // The auto-solver takes precedence. Authored solution(s) are used only when\n        // `force_solution` is set (an explicit override) or as a fallback below when\n        // the auto-solver can't tile the slot.\n        if (o.force_solution && authored.length > 0\n            && playAuthoredSolution(authored, blocks, repByShape)) {\n            return;\n        }\n        var lat = buildLattice();\n        if (lat == null) {\n            // Off-lattice slot — the auto-solver can't tile it. Use an authored\n            // solution if one was supplied, else just reflect the current fill.\n            if (authored.length > 0 && playAuthoredSolution(authored, blocks, repByShape)) {\n                return;\n            }\n            element.custom.showCorrectness(computeFill().filled ? 1 : 2);\n            return;\n        }\n        // Partition: keep blocks already sitting validly inside on whole cells;\n        // everything else is free inventory.\n        var empty = new Array(lat.cells.length).fill(true);\n        var kept = [];\n        var movable = [];\n        blocks.forEach(function (b) {\n            var verts = b.custom.getWorldVertices();\n            var tc = b.custom.triCount;\n            if (tc != null && verts != null && verts.length >= 3 && blockInside(verts)) {\n                var covered = [];\n                for (var i_1 = 0; i_1 < lat.cells.length; i_1 += 1) {\n                    if (empty[lat.cells[i_1].id] && pointInPolygon(lat.cells[i_1].c, verts)) {\n                        covered.push(lat.cells[i_1].id);\n                    }\n                }\n                if (covered.length === tc) {\n                    covered.forEach(function (id) { empty[id] = false; });\n                    kept.push(b);\n                    return;\n                }\n            }\n            movable.push(b);\n        });\n        // 1) Solve the remaining cells, keeping placed blocks fixed.\n        var assignments = solveCells(lat, empty, buildInventory(movable), repByShape, prefThetasByShape(movable));\n        var pool = movable;\n        var keepFixed = kept;\n        // 2) Fallback: nothing fixed — solve the whole slot with every block.\n        if (assignments == null) {\n            var allEmpty = new Array(lat.cells.length).fill(true);\n            assignments = solveCells(lat, allEmpty, buildInventory(blocks), repByShape, prefThetasByShape(blocks));\n            pool = blocks.slice();\n            keepFixed = [];\n        }\n        if (assignments == null) {\n            // Auto-solver couldn't tile (e.g. too little inventory) — fall back to an\n            // authored solution if one was supplied.\n            if (authored.length > 0 && playAuthoredSolution(authored, blocks, repByShape)) {\n                return;\n            }\n            warn(\"[pattern_block_slot \".concat(o.name, \"] show-answer: could not tile the slot with \")\n                + 'the available blocks.');\n            element.custom.showCorrectness(2);\n            return;\n        }\n        // Assign concrete blocks (grouped by shape) to each placement and animate.\n        var pools = {};\n        pool.forEach(function (b) {\n            var sh = b.custom.shape;\n            (pools[sh] = pools[sh] || []).push(b);\n        });\n        var used = new Set();\n        var i = 0;\n        assignments.forEach(function (asg) {\n            // Give the placement the same-shape block already closest to its\n            // orientation, and place it at the symmetry-equivalent nearest that block's\n            // current pose — so correctly-oriented blocks don't spin (see helpers).\n            var b = takeBestForTheta(pools[asg.shape], asg.theta);\n            if (b == null)\n                return;\n            used.add(b);\n            b.custom.placeAt(asg.pivot.x, asg.pivot.y, orientNearCurrent(b, asg.theta), { animate: true, delay: i * 0.06 });\n            if (b.disable)\n                b.disable();\n            i += 1;\n        });\n        // Unused movable blocks go home; kept blocks stay put. Freeze them all.\n        pool.forEach(function (b) {\n            if (!used.has(b)) {\n                if (b.custom.returnHome)\n                    b.custom.returnHome(true);\n                if (b.disable)\n                    b.disable();\n            }\n        });\n        keepFixed.forEach(function (b) { if (b.disable)\n            b.disable(); });\n        element.custom.showCorrectness(1);\n    }\n    // --- STATE & PLUMBING ---------------------------------------------------\n    element.notificationHelper = new NotificationHelper();\n    setupManipulative(element, null, o);\n    element.custom.manipulativeType = 'pattern_block_slot';\n    element.hasTouchableElements = false;\n    element.custom.getBoundingRect = function (space) {\n        return element.getBoundingRect(space);\n    };\n    // Slot state collector calls getState(true); the arg is ignored.\n    element.custom.getState = function () {\n        var f = computeFill();\n        return {\n            full: f.contained,\n            partial: [],\n            filled: f.filled,\n            area: Fig.round(f.area, 5),\n            covered: Fig.round(f.covered, 5),\n        };\n    };\n    element.custom.setState = function () { };\n    element.custom.state = element.custom.getState();\n    // Recolour the outline to show correctness (called by showAnswerInfo with the\n    // AnswerResult code: 1 correct, 2/6 incorrect).\n    element.custom.showCorrectness = function (result) {\n        var _a, _b;\n        if (!o.correctness)\n            return;\n        var correctColor = ((_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect) || o.correctColor;\n        var incorrectColor = ((_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect) || o.incorrectColor;\n        var target = null;\n        if (result === 1)\n            target = correctColor;\n        else if (result === 2 || result === 6)\n            target = incorrectColor;\n        borders.forEach(function (b) { return b.setColor(target != null ? target : b.custom.initialColor); });\n    };\n    element.custom.refreshSnaps = function () {\n        borders.forEach(function (b) { return b.setColor(b.custom.initialColor); });\n    };\n    // Show-answer: solve and reveal a complete tiling (keeping correct placements).\n    // answerInput.ts calls slot.showAnswer(payload, showOptions); the payload is\n    // unused — the slot computes the solution itself. Bridge to custom like the\n    // other self-managing slots (customSlot etc.).\n    element.custom.showAnswer = function () { solveAndShow(); };\n    element.showAnswer = function () {\n        var _a;\n        var args = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            args[_i] = arguments[_i];\n        }\n        return (_a = element.custom).showAnswer.apply(_a, args);\n    };\n    element.unhighlight = function () { };\n    element.disable = function () { };\n    return element;\n};\nexport { patternBlocksSlot, };\n","import { NotificationHelper } from '../tools/notifications';\n/**\n * The descending mark-index steps that define the mark hierarchy for `d`\n * subdivisions, primary first. Repeatedly halve while even, then drop to 1:\n *   10 -> [10, 5, 1]        (primary, halves, tenths)\n *   16 -> [16, 8, 4, 2, 1]  (primary, halves, quarters, eighths, sixteenths)\n * A mark's level is the index of the FIRST step that divides it, so with 10 only\n * the 5th of the nine in-between marks is promoted — the rest are all equal.\n */\nfunction tickSteps(d) {\n    var steps = [d];\n    var s = d;\n    while (s > 1) {\n        s = s % 2 === 0 ? s / 2 : 1;\n        steps.push(s);\n    }\n    return steps;\n}\nvar UNIT_DEFAULTS = {\n    metric: { divisions: 10, length: 10, unitLength: 0.28 },\n    imperial: { divisions: 16, length: 6, unitLength: 0.42 },\n};\nvar deg2rad = function (d) { return (d * Math.PI) / 180; };\nvar cssColor = function (c) {\n    var a = c[3] != null ? c[3] : 1;\n    return \"rgba(\".concat(Math.round(c[0] * 255), \", \").concat(Math.round(c[1] * 255), \", \").concat(Math.round(c[2] * 255), \", \").concat(a, \")\");\n};\nvar SVG_NS = 'http://www.w3.org/2000/svg';\n/**\n * The rotate knob's circular-arrow icon: most of a ring as a thick arc, with a\n * triangular head at the leading end pointing along the sweep.\n *\n * The viewBox is [-1, 1] in both axes — i.e. ONE UNIT IS THE KNOB'S RADIUS — and\n * the svg element is sized to the knob's full diameter, so the drawing is\n * centred on the circle by construction and every dimension below is a plain\n * fraction of the radius.\n *\n * SVG y runs DOWN, so the y of every point is negated to keep the sweep\n * anticlockwise on screen (and the arc's sweep-flag is 0 for the same reason).\n */\nfunction rotateIconSvg(color) {\n    var R = 0.52; // arc radius\n    var SW = 0.15; // arc stroke width\n    var HL = 0.34; // arrowhead length\n    var HW = 0.22; // arrowhead half-width\n    var t0 = deg2rad(110); // start of the sweep\n    var sweep = deg2rad(280); // nearly a full turn, so it can't read as a plain arc\n    var svg = document.createElementNS(SVG_NS, 'svg');\n    svg.setAttribute('viewBox', '-1 -1 2 2');\n    svg.style.display = 'block'; // no inline-baseline gap under the svg box\n    svg.style.overflow = 'visible';\n    var at = function (t) { return [R * Math.cos(t), -R * Math.sin(t)]; };\n    var _a = at(t0), sx = _a[0], sy = _a[1];\n    var tEnd = t0 + sweep;\n    var _b = at(tEnd), ex = _b[0], ey = _b[1];\n    var arc = document.createElementNS(SVG_NS, 'path');\n    // large-arc-flag 1 (the sweep is over 180 degrees), sweep-flag 0 (anticlockwise\n    // on screen, given the negated y).\n    arc.setAttribute('d', \"M \".concat(sx, \" \").concat(sy, \" A \").concat(R, \" \").concat(R, \" 0 1 0 \").concat(ex, \" \").concat(ey));\n    arc.setAttribute('fill', 'none');\n    arc.setAttribute('stroke', color);\n    arc.setAttribute('stroke-width', \"\".concat(SW));\n    arc.setAttribute('stroke-linecap', 'round');\n    svg.appendChild(arc);\n    // Unit tangent of the anticlockwise motion at the arc's end, and its normal.\n    var tx = -Math.sin(tEnd);\n    var ty = -Math.cos(tEnd);\n    var nx = -ty;\n    var ny = tx;\n    var head = document.createElementNS(SVG_NS, 'polygon');\n    head.setAttribute('points', [\n        \"\".concat(ex + tx * HL, \",\").concat(ey + ty * HL),\n        \"\".concat(ex + nx * HW, \",\").concat(ey + ny * HW),\n        \"\".concat(ex - nx * HW, \",\").concat(ey - ny * HW),\n    ].join(' '));\n    head.setAttribute('fill', color);\n    svg.appendChild(head);\n    return svg;\n}\nvar htmlRuler = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var units = options.units === 'imperial' ? 'imperial' : 'metric';\n    var unitDefaults = UNIT_DEFAULTS[units];\n    var o = Fig.joinObjects({\n        units: units,\n        length: unitDefaults.length,\n        unitLength: unitDefaults.unitLength,\n        divisions: unitDefaults.divisions,\n        height: 0.2,\n        fill: [1, 0.97, 0.82, 1],\n        borderWidth: 0.004,\n        corner: 0.02,\n        color: [0.15, 0.15, 0.15, 1],\n        sides: 'both',\n        labels: 'center',\n        labelStart: true,\n        rotate: true,\n        angle: 0,\n        snapAngle: 0,\n        shadow: false,\n        yOffset: 0,\n        isTouchable: true,\n        boundMove: true,\n        zIndex: 100000,\n    }, options);\n    var H = o.height;\n    var n = Math.max(1, Math.round(o.length));\n    var divisions = Math.max(1, Math.round(o.divisions));\n    var unit = o.unitLength;\n    var fill = o.fill;\n    var borderColor = o.border != null\n        ? o.border\n        : [fill[0] * 0.72, fill[1] * 0.68, fill[2] * 0.5, 1];\n    // The body frames the marks — `inset` off each long edge, `margin` off each\n    // end — so no mark ever touches or crosses the outline.\n    var inset = o.tickInset != null ? o.tickInset : H * 0.07;\n    var tick = Fig.joinObjects({ primary: H * 0.22, minor: H * 0.09 }, o.tickLength);\n    var tickW = Fig.joinObjects({ primary: 0.006, secondary: 0.003 }, o.tickWidth);\n    var fontSize = o.fontSize != null ? o.fontSize : H * 0.25;\n    var labelOffset = o.labelOffset != null ? o.labelOffset : H * 0.03;\n    // Half the widest end label, estimated from its digit count. The default\n    // margin is whatever it takes for the 0 and last labels to sit CENTRED on\n    // their marks — half a label plus the outline — with the mark inset as a\n    // floor. Anything less and those two have to be tucked in against the end,\n    // which reads as a mistake next to the centred ones.\n    var halfEndLabel = o.labels === false ? 0 : fontSize * 0.32 * \"\".concat(n).length;\n    var margin = o.margin != null\n        ? o.margin\n        : Math.max(inset, halfEndLabel + o.borderWidth * 5);\n    var bodyLength = n * unit + 2 * margin;\n    var xZero = -bodyLength / 2 + margin; // value 0, relative to the centre\n    var xOf = function (value) { return xZero + value * unit; };\n    var steps = tickSteps(divisions);\n    var levels = steps.length;\n    var levelOf = function (r) {\n        for (var k = 0; k < levels; k += 1) {\n            if (r % steps[k] === 0)\n                return k;\n        }\n        return levels - 1;\n    };\n    var lengthOfLevel = function (level) {\n        if (level === 0 || levels < 2)\n            return tick.primary;\n        return tick.primary + ((tick.minor - tick.primary) * level) / (levels - 1);\n    };\n    var drawTop = o.sides !== 'bottom';\n    var drawBottom = o.sides !== 'top';\n    // '' means no shadow, so a plain truthiness check gates every use below.\n    var shadowCss = o.shadow === true\n        ? '0 2px 8px rgba(0, 0, 0, 0.25)'\n        : (typeof o.shadow === 'string' ? o.shadow : '');\n    var rotateOpts = o.rotate === false\n        ? null\n        : Fig.joinObjects({\n            radius: 0.075,\n            gap: 0.03,\n            color: [0.45, 0.45, 0.45, 1],\n            // The knob is the arrow alone — no disc behind it. Both are still\n            // authorable; see the option docs above.\n            fill: [0, 0, 0, 0],\n            borderWidth: 0,\n            side: 'right',\n            pivot: 'end',\n        }, o.rotate === true ? {} : o.rotate);\n    var canRotate = rotateOpts != null && o.isTouchable !== false;\n    // --- ANCHOR --------------------------------------------------------------\n    // An invisible FigureOne element sized like the ruler body. It does two jobs:\n    // the equation lays it out (so the ruler starts wherever the expression puts\n    // it, like any other element), and it carries the manipulative hooks that\n    // manage.ts looks for. Nothing is ever drawn on it.\n    var anchor = toAdd.add({\n        name: o.name,\n        make: 'rectangle',\n        width: bodyLength,\n        height: H,\n        xAlign: 'left',\n        yAlign: 'middle',\n        position: o.position,\n        color: [0, 0, 0, 0],\n    });\n    anchor.isTouchable = false;\n    anchor.notificationHelper = new NotificationHelper();\n    // --- DOM -----------------------------------------------------------------\n    // Geometry is authored in draw units and applied in real CSS pixels by\n    // layout() below — the panel is NEVER CSS-scaled. An earlier version built the\n    // DOM at a fixed 300px/unit and scaled the panel to fit, which meant the\n    // browser rasterized the marks once and then DOWNSAMPLED them: adjacent\n    // 1.8px bars merged and split unevenly, so identical marks landed on screen\n    // at anywhere from half to double weight. Laying out at the true pixel size\n    // and snapping each mark to the device pixel grid (see snapPx) is what makes\n    // them all render identically.\n    var panel = document.createElement('div');\n    panel.className = 'grok-html-ruler';\n    panel.style.position = 'fixed';\n    panel.style.left = '0';\n    panel.style.top = '0';\n    panel.style.width = '0';\n    panel.style.height = '0';\n    panel.style.zIndex = \"\".concat(o.zIndex);\n    panel.style.transformOrigin = '0 0';\n    panel.style.pointerEvents = o.isTouchable === false ? 'none' : 'auto';\n    panel.style.touchAction = 'none'; // else the browser claims the drag as a pan\n    panel.style.userSelect = 'none';\n    panel.style.webkitUserSelect = 'none';\n    // The body is deliberately BORDERLESS, with `overflow: hidden` and the rounded\n    // corners. Two reasons, both about the marks staying inside the yellow:\n    //   - children of a bordered box are positioned against its PADDING box, not\n    //     its border box, so every mark would sit shifted by the border width and\n    //     the bottom row would spill past the outline.\n    //   - overflow: hidden clips to the rounded rectangle, so nothing can escape\n    //     the fill even at a rounded corner.\n    // The outline is a separate overlay drawn on top (below), which also keeps it\n    // crisp and unbroken rather than half-covered by the end marks.\n    var markColor = cssColor(o.color);\n    var bodyDiv = document.createElement('div');\n    bodyDiv.style.position = 'absolute';\n    bodyDiv.style.background = cssColor(fill);\n    bodyDiv.style.overflow = 'hidden';\n    if (shadowCss) {\n        bodyDiv.style.boxShadow = shadowCss;\n    }\n    bodyDiv.style.cursor = o.isTouchable === false ? 'default' : 'grab';\n    panel.appendChild(bodyDiv);\n    var marks = [];\n    var addBar = function (x, top, len, w) {\n        var el = document.createElement('div');\n        el.className = 'grok-html-ruler__mark';\n        el.style.position = 'absolute';\n        el.style.background = markColor;\n        bodyDiv.appendChild(el);\n        marks.push({ el: el, x: x + bodyLength / 2, top: top + H / 2, len: len, w: w });\n    };\n    var totalMarks = n * divisions;\n    for (var i = 0; i <= totalMarks; i += 1) {\n        var level = levelOf(i % divisions);\n        var len = lengthOfLevel(level);\n        var w = level === 0 ? tickW.primary : tickW.secondary;\n        var x = xOf(i / divisions);\n        // Hang inward from `inset` inside each long edge, never from the edge itself.\n        if (drawTop) {\n            addBar(x, -H / 2 + inset, len, w);\n        }\n        if (drawBottom) {\n            addBar(x, H / 2 - inset - len, len, w);\n        }\n    }\n    // One row of numbers. Each label is a centred box on its mark; the first and\n    // last are pinned inside the body instead so they can't hang off the end.\n    var labelTop = -fontSize / 2; // 'center': straddle the mid-line\n    if (o.labels === 'top') {\n        labelTop = -H / 2 + inset + tick.primary + labelOffset;\n    }\n    else if (o.labels === 'bottom') {\n        labelTop = H / 2 - inset - tick.primary - labelOffset - fontSize;\n    }\n    var labelBoxW = fontSize * 2.4; // wide enough for two digits at any font\n    var labels = [];\n    if (o.labels !== false) {\n        for (var v = o.labelStart ? 0 : 1; v <= n; v += 1) {\n            var el = document.createElement('div');\n            el.textContent = \"\".concat(v);\n            el.style.position = 'absolute';\n            el.style.fontFamily = 'inherit';\n            el.style.color = markColor;\n            // Every label is centred on its mark — the default margin is sized to\n            // make that possible at both ends. This is only the safety net for an\n            // authored `margin` too small to fit them. The limit is the body's inner\n            // edge, NOT the last mark: overhanging into the margin is exactly what\n            // the margin is there for. The box is much wider than the glyph, so the\n            // clamp is on the ESTIMATED glyph width — clamping the box itself would\n            // drag the number visibly off its mark.\n            var cx = xOf(v) + bodyLength / 2;\n            var half = fontSize * 0.32 * \"\".concat(v).length;\n            var edge = o.borderWidth; // clear the outline\n            var left = void 0;\n            if (cx + half > bodyLength - edge) {\n                left = bodyLength - edge - labelBoxW;\n                el.style.textAlign = 'right';\n            }\n            else if (cx - half < edge) {\n                left = edge;\n                el.style.textAlign = 'left';\n            }\n            else {\n                left = cx - labelBoxW / 2;\n                el.style.textAlign = 'center';\n            }\n            bodyDiv.appendChild(el);\n            labels.push({ el: el, left: left });\n        }\n    }\n    // The outline, as an overlay on the same box rather than a border on the body\n    // (see the bodyDiv comment). Drawn after the marks, so it reads as one clean\n    // unbroken frame around them.\n    var outlineDiv = null;\n    if (o.border !== false) {\n        outlineDiv = document.createElement('div');\n        outlineDiv.style.position = 'absolute';\n        outlineDiv.style.boxSizing = 'border-box';\n        outlineDiv.style.borderStyle = 'solid';\n        outlineDiv.style.borderColor = cssColor(borderColor);\n        outlineDiv.style.pointerEvents = 'none'; // the body underneath takes the drag\n        panel.appendChild(outlineDiv);\n    }\n    // The rotate knob: a circular-arrow icon just off one end. The div carrying it\n    // is the touch target and is `radius` wide whether or not anything is painted\n    // behind the arrow, so the grab area does not shrink when the disc is off.\n    //\n    // The icon is DRAWN (inline SVG), not a text glyph. A '⟲' character centred\n    // with flex is centred by its line box, not by its ink — the glyph's own side\n    // bearings and baseline offset left it visibly off-centre, and its ink filled\n    // far less of the em box than the font size suggested, so it also read as too\n    // small. An SVG whose viewBox IS the knob has neither problem: the drawing is\n    // centred by construction and sized in exact fractions of the radius.\n    var knob = null;\n    var knobDir = rotateOpts != null && rotateOpts.side === 'left' ? -1 : 1;\n    var knobBorder = rotateOpts != null && rotateOpts.borderWidth > 0;\n    if (canRotate) {\n        knob = document.createElement('div');\n        knob.className = 'grok-html-ruler__knob';\n        knob.style.position = 'absolute';\n        knob.style.borderRadius = '50%';\n        knob.style.boxSizing = 'border-box';\n        knob.style.cursor = 'grab';\n        knob.style.background = cssColor(rotateOpts.fill);\n        if (knobBorder) {\n            knob.style.borderStyle = 'solid';\n            knob.style.borderColor = cssColor(rotateOpts.color);\n        }\n        // A shadow only makes sense under a DISC; on the bare arrow it would render\n        // as a smudge around an invisible box. So this needs both `shadow` on and\n        // something actually painted behind the arrow.\n        if (shadowCss && (knobBorder || rotateOpts.fill[3] > 0)) {\n            knob.style.boxShadow = shadowCss;\n        }\n        knob.appendChild(rotateIconSvg(cssColor(rotateOpts.color)));\n        panel.appendChild(knob);\n    }\n    // --- LAYOUT ---------------------------------------------------------------\n    // Apply the geometry at `scale` CSS pixels per draw unit. Only run when the\n    // scale actually changes (a resize or an equation relayout) — a drag or a\n    // rotate just moves the panel, which is one transform write.\n    //\n    // Mark widths and edges are snapped to whole DEVICE pixels. A mark is only\n    // 1-3 device pixels wide, so an unsnapped fractional box is split across two\n    // columns by a different ratio for every mark, and identical marks render at\n    // visibly different weights. Snapping costs at most half a device pixel of\n    // position (~0.1mm at a typical scale) and makes every mark identical.\n    var laidOutAt = -1;\n    function layout(scale) {\n        if (scale === laidOutAt || !(scale > 0))\n            return;\n        laidOutAt = scale;\n        var dpr = window.devicePixelRatio || 1;\n        var snap = function (v) { return Math.round(v * dpr) / dpr; };\n        var snapW = function (v) { return Math.max(1 / dpr, Math.round(v * dpr) / dpr); };\n        var u = function (v) { return \"\".concat(v * scale, \"px\"); };\n        bodyDiv.style.left = u(-bodyLength / 2);\n        bodyDiv.style.top = u(-H / 2);\n        bodyDiv.style.width = u(bodyLength);\n        bodyDiv.style.height = u(H);\n        bodyDiv.style.borderRadius = u(o.corner);\n        for (var i = 0; i < marks.length; i += 1) {\n            var m = marks[i];\n            var w = snapW(m.w * scale);\n            var s = m.el.style;\n            // Snap the two long edges independently rather than snapping the left and\n            // adding a snapped width — that keeps the mark centred on its true value\n            // to within half a device pixel either side.\n            s.left = \"\".concat(snap(m.x * scale - w / 2), \"px\");\n            s.width = \"\".concat(w, \"px\");\n            s.top = \"\".concat(snap(m.top * scale), \"px\");\n            s.height = \"\".concat(snapW(m.len * scale), \"px\");\n        }\n        for (var i = 0; i < labels.length; i += 1) {\n            var s = labels[i].el.style;\n            s.left = u(labels[i].left);\n            s.top = u(labelTop + H / 2);\n            s.width = u(labelBoxW);\n            s.height = u(fontSize * 1.2);\n            s.lineHeight = u(fontSize * 1.2);\n            s.fontSize = u(fontSize);\n        }\n        if (outlineDiv != null) {\n            outlineDiv.style.left = u(-bodyLength / 2);\n            outlineDiv.style.top = u(-H / 2);\n            outlineDiv.style.width = u(bodyLength);\n            outlineDiv.style.height = u(H);\n            outlineDiv.style.borderWidth = \"\".concat(snapW(o.borderWidth * scale), \"px\");\n            outlineDiv.style.borderRadius = u(o.corner);\n        }\n        if (knob != null) {\n            var r = rotateOpts.radius;\n            knob.style.left = u(knobDir * (bodyLength / 2 + rotateOpts.gap + r) - r);\n            knob.style.top = u(-r);\n            knob.style.width = u(r * 2);\n            knob.style.height = u(r * 2);\n            var bw = knobBorder ? rotateOpts.borderWidth : 0;\n            if (knobBorder) {\n                knob.style.borderWidth = u(bw);\n            }\n            // The icon's viewBox is the knob, so sizing it to the knob is what centres\n            // it — no font metrics involved. The knob is border-box, so with a disc the\n            // svg has to be the INNER diameter or the border would push it off centre;\n            // with none it gets the full width.\n            var icon = knob.firstElementChild;\n            if (icon != null) {\n                icon.setAttribute('width', \"\".concat((r - bw) * 2 * scale));\n                icon.setAttribute('height', \"\".concat((r - bw) * 2 * scale));\n            }\n        }\n    }\n    // The INJECTED figure's own html layer, not `document.getElementsByClassName(\n    // 'figureone__html')[0]`. A page can hold more than one figure — the main one\n    // and a workpad, or a grid of them in a test harness — and the global lookup\n    // always returned the first, so the ruler could attach to (and be measured\n    // against) a figure it does not belong to. fig.htmlCanvas IS that figure's\n    // layer: FigureOne tags it with the figureone__html class on creation.\n    var htmlLayer = fig.htmlCanvas;\n    if (htmlLayer != null) {\n        // teardownQuestion() clears this layer with innerHTML = '', so the panel is\n        // removed on a question transition without any bookkeeping here.\n        htmlLayer.appendChild(panel);\n    }\n    // --- FIGURE <-> PAGE ------------------------------------------------------\n    // The html layer covers exactly the figure's scene, so its client rect is the\n    // whole mapping between figure coordinates and viewport pixels.\n    function layerRect() {\n        if (htmlLayer == null)\n            return null;\n        var r = htmlLayer.getBoundingClientRect();\n        return r.width > 0 && r.height > 0 ? r : null;\n    }\n    // Pixels per DRAW unit: the figure-to-pixel ratio times the scale of every\n    // collection between the anchor and the root, so a scaled equation scales the\n    // ruler with it (and the ruler keeps measuring its siblings correctly).\n    function drawScale() {\n        var s = 1;\n        var parent = anchor.parent;\n        while (parent != null) {\n            s *= parent.getScale().x;\n            parent = parent.parent;\n        }\n        return s;\n    }\n    function pxPerFigureUnit(rect) {\n        return rect.width / fig.scene.widthNear;\n    }\n    function figureToClient(x, y, rect) {\n        var s = fig.scene;\n        return {\n            x: rect.left + ((x - s.left) / s.widthNear) * rect.width,\n            y: rect.top + ((s.top - y) / s.heightNear) * rect.height,\n        };\n    }\n    function clientToFigure(x, y, rect) {\n        var s = fig.scene;\n        return {\n            x: s.left + ((x - rect.left) / rect.width) * s.widthNear,\n            y: s.top - ((y - rect.top) / rect.height) * s.heightNear,\n        };\n    }\n    // --- POSE ----------------------------------------------------------------\n    // `centre` is the ruler's middle in figure space and `rotation` its angle;\n    // together they are the whole state. Until the learner touches it the ruler\n    // tracks the anchor, so the equation's layout (and any relayout) places it.\n    var centre = null;\n    var rotation = deg2rad(o.angle);\n    // The unsnapped angle behind `rotation`. With `snapAngle` set the ruler clicks\n    // between detents live, as it turns, and each frame is computed from the raw\n    // angle rather than from the snapped one — snapping a running value would\n    // round each frame's small delta straight back off, so a coarse step (say 90\n    // degrees) could never be reached. Identical to `rotation` when snapping is\n    // off, and re-seated onto the detent when a turn ends.\n    var rawRotation = rotation;\n    var snapStep = deg2rad(o.snapAngle);\n    var snapTo = function (r) { return (snapStep > 0 ? Math.round(r / snapStep) * snapStep : r); };\n    // Until the learner takes over, the ruler follows the anchor so the equation's\n    // layout places it. This is a FLAG rather than `centre = null` on purpose:\n    // nulling the centre invalidates it at a point where sync() may not be able to\n    // redraw (the figure container can be hidden or zero-sized mid-transition, and\n    // sync() bails on that). That left the panel drawn at one place while `centre`\n    // held nothing, so the next pointerdown resolved `centre` to the anchor — a\n    // different point — and the first pointermove snapped the ruler by the\n    // difference. It could only ever happen once, because the first press sets\n    // `moved`. With a flag, `centre` is only ever assigned inside a SUCCESSFUL\n    // sync, so what is drawn and what `centre` says can't come apart.\n    var followAnchor = true;\n    function anchorCentre() {\n        // The anchor is xAlign left / yAlign middle, so the body's centre is half a\n        // body-length to its right, in the anchor's own (possibly scaled) frame.\n        var p = anchor.getPosition('figure');\n        var s = drawScale();\n        return { x: p.x + (bodyLength / 2) * s, y: p.y + o.yOffset * s };\n    }\n    // How far the ruler reaches from its centre, in CSS pixels, at the current\n    // rotation — the axis-aligned box around everything that draws. Used to keep\n    // the whole thing on the page rather than just its centre point.\n    //\n    // The panel's transform is `translate(centre) rotate(-rotation)`, so a local\n    // point (lx, ly) lands at centre + (lx*cos + ly*sin, -lx*sin + ly*cos). Taking\n    // the extremes of that over the corners of each drawn box gives the reach.\n    function panelExtent(scale) {\n        var boxes = [\n            [-bodyLength / 2, -H / 2, bodyLength / 2, H / 2],\n        ];\n        if (canRotate) {\n            var kx = knobDir * (bodyLength / 2 + rotateOpts.gap + rotateOpts.radius);\n            var r = rotateOpts.radius;\n            boxes.push([kx - r, -r, kx + r, r]);\n        }\n        var cos = Math.cos(rotation);\n        var sin = Math.sin(rotation);\n        var minX = Infinity;\n        var maxX = -Infinity;\n        var minY = Infinity;\n        var maxY = -Infinity;\n        for (var _i = 0, boxes_1 = boxes; _i < boxes_1.length; _i++) {\n            var _a = boxes_1[_i], x0 = _a[0], y0 = _a[1], x1 = _a[2], y1 = _a[3];\n            for (var _b = 0, _c = [x0, x1]; _b < _c.length; _b++) {\n                var lx = _c[_b];\n                for (var _d = 0, _e = [y0, y1]; _d < _e.length; _d++) {\n                    var ly = _e[_d];\n                    var px = (lx * cos + ly * sin) * scale;\n                    var py = (-lx * sin + ly * cos) * scale;\n                    if (px < minX)\n                        minX = px;\n                    if (px > maxX)\n                        maxX = px;\n                    if (py < minY)\n                        minY = py;\n                    if (py > maxY)\n                        maxY = py;\n                }\n            }\n        }\n        return { minX: minX, maxX: maxX, minY: minY, maxY: maxY };\n    }\n    // Pull the centre back so no part of the ruler leaves the viewport. If the\n    // ruler is longer than the viewport on an axis it cannot fit, so it is centred\n    // on that axis instead of being jammed against one edge.\n    function clampToPage(c, scale) {\n        if (!o.boundMove)\n            return c;\n        var doc = document.documentElement;\n        var w = doc.clientWidth || window.innerWidth;\n        var h = doc.clientHeight || window.innerHeight;\n        var e = panelExtent(scale);\n        var axis = function (v, lo, hi) { return (lo <= hi ? Math.min(Math.max(v, lo), hi) : (lo + hi) / 2); };\n        return {\n            x: axis(c.x, -e.minX, w - e.maxX),\n            y: axis(c.y, -e.minY, h - e.maxY),\n        };\n    }\n    // `clamp: false` re-places the ruler without pulling it back onto the page.\n    // Used by the scroll handler — see the listener below for why.\n    function sync(opts) {\n        if (opts === void 0) { opts = {}; }\n        var rect = layerRect();\n        if (rect == null)\n            return;\n        if (centre == null || followAnchor) {\n            centre = anchorCentre();\n        }\n        // Re-apply the geometry only when the pixels-per-draw-unit actually changes;\n        // layout() no-ops otherwise, so a drag is just the transform write below.\n        var scale = pxPerFigureUnit(rect) * drawScale();\n        layout(scale);\n        var c = figureToClient(centre.x, centre.y, rect);\n        // Bounding happens HERE rather than in the drag handler, so every path that\n        // can move the ruler — drag, rotate, setState, a window resize — is held on\n        // the page by the same code. A clamped pose is written back to `centre` so\n        // the saved state is the bounded one.\n        var bounded = opts.clamp === false ? c : clampToPage(c, scale);\n        if (bounded.x !== c.x || bounded.y !== c.y) {\n            c = bounded;\n            centre = clientToFigure(c.x, c.y, rect);\n        }\n        // Translate + rotate only, NEVER scale — a scaled panel is rasterized once\n        // and resampled, which is what made identical marks render at different\n        // weights. While the ruler is axis-aligned the translation is snapped to the\n        // device pixel grid so the (already grid-snapped) marks stay crisp; once it\n        // is turned nothing can align to the grid anyway, so leave it exact.\n        var dpr = window.devicePixelRatio || 1;\n        var snap = function (v) { return Math.round(v * dpr) / dpr; };\n        var x = rotation === 0 ? snap(c.x) : c.x;\n        var y = rotation === 0 ? snap(c.y) : c.y;\n        // `rotate` is negated: figure y runs up, CSS y runs down, so a positive\n        // (counter-clockwise) figure rotation is a negative CSS one.\n        panel.style.transform = \"translate(\".concat(x, \"px, \").concat(y, \"px) rotate(\").concat(-rotation, \"rad)\");\n        panel.style.display = anchor.isShown === false ? 'none' : '';\n    }\n    anchor.notificationHelper.add(fig, 'ready', function () { return sync(); });\n    anchor.notificationHelper.add(fig, 'autoCentered', function () { return sync(); });\n    // A relayout moves the anchor; follow it only while the learner hasn't taken\n    // over. Once they have, their pose is the truth.\n    anchor.notificationHelper.add(toAdd, 'layoutForms', function () { return sync(); });\n    anchor.notificationHelper.add(anchor, 'setTransform', function () { return sync(); });\n    var onResize = function () { sync(); };\n    window.addEventListener('resize', onResize);\n    // SCROLL. The panel is position: fixed, so it is pinned to the VIEWPORT, while\n    // the position it should be at comes from the figure layer's client rect —\n    // which slides up the viewport as the page scrolls. Without this the panel\n    // stays put on screen while the figure moves out from under it, so the ruler\n    // silently detaches from what it is measuring, and the next drag snaps it back\n    // by the whole scroll offset. Re-placing it here keeps it glued to the figure.\n    //\n    // Deliberately does NOT clamp to the page: scrolling is the learner moving the\n    // PAGE, and the ruler should travel with the content it is measuring rather\n    // than being dragged along the viewport edge (which would also rewrite its\n    // saved pose without the learner touching it).\n    //\n    // capture: true because scroll does not bubble from a scrolling element, but\n    // does capture; passive: true so this never delays scrolling.\n    var onScroll = function () { sync({ clamp: false }); };\n    var scrollOpts = { capture: true, passive: true };\n    window.addEventListener('scroll', onScroll, scrollOpts);\n    if (fig._docListeners == null) {\n        fig._docListeners = [];\n    }\n    fig._docListeners.push({ target: window, event: 'resize', handler: onResize, options: undefined });\n    fig._docListeners.push({ target: window, event: 'scroll', handler: onScroll, options: scrollOpts });\n    // Mobile: pinch-zoom and the address bar sliding away move the VISUAL viewport\n    // without firing a window scroll/resize. Feature-detected — visualViewport is\n    // newer than the browser floor.\n    var vv = window.visualViewport;\n    if (vv != null && typeof vv.addEventListener === 'function') {\n        vv.addEventListener('scroll', onScroll);\n        vv.addEventListener('resize', onResize);\n        fig._docListeners.push({ target: vv, event: 'scroll', handler: onScroll, options: undefined });\n        fig._docListeners.push({ target: vv, event: 'resize', handler: onResize, options: undefined });\n    }\n    // --- STATE ---------------------------------------------------------------\n    function computeState() {\n        var c = centre != null ? centre : anchorCentre();\n        var e_name = typeof eqn_name === 'string' ? eqn_name : eqn_name.getPath();\n        return {\n            e: e_name,\n            p: [Fig.round(c.x, 3), Fig.round(c.y, 3)],\n            r: Fig.round(rotation, 5),\n        };\n    }\n    var tracksState = o.isTouchable !== false;\n    if (tracksState) {\n        anchor.custom.getState = computeState;\n        anchor.custom.setState = function (stats) {\n            centre = { x: stats.p[0], y: stats.p[1] };\n            if (stats.r != null) {\n                rotation = stats.r;\n                rawRotation = stats.r;\n            }\n            followAnchor = false;\n            anchor.custom.moved = true;\n            sync();\n        };\n    }\n    anchor.custom.state = computeState();\n    anchor.custom.manipulativeType = 'html_ruler';\n    anchor.custom.units = units;\n    anchor.custom.divisions = divisions;\n    anchor.custom.isShowable = true;\n    // Exposed for guides / tests.\n    anchor.custom.getRotation = function () { return rotation; };\n    anchor.custom.getAngle = function () { return (rotation * 180) / Math.PI; };\n    anchor.custom.getEnds = function () {\n        var c = centre != null ? centre : anchorCentre();\n        var s = drawScale();\n        var cos = Math.cos(rotation);\n        var sin = Math.sin(rotation);\n        var at = function (x) { return ({\n            x: c.x + x * s * cos,\n            y: c.y + x * s * sin,\n        }); };\n        return { zero: at(xZero), end: at(xOf(n)) };\n    };\n    anchor.custom.placeAt = function (x, y, degrees) {\n        centre = { x: x, y: y };\n        rotation = deg2rad(degrees);\n        rawRotation = rotation;\n        followAnchor = false;\n        anchor.custom.moved = true;\n        anchor.custom.state = computeState();\n        sync();\n    };\n    // The point the ruler turns about, in figure space — the planted end by\n    // default (see rotate.pivot). Exposed because it, not the centre, is what\n    // stays put across a rotation.\n    anchor.custom.getPivot = function () {\n        if (centre == null)\n            centre = anchorCentre();\n        return pivotPoint();\n    };\n    anchor.custom.getPanel = function () { return panel; };\n    anchor.custom.getKnob = function () { return knob; };\n    var drag = null;\n    // Where the pivot sits along the ruler, measured from its centre in draw\n    // units. 'end' puts it on the end opposite the knob (knob right -> pivot left)\n    // so that end stays planted while the knob swings round it; 'center' is 0, the\n    // ruler's middle.\n    var pivotLocalX = rotateOpts != null && rotateOpts.pivot !== 'center'\n        ? -knobDir * (bodyLength / 2)\n        : 0;\n    // The pivot's offset from the centre in FIGURE space at rotation `theta` —\n    // i.e. the local offset scaled into figure units and turned with the ruler.\n    function pivotOffset(theta) {\n        var d = pivotLocalX * drawScale();\n        return { x: d * Math.cos(theta), y: d * Math.sin(theta) };\n    }\n    function pivotPoint() {\n        var d = pivotOffset(rotation);\n        return { x: centre.x + d.x, y: centre.y + d.y };\n    }\n    // The centre that puts the pivot at `pv` when the ruler is turned to `theta`.\n    // Rotating about an end means the CENTRE moves, so this is what keeps the\n    // planted end planted.\n    function centreForPivot(pv, theta) {\n        var d = pivotOffset(theta);\n        return { x: pv.x - d.x, y: pv.y - d.y };\n    }\n    // Angle from a figure-space point to a page point, in figure convention\n    // (anticlockwise positive, y up).\n    function angleAbout(p, clientX, clientY, rect) {\n        var c = figureToClient(p.x, p.y, rect);\n        return Math.atan2(-(clientY - c.y), clientX - c.x);\n    }\n    var onPointerDown = function (kind) { return function (e) {\n        if (o.isTouchable === false)\n            return;\n        var rect = layerRect();\n        if (rect == null)\n            return;\n        if (centre == null)\n            centre = anchorCentre();\n        var f = clientToFigure(e.clientX, e.clientY, rect);\n        if (kind === 'move') {\n            drag = { kind: 'move', grabX: f.x - centre.x, grabY: f.y - centre.y };\n            bodyDiv.style.cursor = 'grabbing';\n        }\n        else {\n            // Measure the pointer angle about the PIVOT, not the centre, so the knob\n            // tracks the finger as it swings round the planted end.\n            var pv = pivotPoint();\n            drag = {\n                kind: 'rotate',\n                startAngle: angleAbout(pv, e.clientX, e.clientY, rect),\n                startRotation: rawRotation,\n                pivot: pv,\n            };\n        }\n        followAnchor = false;\n        anchor.custom.moved = true;\n        // Keep receiving moves even when the pointer slides off the ruler.\n        var target = e.currentTarget;\n        if (target != null && target.setPointerCapture != null && e.pointerId != null) {\n            try {\n                target.setPointerCapture(e.pointerId);\n            }\n            catch ( /* not fatal */_a) { /* not fatal */ }\n        }\n        e.stopPropagation();\n        e.preventDefault();\n    }; };\n    var onPointerMove = function (e) {\n        if (drag == null)\n            return;\n        var rect = layerRect();\n        if (rect == null)\n            return;\n        if (drag.kind === 'move') {\n            var f = clientToFigure(e.clientX, e.clientY, rect);\n            // No clamping here — sync() bounds the pose on every path (drag, rotate,\n            // setState, resize), so it only has to be got right once.\n            centre = { x: f.x - drag.grabX, y: f.y - drag.grabY };\n        }\n        else {\n            // Snap LIVE, as the ruler turns. The raw pointer angle is kept alongside\n            // the snapped one and every frame is computed from the drag's start, so a\n            // coarse step is still reachable — snapping the running value instead\n            // would round each frame's small delta straight back off.\n            rawRotation = drag.startRotation\n                + (angleAbout(drag.pivot, e.clientX, e.clientY, rect) - drag.startAngle);\n            rotation = snapTo(rawRotation);\n            // Hold the pivot still: with an end pivot the centre has to swing round it.\n            centre = centreForPivot(drag.pivot, rotation);\n        }\n        sync();\n        e.preventDefault();\n    };\n    var onPointerUp = function () {\n        if (drag == null)\n            return;\n        if (drag.kind === 'rotate') {\n            // Already on a detent (the snap is live). Re-seat the raw angle on it so\n            // the next turn starts from where the ruler actually is.\n            rawRotation = rotation;\n        }\n        drag = null;\n        bodyDiv.style.cursor = 'grab';\n        anchor.custom.state = computeState();\n        // Tell the engine the answer may have changed. Use the injected `fig` —\n        // addManipulative may pass a non-global figure.\n        fig.answerChanged();\n    };\n    if (o.isTouchable !== false) {\n        bodyDiv.addEventListener('pointerdown', onPointerDown('move'));\n        if (knob != null) {\n            knob.addEventListener('pointerdown', onPointerDown('rotate'));\n        }\n        // A touch anywhere on the ruler belongs to the ruler, never the scene behind.\n        panel.addEventListener('touchstart', function (e) { e.stopPropagation(); });\n        // Document-level listeners must be registered on _docListeners so\n        // teardownQuestion() removes them — clearing the html layer takes the panel\n        // (and its own listeners) but not these.\n        document.addEventListener('pointermove', onPointerMove);\n        document.addEventListener('pointerup', onPointerUp);\n        document.addEventListener('pointercancel', onPointerUp);\n        fig._docListeners.push({ target: document, event: 'pointermove', handler: onPointerMove, options: undefined });\n        fig._docListeners.push({ target: document, event: 'pointerup', handler: onPointerUp, options: undefined });\n        fig._docListeners.push({ target: document, event: 'pointercancel', handler: onPointerUp, options: undefined });\n    }\n    // Freeze once the answer is revealed (answerInput.ts \"show answer\").\n    anchor.disable = function () {\n        panel.style.pointerEvents = 'none';\n        bodyDiv.style.cursor = 'default';\n        if (knob != null)\n            knob.style.cursor = 'default';\n    };\n    // Remove the panel when the manipulative itself is removed. A normal question\n    // transition never needs this (teardown clears the layer), but an explicit\n    // trash() would otherwise leave the DOM node floating over the next question.\n    anchor.trash = function () {\n        anchor.notificationHelper.cleanup();\n        if (panel.parentNode != null)\n            panel.parentNode.removeChild(panel);\n        anchor.parent.remove(anchor.name);\n    };\n    sync();\n    return anchor;\n};\nexport { htmlRuler, tickSteps, };\n","import { baseTenBlocks, } from './baseTenBlocks';\nimport { baseTenBlocksSlot, } from './baseTenBlocksSlot';\nimport { baseTenBlocksMenu, } from './baseTenBlocksMenu';\nimport { baseTenBlocksControl, } from './baseTenBlocksControl';\nimport { linearBlocks, } from './linearBlocks';\nimport { linearBlocksMenu, } from './linearBlocksMenu';\nimport { linearBlocksSlot, } from './linearBlocksSlot';\nimport { linearBlocksControl, } from './linearBlocksControl';\nimport { answerContainer, } from './answerContainer';\nimport { manipulativeTile, } from './tile';\nimport { manipulativeTileSlot, } from './tileSlot';\nimport { simpleBlock, } from './simpleBlock';\nimport { simpleBlockSlot, } from './simpleBlockSlot';\nimport { simpleBlockFillSlot, } from './simpleBlockFillSlot';\nimport { numberlineManipulative, } from './numberline';\nimport { hopManipulative, } from './hop';\nimport { selectorManipulative, } from './selector';\nimport { selectorControlManipulative, } from './selectorControl';\nimport { trashManipulative } from './trash';\nimport { timesTable, } from './timesTable';\nimport { rekenrek } from './rekenrek';\nimport { clock } from './clock';\nimport { entryField } from './entryField';\nimport { rekenrekControl, } from './rekenrekControl';\nimport { rekenrekMenu, } from './rekenrekMenu';\nimport { timesTableControl, } from './timesTableControl';\nimport { timesTableMenu, } from './timesTableMenu';\nimport { trashControlManipulative, } from './trashControl';\nimport { customSlot } from './customSlot';\nimport { templateManipulative, } from './templateManipulative';\nimport { poly } from './poly';\nimport { lineManipulative, } from './lineManipulative';\nimport { splittableShape, } from './splittableShape';\nimport { cube } from './cube';\nimport { cylinder } from './cylinder';\nimport { cone } from './cone';\nimport { sphere } from './sphere';\nimport { pyramid } from './pyramid';\nimport { prism } from './prism';\nimport { patternBlocks, } from './patternBlocks';\nimport { patternBlocksSlot, } from './patternBlocksSlot';\nimport { htmlRuler } from './htmlRuler';\nfunction addManipulative(manipulativeOptions) {\n    var manipulatives = {\n        linearBlocks: linearBlocks,\n        linearBlocksMenu: linearBlocksMenu,\n        linearBlocksSlot: linearBlocksSlot,\n        linearBlocksControl: linearBlocksControl,\n        baseTenBlocks: baseTenBlocks,\n        baseTenBlocksSlot: baseTenBlocksSlot,\n        baseTenBlocksMenu: baseTenBlocksMenu,\n        baseTenBlocksControl: baseTenBlocksControl,\n        answerContainer: answerContainer,\n        simpleBlock: simpleBlock,\n        simpleBlockSlot: simpleBlockSlot,\n        simpleBlockFillSlot: simpleBlockFillSlot,\n        manipulativeTile: manipulativeTile,\n        manipulativeTileSlot: manipulativeTileSlot,\n        numberlineManipulative: numberlineManipulative,\n        hopManipulative: hopManipulative,\n        selectorManipulative: selectorManipulative,\n        selectorControlManipulative: selectorControlManipulative,\n        trashManipulative: trashManipulative,\n        trashControlManipulative: trashControlManipulative,\n        timesTable: timesTable,\n        timesTableControl: timesTableControl,\n        timesTableMenu: timesTableMenu,\n        rekenrek: rekenrek,\n        rekenrekControl: rekenrekControl,\n        rekenrekMenu: rekenrekMenu,\n        entryField: entryField,\n        clock: clock,\n        customSlot: customSlot,\n        templateManipulative: templateManipulative,\n        cube: cube,\n        cylinder: cylinder,\n        cone: cone,\n        sphere: sphere,\n        pyramid: pyramid,\n        prism: prism,\n        poly: poly,\n        lineManipulative: lineManipulative,\n        splittableShape: splittableShape,\n        patternBlocks: patternBlocks,\n        patternBlocksSlot: patternBlocksSlot,\n        htmlRuler: htmlRuler,\n    };\n    // console.log(manipulativeOptions)\n    var manipulative = manipulativeOptions.manipulative, eqn = manipulativeOptions.eqn, options = manipulativeOptions.options;\n    // if (eqn == 'expression.elements.Tile1') {\n    //   eqn = 'expression.Tile1'\n    // }\n    // if (eqn == 'expression.elements.Tile2') {\n    //   eqn = 'expression.Tile2'\n    // }\n    var f = manipulativeOptions.figure != null ? manipulativeOptions.figure : figure;\n    // @ts-expect-error TS2345\n    return manipulatives[manipulative](eqn, options, f);\n}\nvar STOP_SCROLL_BOUNDS = {\n    left: 0.2,\n    right: 0.2,\n    bottom: 0.2,\n    top: 0.2,\n};\nvar SECONDARY_TOUCH_BOUNDS = {\n    left: 0.1,\n    right: 0.1,\n    bottom: 0.1,\n    top: 0.1,\n    priority: 1,\n};\n// Ray-casting point-in-polygon for a contour of {x, y} points (used by polygon\n// `secondaryTouchBounds`, e.g. the poly manipulative's near-touch area). The\n// contour is treated as closed.\nfunction pointInPolygon(pt, poly) {\n    var inside = false;\n    var j = poly.length - 1;\n    for (var i = 0; i < poly.length; i += 1) {\n        var xi = poly[i].x;\n        var yi = poly[i].y;\n        var xj = poly[j].x;\n        var yj = poly[j].y;\n        if ((yi > pt.y) !== (yj > pt.y) &&\n            pt.x < ((xj - xi) * (pt.y - yi)) / (yj - yi) + xi) {\n            inside = !inside;\n        }\n        j = i;\n    }\n    return inside;\n}\n// Perpendicular distance from a point to a line segment a-b.\nfunction distToSegment(pt, a, b) {\n    var dx = b.x - a.x;\n    var dy = b.y - a.y;\n    var len2 = dx * dx + dy * dy;\n    var t = len2 === 0 ? 0 : ((pt.x - a.x) * dx + (pt.y - a.y) * dy) / len2;\n    t = Math.max(0, Math.min(1, t));\n    var cx = a.x + t * dx;\n    var cy = a.y + t * dy;\n    return Math.sqrt(Math.pow((pt.x - cx), 2) + Math.pow((pt.y - cy), 2));\n}\n// How deep an (already-inside) point sits within a polygon: the distance to its\n// nearest edge. Used to rank overlapping near-touch polygons so the element the\n// touch is most squarely inside wins (e.g. two crossing line pads — the line whose\n// body the touch is nearest the centre of, rather than whichever draws on top).\nfunction polygonDepth(pt, poly) {\n    var d = Infinity;\n    var j = poly.length - 1;\n    for (var i = 0; i < poly.length; i += 1) {\n        d = Math.min(d, distToSegment(pt, poly[j], poly[i]));\n        j = i;\n    }\n    return d;\n}\n/**\n * In future, go through all elements each time, and select the element that is\n * closest to the\n */\nfunction teardownNearTouch() {\n    var stored = window.__nearTouchListeners;\n    if (stored) {\n        for (var _i = 0, stored_1 = stored; _i < stored_1.length; _i++) {\n            var _a = stored_1[_i], canvas = _a.canvas, event_1 = _a.event, handler = _a.handler;\n            canvas.removeEventListener(event_1, handler, false);\n        }\n    }\n    window.__nearTouchListeners = [];\n}\nfunction setupNearTouch(startIndex) {\n    if (startIndex === void 0) { startIndex = 0; }\n    // Remove previously attached near-touch listeners to avoid accumulation.\n    if (startIndex === 0) {\n        teardownNearTouch();\n    }\n    var select = function (event, f) {\n        // If an element touched is already being processed, then do nothing\n        if (f.beingTouchedElement != null) {\n            return;\n        }\n        // Get the figure point p of the touch\n        var pixelPoint;\n        if (event.touches != null) {\n            pixelPoint = f.clientToPixel(new Fig.Point(event.touches[0].clientX, event.touches[0].clientY));\n        }\n        else {\n            pixelPoint = f.clientToPixel(new Fig.Point(event.clientX, event.clientY));\n        }\n        var p = f.elements.pointFromSpaceToSpace(pixelPoint, 'pixel', 'figure');\n        var closestElement = {};\n        var closestDistance = {};\n        // let closestElement: null | FigureOneElement = null;\n        // let closestDistance: null | number = null;\n        var stopScroll = false;\n        function getTouchableElements(collection) {\n            var _a;\n            for (var i = collection.drawOrder.length - 1; i >= 0; i -= 1) {\n                var element = collection.elements[collection.drawOrder[i]];\n                if (element.isTouchable === true &&\n                    element.isShown &&\n                    element.custom.secondaryTouchBounds != null) {\n                    if (element.getPath() == 'workPad.tiles._space.move') {\n                        continue;\n                    }\n                    if (element.custom.secondaryTouchBounds == null) {\n                        continue;\n                    }\n                    // A polygon secondary touch bound (an array of points in the\n                    // element's draw space) grabs by point-in-polygon, so the near-touch\n                    // area follows the shape (e.g. the poly manipulative's outset\n                    // outline) rather than a bounding rectangle. The touch point is\n                    // mapped through the element's current transform, so it tracks\n                    // moves/reshapes.\n                    if (Array.isArray(element.custom.secondaryTouchBounds)) {\n                        var poly_1 = element.custom.secondaryTouchBounds;\n                        var drawPoint = element.pointFromSpaceToSpace(p, 'figure', 'draw');\n                        if (pointInPolygon(drawPoint, poly_1)) {\n                            stopScroll = true;\n                            var pr = SECONDARY_TOUCH_BOUNDS.priority.toString();\n                            // Rank by depth inside the polygon (deeper = closer to its centre), so\n                            // where two near-touch areas overlap the touch grabs the element it is\n                            // most squarely inside — not just whichever draws on top. Stored as a\n                            // negative distance so \"deepest\" sorts as \"closest\" alongside the\n                            // distance-to-bounds values the rectangle branch records.\n                            var dist = -polygonDepth(drawPoint, poly_1);\n                            if (closestElement[pr] == null || dist < ((_a = closestDistance[pr]) !== null && _a !== void 0 ? _a : Infinity)) {\n                                closestElement[pr] = element;\n                                closestDistance[pr] = dist;\n                            }\n                        }\n                        if (element.hasTouchableElements === true) {\n                            // @ts-expect-error: TS2345:\n                            var result = getTouchableElements(element);\n                            if (result) {\n                                return result;\n                            }\n                        }\n                        continue;\n                    }\n                    var bounds = void 0;\n                    if (element.custom.getBoundingRect) {\n                        bounds = element.custom.getBoundingRect('figure');\n                    }\n                    else {\n                        bounds = element.getBoundingRect('figure');\n                    }\n                    // Define the element's secondary touch bounds. Each element can have its\n                    // own custom bounds, or the default SECONDARY_TOUCH_BOUNDS will be used.\n                    // The custom bounds can either be defined as a number, or object with\n                    // 'left', 'right', 'bottom', 'top' keys.\n                    var s = SECONDARY_TOUCH_BOUNDS;\n                    if (typeof element.custom.secondaryTouchBounds !== 'boolean') {\n                        if (typeof element.custom.secondaryTouchBounds === 'number') {\n                            s.left = element.custom.secondaryTouchBounds;\n                            s.right = element.custom.secondaryTouchBounds;\n                            s.bottom = element.custom.secondaryTouchBounds;\n                            s.top = element.custom.secondaryTouchBounds;\n                            s.priority = SECONDARY_TOUCH_BOUNDS.priority;\n                        }\n                        else {\n                            s = element.custom.secondaryTouchBounds;\n                        }\n                    }\n                    // If the touch is within the secondary touch bounds of the element, then\n                    // set that element as clicked, and stop checking all remaining elements\n                    // in the figure\n                    if (!(p.x < bounds.left - s.left ||\n                        p.x > bounds.right + s.right ||\n                        p.y < bounds.bottom - s.bottom ||\n                        p.y > bounds.top + s.top)) {\n                        var deltaX = 0;\n                        var deltaY = 0;\n                        if (p.x > bounds.right) {\n                            deltaX = p.x - bounds.right;\n                        }\n                        else if (p.x < bounds.left) {\n                            deltaX = bounds.left - p.x;\n                        }\n                        if (p.y > bounds.top) {\n                            deltaY = p.y - bounds.top;\n                        }\n                        else if (p.y < bounds.bottom) {\n                            deltaY = bounds.bottom - p.y;\n                        }\n                        var distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n                        stopScroll = true;\n                        if (closestElement[s.priority.toString()] == null ||\n                            distance < closestDistance[s.priority]) {\n                            closestElement[s.priority.toString()] = element;\n                            closestDistance[s.priority.toString()] = distance;\n                        }\n                    }\n                    // If the the touch didn't go within the element move bounds, then check\n                    // if it within the stop scroll bounds\n                    if (stopScroll === false && closestDistance == null) {\n                        var s_1 = STOP_SCROLL_BOUNDS;\n                        if (!(p.x < bounds.left - s_1.left ||\n                            p.x > bounds.right + s_1.right ||\n                            p.y < bounds.bottom - s_1.bottom ||\n                            p.y > bounds.top + s_1.top)) {\n                            stopScroll = true;\n                        }\n                    }\n                }\n                if (element.hasTouchableElements === true) {\n                    // @ts-expect-error: TS2345:\n                    var result = getTouchableElements(element);\n                    if (result) {\n                        return result;\n                    }\n                }\n            }\n            return false;\n        }\n        getTouchableElements(f.elements);\n        var priorities = Object.keys(closestElement).sort();\n        if (priorities.length > 0) {\n            if (closestElement[priorities[0]] != null) {\n                f.notifications.publish('nearElementTouch');\n                f.selectElement(closestElement[priorities[0]], f.elements.pointFromSpaceToSpace(p, 'figure', 'gl'));\n            }\n        }\n        if (stopScroll) {\n            // console.log('Stop Scroll')\n            event.preventDefault();\n        }\n    };\n    if (!window.__nearTouchListeners) {\n        window.__nearTouchListeners = [];\n    }\n    var _loop_1 = function (i) {\n        var f = window.figureOneFigures[i];\n        // Dispatch against the figure whose canvas was touched. This used to be two\n        // fixed handlers — index 0 read figureOneFigures[0] and EVERY other index\n        // read figureOneFigures[1] — which is right for production (the main figure\n        // plus the workpad) but silently wrong on any page with three or more\n        // figures, where every figure from the third on resolved its near-touch\n        // against the workpad's coordinate space. The index is still looked up at\n        // EVENT time, not captured, so a figure that is replaced in place (the\n        // workpad is rebuilt at its own index) keeps working exactly as before.\n        var handler = function (event) {\n            select(event, window.figureOneFigures[i]);\n        };\n        f.htmlCanvas.addEventListener('touchstart', handler, false);\n        f.htmlCanvas.addEventListener('mousedown', handler, false);\n        window.__nearTouchListeners.push({ canvas: f.htmlCanvas, event: 'touchstart', handler: handler }, { canvas: f.htmlCanvas, event: 'mousedown', handler: handler });\n    };\n    for (var i = startIndex; i < window.figureOneFigures.length; i += 1) {\n        _loop_1(i);\n    }\n}\nexport default addManipulative;\nexport { setupNearTouch, teardownNearTouch };\n","// import request from './question/request/request';\n// import makeDiv from './session_summary/makeDiv';\n// import makeTitleLabelDiv from './session_summary/makeTitleLabelDiv';\nimport React from 'react';\nimport { useState } from 'react';\nimport { createRoot } from 'react-dom/client';\n// import TimelineData from './timeline/data';\n// import TimelineHeader from './timeline/header';\n// import TimelineFilters from './timeline/filters';\n// import {TypeOptions} from './timeline/tools';\nimport { joinObjects } from '../tools/joinObjects';\nimport { updateLastAction } from '../workpad_new/tools';\nimport addManipulative from './addManipulative';\n// import {getActions} from './timeline/filtersActions';\n// import {getModes, getMathSteps} from './timeline/filtersMathSteps';\n// import {getSessions} from './timeline/filtersSessions';\n// import {getSessionLogs} from './timeline/filtersLog';\n// import {getResults, getSessionAnswers, getSpeeds, getQuestions} from './timeline/filtersAnswers';\n// declare global {\n//   interface Window {\n//     snapshots_finished: boolean;\n//   }\n// }\n// function getDataFromId(id: string) {\n//   return JSON.parse(\n//     document.getElementById(id).textContent,\n//   );\n// }\nfunction createManipulativeControl(figureWP, workPad, manipulative) {\n    if (manipulative == null || manipulative.name == null) {\n        return;\n    }\n    if (workPad._tiles.elements[\"\".concat(manipulative.name)] == null) {\n        if (manipulative.name === 'linearBlocks') {\n            addManipulative({\n                manipulative: 'linearBlocksMenu',\n                options: Fig.joinObjects({\n                    name: 'linearBlocks',\n                    position: [-1.5, 0],\n                    justify: 'right',\n                    controls: ['trash'],\n                }, manipulative),\n                eqn: 'workPad.tiles',\n                figure: figureWP,\n            });\n        }\n        if (manipulative.name === 'baseTenBlocks') {\n            addManipulative({\n                manipulative: 'baseTenBlocksMenu',\n                options: Fig.joinObjects({\n                    name: 'baseTenBlocks',\n                    position: [-1.5, 0],\n                    justify: 'right',\n                    controls: ['trash', 'break'],\n                }, manipulative),\n                eqn: 'workPad.tiles',\n                figure: figureWP,\n            });\n        }\n        if (manipulative.name === 'timesTables') {\n            addManipulative({\n                manipulative: 'timesTableMenu',\n                options: Fig.joinObjects({\n                    name: 'timesTable',\n                    position: [-1.5, 0],\n                    justify: 'right',\n                    controls: ['trash'],\n                }, manipulative),\n                eqn: 'workPad.tiles',\n                figure: figureWP,\n            });\n        }\n        if (manipulative.name === 'rekenrek') {\n            addManipulative({\n                manipulative: 'rekenrekMenu',\n                options: Fig.joinObjects({\n                    name: 'rekenrek',\n                    position: [-1.5, 0],\n                    justify: 'right',\n                    controls: ['trash'],\n                }, manipulative),\n                eqn: 'workPad.tiles',\n                figure: figureWP,\n            });\n        }\n        // if (manipulative.name === 'linearHBlocks') {\n        //   addManipulative({\n        //     manipulative: 'linearHBlocksMenu',\n        //     options: { name: 'linearHBlocks', position: [-1.5, 0], justify: 'right' },\n        //     eqn: 'workPad.tiles',\n        //     figure: figureWP,\n        //   });\n        // }\n        // if (manipulative.name === 'linearVBlocks') {\n        //   addManipulative({\n        //     manipulative: 'linearVBlocksMenu',\n        //     options: { name: 'linearVBlocks', position: [0, -1], justify: 'top' },\n        //     eqn: 'workPad.tiles',\n        //     figure: figureWP,\n        //   });\n        // }\n    }\n}\nfunction Item(_a) {\n    var options = _a.options, updateOptions = _a.updateOptions, manipulative = _a.manipulative, workPad = _a.workPad, figureWP = _a.figureWP;\n    var classes = \"palette_table_col palette_icon palette_icon_\".concat(manipulative.name, \" \").concat(manipulative.name == options.select ? 'palette_icon_selected' : '');\n    var toggleDone = function () {\n        window.grokkoli.paletteTouchStart = null;\n    };\n    var onToggle = function (event) {\n        event.stopPropagation();\n        event.nativeEvent.stopImmediatePropagation();\n        if (window.grokkoli.paletteTouchStart != null &&\n            performance.now() - window.grokkoli.paletteTouchStart < 1000) {\n            return;\n        }\n        window.grokkoli.paletteTouchStart = performance.now();\n        if (options.select == manipulative.name) {\n            options.select = null;\n        }\n        else {\n            options.select = manipulative.name;\n        }\n        updateOptions(options);\n    };\n    if (options.select == manipulative.name) {\n        if (workPad._tiles.elements[\"\".concat(manipulative.name)] == null) {\n            createManipulativeControl(figureWP, workPad, manipulative);\n        }\n        if (manipulative.name === 'keypad') {\n            workPad._controlTiles.show();\n            workPad._controlTilesFill.show();\n            workPad._tiles._cursor.startBlinking();\n            workPad.custom.showHighlight = true;\n            updateLastAction(workPad, {\n                tile: null,\n                action: 'click',\n                position: new Fig.Point(0, 0),\n                cursorAnimateFrom: 1,\n            });\n            document.dispatchEvent(new CustomEvent('scroll'));\n            // workPad.custom.positionControls()\n            // } else {\n        }\n        workPad._tiles.elements[\"\".concat(manipulative.name)].show();\n        workPad._tiles.elements[\"\".concat(manipulative.name)].hasTouchableElements = true;\n        if (workPad._tiles.elements[\"\".concat(manipulative.name)].custom.controlElements !=\n            null) {\n            for (var i = 0; i <\n                workPad._tiles.elements[\"\".concat(manipulative.name)].custom.controlElements\n                    .length; i += 1) {\n                workPad._tiles.elements[\"\".concat(manipulative.name)].custom.controlElements[i].show();\n            }\n        }\n        // }\n    }\n    else {\n        if (manipulative.name === 'keypad') {\n            workPad._controlTiles.hide();\n            workPad._controlTilesFill.hide();\n            workPad._tiles._cursor.stopBlinking();\n            workPad.custom.showHighlight = false;\n            document.dispatchEvent(new CustomEvent('scroll'));\n            workPad._controlTiles.setPosition(1000, 1000);\n            workPad._controls.hide();\n            workPad._controlsFill.hide();\n            workPad._controls.setPosition(1000, 1000);\n        }\n        if (workPad._tiles.elements[\"\".concat(manipulative.name)] != null) {\n            workPad._tiles.elements[\"\".concat(manipulative.name)].hide();\n            workPad._tiles.elements[\"\".concat(manipulative.name)].hasTouchableElements =\n                false;\n            if (workPad._tiles.elements[\"\".concat(manipulative.name)].custom\n                .controlElements != null) {\n                for (var i = 0; i <\n                    workPad._tiles.elements[\"\".concat(manipulative.name)].custom.controlElements\n                        .length; i += 1) {\n                    workPad._tiles.elements[\"\".concat(manipulative.name)].custom.controlElements[i].hide();\n                }\n            }\n        }\n    }\n    return (React.createElement(\"td\", { className: \"palette-td-container\" },\n        React.createElement(\"div\", { className: classes, onTouchStart: onToggle, onMouseDown: onToggle, onClick: toggleDone })));\n}\nfunction Palette(_a) {\n    var manipulatives = _a.manipulatives, options = _a.options, updateOptions = _a.updateOptions, paletteOptions = _a.paletteOptions, workPad = _a.workPad, figureWP = _a.figureWP;\n    var rows = [];\n    var numRows = paletteOptions.yNum == null ? manipulatives.length : paletteOptions.yNum;\n    var numCols = paletteOptions.xNum == null ? manipulatives.length : paletteOptions.xNum;\n    for (var i = 0; i < numRows; i += 1) {\n        var columns = [];\n        for (var j = 0; j < numCols; j += 1) {\n            var index = i * numRows + j;\n            if (index > manipulatives.length - 1) {\n                columns.push(React.createElement(\"td\", null));\n            }\n            else {\n                columns.push(React.createElement(Item, { updateOptions: updateOptions, manipulative: manipulatives[index], options: options, workPad: workPad, figureWP: figureWP }));\n            }\n        }\n        var row = React.createElement(\"tr\", { className: \"palette_table_row\" }, columns);\n        rows.push(row);\n    }\n    return (React.createElement(\"div\", null,\n        React.createElement(\"table\", { className: \"palette_table\" }, rows)));\n}\nfunction addPalette(figureWP, workPad, manipulatives, paletteOptions) {\n    function MainComponent() {\n        var _a = useState({\n            select: paletteOptions.initialSelect,\n            // select: null,\n        }), options = _a[0], setOptions = _a[1];\n        var updateOptions = function (newOptions) {\n            // setOptions(JSON.parse(JSON.stringify(joinObjects(options, newOptions))));\n            setOptions(joinObjects({}, options, newOptions));\n        };\n        return (React.createElement(\"div\", { className: \"timeline_container\" },\n            React.createElement(Palette, { manipulatives: manipulatives, options: options, updateOptions: updateOptions, paletteOptions: paletteOptions, workPad: workPad, figureWP: figureWP })));\n    }\n    var paletteContainer = document.getElementById('manipulatives-palette');\n    var root = createRoot(paletteContainer);\n    root.render(React.createElement(MainComponent, null));\n    if (!window._grokkoliReactRoots)\n        window._grokkoliReactRoots = [];\n    window._grokkoliReactRoots.push(root);\n    workPad._controlTiles.setPosition(1000, 1000);\n    // Create all the menus in the palette for debug snapshots\n    // generating all the manipulatives\n    workPad.custom.createPalette = function () {\n        for (var i = 0; i < manipulatives.length; i += 1) {\n            var manipulative = manipulatives[i];\n            createManipulativeControl(figureWP, workPad, manipulative);\n        }\n    };\n}\nexport { createManipulativeControl, addPalette };\n","import { createEquation, setFontFamily } from '../tools/equation';\nimport { isPointInPolygon, getEllipseBorder, getClosestEllipsePoint, isPointInsideEllipse, isPointInsideRoundedRect, getClosestRoundedRectPoint, } from '../tools/geometry';\nimport { getRectangleBorder } from '../tools/getRectPoints';\nimport { doRectsOverlap } from '../workpad_new/tools';\nimport { getManipulativesMap } from './manage';\nimport { suppressManipulativeTouch, releaseManipulativeTouch, } from './tools';\nfunction makeSnapGrid(o) {\n    if (o.snaps == null) {\n        return [];\n    }\n    var points = [];\n    var snaps = o.snaps;\n    // Shift the whole grid (or explicit points) off-center. Useful for placing an\n    // auto grid into one part of a region (e.g. a Venn crescent) without dropping\n    // to explicit points. Applied in the same frame as the grid (region-local for\n    // regions, container-local for a plain container).\n    var gridOffset = snaps.offset != null\n        ? Fig.parsePoint(snaps.offset)\n        : new Fig.Point(0, 0);\n    if (snaps.points != null) {\n        for (var i = 0; i < snaps.points.length; i += 1) {\n            points.push(Fig.parsePoint(snaps.points[i]).add(gridOffset));\n        }\n        return points;\n    }\n    // Size and space default to 0 — harmless for a 1×1 layout (a single centered\n    // snap, where separation is multiplied by 0 anyway) and a sane fallback for\n    // any grid that omits them.\n    var size = snaps.size || [0, 0];\n    var space = Array.isArray(snaps.space)\n        ? snaps.space\n        : [snaps.space || 0, snaps.space || 0];\n    var xSeparation = size[0] + space[0];\n    var ySeparation = size[1] + space[1];\n    var xNum = snaps.order[1];\n    var yNum = snaps.order[0];\n    var topLeft = new Fig.Point(o.width / 2 - ((xNum - 1) * (space[0] + size[0])) / 2 + gridOffset.x, o.height - (o.height - (yNum - 1) * (space[1] + size[1])) / 2\n        + gridOffset.y);\n    if (snaps.fillOrder === 'rowFirst') {\n        for (var j = 0; j < yNum; j += 1) {\n            for (var i = 0; i < xNum; i += 1) {\n                points.push(new Fig.Point(topLeft.x + i * xSeparation, topLeft.y - j * ySeparation));\n            }\n        }\n    }\n    else {\n        for (var i = 0; i < xNum; i += 1) {\n            for (var j = 0; j < yNum; j += 1) {\n                points.push(new Fig.Point(topLeft.x + i * xSeparation, topLeft.y - j * ySeparation));\n            }\n        }\n    }\n    return points;\n}\n// Shoelace area of a closed polygon (sign-agnostic). Used to rank overlapping\n// regions so a tile in an intersection homes to the innermost (smallest) one.\nfunction polygonArea(points) {\n    var area = 0;\n    for (var i = 0; i < points.length; i += 1) {\n        var j = (i + 1) % points.length;\n        area += points[i].x * points[j].y - points[j].x * points[i].y;\n    }\n    return Math.abs(area) / 2;\n}\n// Resolve a region-label anchor component to a region-local coordinate.\n// Keywords map to an edge or the center of the dimension; a number is a\n// fraction (0..1) of the dimension. 'left'/'bottom' = 0, 'right'/'top' = dim,\n// 'center'/'middle' = dim/2.\nfunction resolveAnchor(v, dim, fallback) {\n    if (v == null)\n        return fallback;\n    if (typeof v === 'number')\n        return v * dim;\n    if (v === 'left' || v === 'bottom')\n        return 0;\n    if (v === 'right' || v === 'top')\n        return dim;\n    return dim / 2;\n}\nvar answerContainer = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var o = Fig.joinObjects({\n        fill: {\n            color: [0, 0, 0, 0],\n            show: true,\n            colorSelect: [0.96, 0.96, 1, 1],\n            colorCorrect: colors.COLOR_GROKKOLI_GREEN,\n            colorIncorrect: colors.COLOR_GROKKOLI_ORANGE,\n        },\n        style: 'rectangle',\n        width: 0.5,\n        height: 0.5,\n        yOffset: 0,\n        radius: 0.08,\n        sides: null,\n        borderSides: 15,\n        debug: false,\n        line: {\n            // dash: [0.1, 0.01],\n            color: [0.5, 0.5, 0.5, 1],\n            colorSelect: colors.COLOR_GROKKOLI_BLUE,\n            width: 0.01,\n            show: true,\n            colorCorrect: colors.COLOR_GROKKOLI_GREEN,\n            colorIncorrect: colors.COLOR_GROKKOLI_ORANGE,\n        },\n        label: '?',\n        xLabelOffset: 0,\n        yLabelOffset: 0,\n        font: {\n            size: 0.2,\n            color: [0.6, 0.6, 0.6, 1],\n            render: 'gl',\n            family: defaultFontFamilyMath,\n            style: 'normal',\n            weight: '400',\n        },\n        textFont: {\n            family: defaultFontFamily,\n            style: 'normal',\n            weight: '300',\n            render: 'gl',\n            color: [0.6, 0.6, 0.6, 1],\n        },\n        correctness: true,\n        snapTo: 'container',\n        snaps: null,\n        onRemove: null,\n        static: false,\n        drawOrder: true,\n    }, options);\n    var element = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var width = o.width;\n    var height = o.height;\n    var borderOffset = o.line.show ? o.line.width / 2 : 0;\n    if (o.sides == null) {\n        if (o.style === 'rectangle') {\n            o.sides = 10;\n        }\n        else if (o.style === 'ellipse') {\n            o.sides = 50;\n        }\n    }\n    if (o.style === 'rectangle') {\n        if (o.radius > Math.min(o.width / 2, o.height / 2)) {\n            o.radius = Math.min(o.width / 2, o.height / 2);\n        }\n    }\n    var fill;\n    if (o.fill.show) {\n        if (o.style === 'rectangle') {\n            fill = element.add({\n                make: 'rectangle',\n                name: 'fill',\n                width: width,\n                height: height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                color: o.fill.color,\n                corner: {\n                    radius: o.radius,\n                    sides: o.sides,\n                },\n                position: [borderOffset, o.yOffset],\n            });\n        }\n        else if (o.style === 'ellipse') {\n            fill = element.add({\n                make: 'ellipse',\n                name: 'fill',\n                width: width,\n                height: height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                color: o.fill.color,\n                sides: o.sides,\n                position: [borderOffset, o.yOffset],\n            });\n        }\n    }\n    var border;\n    if (o.line.show) {\n        if (o.style === 'rectangle') {\n            border = element.add({\n                make: 'rectangle',\n                name: 'border',\n                width: width,\n                height: height,\n                color: o.line.color,\n                line: { width: o.line.width, dash: o.line.dash },\n                xAlign: 'left',\n                yAlign: 'bottom',\n                corner: {\n                    radius: o.radius,\n                    sides: o.sides,\n                },\n                position: [borderOffset, o.yOffset],\n            });\n            border.custom.initialColor = border.color.slice();\n            if (o.borderInSize === false) {\n                border.border = [\n                    [\n                        new Fig.Point(0, 0),\n                        new Fig.Point(width, 0),\n                        new Fig.Point(width, height),\n                        new Fig.Point(0, height),\n                    ],\n                ];\n            }\n            element.custom.border = getRectangleBorder({\n                width: o.width,\n                height: o.height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                corner: {\n                    radius: o.radius,\n                    sides: Math.min(o.sides, 5),\n                },\n                offset: new Fig.Point(0, 0),\n            });\n        }\n        else if (o.style === 'ellipse') {\n            border = element.add({\n                make: 'ellipse',\n                name: 'border',\n                width: width,\n                height: height,\n                sides: o.sides,\n                color: o.line.color,\n                line: { width: o.line.width, dash: o.line.dash },\n                xAlign: 'left',\n                yAlign: 'bottom',\n                position: [borderOffset, o.yOffset],\n            });\n            border.custom.initialColor = border.color.slice();\n            element.custom.border = getEllipseBorder({\n                width: o.width,\n                height: o.height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                sides: o.borderSides,\n            });\n            element.custom.border.push(element.custom.border[0]);\n        }\n    }\n    // The hit-test polygon (used by doesContain) is normally built alongside the\n    // visible border. When the border is hidden (common for region containers,\n    // where the regions carry the visuals), build the bounding polygon anyway so\n    // outside manipulatives can still be detected as over the container.\n    if (element.custom.border == null) {\n        if (o.style === 'ellipse') {\n            element.custom.border = getEllipseBorder({\n                width: o.width,\n                height: o.height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                sides: o.borderSides,\n            });\n            element.custom.border.push(element.custom.border[0]);\n        }\n        else {\n            element.custom.border = getRectangleBorder({\n                width: o.width,\n                height: o.height,\n                xAlign: 'left',\n                yAlign: 'bottom',\n                corner: { radius: o.radius, sides: Math.min(o.sides, 5) },\n                offset: new Fig.Point(0, 0),\n            });\n        }\n    }\n    if (o.label) {\n        if (typeof o.label === 'string') {\n            setFontFamily(o.font, o.label);\n            element.add({\n                make: 'text',\n                name: 'label',\n                text: o.label,\n                font: o.font,\n                xAlign: 'center',\n                yAlign: 'middle',\n                position: [\n                    borderOffset + width / 2 + o.xLabelOffset,\n                    height / 2 + o.yLabelOffset + o.yOffset,\n                ],\n            });\n        }\n        else {\n            createEquation(element, Fig.joinObjects({}, o, {\n                position: [\n                    borderOffset + width / 2 + o.xLabelOffset,\n                    height / 2 + o.yLabelOffset + o.yOffset,\n                ],\n            }));\n        }\n    }\n    element.preserveChildColor = true;\n    // When static, leave manipulativeType unset so getAllAnswerContainers (and\n    // answerInput state collection) skip this container entirely. Discovery is\n    // by manipulativeType, so absence == invisible.\n    if (!o.static) {\n        element.custom.manipulativeType = 'answerContainer';\n    }\n    element.contained = []; // List of elements in this container\n    // Region pools: each declared region gets its own snap grid, occupancy, and\n    // container-local hit-test polygon. A dropped tile is homed into exactly one\n    // pool (see moveInside); grading reports occupants per region (see getState).\n    var pools = null;\n    // Grid mode auto-generates the cell regions (each becomes a normal region\n    // pool, so homing/grading/snapping all come for free) and captures the\n    // geometry needed to draw the frame, separators, and headings afterwards.\n    var regionDefs = o.regions || null;\n    var gridGeom = null;\n    if (o.grid != null) {\n        var g_1 = o.grid;\n        var sp = Array.isArray(g_1.space)\n            ? g_1.space\n            : [g_1.space || 0, g_1.space || 0];\n        var spaceX_1 = sp[0];\n        var spaceY_1 = sp[1];\n        var cellW_1 = g_1.cellWidth;\n        var cellH_1 = g_1.cellHeight;\n        var blockW = g_1.cols * cellW_1 + (g_1.cols - 1) * spaceX_1;\n        var blockH = g_1.rows * cellH_1 + (g_1.rows - 1) * spaceY_1;\n        var gridPos_1 = Fig.parsePoint(g_1.position || [0, 0]);\n        // Headings can extend to the *left* of the grid (negative local x): row\n        // headings always sit left of their row band, and a column heading wider than\n        // its cell overhangs left of its column. When a heading is included in the\n        // container's measured size (inSize === true), that left overhang otherwise\n        // reads as phantom space on the *right*: the measured width grows by the\n        // overhang but the content origin stays at the grid's left edge, so the grid\n        // sits at x=0 and the extra width hangs off the right. Shift the whole grid\n        // right by the largest overhang so the left-most heading edge sits at x=0 and\n        // no phantom space is added. Every grid element (cells, fills, separators,\n        // frame, snaps, headings) derives its x from gridPos, so shifting gridPos\n        // moves them together. (Column headings extend *up* from the grid top, which\n        // grows the box in the same direction as its origin, so they need no vertical\n        // correction — only this horizontal case.)\n        var measureTextWidth = function (text, font) {\n            var hf = Fig.joinObjects({}, o.font, font || {});\n            setFontFamily(hf, text);\n            var tmp = element.add({\n                make: 'text', name: '_head_measure',\n                text: text,\n                font: hf,\n            });\n            var w = tmp.getBoundingRect('local').width;\n            element.remove('_head_measure');\n            return w;\n        };\n        // Left edge of a text of width `w`, relative to its anchor, for an xAlign.\n        var alignLeft = function (xAlign, w) {\n            if (typeof xAlign === 'number')\n                return -xAlign * w;\n            if (xAlign === 'right')\n                return -w;\n            if (xAlign === 'center')\n                return -w / 2;\n            return 0; // 'left'\n        };\n        var overhang = 0;\n        // Row headings: anchor within the row band (default xPosition 'left' -> 0),\n        // text aligned right; the band's left is gridPos.x for every row.\n        if (g_1.rowHeadings != null && g_1.rowHeadings.labels != null\n            && g_1.rowHeadings.inSize === true) {\n            var h = g_1.rowHeadings;\n            var off = Fig.parsePoint(h.offset || [0, 0]);\n            var ax = resolveAnchor(h.xPosition, blockW, 0);\n            var xAlign = h.xAlign != null ? h.xAlign : 'right';\n            for (var rr = 0; rr < g_1.rows; rr += 1) {\n                var text = h.labels[rr];\n                if (text == null || text === '')\n                    continue;\n                var leftEdge = ax + off.x\n                    + alignLeft(xAlign, measureTextWidth(text, h.font));\n                if (-leftEdge > overhang)\n                    overhang = -leftEdge;\n            }\n        }\n        // Column headings: anchor within each column band (default xPosition center\n        // -> cellW/2), text centered. Band left for column c is c*(cellW+spaceX)\n        // relative to gridPos.x; only a heading wider than its column reaches left of\n        // gridPos.x (typically just column 0).\n        if (g_1.colHeadings != null && g_1.colHeadings.labels != null\n            && g_1.colHeadings.inSize === true) {\n            var h = g_1.colHeadings;\n            var off = Fig.parsePoint(h.offset || [0, 0]);\n            var ax = resolveAnchor(h.xPosition, cellW_1, cellW_1 / 2);\n            var xAlign = h.xAlign != null ? h.xAlign : 'center';\n            for (var cc = 0; cc < g_1.cols; cc += 1) {\n                var text = h.labels[cc];\n                if (text == null || text === '')\n                    continue;\n                var bandLeft = cc * (cellW_1 + spaceX_1);\n                var leftEdge = bandLeft + ax + off.x\n                    + alignLeft(xAlign, measureTextWidth(text, h.font));\n                if (-leftEdge > overhang)\n                    overhang = -leftEdge;\n            }\n        }\n        if (overhang > 0)\n            gridPos_1 = gridPos_1.add(new Fig.Point(overhang, 0));\n        var leftX = function (c) { return gridPos_1.x + c * (cellW_1 + spaceX_1); };\n        // Row 0 is the top row; cells stack downward.\n        var bottomY = function (rr) {\n            return gridPos_1.y + (g_1.rows - 1 - rr) * (cellH_1 + spaceY_1);\n        };\n        var snapTo = g_1.snapTo || 'snapInOrder';\n        var defs = [];\n        for (var rr = 0; rr < g_1.rows; rr += 1) {\n            for (var cc = 0; cc < g_1.cols; cc += 1) {\n                var idx = rr * g_1.cols + cc;\n                var cellColor = void 0;\n                if (g_1.cellFill != null && g_1.cellFill[idx] != null) {\n                    cellColor = g_1.cellFill[idx];\n                }\n                else if (g_1.colFill != null && g_1.colFill[cc] != null) {\n                    cellColor = g_1.colFill[cc];\n                }\n                else if (g_1.rowFill != null && g_1.rowFill[rr] != null) {\n                    cellColor = g_1.rowFill[rr];\n                }\n                else if (g_1.fill != null && g_1.fill.color != null) {\n                    cellColor = g_1.fill.color;\n                }\n                defs.push({\n                    name: \"r\".concat(rr, \"c\").concat(cc),\n                    style: 'rectangle',\n                    radius: 0,\n                    position: [leftX(cc), bottomY(rr)],\n                    width: cellW_1,\n                    height: cellH_1,\n                    fill: cellColor != null ? { color: cellColor } : undefined,\n                    snapTo: snapTo,\n                    onRemove: g_1.onRemove || null,\n                    snaps: g_1.snaps,\n                });\n            }\n        }\n        regionDefs = defs;\n        gridGeom = {\n            g: g_1,\n            gridPos: gridPos_1,\n            blockW: blockW,\n            blockH: blockH,\n            spaceX: spaceX_1,\n            spaceY: spaceY_1,\n            cellW: cellW_1,\n            cellH: cellH_1,\n            leftX: leftX,\n            bottomY: bottomY,\n        };\n    }\n    if (regionDefs != null) {\n        pools = [];\n        var _loop_1 = function (r) {\n            var region = regionDefs[r];\n            var offset = Fig.parsePoint(region.position || [0, 0]);\n            var regionStyle = region.style || 'rectangle';\n            var regionSides = region.sides != null\n                ? region.sides\n                : (regionStyle === 'ellipse' ? 50 : 10);\n            var regionDebug = o.debug || region.debug === true;\n            var regionBorder = void 0;\n            if (regionStyle === 'ellipse') {\n                regionBorder = getEllipseBorder({\n                    width: region.width,\n                    height: region.height,\n                    xAlign: 'left',\n                    yAlign: 'bottom',\n                    sides: regionSides,\n                }).map(function (p) { return p.add(offset); });\n                regionBorder.push(regionBorder[0]);\n            }\n            else {\n                regionBorder = getRectangleBorder({\n                    width: region.width,\n                    height: region.height,\n                    xAlign: 'left',\n                    yAlign: 'bottom',\n                    corner: { radius: region.radius || 0, sides: Math.min(regionSides, 5) },\n                    offset: offset,\n                });\n            }\n            // Adaptive pools build one layout per declared count; `grid` (the largest\n            // layout) is used for capacity / the union snaps / debug markers.\n            var layouts = null;\n            var grid = void 0;\n            if (region.snaps != null && region.snaps.adaptive != null) {\n                layouts = region.snaps.adaptive.map(function (entry) {\n                    return makeSnapGrid({\n                        width: region.width,\n                        height: region.height,\n                        snaps: entry,\n                    }).map(function (p) { return p.add(offset); });\n                });\n                grid = layouts.reduce(function (a, b) { return (b.length > a.length ? b : a); }, layouts[0] || []);\n            }\n            else {\n                grid = makeSnapGrid({\n                    width: region.width,\n                    height: region.height,\n                    snaps: region.snaps,\n                }).map(function (p) { return p.add(offset); });\n            }\n            // Optional per-region visuals.\n            if (region.fill != null) {\n                var fillOpts = {\n                    make: regionStyle === 'ellipse' ? 'ellipse' : 'rectangle',\n                    name: \"region_\".concat(region.name, \"_fill\"),\n                    width: region.width,\n                    height: region.height,\n                    xAlign: 'left',\n                    yAlign: 'bottom',\n                    color: region.fill.color || [0, 0, 0, 0],\n                    position: [borderOffset + offset.x, offset.y + o.yOffset],\n                };\n                if (regionStyle === 'ellipse') {\n                    fillOpts.sides = regionSides;\n                }\n                else {\n                    fillOpts.corner = { radius: region.radius || 0, sides: regionSides };\n                }\n                element.add(fillOpts);\n            }\n            if (region.line != null) {\n                var lineOpts_1 = {\n                    make: regionStyle === 'ellipse' ? 'ellipse' : 'rectangle',\n                    name: \"region_\".concat(region.name, \"_border\"),\n                    width: region.width,\n                    height: region.height,\n                    xAlign: 'left',\n                    yAlign: 'bottom',\n                    color: region.line.color || o.line.color,\n                    line: { width: region.line.width || o.line.width, dash: region.line.dash },\n                    position: [borderOffset + offset.x, offset.y + o.yOffset],\n                };\n                if (regionStyle === 'ellipse') {\n                    lineOpts_1.sides = regionSides;\n                }\n                else {\n                    lineOpts_1.corner = { radius: region.radius || 0, sides: regionSides };\n                }\n                element.add(lineOpts_1);\n            }\n            if (region.label) {\n                var lbl = typeof region.label === 'string'\n                    ? { label: region.label }\n                    : region.label;\n                if (lbl.label) {\n                    var labelFont = Fig.joinObjects({}, o.font, lbl.font || {});\n                    // Color precedence: label.color > font.color > figure font color\n                    // (fig.defaultColor). Falls back to the container font default only if\n                    // the figure has no default color.\n                    var labelColor = lbl.color\n                        || (lbl.font ? lbl.font.color : null)\n                        || fig.defaultColor;\n                    if (labelColor != null) {\n                        labelFont.color = labelColor;\n                    }\n                    setFontFamily(labelFont, lbl.label);\n                    var lblOffset = Fig.parsePoint(lbl.offset || [0, 0]);\n                    // Anchor within the region (defaults: top-center). Text alignment to\n                    // that anchor (defaults: bottom-center) makes a string label sit as a\n                    // centered header just above the region's top edge.\n                    var anchorX = resolveAnchor(lbl.xPosition, region.width, region.width / 2);\n                    var anchorY = resolveAnchor(lbl.yPosition, region.height, region.height);\n                    var labelEl = element.add({\n                        make: 'text',\n                        name: \"region_\".concat(region.name, \"_label\"),\n                        text: lbl.label,\n                        font: labelFont,\n                        xAlign: lbl.xAlign != null ? lbl.xAlign : 'center',\n                        yAlign: lbl.yAlign != null ? lbl.yAlign : 'bottom',\n                        position: [\n                            borderOffset + offset.x + anchorX + lblOffset.x,\n                            offset.y + anchorY + lblOffset.y + o.yOffset,\n                        ],\n                    });\n                    // By default keep the label out of the container's measured size (a\n                    // header above the region must not expand the container's bounds).\n                    // `inSize: true` opts the label back into the size.\n                    if (lbl.inSize !== true) {\n                        labelEl.border = [[]];\n                    }\n                }\n            }\n            if (regionDebug) {\n                // Outline the homing zone: the exact polygon isPointInPolygon tests\n                // against when deciding which region a dropped tile belongs to. Drawn\n                // in the same container-local frame as the hit test (no border/yOffset\n                // shift), so it shows the true catch boundary even for invisible\n                // regions and reveals any divergence from the visible border.\n                element.add({\n                    make: 'polyline',\n                    name: \"_debug_\".concat(region.name, \"_zone\"),\n                    points: regionBorder,\n                    close: true,\n                    width: 0.005,\n                    color: [1, 0, 1, 0.9],\n                });\n                for (var j = 0; j < grid.length; j += 1) {\n                    element.add({\n                        make: 'polygon',\n                        name: \"_debug_\".concat(region.name, \"_snap_\").concat(j),\n                        radius: 0.02,\n                        sides: 5,\n                        color: [0, 0, 1, 0.7],\n                        position: [grid[j].x, grid[j].y],\n                    });\n                }\n            }\n            // Adaptive: smallest positive y-gap among the capacity snaps → half of it\n            // is the row tolerance used to group snaps/tiles into rows when re-flowing.\n            var rowTol = Infinity;\n            if (layouts != null) {\n                var minDy = Infinity;\n                for (var a = 0; a < grid.length; a += 1) {\n                    for (var b = a + 1; b < grid.length; b += 1) {\n                        var dy = Math.abs(grid[a].y - grid[b].y);\n                        if (dy > 1e-6 && dy < minDy)\n                            minDy = dy;\n                    }\n                }\n                rowTol = minDy === Infinity ? Infinity : minDy / 2;\n            }\n            pools.push({\n                name: region.name,\n                border: regionBorder,\n                area: polygonArea(regionBorder),\n                snaps: grid,\n                occupants: grid.map(function () { return null; }),\n                snapToMode: region.snapTo === 'snap' ? 'snap' : 'snapInOrder',\n                onRemove: region.onRemove || null,\n                layouts: layouts || undefined,\n                tiles: layouts != null ? [] : undefined,\n                rowTol: rowTol,\n            });\n        };\n        for (var r = 0; r < regionDefs.length; r += 1) {\n            _loop_1(r);\n        }\n    }\n    // Draw the grid chrome (separators, outer frame, headings) on top of the cell\n    // fills produced by the pool loop above. Uses the same borderOffset/yOffset\n    // shift as the region visuals so it aligns with the generated cells.\n    if (gridGeom != null && o.grid != null) {\n        var g = o.grid;\n        var gridPos = gridGeom.gridPos, blockW = gridGeom.blockW, blockH = gridGeom.blockH, spaceX = gridGeom.spaceX, spaceY = gridGeom.spaceY, cellW = gridGeom.cellW, cellH = gridGeom.cellH, leftX = gridGeom.leftX, bottomY = gridGeom.bottomY;\n        var bx_1 = borderOffset;\n        var by_1 = o.yOffset;\n        if (g.separators !== false) {\n            var baseLine = { width: 0.01, color: [0.5, 0.5, 0.5, 1] };\n            var colLine = Fig.joinObjects({}, baseLine, g.line || {}, g.colLine || {});\n            var rowLine = Fig.joinObjects({}, baseLine, g.line || {}, g.rowLine || {});\n            for (var c = 1; c < g.cols; c += 1) {\n                var x = leftX(c) - spaceX / 2;\n                element.add({\n                    make: 'polyline',\n                    name: \"_grid_vline_\".concat(c),\n                    points: [\n                        [bx_1 + x, gridPos.y + by_1],\n                        [bx_1 + x, gridPos.y + blockH + by_1],\n                    ],\n                    width: colLine.width,\n                    color: colLine.color,\n                });\n            }\n            for (var r = 1; r < g.rows; r += 1) {\n                var y = bottomY(r) + cellH + spaceY / 2;\n                element.add({\n                    make: 'polyline',\n                    name: \"_grid_hline_\".concat(r),\n                    points: [\n                        [bx_1 + gridPos.x, y + by_1],\n                        [bx_1 + gridPos.x + blockW, y + by_1],\n                    ],\n                    width: rowLine.width,\n                    color: rowLine.color,\n                });\n            }\n        }\n        var frame = Fig.joinObjects({}, { width: 0.01, color: [0.5, 0.5, 0.5, 1], radius: 0.05, sides: 10 }, g.border || {});\n        element.add({\n            make: 'rectangle',\n            name: '_grid_frame',\n            width: blockW,\n            height: blockH,\n            xAlign: 'left',\n            yAlign: 'bottom',\n            color: frame.color,\n            line: { width: frame.width },\n            corner: { radius: frame.radius, sides: frame.sides },\n            position: [bx_1 + gridPos.x, gridPos.y + by_1],\n        });\n        // Headings — drawn out of size (border [[]]) so they never expand the\n        // container bounds. Anchor resolves within the row/column band; text\n        // alignment to that anchor follows the heading's xAlign/yAlign.\n        var addHeading = function (name, text, h, bandOx, bandOy, bandW, bandH, defXPos, defYPos, defXAlign, defYAlign) {\n            var hf = Fig.joinObjects({}, o.font, h.font || {});\n            var hc = h.color || (h.font ? h.font.color : null) || fig.defaultColor;\n            if (hc != null) {\n                hf.color = hc;\n            }\n            setFontFamily(hf, text);\n            var off = Fig.parsePoint(h.offset || [0, 0]);\n            var ax = resolveAnchor(h.xPosition, bandW, defXPos);\n            var ay = resolveAnchor(h.yPosition, bandH, defYPos);\n            var el = element.add({\n                make: 'text',\n                name: name,\n                text: text,\n                font: hf,\n                xAlign: h.xAlign != null ? h.xAlign : defXAlign,\n                yAlign: h.yAlign != null ? h.yAlign : defYAlign,\n                position: [bx_1 + bandOx + ax + off.x, bandOy + ay + off.y + by_1],\n            });\n            // Default: keep the heading out of the container's measured size.\n            if (h.inSize !== true) {\n                el.border = [[]];\n            }\n        };\n        if (g.rowHeadings != null && g.rowHeadings.labels != null) {\n            var h = g.rowHeadings;\n            for (var r = 0; r < g.rows; r += 1) {\n                var text = h.labels[r];\n                if (text == null || text === '')\n                    continue;\n                addHeading(\"_grid_rowhead_\".concat(r), text, h, gridPos.x, bottomY(r), blockW, cellH, 0, cellH / 2, 'right', 'middle');\n            }\n        }\n        if (g.colHeadings != null && g.colHeadings.labels != null) {\n            var h = g.colHeadings;\n            for (var c = 0; c < g.cols; c += 1) {\n                var text = h.labels[c];\n                if (text == null || text === '')\n                    continue;\n                addHeading(\"_grid_colhead_\".concat(c), text, h, leftX(c), gridPos.y, cellW, blockH, cellW / 2, blockH, 'center', 'bottom');\n            }\n        }\n    }\n    if (pools != null) {\n        // Container-level snaps are the union of all pools — read only by external\n        // capacity checks (getAllAnswerContainers callers compare\n        // contained.length >= snaps.length). Per-pool occupancy is the real source\n        // of truth. snapToMode is forced off 'container' so the \"full\" check in\n        // checkAnswerContainers stays active when every region is full.\n        element.snaps = [];\n        for (var i = 0; i < pools.length; i += 1) {\n            for (var j = 0; j < pools[i].snaps.length; j += 1) {\n                element.snaps.push(pools[i].snaps[j]);\n            }\n        }\n        element.snapToMode = 'snap';\n    }\n    else {\n        element.snaps = makeSnapGrid(o);\n        element.snapToMode = o.snapTo;\n    }\n    // Track which snap index is occupied by which manipulative (null = free).\n    // Legacy (non-region) placement path only; region placement uses pool\n    // occupants above.\n    var snapOccupants = [];\n    for (var i = 0; i < element.snaps.length; i += 1) {\n        snapOccupants.push(null);\n    }\n    if (o.debug && pools == null && element.snaps.length > 0) {\n        for (var i = 0; i < element.snaps.length; i += 1) {\n            element.add({\n                make: 'polygon',\n                name: \"_debug_snap_\".concat(i),\n                radius: 0.02,\n                sides: 5,\n                color: [1, 0, 0, 0.7],\n                position: [element.snaps[i].x, element.snaps[i].y],\n            });\n        }\n    }\n    element.getManipulativeBaseSnap = function () { return 'center'; };\n    element.getSnapPosition = function (snapIndex) {\n        return element.getPosition().add(element.snaps[snapIndex]);\n    };\n    // The next open spot: the first free snap, in figure space, or null when\n    // every snap is taken or the container has no plain snaps (region pools,\n    // 'container' mode). A manipulative dropped there goes to that snap in\n    // both 'snap' (nearest free) and 'snapInOrder' (first free) modes. The tap\n    // finger aims a dragged tile at it (see tapFinger's moveTo).\n    element.getNextFreeSnapPoint = function () {\n        if (pools != null || element.snaps.length === 0)\n            return null;\n        for (var i = 0; i < snapOccupants.length; i += 1) {\n            if (snapOccupants[i] == null) {\n                return element.pointFromSpaceToSpace(element.getPosition().add(element.snaps[i]), 'local', 'figure');\n            }\n        }\n        return null;\n    };\n    // Reference position used by the setTransform handler below to compute how\n    // far the container has moved since contained items were last positioned.\n    // The equation form's initial layout positions the container without firing\n    // setTransform, so we re-anchor this whenever an item is added/placed —\n    // those callsites run after layout in practice, so the reference is correct.\n    var lastPosition = element.getPosition();\n    // Place a manipulative at a snap and update bookkeeping. Touch is always\n    // suppressed *during* an animation so a rapid follow-up click on the source\n    // stack falls through to the next tile; the final state is governed by\n    // `makeTouchable`. If `snapIndex` is omitted, uses the first free snap\n    // (returns silently if none). Returns silently if the index is out of range\n    // or the container has no snaps.\n    // Core placement: move `manipulative` to snaps[index], recording it in\n    // occupants[index] and element.contained. Shared by the legacy\n    // container-level path (element.snaps/snapOccupants) and per-region pools.\n    // If `snapIndex` is omitted, uses the first free occupant slot.\n    var placeAtSnap = function (manipulative, snaps, occupants, snapIndex, duration, makeTouchable) {\n        if (duration === void 0) { duration = 0.5; }\n        if (makeTouchable === void 0) { makeTouchable = true; }\n        if (snaps.length === 0)\n            return;\n        var index = snapIndex;\n        if (index == null) {\n            index = -1;\n            for (var i = 0; i < occupants.length; i += 1) {\n                if (occupants[i] == null) {\n                    index = i;\n                    break;\n                }\n            }\n            if (index === -1)\n                return;\n        }\n        if (index < 0 || index >= snaps.length)\n            return;\n        var manipSnapPoint = manipulative.getSnapPosition(0);\n        var snapWorld = element.getPosition().add(snaps[index]);\n        var snapOffset = manipSnapPoint.sub(manipulative.getPosition());\n        var target = snapWorld.sub(snapOffset);\n        occupants[index] = manipulative;\n        if (element.contained.indexOf(manipulative) === -1) {\n            element.contained.push(manipulative);\n        }\n        lastPosition = element.getPosition();\n        if (duration === 0) {\n            manipulative.setPosition(target);\n            if (!makeTouchable) {\n                manipulative.hasTouchableElements = false;\n            }\n            return;\n        }\n        manipulative.custom.moved = true;\n        suppressManipulativeTouch(manipulative);\n        // Name the completion trigger via fnMap (owner = figure.elements, the root\n        // manager this animation runs on) so the touch-release survives speech\n        // pause/resume: an inline .trigger is dropped from figure.getState(), so a\n        // pause mid-move would land the tile but leave it permanently touch-suppressed\n        // (unbalanced suppress depth). Keyed per manipulative so concurrent placements\n        // don't clobber each other. beforeFrame stays inline (can't be a string).\n        var placeKey = \"acPlaceSnap:\".concat(manipulative.name);\n        figure.elements.fnMap.add(placeKey, function () {\n            releaseManipulativeTouch(manipulative);\n            if (!makeTouchable) {\n                manipulative.hasTouchableElements = false;\n            }\n        });\n        figure.elements.animations\n            .new()\n            .position({\n            element: manipulative,\n            target: target,\n            duration: duration,\n            beforeFrame: function () {\n                manipulative.custom.state.p = manipulative.getPosition().toArray(2);\n            },\n        })\n            .trigger({ callback: placeKey })\n            .start();\n    };\n    element.snapElement = function (manipulative, snapIndex, duration, makeTouchable) {\n        if (duration === void 0) { duration = 0.5; }\n        if (makeTouchable === void 0) { makeTouchable = true; }\n        placeAtSnap(manipulative, element.snaps, snapOccupants, snapIndex, duration, makeTouchable);\n    };\n    // Convenience wrapper for the static-container use case: place an item at\n    // a snap immediately and lock it (no animation, never touchable again).\n    element.staticSnapElement = function (manipulative, snapIndex) {\n        element.snapElement(manipulative, snapIndex, 0, false);\n    };\n    // Reveal the answer: hold `show` at snaps 0..n-1 and send everything else\n    // home. The container owns this (like baseTenBlocksSlot) instead of being\n    // driven tile-by-tile from answerInput's generic path. That path had to\n    // remove and re-add each tile as bookkeeping, and to a container with\n    // `onRemove: 'fillFromStart'` every removal reads as the learner taking a\n    // tile out -- so it compacted the survivors down an index and dragged the\n    // tiles still being revealed onto snap 0, stacking them into one. Here the\n    // whole layout is decided up front and then applied, so nothing reacts to\n    // anything mid-reveal.\n    //\n    // Region pools deliberately do NOT define this and stay on the generic path:\n    // a `show` payload carries no region, so a pooled container has nothing\n    // better to do with it than the union-of-snaps order that path already uses.\n    if (pools == null) {\n        element.showAnswer = function (show, showOptions) {\n            if (showOptions === void 0) { showOptions = {}; }\n            var duration = showOptions.test ? 0 : 1;\n            var map = getManipulativesMap();\n            var showList = Array.isArray(show) ? show : [show];\n            var wanted = [];\n            for (var i = 0; i < showList.length; i += 1) {\n                var manipulative = map[showList[i]];\n                if (manipulative != null && wanted.indexOf(manipulative) === -1) {\n                    wanted.push(manipulative);\n                }\n            }\n            var previous = element.contained.slice();\n            // Clear the bookkeeping BEFORE touching any tile: with `contained` empty\n            // and the occupants nulled, the per-tile removeFromContainer calls below\n            // return early on this container, so none of them can kick off a\n            // compaction that fights the placement.\n            element.contained.length = 0;\n            for (var i = 0; i < snapOccupants.length; i += 1) {\n                snapOccupants[i] = null;\n            }\n            for (var i = 0; i < wanted.length; i += 1) {\n                var manipulative = wanted[i];\n                if (manipulative.removeFromContainer != null) {\n                    manipulative.removeFromContainer();\n                }\n                var containers = manipulative.answerContainers;\n                // Registered synchronously (placeAtSnap only animates the move) so a\n                // guide running |hide_unsnapped| straight after the reveal still counts\n                // these as inside the container.\n                if (containers != null && containers.indexOf(element) === -1) {\n                    containers.push(element);\n                }\n                placeAtSnap(manipulative, element.snaps, snapOccupants, i, duration, false);\n            }\n            var _loop_2 = function (i) {\n                var manipulative = previous[i];\n                if (wanted.indexOf(manipulative) > -1) {\n                    return \"continue\";\n                }\n                if (manipulative.unsnap != null) {\n                    manipulative.unsnap();\n                }\n                // Clears the tile's own `answerContainers`, so a following\n                // |hide_unsnapped| treats it as outside and fades it out.\n                if (manipulative.removeFromContainer != null) {\n                    manipulative.removeFromContainer();\n                }\n                manipulative.custom.moved = true;\n                if (duration === 0) {\n                    manipulative.setPosition(manipulative.custom.initialPosition);\n                    manipulative.notifications.publish('stopBeingMoved');\n                    return \"continue\";\n                }\n                // Named via fnMap for the same reason as placeAtSnap: an inline trigger\n                // is dropped from figure.getState(), so a speech pause mid-move would\n                // lose it.\n                var homeKey = \"acShowAnswerHome:\".concat(manipulative.name);\n                figure.elements.fnMap.add(homeKey, function () {\n                    manipulative.notifications.publish('stopBeingMoved');\n                });\n                figure.elements.animations\n                    .new()\n                    .position({\n                    element: manipulative,\n                    target: manipulative.custom.initialPosition,\n                    duration: duration,\n                    beforeFrame: function () {\n                        manipulative.custom.state.p = manipulative\n                            .getPosition()\n                            .toArray(2);\n                    },\n                })\n                    .trigger({ callback: homeKey })\n                    .start();\n            };\n            for (var i = 0; i < previous.length; i += 1) {\n                _loop_2(i);\n            }\n            // Draw order, same as every other placement path (placeInPool, moveInside\n            // and the drop handler all call this). Without it a revealed tile keeps\n            // whatever z-order it happened to have, and a tile that has never been\n            // dropped into this container sits BEHIND the container's fill -- it\n            // animates correctly into place and is then simply not visible.\n            // Intermittent in practice: a tile the learner had already dropped was\n            // brought to the front by that drop, so only the ones showAnswer tops up\n            // on its own disappear.\n            applyDrawOrderTo(element.snaps, snapOccupants);\n        };\n    }\n    // Adaptive re-flow: move a tile to a container-local snap point, cancelling\n    // any in-flight re-flow animation first (and balancing the touch-suppression\n    // depth so a cancelled animation never leaves a tile permanently untouchable).\n    var moveTileToLocalSnap = function (tile, localSnap, duration) {\n        var manipSnapPoint = tile.getSnapPosition(0);\n        var snapWorld = element.getPosition().add(localSnap);\n        var snapOffset = manipSnapPoint.sub(tile.getPosition());\n        var target = snapWorld.sub(snapOffset);\n        // Animate on the GLOBAL animation manager, not the tile's own manager: when\n        // a tile is dropped it is the figure's beingMovedElement, and ending that\n        // move tears down the tile's per-element animations — which would silently\n        // kill a just-dropped tile's re-flow. The global manager is independent of\n        // the move lifecycle. A per-tile animation name lets a later re-flow cancel\n        // an in-flight one (preventing stacked, fighting position animations); the\n        // `acSuppressed` flag balances touch-suppression depth when we cancel\n        // before the prior animation's release trigger could fire.\n        var animName = \"acReflow_\".concat(tile.name);\n        figure.elements.animations.cancel(animName);\n        if (tile.custom.acSuppressed) {\n            releaseManipulativeTouch(tile);\n            tile.custom.acSuppressed = false;\n        }\n        if (duration === 0 || tile.getPosition().sub(target).distance() < 1e-4) {\n            tile.setPosition(target);\n            tile.custom.state.p = tile.getPosition().toArray(2);\n            return;\n        }\n        tile.custom.moved = true;\n        suppressManipulativeTouch(tile);\n        tile.custom.acSuppressed = true;\n        // fnMap-named trigger (owner = figure.elements) so the touch-release +\n        // acSuppressed reset survive speech pause/resume; an inline trigger drops the\n        // whole builder, leaving the tile stuck untouchable. Keyed per tile — reflows\n        // fire concurrently. beforeFrame stays inline.\n        var reflowKey = \"acReflowDone:\".concat(tile.name);\n        figure.elements.fnMap.add(reflowKey, function () {\n            releaseManipulativeTouch(tile);\n            tile.custom.acSuppressed = false;\n        });\n        figure.elements.animations\n            .new(animName)\n            .position({\n            element: tile,\n            target: target,\n            duration: duration,\n            beforeFrame: function () {\n                tile.custom.state.p = tile.getPosition().toArray(2);\n            },\n        })\n            .trigger({ callback: reflowKey })\n            .start();\n    };\n    // Re-flow an adaptive pool: pick the layout for the current tile count and\n    // assign every tile to a snap in reading order (top-to-bottom, left-to-right).\n    // Sorting tiles by their current position means a freshly dropped tile lands\n    // at the snap nearest its drop and the others slide to the remaining snaps.\n    var reflowPool = function (pool, animate) {\n        if (pool.layouts == null || pool.tiles == null)\n            return;\n        var n = pool.tiles.length;\n        if (n === 0)\n            return;\n        var layout = pool.layouts[Math.min(n, pool.layouts.length) - 1];\n        var tol = pool.rowTol != null ? pool.rowTol : Infinity;\n        var order = function (ay, ax, by, bx) {\n            if (Math.abs(ay - by) > tol)\n                return by - ay;\n            return ax - bx;\n        };\n        var snapsSorted = layout\n            .slice()\n            .sort(function (a, b) { return order(a.y, a.x, b.y, b.x); });\n        var pos = element.getPosition();\n        var tilesSorted = pool.tiles.slice().sort(function (a, b) {\n            var pa = a.getSnapPosition(0).sub(pos);\n            var pb = b.getSnapPosition(0).sub(pos);\n            return order(pa.y, pa.x, pb.y, pb.x);\n        });\n        for (var i = 0; i < tilesSorted.length && i < snapsSorted.length; i += 1) {\n            moveTileToLocalSnap(tilesSorted[i], snapsSorted[i], animate ? 0.4 : 0);\n        }\n        // tilesSorted is index-aligned with snapsSorted (reading order), so this is\n        // already the target reading order — front-most ends up bottom-right.\n        if (o.drawOrder !== false) {\n            bringToFrontInOrder(tilesSorted);\n        }\n        lastPosition = element.getPosition();\n    };\n    // Re-order draw (z) order: each tile is brought to the front in turn, so the\n    // last one (bottom-right in reading order) ends up front-most and the first\n    // (top-left) sits furthest back among them.\n    var bringToFrontInOrder = function (ordered) {\n        for (var i = 0; i < ordered.length; i += 1) {\n            var parent_1 = ordered[i].parent;\n            if (parent_1 != null && typeof parent_1.toFront === 'function') {\n                parent_1.toFront(ordered[i]);\n            }\n        }\n    };\n    // Draw-order for a fixed snap set: order occupants by their snap positions\n    // (exact coords, so no row tolerance needed) in reading order. Works for both\n    // region pools (pool.snaps/occupants) and the legacy container grid\n    // (element.snaps/snapOccupants).\n    var applyDrawOrderTo = function (snaps, occupants) {\n        if (o.drawOrder === false)\n            return;\n        var pairs = [];\n        for (var i = 0; i < occupants.length; i += 1) {\n            var occ = occupants[i];\n            if (occ != null) {\n                pairs.push({ tile: occ, y: snaps[i].y, x: snaps[i].x });\n            }\n        }\n        pairs.sort(function (a, b) { return (Math.abs(a.y - b.y) > 1e-6 ? b.y - a.y : a.x - b.x); });\n        bringToFrontInOrder(pairs.map(function (p) { return p.tile; }));\n    };\n    // A pool is full when its dense tile list (adaptive) or all its snap slots\n    // (fixed) are occupied.\n    var poolIsFull = function (pool) { return (pool.tiles != null\n        ? pool.tiles.length >= pool.snaps.length\n        : pool.occupants.indexOf(null) === -1); };\n    // Place a manipulative into a specific region pool and reflow. Adaptive pools\n    // append to the dense tile list and re-flow every tile into the layout for the\n    // new count; fixed pools take the nearest free snap ('snap') or the lowest free\n    // index ('snapInOrder'). Returns false if the pool has no room. Shared by\n    // moveInside (which picks the pool by position) and moveTileToRegion (by name).\n    var placeInPool = function (manipulative, home) {\n        if (home.layouts != null && home.tiles != null) {\n            if (home.tiles.indexOf(manipulative) === -1) {\n                home.tiles.push(manipulative);\n            }\n            if (element.contained.indexOf(manipulative) === -1) {\n                element.contained.push(manipulative);\n            }\n            reflowPool(home, true);\n            return true;\n        }\n        var manipSnapPoint = manipulative.getSnapPosition(0);\n        var bestIndex = -1;\n        if (home.snapToMode === 'snap') {\n            var bestDist = Infinity;\n            for (var i = 0; i < home.snaps.length; i += 1) {\n                if (home.occupants[i] != null)\n                    continue;\n                var d = element\n                    .getPosition()\n                    .add(home.snaps[i])\n                    .sub(manipSnapPoint)\n                    .distance();\n                if (d < bestDist) {\n                    bestDist = d;\n                    bestIndex = i;\n                }\n            }\n        }\n        else {\n            for (var i = 0; i < home.snaps.length; i += 1) {\n                if (home.occupants[i] == null) {\n                    bestIndex = i;\n                    break;\n                }\n            }\n        }\n        if (bestIndex === -1)\n            return false;\n        placeAtSnap(manipulative, home.snaps, home.occupants, bestIndex);\n        applyDrawOrderTo(home.snaps, home.occupants);\n        return true;\n    };\n    /**\n     * State is a list of names of contained elements\n     */\n    element.custom.getState = function () {\n        var contained = [];\n        for (var i = 0; i < element.contained.length; i += 1) {\n            contained.push(element.contained[i].name);\n        }\n        var state = { full: contained, partial: [] };\n        // Region membership is reported as sibling keys (state[regionName]) so\n        // get_manipulative_slots(key=regionName) reads each region directly.\n        // Membership is by home pool (disjoint), not geometry.\n        if (pools != null) {\n            for (var i = 0; i < pools.length; i += 1) {\n                var names = [];\n                var pool = pools[i];\n                if (pool.tiles != null) {\n                    // Adaptive: dense ordered tile list.\n                    for (var j = 0; j < pool.tiles.length; j += 1) {\n                        names.push(pool.tiles[j].name);\n                    }\n                }\n                else {\n                    for (var j = 0; j < pool.occupants.length; j += 1) {\n                        var occ = pool.occupants[j];\n                        if (occ != null) {\n                            names.push(occ.name);\n                        }\n                    }\n                }\n                state[pool.name] = names;\n            }\n        }\n        return state;\n    };\n    /**\n     * Correctness can be shown with the border or fill\n     * @param result\n     */\n    element.custom.showCorrectness = function (result) {\n        var _a, _b, _c, _d;\n        var correctColor = (_a = fig.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect;\n        var incorrectColor = (_b = fig.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect;\n        if (border != null && o.correctness) {\n            if (result === 1) {\n                border.setColor(correctColor || o.line.colorCorrect);\n            }\n            else {\n                border.setColor(incorrectColor || o.line.colorIncorrect);\n            }\n        }\n        if (fill != null && o.correctness) {\n            if (result === 1) {\n                fill.setColor(correctColor || o.fill.colorCorrect);\n            }\n            else {\n                fill.setColor(incorrectColor || o.fill.colorIncorrect);\n            }\n        }\n        for (var i = 0; i < element.contained.length; i += 1) {\n            (_d = (_c = element.contained[i].custom) === null || _c === void 0 ? void 0 : _c.showCorrectness) === null || _d === void 0 ? void 0 : _d.call(_c, result);\n        }\n    };\n    /**\n     * @param bounds\n     * @returns True if bounds is within the container bounds\n     */\n    element.isInBorder = function (bounds) {\n        // Use bounds for an initial check\n        var elementBorder = [];\n        if (bounds.rect != null) {\n            var elementRect = element.getBoundingRect();\n            var elementCenter = elementRect.center();\n            // If there is no rect overlap, then there is no chance the manipulative is\n            // over the container\n            if (!doRectsOverlap(elementRect, bounds.rect)) {\n                return false;\n            }\n            // If there is rect overlap, and the rectangle is being used, then the\n            // manipulative is over the container\n            if (o.style === 'rectangle' && o.radius < 0.05) {\n                return true;\n            }\n            // If we got here, we need to check if any corner of the manipulative\n            // rect border is inside the container border\n            var pos_1 = element.getPosition();\n            var rect = bounds.rect;\n            var rectBorder = [\n                new Fig.Point(rect.left, rect.bottom),\n                new Fig.Point(rect.left, rect.top),\n                new Fig.Point(rect.right, rect.top),\n                new Fig.Point(rect.right, rect.bottom),\n            ];\n            element.custom.border.forEach(function (p) {\n                return elementBorder.push(p.add(pos_1));\n            });\n            for (var i = 0; i < rectBorder.length; i += 1) {\n                if (isPointInPolygon(rectBorder[i], elementBorder)) {\n                    return true;\n                }\n            }\n            // For the ellipse or very rounded rect - there is a chance the end points of the\n            // rect corners will be outside the border, while the mid points are not.\n            // For example, imagine a large manipulative rectangle side just touching the\n            // left, bottom, top or right curve of the ellipse, or touching the flat surface\n            // of the rounded rect, where the radius is so large the distance between corners\n            // is longer than the flat side.\n            //\n            // It is already determined, the manipulative rect is inside the container rect.\n            // Therefore, we just need to check if the manipulative rect crosses either axis\n            // of the container\n            if ((rect.left < elementCenter.x && rect.right >= elementCenter.x) ||\n                (rect.bottom < elementCenter.y && rect.top >= elementCenter.y)\n            // rect.isPointInside(new Fig.Point(elementCenter.x, elementRect.bottom))\n            // || rect.isPointInside(new Fig.Point(elementCenter.x, elementRect.top))\n            // || rect.isPointInside(new Fig.Point(elementRect.left, elementCenter.y))\n            // || rect.isPointInside(new Fig.Point(elementRect.right, elementCenter.y))\n            ) {\n                return true;\n            }\n            return false;\n        }\n        if (elementBorder.length === 0) {\n            var pos_2 = element.getPosition();\n            element.custom.border.forEach(function (p) {\n                return elementBorder.push(p.add(pos_2));\n            });\n        }\n        if (bounds.points != null) {\n            var points = void 0;\n            if (!Array.isArray(bounds.points)) {\n                points = [bounds.points];\n            }\n            else {\n                points = bounds.points;\n            }\n            for (var i = 0; i < points.length; i += 1) {\n                if (isPointInPolygon(points[i], elementBorder)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    };\n    /**\n     * @param manipulative\n     * @returns True if manipuliatve bounds is within container bounds\n     */\n    element.doesContain = function (manipulative) {\n        if (element.isInBorder(manipulative.getContainerBounds())) {\n            return true;\n        }\n        return false;\n    };\n    /**\n     * Container highlights when a manipulative hovers over it\n     */\n    element.highlight = function () {\n        if (border != null) {\n            border.setColor(o.line.colorSelect);\n        }\n        if (fill != null) {\n            fill.setColor(o.fill.colorSelect);\n        }\n    };\n    element.unhighlight = function () {\n        if (border != null) {\n            border.setColor(o.line.color);\n        }\n        if (fill != null) {\n            fill.setColor(o.fill.color);\n        }\n    };\n    /**\n     * Add a manipulative to the container\n     * @param manipulative\n     */\n    element.addToContainer = function (manipulative) {\n        // contained is kept in append-order; for snapInOrder mode moveInside uses\n        // contained.indexOf(manipulative) as the preferred snap index, so this\n        // ordering is part of the public contract — don't reorder.\n        if (element.contained.indexOf(manipulative) === -1) {\n            element.contained.push(manipulative);\n        }\n        lastPosition = element.getPosition();\n        fig.answerChanged();\n    };\n    /**\n     * Remove a manipulative from the container\n     * @param manipulative\n     * @returns\n     */\n    element.removeFromContainer = function (manipulative) {\n        var _a, _b;\n        var index = element.contained.indexOf(manipulative);\n        if (index === -1) {\n            return;\n        }\n        element.contained.splice(index, 1);\n        // Any correctness colouring no longer applies once it's out (as for a tile\n        // slot's unsnap).\n        (_b = (_a = manipulative).resetColors) === null || _b === void 0 ? void 0 : _b.call(_a);\n        // Regions: clear the manipulative from its home pool and compact that pool\n        // independently (per-region onRemove).\n        if (pools != null) {\n            for (var p = 0; p < pools.length; p += 1) {\n                var pool = pools[p];\n                // Adaptive: drop the tile from the dense list and re-flow the rest into\n                // the layout for the new count.\n                // Remember where the tile came from, so a `swap` drop can send the tile\n                // it lands on back here (see swapOnDrop).\n                if (pool.tiles != null) {\n                    var ti = pool.tiles.indexOf(manipulative);\n                    if (ti === -1)\n                        continue;\n                    pool.tiles.splice(ti, 1);\n                    manipulative.custom.answerContainerOrigin = { container: element, pool: pool, index: ti };\n                    reflowPool(pool, true);\n                    break;\n                }\n                var occIndex = pool.occupants.indexOf(manipulative);\n                if (occIndex === -1)\n                    continue;\n                pool.occupants[occIndex] = null;\n                manipulative.custom.answerContainerOrigin = { container: element, pool: pool, index: occIndex };\n                if (pool.onRemove === 'fillFromStart') {\n                    var remaining = [];\n                    for (var i = 0; i < pool.occupants.length; i += 1) {\n                        if (pool.occupants[i] != null) {\n                            remaining.push(pool.occupants[i]);\n                        }\n                    }\n                    for (var i = 0; i < pool.occupants.length; i += 1) {\n                        var target = i < remaining.length ? remaining[i] : null;\n                        if (pool.occupants[i] !== target) {\n                            if (target != null) {\n                                placeAtSnap(target, pool.snaps, pool.occupants, i);\n                            }\n                            else {\n                                pool.occupants[i] = null;\n                            }\n                        }\n                    }\n                }\n                applyDrawOrderTo(pool.snaps, pool.occupants);\n                break;\n            }\n            // Re-ordering the tiles left behind brings them to the front, so put the\n            // removed (usually now being dragged) tile back above them.\n            bringToFrontInOrder([manipulative]);\n            fig.answerChanged();\n            return;\n        }\n        for (var i = 0; i < snapOccupants.length; i += 1) {\n            if (snapOccupants[i] === manipulative) {\n                snapOccupants[i] = null;\n            }\n        }\n        // True compaction: collect remaining occupants, write them back starting\n        // at index 0, animate any whose snap index changed. Works correctly even\n        // if pre-existing gaps were present (e.g. under snapTo: 'snap'), where\n        // shift-by-one would have left holes.\n        if (o.onRemove === 'fillFromStart') {\n            var remaining = [];\n            for (var i = 0; i < snapOccupants.length; i += 1) {\n                if (snapOccupants[i] != null) {\n                    remaining.push(snapOccupants[i]);\n                }\n            }\n            for (var i = 0; i < snapOccupants.length; i += 1) {\n                var target = i < remaining.length ? remaining[i] : null;\n                if (snapOccupants[i] !== target) {\n                    if (target != null) {\n                        element.snapElement(target, i);\n                    }\n                    else {\n                        snapOccupants[i] = null;\n                    }\n                }\n            }\n        }\n        applyDrawOrderTo(element.snaps, snapOccupants);\n        bringToFrontInOrder([manipulative]);\n        fig.answerChanged();\n    };\n    // `swap`: a tile dragged out of one region and dropped on top of a tile in a\n    // different region takes that tile's place, and that tile goes to the spot the\n    // dragged tile came from (recorded by removeFromContainer when the drag\n    // began). Only a tile that was picked up out of this container counts\n    // (`wasInContainer`, set by the tile on pickup), so a stale origin from an\n    // earlier programmatic removal is never used. Returns true if it swapped.\n    var swapOnDrop = function (manipulative) {\n        var _a, _b;\n        var origin = manipulative.custom.answerContainerOrigin;\n        manipulative.custom.answerContainerOrigin = undefined;\n        if (o.swap !== true || pools == null || origin == null\n            || origin.container !== element || manipulative.custom.wasInContainer !== true) {\n            return false;\n        }\n        // The tile it was dropped on: one whose bounds contain the dragged tile's\n        // centre, in a region other than the one it came from.\n        var point = manipulative.getBoundingRect('figure').center();\n        var target = null;\n        var targetPool = null;\n        var targetIndex = -1;\n        for (var i = 0; i < pools.length && target == null; i += 1) {\n            var pool = pools[i];\n            if (pool === origin.pool)\n                continue;\n            var tiles = pool.tiles != null ? pool.tiles : pool.occupants;\n            for (var j = 0; j < tiles.length; j += 1) {\n                var t = tiles[j];\n                if (t == null || t === manipulative)\n                    continue;\n                var r = t.getBoundingRect('figure');\n                if (point.x >= r.left && point.x <= r.right && point.y >= r.bottom && point.y <= r.top) {\n                    target = t;\n                    targetPool = pool;\n                    targetIndex = j;\n                    break;\n                }\n            }\n        }\n        if (target == null || targetPool == null)\n            return false;\n        (_b = (_a = target).resetColors) === null || _b === void 0 ? void 0 : _b.call(_a);\n        var from = origin.pool;\n        // Where the dropped-on tile goes: the dragged tile's old spot, or (if that's\n        // since been taken) the first free one. Bail out before changing anything if\n        // there's no room.\n        var fromIndex = -1;\n        if (from.tiles == null) {\n            fromIndex = from.occupants[origin.index] == null\n                ? origin.index : from.occupants.indexOf(null);\n            if (fromIndex === -1)\n                return false;\n        }\n        if (targetPool.tiles != null) {\n            targetPool.tiles[targetIndex] = manipulative;\n            if (element.contained.indexOf(manipulative) === -1)\n                element.contained.push(manipulative);\n            reflowPool(targetPool, true);\n        }\n        else {\n            targetPool.occupants[targetIndex] = null;\n            placeAtSnap(manipulative, targetPool.snaps, targetPool.occupants, targetIndex);\n            applyDrawOrderTo(targetPool.snaps, targetPool.occupants);\n        }\n        if (from.tiles != null) {\n            from.tiles.splice(Math.min(origin.index, from.tiles.length), 0, target);\n            reflowPool(from, true);\n        }\n        else {\n            placeAtSnap(target, from.snaps, from.occupants, fromIndex);\n            applyDrawOrderTo(from.snaps, from.occupants);\n        }\n        // While they animate, the dropped-on tile passes over everything else but\n        // under the dragged tile (the draw orders above would otherwise put it on\n        // top, so it jumps above the tile that was just dropped on it).\n        bringToFrontInOrder([target, manipulative]);\n        fig.answerChanged();\n        return true;\n    };\n    element.placeTapped = function (manipulative) {\n        manipulative.custom.answerContainerOrigin = undefined;\n        if (pools != null && o.tapPlacement === 'first') {\n            for (var i = 0; i < pools.length; i += 1) {\n                if (!poolIsFull(pools[i])) {\n                    placeInPool(manipulative, pools[i]);\n                    return;\n                }\n            }\n            return;\n        }\n        element.moveInside(manipulative);\n    };\n    element.moveInside = function (manipulative) {\n        if (swapOnDrop(manipulative))\n            return;\n        // Regions: home the tile into one pool. Prefer the smallest-area region\n        // whose polygon contains the tile's snap point and still has a free snap\n        // (so an intersection homes to the innermost region); otherwise fall back\n        // to the pool with the nearest free snap. Then place within that pool's own\n        // ordering ('snapInOrder' = lowest free index, 'snap' = nearest free snap).\n        if (pools != null) {\n            var manipSnapPoint = manipulative.getSnapPosition(0);\n            var local = manipSnapPoint.sub(element.getPosition());\n            var home = null;\n            var homeArea = Infinity;\n            for (var i = 0; i < pools.length; i += 1) {\n                var pool = pools[i];\n                if (poolIsFull(pool))\n                    continue;\n                if (isPointInPolygon(local, pool.border) && pool.area < homeArea) {\n                    home = pool;\n                    homeArea = pool.area;\n                }\n            }\n            if (home == null) {\n                var bestDist = Infinity;\n                for (var i = 0; i < pools.length; i += 1) {\n                    var pool = pools[i];\n                    if (poolIsFull(pool))\n                        continue;\n                    for (var j = 0; j < pool.snaps.length; j += 1) {\n                        if (pool.tiles == null && pool.occupants[j] != null)\n                            continue;\n                        var d = element\n                            .getPosition()\n                            .add(pool.snaps[j])\n                            .sub(manipSnapPoint)\n                            .distance();\n                        if (d < bestDist) {\n                            bestDist = d;\n                            home = pool;\n                        }\n                    }\n                }\n            }\n            if (home == null)\n                return; // every pool full\n            // Placement + reflow (adaptive or fixed) is shared with moveTileToRegion.\n            placeInPool(manipulative, home);\n            return;\n        }\n        // 'snap' / 'snapInOrder' modes: animate to a free snap position\n        if ((o.snapTo === 'snap' || o.snapTo === 'snapInOrder') &&\n            element.snaps.length > 0) {\n            var manipSnapPoint = manipulative.getSnapPosition(0);\n            var bestIndex = -1;\n            // If this manipulative is already in `contained`, prefer that index —\n            // `contained` is the synchronous source of truth and avoids a race where\n            // a second click arrives before the previous animation marks its snap.\n            var containedIndex = element.contained.indexOf(manipulative);\n            if (o.snapTo === 'snapInOrder' &&\n                containedIndex !== -1 &&\n                containedIndex < element.snaps.length &&\n                snapOccupants[containedIndex] == null) {\n                bestIndex = containedIndex;\n            }\n            else if (o.snapTo === 'snapInOrder') {\n                for (var i = 0; i < element.snaps.length; i += 1) {\n                    if (snapOccupants[i] == null) {\n                        bestIndex = i;\n                        break;\n                    }\n                }\n            }\n            else {\n                var bestDist = Infinity;\n                for (var i = 0; i < element.snaps.length; i += 1) {\n                    if (snapOccupants[i] != null)\n                        continue;\n                    var snapWorld = element.getPosition().add(element.snaps[i]);\n                    var d = snapWorld.sub(manipSnapPoint).distance();\n                    if (d < bestDist) {\n                        bestDist = d;\n                        bestIndex = i;\n                    }\n                }\n            }\n            if (bestIndex === -1)\n                return; // all snaps occupied\n            element.snapElement(manipulative, bestIndex);\n            applyDrawOrderTo(element.snaps, snapOccupants);\n            return;\n        }\n        // 'container' mode (default): keep manipulative inside the border\n        var rect;\n        if (manipulative.custom.getBoundingRect) {\n            rect = manipulative.custom.getBoundingRect('local');\n        }\n        else {\n            rect = manipulative.getBoundingRect('local');\n        }\n        var center = element.getBoundingRect().center();\n        // Get the furthest point of the manipulative by comparing the manipulative center\n        // to the container center. Furthest point is in local coordinates\n        var manipulativeCenter = rect.center();\n        var x = manipulativeCenter.x < center.x ? rect.left : rect.right;\n        var y = manipulativeCenter.y < center.y ? rect.bottom : rect.top;\n        var furthestPoint = new Fig.Point(x, y);\n        // If the furthest Point is already in the ellipse, then do nothing\n        if (o.style === 'ellipse' &&\n            isPointInsideEllipse(furthestPoint.sub(center), o.width, o.height)) {\n            return;\n            // If the furthest Point is already in the rect, then do nothing\n        }\n        else if (o.style === 'rectangle' &&\n            isPointInsideRoundedRect(furthestPoint.sub(center), o.width, o.height, o.radius)) {\n            return;\n        }\n        // deltaFromBottomLeft is the new position the farthest point must move to relative\n        // to the bottom left corner of the container\n        var deltaFromBottomLeft;\n        var f = furthestPoint.sub(element.getPosition());\n        if (o.style === 'ellipse') {\n            deltaFromBottomLeft = Fig.parsePoint(getClosestEllipsePoint(f.x, f.y, rect.width, rect.height, o.width, o.height));\n        }\n        else if (o.style === 'rectangle') {\n            deltaFromBottomLeft = Fig.parsePoint(getClosestRoundedRectPoint(f.x, f.y, rect.width, rect.height, o.width, o.height, o.radius));\n        }\n        // pos converts the deltaFromBottomLeft into a local position for the element\n        // to move to\n        var pos = element\n            .getPosition()\n            .add(deltaFromBottomLeft)\n            .sub(furthestPoint.sub(new Fig.Point(rect.left, rect.bottom)));\n        manipulative.custom.moved = true;\n        suppressManipulativeTouch(manipulative);\n        // fnMap-named trigger (owner = figure.elements) so the touch-release survives\n        // speech pause/resume; an inline trigger drops the whole builder, leaving the\n        // tile stuck untouchable. Keyed per manipulative — moves fire concurrently.\n        var insideKey = \"acMoveInside:\".concat(manipulative.name);\n        figure.elements.fnMap.add(insideKey, function () {\n            releaseManipulativeTouch(manipulative);\n        });\n        figure.elements.animations\n            .new()\n            .position({\n            element: manipulative,\n            target: pos,\n            duration: 0.5,\n            beforeFrame: function () {\n                manipulative.custom.state.p = manipulative.getPosition().toArray(2);\n            },\n        })\n            .trigger({ callback: insideKey })\n            .start();\n    };\n    // Register a manipulative in this container and animate it to its place: the\n    // next free snap, or — for adaptive regions — into the layout for the new tile\n    // count, re-flowing the already-placed tiles concurrently (moveInside →\n    // reflowPool animates every tile, incoming and existing, at once). Thin public\n    // entry over addToContainer + moveInside; a tile's moveToContainer() wraps this\n    // after detaching the tile from any previous container. Assumes the tile is not\n    // already placed elsewhere (the caller detaches first).\n    element.moveTile = function (manipulative) {\n        if (manipulative.answerContainers == null) {\n            manipulative.answerContainers = [];\n        }\n        if (manipulative.answerContainers.indexOf(element) === -1) {\n            manipulative.answerContainers.push(element);\n        }\n        element.addToContainer(manipulative);\n        element.moveInside(manipulative);\n    };\n    // Home a manipulative into a NAMED region pool (adaptive reflow), instead of\n    // moveInside's position-based homing. Returns false if the region is unknown or\n    // full. Assumes the tile has been detached from any prior container/region\n    // (tile.moveToRegion does that first). No pre-positioning needed — the pool's\n    // layout (adaptive) or nearest free snap decides the final position.\n    element.moveTileToRegion = function (manipulative, regionName) {\n        if (pools == null)\n            return false;\n        var home = null;\n        for (var i = 0; i < pools.length; i += 1) {\n            if (pools[i].name === regionName) {\n                home = pools[i];\n                break;\n            }\n        }\n        if (home == null || poolIsFull(home))\n            return false;\n        if (manipulative.answerContainers == null) {\n            manipulative.answerContainers = [];\n        }\n        if (manipulative.answerContainers.indexOf(element) === -1) {\n            manipulative.answerContainers.push(element);\n        }\n        return placeInPool(manipulative, home);\n    };\n    if (pools != null) {\n        var regionPools_1 = pools;\n        element.swapTiles = function (a, b) {\n            var _a, _b;\n            var map = getManipulativesMap();\n            var tileA = typeof a === 'string' ? map[a] : a;\n            var tileB = typeof b === 'string' ? map[b] : b;\n            if (tileA == null || tileB == null || tileA === tileB)\n                return false;\n            var find = function (m) {\n                for (var i = 0; i < regionPools_1.length; i += 1) {\n                    var tiles_1 = regionPools_1[i].tiles != null ? regionPools_1[i].tiles : regionPools_1[i].occupants;\n                    var index = tiles_1.indexOf(m);\n                    if (index !== -1)\n                        return { pool: regionPools_1[i], index: index };\n                }\n                return null;\n            };\n            var at = [find(tileA), find(tileB)];\n            if (at[0] == null || at[1] == null)\n                return false;\n            var tiles = [tileA, tileB];\n            for (var i = 0; i < 2; i += 1) {\n                tiles[i].custom.answerContainerOrigin = undefined;\n                (_b = (_a = tiles[i]).resetColors) === null || _b === void 0 ? void 0 : _b.call(_a);\n                // Free both spots first, so placeAtSnap can take them.\n                var _c = at[i], pool = _c.pool, index = _c.index;\n                if (pool.tiles == null)\n                    pool.occupants[index] = null;\n            }\n            var changed = [];\n            for (var i = 0; i < 2; i += 1) {\n                var tile = tiles[1 - i];\n                var _d = at[i], pool = _d.pool, index = _d.index;\n                if (pool.tiles != null) {\n                    pool.tiles[index] = tile;\n                }\n                else {\n                    placeAtSnap(tile, pool.snaps, pool.occupants, index);\n                }\n                if (changed.indexOf(pool) === -1)\n                    changed.push(pool);\n            }\n            for (var i = 0; i < changed.length; i += 1) {\n                if (changed[i].tiles != null) {\n                    reflowPool(changed[i], true);\n                }\n                else {\n                    applyDrawOrderTo(changed[i].snaps, changed[i].occupants);\n                }\n            }\n            // While they animate, both pass over every other tile.\n            bringToFrontInOrder(tiles);\n            fig.answerChanged();\n            return true;\n        };\n    }\n    element.custom.toPulse = function (pulseOptions) {\n        for (var i = 0; i < element.contained.length; i += 1) {\n            element.contained[i].animations.new().pulse(pulseOptions).start();\n        }\n    };\n    // Keep contained manipulatives aligned with the container as it moves.\n    // Snap positions are stored container-local, so shifting each contained\n    // manipulative by the container's positional delta preserves their snap\n    // alignment (or, in 'container' mode, their relative placement inside).\n    element.notifications.add('setTransform', function () {\n        var currentPosition = element.getPosition();\n        var delta = currentPosition.sub(lastPosition);\n        if (delta.x === 0 && delta.y === 0)\n            return;\n        lastPosition = currentPosition;\n        for (var i = 0; i < element.contained.length; i += 1) {\n            var m = element.contained[i];\n            m.setPosition(m.getPosition().add(delta));\n        }\n    });\n    return element;\n};\nexport { answerContainer, };\n","var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n        if (ar || !(i in from)) {\n            if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n            ar[i] = from[i];\n        }\n    }\n    return to.concat(ar || Array.prototype.slice.call(from));\n};\nimport submitAnswer from '../answer/submitAnswer';\nimport { getAnswerInfoInputResult } from '../answerInputs/answerInfo';\nimport { create_button } from '../tools/createButton';\nimport { getManipulativeSlotsState, \n// getManipulativeSlots,\ngetManipulatives, getManipulativesState, getManipulativeSlotsMap, getManipulativesMap, getManipulativesValueMap, } from './manage';\n// ManipulativeSlotShowAnswer\nfunction getElements(fig, elementNameOrNames) {\n    var out = [];\n    var elementNames = typeof elementNameOrNames === 'string'\n        ? [elementNameOrNames]\n        : elementNameOrNames;\n    for (var i = 0; i < elementNames.length; i += 1) {\n        var name_1 = elementNames[i];\n        var e = void 0;\n        if (name_1.indexOf('.') > -1) {\n            e = figure.elements.getElements(name_1);\n            if (e.length > 0) {\n                out.push(e[0]);\n                continue;\n            }\n            if (figure.elements._expression != null) {\n                e = figure.elements._expression.getElements(name_1);\n                if (e.length > 0) {\n                    out.push(e[0]);\n                    continue;\n                }\n            }\n        }\n        e = figure.elements.elements[name_1];\n        if (e != null) {\n            out.push(e);\n            continue;\n        }\n        if (figure.elements._expression != null) {\n            e = figure.elements._expression.elements[name_1];\n            if (e != null) {\n                out.push(e);\n                continue;\n            }\n        }\n    }\n    return out;\n}\nfunction createManipulativeAnswerInput(position, options, autoSetup, name, answer_input_type) {\n    if (autoSetup === void 0) { autoSetup = true; }\n    if (name === void 0) { name = 'answer_input_manipulative'; }\n    if (answer_input_type === void 0) { answer_input_type = 'manipulative'; }\n    var answer_input = figure.add({\n        make: 'collection',\n        name: name,\n        position: position,\n    });\n    answer_input.custom._answer_input = answer_input_type;\n    answer_input.custom.style = 'submit';\n    answer_input.showAnswer = function (answerToShow) { };\n    var submitButton = create_button([0, 0], 'Submit', 0.5, 'submit', {}, 0.2, 1, 1, answer_input, 0.11);\n    // answer_input.custom.disableInteraction = () => {\n    //   figure.elements.animations.cancel('answerInputFadeIn');\n    // We need to stop any animations started by enableInteraction first\n    // submitButton._fill.animations.cancelAll();\n    // answer_input._continue._fill.animations.cancelAll();\n    // submitButton._fill.setColor([0.5, 0.5, 0.5, 1]);\n    // answer_input._continue._fill.setColor([0.5, 0.5, 0.5, 1]);\n    // }\n    // answer_input.custom.enableInteraction = () => {\n    // if (submitButton.isShown) {\n    //   submitButton._fill.animations.new()\n    //     .color({target: colors.COLOR_GROKKOLI_BLUE, duration: 1})\n    //     .start();\n    // } else {\n    //   submitButton._fill.setColor(colors.COLOR_GROKKOLI_BLUE);\n    // }\n    // if (answer_input._continue.isShown) {\n    //   answer_input._continue._fill.animations.new()\n    //     .color({target: colors.COLOR_GROKKOLI_BLUE, duration: 1})\n    //     .start();\n    // } else {\n    //   answer_input._continue._fill.setColor(colors.COLOR_GROKKOLI_BLUE)\n    // }\n    //   answer_input.hasTouchableElements = true;\n    //   answer_input.animations.new()\n    //     .opacity({target: 1, duration: 1})\n    //     .start();\n    // }\n    answer_input.custom.getCorrectnessElements = function () {\n        if (options.correctness == null) {\n            return null;\n        }\n        return getElements(figure, options.correctness);\n    };\n    answer_input.custom.setupSubmitClicked = function (callback) {\n        submitButton.notifications.add('onClick', function () {\n            window.clickHandled = true;\n            figure.stop('complete');\n            // answer_input.hasTouchableElements = false;\n            figure.custom.bubble.tag(submitButton.getPath());\n            var answer = callback();\n            figure.notifications.publish('submitButtonClicked');\n            // if (figure.custom._keyboard_div) {\n            //   figure.custom._keyboard_div.style.visibility = 'hidden';\n            // }\n            // if (figure.custom._keyboard_input) {\n            //   figure.custom._keyboard_input = null;\n            //   figure.notifications.publish('keyboardChange');\n            // }\n            // console.log(answer)\n            submitAnswer({ answer: answer }, true, answer_input.getPath());\n        });\n        figure.custom.getSubmittedAnswer = function () { return callback(); };\n        window.helpAnswerYes = { submit: function () {\n                window.clickHandled = true;\n                figure.stop('complete');\n                figure.custom.bubble.tag(submitButton.getPath());\n                submitAnswer({ answer: Fig.joinObjects({ help: true }, callback()) }, true, answer_input.getPath());\n            } };\n    };\n    if (autoSetup) {\n        answer_input.custom.setupSubmitClicked(getManipulativesState);\n    }\n    answer_input.custom.showCorrectness = function () { };\n    answer_input.custom.showAnswerInfo = function () { };\n    // figure.notifications.add('ready', () => {\n    // });\n    var continueButton = create_button([0, 0], 'Continue', 0.6, 'continue', {}, 0.2, 1, 1, answer_input, 0.11, 0.02);\n    if (options.continueOffset != null) {\n        continueButton.setPosition(continueButton.getPosition().add(options.continueOffset[0], options.continueOffset[1]));\n    }\n    continueButton.custom.type = 'button_continue';\n    continueButton.notifications.add('onClick', function () {\n        window.clickHandled = true;\n        continueButton.custom.canBeDisabled = true;\n        submitAnswer({ answer: true }, true, answer_input.getPath());\n        // continueButton.animations\n        //   .new()\n        //   .color({\n        //     element: continueButton._fill,\n        //     target: [0.5, 0.5, 0.5, 1],\n        //     duration: 0.2,\n        //   })\n        //   .start();\n        // continueButton.isTouchable = false;\n    });\n    continueButton.color[3] = 0;\n    continueButton.isTouchable = false;\n    // Keep the (hidden) continue button out of the generic disable/enable cycle\n    // until finishShow legitimately reveals it. Otherwise, if it gets swept into\n    // the figure's wasDisabled bookkeeping, a guide-speech `playFinished` ->\n    // enableInteraction can flip its isTouchable to true while it's still\n    // invisible (overlapping the submit), letting a stray tap submit `true`.\n    // finishShow sets this same flag; the continue's own onClick re-enables it.\n    continueButton.custom.canBeDisabled = false;\n    continueButton.hide();\n    // continueButton.custom.enableInteraction = () => {\n    //   if (continueButton.isShown) {\n    //     continueButton._fill.animations.new()\n    //       .color({target: colors.COLOR_GROKKOLI_BLUE, duration: 1})\n    //       .start();\n    //   } else {\n    //     continueButton._fill.setColor(colors.COLOR_GROKKOLI_BLUE)\n    //   }\n    // }\n    return answer_input;\n}\nfunction getAvailableManipulatives() {\n    var manipulatives = getManipulatives();\n    var out = [];\n    for (var _i = 0, manipulatives_1 = manipulatives; _i < manipulatives_1.length; _i++) {\n        var m = manipulatives_1[_i];\n        out.push(m.name);\n    }\n    return out;\n}\nfunction removeManipulative(name, fromList) {\n    var index = fromList.indexOf(name);\n    if (index > -1) {\n        fromList.splice(index, 1);\n    }\n}\n/**\n * Return snapped full manipulatives in each slot\n * {\n *    Slot1: [M1, M2],\n *    Slot2: [],\n *    Slot3: [M3],\n *    ...\n * }\n * @returns {[slotName: string]: Array<string>}\n */\nfunction getSnappedManipulatives(slotsState) {\n    // const slotsState = getManipulativeSlotsState();\n    var out = {};\n    Object.keys(slotsState.slots).forEach(function (slotName) {\n        out[slotName] = __spreadArray(__spreadArray([], slotsState.slots[slotName].full, true), slotsState.slots[slotName].partial, true);\n    });\n    return out;\n}\nfunction cleanShow(show) {\n    var out = {};\n    Object.keys(show).forEach(function (slotName) {\n        var manipulativeNames;\n        if (!Array.isArray(show[slotName])) {\n            manipulativeNames = [show[slotName]];\n        }\n        else {\n            manipulativeNames = show[slotName];\n        }\n        out[slotName] = manipulativeNames;\n    });\n    return out;\n}\n/**\n * Generate a map of detailing the list of element names to be shown in each slot.\n *\n * showIn is comes from yaml and is a map of slots and lists of explicit and implicit\n * elements to be shown in each slot.\n *\n * An explicit element is one called out by name (like 'M1').\n *\n * An implicit element is one called out by n value, and can have any element with the\n * same n value used.\n *\n * The purpose of this function is to take the showIn map and convert it to a show map\n * of only explicit elements.\n *\n * Several passes must be completed to generate the show map.\n *\n * First, all explicit elements called out in showIn must be used in their defined\n * slot. The remaining elements in showIn are then going to be implicit.\n *\n * Next, don't allow implicit element choice to be any elements from snapped slots\n * that are not in the showIn map. Fully snapped elements in such slots are considered\n * correct and should not be moved.\n *\n * Then, prioritize choice of element by:\n * 1) Is an element with the same n value already snapped in the slot of\n *    interest? (full or partial snap ok)\n * 2) Get an element with the same n value that has been moved\n * 3) Get any remaining element with the same n value\n *\n * Returns a map of slots and the corresponding list of element names to show\n * in that slot.\n *\n * {\n *    Slot1: ['M1', 'M2'],\n *    Slot2: ['M3', 'M4'],\n *    ...\n * }\n * @param show\n */\nfunction getShow(showIn, slotsState, slots) {\n    var manipulativeMap = getManipulativesMap();\n    var manipulativeValueMap = getManipulativesValueMap();\n    var snapped = getSnappedManipulatives(slotsState);\n    var show = cleanShow(showIn);\n    var availableManipulatives = getAvailableManipulatives();\n    var out = {};\n    // Initial setup of out and include all explicitly defined element\n    // names from the show object\n    Object.keys(show).forEach(function (slotName) {\n        out[slotName] = [];\n        var showManipulatives = show[slotName];\n        if (slots[slotName].custom.manipulativeType === 'entryFieldSlot'\n            || slots[slotName].custom.manipulativeType === 'customSlot'\n            || slots[slotName].custom.manipulativeType === 'splittableShapeSlot'\n            || slots[slotName].custom.manipulativeType === 'pattern_block_slot') {\n            // @ts-expect-error TS2345\n            out[slotName].push(showManipulatives);\n            return;\n        }\n        for (var _i = 0, _a = __spreadArray([], showManipulatives, true); _i < _a.length; _i++) {\n            var manipulativeDef = _a[_i];\n            if (slots[slotName].custom.manipulativeType === 'rekenrekSlot') {\n                out[slotName].push(manipulativeDef);\n                continue;\n            }\n            if (slots[slotName].custom.manipulativeType === 'clockSlot') {\n                out[slotName].push(manipulativeDef);\n                continue;\n            }\n            if (typeof manipulativeDef === 'string') {\n                out[slotName].push(manipulativeDef);\n                removeManipulative(manipulativeDef, availableManipulatives);\n                removeManipulative(manipulativeDef, show[slotName]);\n            }\n        }\n    });\n    // Remove manipulatives that are snapped in slots that are not in the show\n    // dict, from being available\n    Object.keys(slotsState.slots).forEach(function (slotName) {\n        if (slots[slotName].custom.manipulativeType === 'rekenrekSlot'\n            || slots[slotName].custom.manipulativeType === 'entryFieldSlot'\n            || slots[slotName].custom.manipulativeType === 'clockSlot'\n            || slots[slotName].custom.manipulativeType === 'customSlot'\n            || slots[slotName].custom.manipulativeType === 'splittableShapeSlot'\n            || slots[slotName].custom.manipulativeType === 'pattern_block_slot'\n            // baseTenBlocksSlot reveals via its own showAnswer, so the generic show\n            // engine must not drain its show list or return-home its blocks.\n            || slots[slotName].custom.manipulativeType === 'baseTenBlocksSlot') {\n            return;\n        }\n        if (show[slotName] == null) {\n            for (var i = 0; i < slotsState.slots[slotName].full.length; i += 1) {\n                removeManipulative(slotsState.slots[slotName].full[i], availableManipulatives);\n            }\n        }\n    });\n    // Go through each slot, and if the slot has a snapped manipulative whose\n    // n value matches an n value in the show answer of that slot, then add that\n    // manipulative to the final show. Note, there will only be number definitions\n    // of manipulatives now, as all string will have been removed by above\n    Object.keys(show).forEach(function (slotName) {\n        if (slots[slotName].custom.manipulativeType === 'rekenrekSlot'\n            || slots[slotName].custom.manipulativeType === 'entryFieldSlot'\n            || slots[slotName].custom.manipulativeType === 'clockSlot'\n            || slots[slotName].custom.manipulativeType === 'customSlot'\n            || slots[slotName].custom.manipulativeType === 'splittableShapeSlot'\n            || slots[slotName].custom.manipulativeType === 'pattern_block_slot'\n            // baseTenBlocksSlot reveals via its own showAnswer, so the generic show\n            // engine must not drain its show list or return-home its blocks.\n            || slots[slotName].custom.manipulativeType === 'baseTenBlocksSlot') {\n            return;\n        }\n        var showManipulatives = show[slotName];\n        for (var _i = 0, _a = __spreadArray([], showManipulatives, true); _i < _a.length; _i++) {\n            var manipulativeDef = _a[_i];\n            for (var _b = 0, _c = snapped[slotName]; _b < _c.length; _b++) {\n                var snappedManipulative = _c[_b];\n                var snappedValue = manipulativeMap[snappedManipulative].custom.n;\n                if (manipulativeDef === snappedValue &&\n                    availableManipulatives.indexOf(snappedManipulative) > -1) {\n                    out[slotName].push(snappedManipulative);\n                    removeManipulative(snappedManipulative, availableManipulatives);\n                    removeManipulative(snappedValue, show[slotName]);\n                    break;\n                }\n            }\n            // out[slotName].push(manipulative);\n            // removeManipulative(manipulative, availableManipulatives);\n            // removeManipulative(manipulative, show[slotName]);\n        }\n    });\n    // The remaining definitions in show can come from any manipulative that has moved,\n    // and then any manipulative at all\n    Object.keys(show).forEach(function (slotName) {\n        if (slots[slotName].custom.manipulativeType === 'rekenrekSlot'\n            || slots[slotName].custom.manipulativeType === 'entryFieldSlot'\n            || slots[slotName].custom.manipulativeType === 'clockSlot'\n            || slots[slotName].custom.manipulativeType === 'customSlot'\n            || slots[slotName].custom.manipulativeType === 'splittableShapeSlot'\n            || slots[slotName].custom.manipulativeType === 'pattern_block_slot'\n            // baseTenBlocksSlot reveals via its own showAnswer, so the generic show\n            // engine must not drain its show list or return-home its blocks.\n            || slots[slotName].custom.manipulativeType === 'baseTenBlocksSlot') {\n            return;\n        }\n        var showManipulatives = show[slotName];\n        for (var _i = 0, _a = __spreadArray([], showManipulatives, true); _i < _a.length; _i++) {\n            var manipulativeDef = _a[_i];\n            // First try to find a moved manipulative\n            var found = null;\n            // @ts-expect-error TS2483\n            for (var _b = 0, _c = manipulativeValueMap[manipulativeDef]; _b < _c.length; _b++) {\n                var m = _c[_b];\n                if (availableManipulatives.indexOf(m.name) > -1 && m.custom.moved) {\n                    found = m;\n                    break;\n                }\n            }\n            if (found) {\n                out[slotName].push(found.name);\n                removeManipulative(found.name, availableManipulatives);\n                removeManipulative(found.name, show[slotName]);\n                continue;\n            }\n            // Then try for any manipulative\n            // @ts-expect-error TS7015\n            for (var _d = 0, _e = manipulativeValueMap[manipulativeDef]; _d < _e.length; _d++) {\n                var m = _e[_d];\n                if (availableManipulatives.indexOf(m.name) > -1) {\n                    out[slotName].push(m.name);\n                    removeManipulative(m.name, availableManipulatives);\n                    removeManipulative(m.name, show[slotName]);\n                    break;\n                }\n            }\n        }\n    });\n    return out;\n}\nfunction createManipulativeSlotAnswerInput(position, options) {\n    var answer_input = createManipulativeAnswerInput(position, options, false);\n    var finishShow = function (delay) {\n        if (delay === void 0) { delay = 0; }\n        answer_input._submit.hide();\n        answer_input._submit.isTouchable = false;\n        answer_input._submit.setPosition(1000, 1000);\n        answer_input.setOpacity(1);\n        // answer_input._continue.setOpacity(0);\n        answer_input._continue.color[3] = 1;\n        answer_input._continue.isTouchable = false;\n        answer_input._continue.hide();\n        answer_input._continue.isTouchable = true;\n        answer_input._continue.custom.canBeDisabled = false;\n        figure.custom.disableBackgroundGesture();\n        answer_input.animations.new()\n            .dissolveIn({ element: answer_input._continue, duration: 0.5, delay: delay })\n            .start();\n    };\n    answer_input.showContinue = finishShow;\n    answer_input.showAnswer = function (answer_info, showOptions) {\n        if (showOptions === void 0) { showOptions = {}; }\n        // The last attempt comes here rather than to showAnswerInfo, so mark the\n        // learner's own tiles first.\n        showManipulativeResults(answer_info);\n        /**\n         * answer_info.show defines which manipulatives to move to which slots.\n         * All other manipulatives should be unmoved, unless they are snapped (partially\n         * or fully) to slots - and then they should be moved back to their initial position.\n         * So:\n         *    - All elements in show -> slot\n         *    - All n values in show -> slot\n         *    - All elements that are snapped, but not in show -> initial position\n         * {\n         *    Slot1: [L2, L3],    // Move elements L2 and L3 to Slot 1\n         *    Slot2: L4,          // Move elements L4 to Slot 2\n         *    Slot3: [5, 6],      // Move first manipulatives with n=5, n=6 that are\n         *                           not already being moved to a slot to Slot3\n         *    Slot4: 7,           // Move first manipulative with n=7 that is not already\n         *                           being moved to a slot to Slot4\n         * }\n         */\n        if (answer_info.show != null) {\n            var slots_1 = getManipulativeSlotsMap();\n            var manipulativesMap_1 = getManipulativesMap();\n            // const manipulativesValueMap = getManipulativesValueMap();\n            var slotsState_1 = getManipulativeSlotsState();\n            var show_1 = getShow(answer_info.show, slotsState_1, slots_1);\n            // optimizeShowOrder(show, slots, slotsState);\n            var usedManipulatives_1 = [];\n            for (var _i = 0, _a = Object.values(show_1); _i < _a.length; _i++) {\n                var manipulativeDefs = _a[_i];\n                usedManipulatives_1.push.apply(usedManipulatives_1, manipulativeDefs);\n            }\n            // Go through each touchable slot that isn't in the show and make it untouchable\n            Object.keys(slotsState_1.slots).forEach(function (slotName) {\n                if (show_1[slotName] == null) {\n                    if (slots_1[slotName].disable) {\n                        slots_1[slotName].disable();\n                    }\n                }\n            });\n            // Go through each manipulative and disable it\n            Object.keys(manipulativesMap_1).forEach(function (manipulativeName) {\n                if (manipulativesMap_1[manipulativeName].disable) {\n                    manipulativesMap_1[manipulativeName].disable();\n                }\n            });\n            // Go through each show, and animate manipulatives to their place.\n            // NOTE for slot authors adding a `showAnswer`: host the reveal/move\n            // animation on the figure ROOT manager (`figure.elements.animations`), not\n            // on the element's own `.animations`. This reveal runs while the demonstrate\n            // guide's speech plays, and speech calls `speechManager.stopFigure()` ->\n            // `_expression.stop('complete')`, which force-completes every animation owned\n            // by the expression equation and its descendants. Manipulatives rendered\n            // inside the expression (e.g. pattern blocks) would otherwise snap straight\n            // to the end pose with no visible slide. See answerContainer.ts (placeAtSnap\n            // / moveTileToLocalSnap) and patternBlocks.ts (placeAt) for the pattern.\n            Object.keys(show_1).forEach(function (slotName) {\n                var slot = slots_1[slotName];\n                // A plain answer_container reveals itself: it holds the shown tiles at\n                // its own snaps and sends the rest home, so the generic remove/re-add\n                // below (which makes an `onRemove: 'fillFromStart'` container compact\n                // the tiles still being revealed onto each other) never runs for it.\n                // Region-pool containers define no showAnswer and fall through here.\n                // NOTE: `show[slotName]`, not `answer_info.show[slotName]` - the\n                // container wants the resolved element names getShow produced.\n                if (slot.custom.manipulativeType === 'answerContainer'\n                    && slot.showAnswer != null) {\n                    slot.showAnswer(show_1[slotName], showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'rekenrekSlot') {\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], 2, false, showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'clockSlot') {\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], 0.75, false, showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'entryFieldSlot') {\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], false, showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'customSlot') {\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'splittableShapeSlot') {\n                    // The shape glides its cut lines to the authored answerLines; the show\n                    // payload is unused (the answer is a pattern, matched to the lines).\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'pattern_block_slot') {\n                    // The pattern-block slot solves and reveals its own tiling; the show\n                    // payload is unused. (See patternBlocksSlot.showAnswer / solveAndShow.)\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'baseTenBlocksSlot') {\n                    // Base-ten slots place blocks through their own snap()/container\n                    // model (no getSnapPosition), so they reveal the answer via their\n                    // own showAnswer rather than the generic placement path below.\n                    // @ts-expect-error TS2339\n                    slot.showAnswer(answer_info.show[slotName], showOptions);\n                    return;\n                }\n                if (slot.custom.manipulativeType === 'simpleBlockFillSlot') {\n                    for (var i = slot.snappedBlocks.length - 1; i >= 0; i -= 1) {\n                        slot.snappedBlocks[i].unsnap();\n                        // slot.unsnap(slot.snappedBlocks[i])\n                    }\n                }\n                // The generic placement path below positions each manipulative via\n                // slot.getSnapPosition() / getManipulativeBaseSnap(). Slot types that\n                // don't expose that API — notably baseTenBlocksSlot, which places\n                // blocks through its own snap()/container model — can't be driven here.\n                // Skip rather than throw \"slot.getSnapPosition is not a function\"\n                // (seen in prod on base-ten questions). A dedicated showAnswer branch\n                // for such slots can hook in above with an early return.\n                if (typeof slot.getSnapPosition !== 'function') {\n                    return;\n                }\n                var nextSnap = 0;\n                var toShow = show_1[slotName];\n                if (!Array.isArray(toShow)) {\n                    toShow = [toShow];\n                }\n                var lastX = 0;\n                var _loop_1 = function (i) {\n                    var nameOrValue = toShow[i];\n                    var block = manipulativesMap_1[nameOrValue];\n                    if (block == null) {\n                        return \"continue\";\n                    }\n                    var slotSnapPosition = slot.getSnapPosition(nextSnap);\n                    var blockSnapPosition = block.getSnapPosition(slot.getManipulativeBaseSnap());\n                    // If using a fill slot, then need to track the width of the blocks filling\n                    // up the slot\n                    if (slot.custom.manipulativeType === 'simpleBlockFillSlot') {\n                        blockSnapPosition = block.getSnapPosition(slot.getManipulativeBaseSnap());\n                        var blockRect = block.custom.getBoundingRect();\n                        slotSnapPosition.x += lastX;\n                        lastX += blockRect.width;\n                    }\n                    block.custom.moved = true;\n                    var deltaPosition = slotSnapPosition.sub(blockSnapPosition);\n                    if (slot.custom.manipulativeType !== 'manipulativeTileSlot'\n                        || deltaPosition.distance() > 0.0001) {\n                        block.unsnap();\n                        block.parent.toFront(block);\n                        block.animations\n                            .new()\n                            .position({\n                            target: block\n                                .getPosition()\n                                .add(slotSnapPosition.sub(blockSnapPosition)),\n                            duration: 1,\n                            beforeFrame: function () {\n                                block.custom.state.p = block.getPosition().toArray(2);\n                            },\n                        })\n                            // Publish a stopBeingMoved notification which will refresh the slots.\n                            // Skip for answerContainer: those tiles are registered in their\n                            // target container synchronously below, so stopBeingMoved is\n                            // redundant and its checkAnswerContainers side-effects can\n                            // incorrectly send an already-correctly-placed tile back home.\n                            .trigger(function () {\n                            if (slot.custom.manipulativeType !== 'answerContainer') {\n                                block.notifications.publish('stopBeingMoved');\n                            }\n                            slot.unhighlight();\n                        })\n                            .start();\n                    }\n                    if (slot.custom.manipulativeType === 'answerContainer') {\n                        // Register the shape as contained synchronously. The position above\n                        // is only animated; without this the container's `contained` list\n                        // and the tile's `answerContainers` marker would not be set until\n                        // the post-animation `stopBeingMoved` fires — too late for a guide\n                        // that runs `|hide_unsnapped|` immediately after showAnswer (it\n                        // would treat these shapes as outside the container and hide them).\n                        var container = slot;\n                        // Evict from any current containers before registering in the\n                        // target. Without this, stale `contained` counts make the target\n                        // look \"full\" when stopBeingMoved fires, causing isFull to send\n                        // the tile to initialPosition instead of keeping it in place.\n                        if (block.removeFromContainer != null) {\n                            block.removeFromContainer();\n                        }\n                        if (container.contained == null\n                            || container.contained.indexOf(block) === -1) {\n                            if (block.answerContainers != null) {\n                                block.answerContainers.push(container);\n                            }\n                            if (container.addToContainer != null) {\n                                container.addToContainer(block);\n                            }\n                        }\n                        nextSnap += 1;\n                    }\n                    else if (slot.custom.manipulativeType === 'simpleBlockSlot') {\n                        nextSnap += block.snaps.length;\n                    }\n                    else {\n                        nextSnap += block.custom.n;\n                    }\n                };\n                // Get the list of manipulatives that\n                for (var i = 0; i < toShow.length; i += 1) {\n                    _loop_1(i);\n                }\n            });\n            // Go through each snapped element that is not part of the show, and move to\n            // initial position\n            Object.keys(slotsState_1.slots).forEach(function (slotName) {\n                if (slots_1[slotName].custom.manipulativeType === 'rekenrekSlot'\n                    || slots_1[slotName].custom.manipulativeType === 'entryFieldSlot'\n                    || slots_1[slotName].custom.manipulativeType === 'clockSlot'\n                    || slots_1[slotName].custom.manipulativeType === 'customSlot'\n                    || slots_1[slotName].custom.manipulativeType === 'splittableShapeSlot'\n                    || slots_1[slotName].custom.manipulativeType === 'pattern_block_slot'\n                    || slots_1[slotName].custom.manipulativeType === 'baseTenBlocksSlot'\n                    || (slots_1[slotName].custom.manipulativeType === 'answerContainer'\n                        && slots_1[slotName].showAnswer != null)) {\n                    // pattern_block_slot and baseTenBlocksSlot manage their own blocks in\n                    // showAnswer (and pattern blocks have no unsnap()); never run the\n                    // generic return-home here — it would unsnap the just-revealed answer.\n                    // A self-revealing answer_container likewise sent its own unwanted\n                    // tiles home, and running this loop over it would remove tiles it has\n                    // just placed (each removal also re-triggering fillFromStart).\n                    return;\n                }\n                var slotState = slotsState_1.slots[slotName];\n                var allBlocks = slotState.full.slice();\n                allBlocks.push.apply(allBlocks, slotState.partial);\n                var _loop_2 = function (i) {\n                    var blockName = allBlocks[i];\n                    if (usedManipulatives_1.indexOf(blockName) === -1) {\n                        var block_1 = manipulativesMap_1[blockName];\n                        block_1.unsnap();\n                        // unsnap() only clears tile-slot membership; for shapes that live\n                        // in an answer_container (snapTo: answer_container) it is a no-op.\n                        // Explicitly clear container membership so the shape is no longer\n                        // counted as \"in a container\" once it animates home — otherwise a\n                        // following |hide_unsnapped| would treat it as still contained.\n                        if (block_1.removeFromContainer != null) {\n                            block_1.removeFromContainer();\n                        }\n                        block_1.custom.moved = true;\n                        block_1.animations\n                            .new()\n                            .position({\n                            target: block_1.custom.initialPosition,\n                            duration: 1,\n                            beforeFrame: function () {\n                                block_1.custom.state.p = block_1.getPosition().toArray(2);\n                            },\n                        })\n                            // Publish a stopBeingMoved notification which will refresh the slots\n                            .trigger(function () { return block_1.notifications.publish('stopBeingMoved'); })\n                            .start();\n                    }\n                };\n                for (var i = 0; i < allBlocks.length; i += 1) {\n                    _loop_2(i);\n                }\n            });\n        }\n        answer_input.stop();\n        if (showOptions.test == null) {\n            // answer_input._submit.hide();\n            // answer_input._submit.isTouchable = false;\n            // answer_input._submit.setPosition(1000, 1000);\n            // answer_input.setOpacity(1);\n            // // answer_input._continue.setOpacity(0);\n            // answer_input._continue.color[3] = 1;\n            // answer_input._continue.isTouchable = false;\n            // answer_input._continue.hide();\n            var continueDelay = 3;\n            if (options.continue_delay != null) {\n                continueDelay = options.continue_delay;\n            }\n            answer_input.animations\n                .new()\n                // .inParallel()\n                .delay(continueDelay)\n                .trigger(function () {\n                if (figure.helper && figure.helper.isPlaying && figure.helper.isGuide) {\n                    figure.helper.notifications.add('stopped', function () { return finishShow(1); }, 1);\n                }\n                else {\n                    finishShow();\n                }\n            })\n                .start();\n        }\n    };\n    answer_input.custom.setupSubmitClicked(getManipulativeSlotsState);\n    // An input_results entry can name a single manipulative (e.g. a tile) rather\n    // than a slot, to mark just that one: an answer_check that knows which tiles\n    // are in the right place can colour each on its own, instead of the whole\n    // slot's tiles getting the slot's one result.\n    var showManipulativeResults = function (answer_info) {\n        if (answer_info == null || answer_info.input_results == null)\n            return;\n        var slots = getManipulativeSlotsMap();\n        var manipulatives = getManipulativesMap();\n        Object.keys(answer_info.input_results).forEach(function (name) {\n            var _a, _b;\n            var manipulative = manipulatives[name];\n            if (slots[name] != null || manipulative == null)\n                return;\n            var result = getAnswerInfoInputResult(answer_info, name);\n            (_b = (_a = manipulative.custom).showCorrectness) === null || _b === void 0 ? void 0 : _b.call(_a, result);\n        });\n    };\n    answer_input.custom.showAnswerInfo = function (answer_info) {\n        var _a, _b;\n        // Change the color of the slot border to show correctness at the slot level\n        var slots = getManipulativeSlotsMap();\n        if (answer_info != null && answer_info.input_results != null) {\n            Object.keys(answer_info.input_results).forEach(function (slotName) {\n                var result = getAnswerInfoInputResult(answer_info, slotName);\n                var slot = slots[slotName];\n                if (slot != null && slot.custom.showCorrectness != null) {\n                    slot.custom.showCorrectness(result);\n                }\n            });\n        }\n        showManipulativeResults(answer_info);\n        if (answer_info != null && answer_info.result != null) {\n            var color = void 0;\n            if (answer_info.result === 1) {\n                color = ((_a = figure.custom) === null || _a === void 0 ? void 0 : _a.colorCorrect) || colors.COLOR_GROKKOLI_GREEN;\n            }\n            else if (answer_info.result === 2 || answer_info.result === 6) {\n                color = ((_b = figure.custom) === null || _b === void 0 ? void 0 : _b.colorIncorrect) || colors.COLOR_GROKKOLI_ORANGE;\n            }\n            if (color == null) {\n                return;\n            }\n            var correctnessElements = answer_input.custom.getCorrectnessElements();\n            if (correctnessElements != null && correctnessElements.length > 0) {\n                for (var i = 0; i < correctnessElements.length; i += 1) {\n                    var e = correctnessElements[i];\n                    var c = __spreadArray([], e.color, true);\n                    e.setColor(color);\n                    e.animations\n                        .new()\n                        .delay(2)\n                        .color({ target: c, duration: 0.5 })\n                        .start();\n                    if (e._container) {\n                        var c1 = __spreadArray([], e._container.color, true);\n                        e._container.setColor(color);\n                        e._container.animations\n                            .new()\n                            .delay(2)\n                            .color({ target: c1, duration: 0.5 })\n                            .start();\n                    }\n                }\n            }\n        }\n    };\n}\nexport { createManipulativeAnswerInput, createManipulativeSlotAnswerInput, cleanShow, getSnappedManipulatives, getShow, removeManipulative };\n","var slotTypes = [\n    'linearBlocksSlot',\n    'baseTenBlocksSlot',\n    'answerContainer',\n    'manipulativeTileSlot',\n    'simpleBlockSlot',\n    'simpleBlockFillSlot',\n    'entryFieldSlot',\n    'pattern_block_slot',\n];\nvar combinedSlotTypes = ['rekenrekSlot', 'clockSlot', 'customSlot', 'splittableShapeSlot'];\nfunction getManipulatives(asMap, withParent, inFigure, worksWith, onlyShown) {\n    if (asMap === void 0) { asMap = false; }\n    if (withParent === void 0) { withParent = null; }\n    if (inFigure === void 0) { inFigure = null; }\n    if (worksWith === void 0) { worksWith = null; }\n    if (onlyShown === void 0) { onlyShown = false; }\n    var out = [];\n    var count = 0;\n    for (var f = 0; f < window.figureOneFigures.length; f += 1) {\n        var fig = window.figureOneFigures[f];\n        if (inFigure != null && fig != inFigure) {\n            continue;\n        }\n        var elements = fig.elements.getAllElements();\n        for (var i = 0; i < elements.length; i += 1) {\n            if (elements[i].custom.manipulativeType == null) {\n                continue;\n            }\n            if (onlyShown && elements[i].isShown === false) {\n                continue;\n            }\n            if (withParent != null && elements[i].parent !== withParent) {\n                continue;\n            }\n            if (slotTypes.indexOf(elements[i].custom.manipulativeType) > -1) {\n                continue;\n            }\n            if (worksWith != null) {\n                if (elements[i].custom.worksWith == null ||\n                    elements[i].custom.worksWith[worksWith] == null ||\n                    elements[i].custom.worksWith[worksWith] === false) {\n                    continue;\n                }\n            }\n            out.push(elements[i]);\n            count += 1;\n            if (count > 500) {\n                return out;\n            }\n        }\n    }\n    return out;\n}\nfunction getManipulativeControls(asMap, withParent, inFigure) {\n    if (asMap === void 0) { asMap = false; }\n    if (withParent === void 0) { withParent = null; }\n    if (inFigure === void 0) { inFigure = null; }\n    var out = [];\n    var count = 0;\n    for (var f = 0; f < window.figureOneFigures.length; f += 1) {\n        var fig = window.figureOneFigures[f];\n        if (inFigure != null && fig != inFigure) {\n            continue;\n        }\n        var elements = fig.elements.getAllElements();\n        for (var i = 0; i < elements.length; i += 1) {\n            if (elements[i].custom.manipulativeControlType == null) {\n                continue;\n            }\n            if (withParent != null && elements[i].parent !== withParent) {\n                continue;\n            }\n            if (slotTypes.indexOf(elements[i].custom.manipulativeControlType) > -1) {\n                continue;\n            }\n            out.push(elements[i]);\n            count += 1;\n            if (count > 500) {\n                return out;\n            }\n        }\n    }\n    return out;\n}\nfunction getSelectors(asMap, withParent, selectedOnly, inFigure) {\n    if (asMap === void 0) { asMap = false; }\n    if (withParent === void 0) { withParent = null; }\n    if (selectedOnly === void 0) { selectedOnly = false; }\n    if (inFigure === void 0) { inFigure = null; }\n    var out = [];\n    var count = 0;\n    for (var f = 0; f < window.figureOneFigures.length; f += 1) {\n        var fig = window.figureOneFigures[f];\n        if (inFigure != null && fig != inFigure) {\n            continue;\n        }\n        var elements = fig.elements.getAllElements();\n        for (var i = 0; i < elements.length; i += 1) {\n            if (elements[i].custom.selectorType == null) {\n                continue;\n            }\n            if (withParent != null && elements[i].parent !== withParent) {\n                continue;\n            }\n            if (selectedOnly && elements[i].custom.selected === false) {\n                continue;\n            }\n            // if (slotTypes.indexOf(elements[i].custom.manipulativeType) > -1) {\n            //   continue;\n            // }\n            out.push(elements[i]);\n            count += 1;\n            if (count > 100) {\n                return out;\n            }\n        }\n    }\n    return out;\n}\nfunction getSelectedSelector(inFigure) {\n    if (inFigure === void 0) { inFigure = null; }\n    var selectors = getSelectors(false, null, true, inFigure);\n    if (selectors.length === 0) {\n        return null;\n    }\n    return selectors[0];\n}\nfunction getManipulativesMap() {\n    var m = getManipulatives();\n    var map = {};\n    for (var i = 0; i < m.length; i += 1) {\n        if (m[i].custom.isShowable === false) {\n            continue;\n        }\n        map[m[i].name] = m[i];\n    }\n    return map;\n}\nfunction getManipulativesValueMap() {\n    var m = getManipulatives();\n    var map = {};\n    for (var i = 0; i < m.length; i += 1) {\n        if (m[i].custom.isShowable === false) {\n            continue;\n        }\n        if (map[m[i].custom.n] == null) {\n            map[m[i].custom.n] = [];\n        }\n        map[m[i].custom.n].push(m[i]);\n    }\n    return map;\n}\nfunction getManipulativesState() {\n    var out = {};\n    var count = 0;\n    for (var f = 0; f < window.figureOneFigures.length; f += 1) {\n        var fig = window.figureOneFigures[f];\n        out[f.toString()] = {};\n        var elements = fig.elements.getAllElements();\n        for (var i = 0; i < elements.length; i += 1) {\n            if (elements[i].custom.manipulativeType == null ||\n                elements[i].custom.manipulativeType == 'keypad') {\n                continue;\n            }\n            if (slotTypes.indexOf(elements[i].custom.manipulativeType) > -1) {\n                continue;\n            }\n            // A manipulative opts into state tracking by defining getState. Skip those\n            // that don't (e.g. static, non-rotatable solids) so they contribute\n            // nothing to the answer payload.\n            if (typeof elements[i].custom.getState !== 'function') {\n                continue;\n            }\n            // A getState may also return null to opt out for this submission (e.g. an\n            // opened-but-unused calculator). Skip those so they add nothing.\n            var state = elements[i].custom.getState();\n            if (state == null) {\n                continue;\n            }\n            out[f][elements[i].name] = state;\n            count += 1;\n            if (count > 100) {\n                return out;\n            }\n        }\n    }\n    return out;\n}\nfunction getManipulativeSlots() {\n    var out = [];\n    var elements = figure.elements.getAllElements();\n    for (var i = 0; i < elements.length; i += 1) {\n        if (elements[i].custom.manipulativeType == null) {\n            continue;\n        }\n        if (slotTypes.indexOf(elements[i].custom.manipulativeType) > -1 ||\n            combinedSlotTypes.indexOf(elements[i].custom.manipulativeType) > -1) {\n            out.push(elements[i]);\n        }\n    }\n    return out;\n}\nfunction getManipulativeSlotsMap() {\n    var slots = getManipulativeSlots();\n    var objOut = {};\n    for (var i = 0; i < slots.length; i += 1) {\n        objOut[slots[i].name] = slots[i];\n    }\n    return objOut;\n}\nfunction getManipulativeSlotsState() {\n    var slots = {};\n    var count = 0;\n    var manipulativesToRecord = [];\n    var manipulatives = {};\n    var elements = figure.elements.getAllElements();\n    for (var i = 0; i < elements.length; i += 1) {\n        if (elements[i].custom.manipulativeType == null ||\n            elements[i].custom.manipulativeType == 'keypad') {\n            continue;\n        }\n        if (slotTypes.indexOf(elements[i].custom.manipulativeType) > -1 ||\n            combinedSlotTypes.indexOf(elements[i].custom.manipulativeType) > -1) {\n            var state = elements[i].custom.getState(true);\n            if (Array.isArray(state)) {\n                for (var i_1 = 0; i_1 < state.length; i_1 += 1) {\n                    manipulativesToRecord.push(state[i_1]);\n                }\n            }\n            else {\n                for (var i_2 = 0; i_2 < state.full.length; i_2 += 1) {\n                    if (manipulativesToRecord.indexOf(state.full[i_2]) == -1) {\n                        manipulativesToRecord.push(state.full[i_2]);\n                    }\n                }\n                for (var i_3 = 0; i_3 < state.partial.length; i_3 += 1) {\n                    if (manipulativesToRecord.indexOf(state.partial[i_3]) == -1) {\n                        manipulativesToRecord.push(state.partial[i_3]);\n                    }\n                }\n            }\n            slots[elements[i].name] = state;\n            count += 1;\n            if (count > 100) {\n                break;\n            }\n        }\n    }\n    for (var i = 0; i < elements.length; i += 1) {\n        if (elements[i].custom.manipulativeType == null) {\n            continue;\n        }\n        if (manipulativesToRecord.indexOf(elements[i].name) > -1) {\n            if (elements[i].custom.n != null) {\n                manipulatives[elements[i].name] = elements[i].custom.n;\n            }\n        }\n    }\n    // Slots should only exist on primary figure\n    return {\n        slots: slots,\n        manips: manipulatives,\n    };\n}\nfunction refreshManipulativeSlots() {\n    var manipulatives = getManipulatives();\n    for (var i = 0; i < manipulatives.length; i += 1) {\n        if (manipulatives[i].checkSlotSnaps != null) {\n            manipulatives[i].checkSlotSnaps();\n        }\n    }\n    var slots = getManipulativeSlots();\n    for (var i = 0; i < slots.length; i += 1) {\n        if (slots[i].refreshSnaps != null) {\n            slots[i].refreshSnaps();\n        }\n    }\n}\nfunction setManipulatives(states) {\n    var _loop_1 = function (f) {\n        var fig = window.figureOneFigures[f];\n        var allElements = fig.elements.getAllElements();\n        var elementMap = {};\n        for (var i = 0; i < allElements.length; i += 1) {\n            var e = allElements[i];\n            elementMap[e.name] = e;\n        }\n        var figureStates = states[f.toString()];\n        // Line manipulatives restored below. A splittable_shape persists only whether\n        // a split is shown (not the cut geometry — see splittableShape's state); the\n        // cut is re-driven from its lines. setState restores a line's endpoints but\n        // publishes 'stopBeingMoved' on the line ELEMENT, which never reaches the\n        // shape's resplit (wired to the line's pads' 'stopBeingMoved' and the line's\n        // 'rotated'). So collect the restored lines and, once EVERY manipulative has\n        // been restored to its final pose, publish 'rotated' on each — the same signal\n        // a settle/rotate uses — so the shape re-splits at the answered pose. Deferring\n        // to a second pass matters: the resplit reads all lines, so they must all be\n        // restored first.\n        var restoredLines = [];\n        Object.keys(figureStates).forEach(function (manipulativeName) {\n            var state = figureStates[manipulativeName];\n            var element = figure.get(\"\".concat(state.e, \".\").concat(manipulativeName));\n            if (element == null && state.c != null) {\n                var controlElement = fig.getElement(state.e + '.' + state.c);\n                if (controlElement != null) {\n                    element = controlElement.custom.create(manipulativeName, state.n);\n                    element.custom.startMove = performance.now() - 10000;\n                }\n            }\n            // if (\n            //   element == null\n            //   // && state.e === 'workPad.tiles'\n            //   && manipulativeName.startsWith('__M_LB')\n            // ) {\n            //   const num = parseInt(manipulativeName.match(/__M_LB(\\d+)_/)[1], 10);\n            //   element = addManipulative({\n            //     manipulative: 'linearBlocks',\n            //     options: {\n            //       name: manipulativeName,\n            //       n: num,\n            //       scale: state.s,\n            //     },\n            //     eqn: state.e,\n            //     figure: fig,\n            //   })\n            // }\n            // if (\n            //   element == null\n            //   // && state.e === 'workPad.tiles'\n            //   && manipulativeName.startsWith('__M_B10B')\n            // ) {\n            //   const num = parseInt(manipulativeName.match(/__M_B10B(\\d+)_/)[1], 10);\n            //   element = addManipulative({\n            //     manipulative: 'baseTenBlocks',\n            //     options: {\n            //       name: manipulativeName,\n            //       n: num,\n            //       scale: state.s,\n            //     },\n            //     eqn: state.e,\n            //     figure: fig,\n            //   })\n            // }\n            // Guard setState: an old saved snapshot may still carry state for an\n            // element that no longer tracks it (now static). Skip rather than crash on\n            // an undefined setState.\n            if (element != null && typeof element.custom.setState === 'function') {\n                element.custom.moved = true;\n                element.show();\n                element.custom.setState(state);\n                // A setState that left the element hidden means it wasn't on screen when\n                // the state was captured (only baseTenBlocks and linearBlocks record\n                // visibility, via `sh`). Stop here rather than publishing\n                // 'stopBeingMoved': that drives the drag-end snap check, and a hidden\n                // element's getBoundingRect('local') collapses to a zero-size rect at\n                // the equation origin. Any slot whose snap border covers that origin\n                // then accepts the block, so invisible blocks silently take up slot\n                // cells and push the visible ones along.\n                //\n                // This also skips the restoredLines collection below. That is correct\n                // today because no line_manipulative records `sh`, so one can never\n                // reach here -- but if another type starts recording visibility, check\n                // whether it needs the second pass before widening this.\n                if (!element.isShown) {\n                    return;\n                }\n                element.parent.toFront(element);\n                element.notifications.publish('stopBeingMoved');\n                if (element.custom.manipulativeType === 'line_manipulative') {\n                    restoredLines.push(element);\n                }\n            }\n        });\n        // Second pass (see note above): all manipulatives are now at their final\n        // restored pose, so re-drive any line-fed splits at the answered geometry.\n        for (var i = 0; i < restoredLines.length; i += 1) {\n            restoredLines[i].notifications.publish('rotated');\n        }\n        // Third pass: re-place every block a baseTenBlocksSlot owns at the cell the\n        // slot puts it in *now*. setState above restored absolute positions, which\n        // only line up if the equation lays out exactly as it did when the state was\n        // captured -- it doesn't on the snapshot page, so blocks render beside their\n        // slot. 'stopBeingMoved' does snap each block into the slot, and commitSnap's\n        // layoutAll would move it, but that layout is animated and the snapshot page\n        // runs figure.stop('freeze') on the same tick, cancelling it in place.\n        // refreshSnaps is the synchronous (duration 0) equivalent, so there is\n        // nothing left in flight to cancel.\n        //\n        // Scoped to baseTenBlocksSlot deliberately: the other slot types' refreshSnaps\n        // do more than re-position (linearBlocksSlot re-picks primary snaps and resets\n        // the border colour), and they are only exercised from the snapshot page's\n        // refreshManipulativeSlots() today. Widen this only after checking each.\n        for (var i = 0; i < allElements.length; i += 1) {\n            var e = allElements[i];\n            if (e.custom.manipulativeType === 'baseTenBlocksSlot'\n                && typeof e.refreshSnaps === 'function') {\n                e.refreshSnaps();\n            }\n        }\n    };\n    for (var f = 0; f < window.figureOneFigures.length; f += 1) {\n        _loop_1(f);\n    }\n}\nexport { getManipulativesState, setManipulatives, getManipulativeSlotsState, getManipulativeSlots, getManipulatives, getManipulativeSlotsMap, getManipulativesMap, getManipulativesValueMap, refreshManipulativeSlots, getSelectors, getSelectedSelector, getManipulativeControls, };\n","import { setupManipulative } from './tools';\nimport { NotificationHelper } from '../tools/notifications';\nimport { getManipulativeControls, getManipulatives, getSelectors, } from './manage';\nvar selectorManipulative = function (eqn_name, options, fig) {\n    var eqn = fig.get(eqn_name);\n    var toAdd = eqn ? eqn : fig.elements;\n    if (Array.isArray(toAdd)) {\n        toAdd = toAdd[0];\n    }\n    var ICONS = {\n        break: [0.598, 0],\n        trash: [0.2, 0],\n    };\n    var NEGATIVE_ICONS = {\n        break: [0.798, 0],\n        trash: [0.4, 0],\n    };\n    var SCALE = {\n        break: 1,\n        trash: 1,\n    };\n    var BACKGROUND = {\n        break: [1, 0.6],\n        trash: [0.7, 0.7],\n    };\n    var o = Fig.joinObjects({\n        width: 0.4,\n        height: 0.4,\n        method: 'split',\n        yOffset: 0,\n        debug: false,\n        select: 'b10_blocks',\n        selected: {\n            color: [0, 0, 0, 1],\n        },\n        radius: 0.02,\n        sides: 10,\n    }, options);\n    if (o.selectPosition == null) {\n        o.selectPosition = [o.width * 0.5, o.height * 0.9];\n    }\n    var selector = toAdd.add({\n        name: o.name,\n        make: 'collection',\n        position: o.position,\n    });\n    var container = selector.add({\n        name: 'container',\n        make: 'collection',\n        position: [0, o.yOffset],\n    });\n    var selectBorder = container.add({\n        name: 'select',\n        make: 'rectangle',\n        width: o.width * BACKGROUND[o.method][0],\n        height: o.height * BACKGROUND[o.method][1],\n        xAlign: 'center',\n        yAlign: 'middle',\n        corner: {\n            radius: o.radius,\n            sides: o.sides,\n        },\n        // line: o.line,\n        color: o.selected.color,\n        position: [o.width / 2, o.height / 2],\n    });\n    var s = 0.12;\n    var target = container.add({\n        make: 'collection',\n        elements: [\n            {\n                make: 'rectangle',\n                name: 'line1',\n                // dash: [0.04, 0.01],\n                // width: 0.02,\n                corner: {\n                    radius: 0.01,\n                    sides: 5,\n                },\n                color: [1, 1, 1, 0],\n                position: o.selectPosition,\n                width: s * 2 + 0.02,\n                height: 0.02,\n                // p1: [o.selectPosition[0] - s - 0.01, o.selectPosition[1]],\n                // p2: [o.selectPosition[0] + s + 0.01, o.selectPosition[1]],\n            },\n            {\n                make: 'rectangle',\n                name: 'line2',\n                // dash: [0.04, 0.01],\n                corner: {\n                    radius: 0.01,\n                    sides: 5,\n                },\n                color: [1, 1, 1, 0],\n                height: s * 2 + 0.02,\n                width: 0.02,\n                position: o.selectPosition,\n                // p1: [o.selectPosition[0], o.selectPosition[1] - s - 0.01],\n                // p2: [o.selectPosition[0], o.selectPosition[1] + s + 0.01],\n            },\n            {\n                make: 'line',\n                name: 'line3',\n                dash: [0.04, 0.01],\n                width: 0.005,\n                color: [0.5, 0.5, 0.5, 0],\n                p1: [o.selectPosition[0] - s, o.selectPosition[1]],\n                p2: [o.selectPosition[0] + s, o.selectPosition[1]],\n            },\n            {\n                make: 'line',\n                name: 'line4',\n                dash: [0.04, 0.01],\n                width: 0.005,\n                color: [0.5, 0.5, 0.5, 0],\n                p1: [o.selectPosition[0], o.selectPosition[1] - s],\n                p2: [o.selectPosition[0], o.selectPosition[1] + s],\n            },\n        ],\n        // color: [0.5, 0.5, 0.5, 0],\n    });\n    var icon = container.add({\n        name: 'icon',\n        make: 'rectangle',\n        width: o.width,\n        height: o.height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        texture: {\n            src: window.location.origin + '/static/img/control_atlas.png',\n            mapFrom: new Fig.Rect(ICONS[o.method][0], ICONS[o.method][1], 0.2, 0.2),\n            mapTo: new Fig.Rect(0, 0, o.width, o.height),\n            loadColor: [0, 0, 0, 0],\n        },\n    });\n    var negativeIcon = container.add({\n        name: 'negativeIcon',\n        make: 'rectangle',\n        width: o.width,\n        height: o.height,\n        xAlign: 'left',\n        yAlign: 'bottom',\n        texture: {\n            src: window.location.origin + '/static/img/control_atlas.png',\n            mapFrom: new Fig.Rect(NEGATIVE_ICONS[o.method][0], ICONS[o.method][1], 0.2, 0.2),\n            mapTo: new Fig.Rect(0, 0, o.width, o.height),\n            loadColor: [0, 0, 0, 0],\n        },\n    });\n    negativeIcon.setOpacity(0);\n    selectBorder.hide();\n    if (SCALE[o.method] !== 1) {\n        icon.setScale(SCALE[o.method]);\n        var d = (o.width - o.width * SCALE[o.method]) / 2;\n        icon.setPosition(d, d);\n    }\n    if (o.debug) {\n        container.add({\n            make: 'rectangle',\n            line: { width: 0.01 },\n            width: o.width,\n            height: o.height,\n            xAlign: 'left',\n            yAlign: 'bottom',\n        });\n        container.add({\n            make: 'polygon',\n            position: o.selectPosition,\n            radius: 0.01,\n            color: [0, 0, 0, 1],\n            sides: 10,\n        });\n    }\n    selector.notificationHelper = new NotificationHelper();\n    setupManipulative(selector, selectBorder, o);\n    selector.custom.select = function () {\n        selectBorder.show();\n        selectBorder.color[3] = 1;\n        negativeIcon.show();\n        negativeIcon.setOpacity(1);\n        icon.setOpacity(0);\n        icon.hide();\n        selector.custom.selected = true;\n    };\n    selector.custom.deselect = function () {\n        selectBorder.hide();\n        selectBorder.color[3] = 0;\n        negativeIcon.hide();\n        icon.show();\n        negativeIcon.setOpacity(0);\n        icon.setOpacity(1);\n        selector.custom.selected = false;\n    };\n    selector.custom.getBoundingRect = function (space) {\n        return selector.getBoundingRect(space);\n    };\n    selector.custom.getState = function () {\n        var p = selector.getPosition();\n        return {\n            p: [Fig.round(p.x, 3), Fig.round(p.y, 3)],\n        };\n    };\n    selector.custom.setState = function (stats) {\n        selector.setPosition(Fig.parsePoint(stats.p));\n        selector.custom.moved = true;\n    };\n    selector.custom.state = selector.custom.getState();\n    selector.notificationHelper.add(toAdd, 'layoutForms', function () {\n        if (selector.custom.moved) {\n            selector.setPosition(Fig.parsePoint(selector.custom.state.p));\n        }\n    });\n    selector.custom.initialPosition = selector.getPosition();\n    selector.notificationHelper.add(fig, 'ready', function () {\n        selector.custom.initialPosition = selector.getPosition();\n    });\n    selector.custom.lastPosition = selector.getPosition();\n    selector.custom.highlighted = null;\n    selector.notificationHelper.add(selector, 'moved', function () {\n        selector.custom.moved = true;\n        selector.custom.state.p = selector.getPosition();\n        // If there hasn't been enough movement, then do nothing.\n        if (selector.custom.lastPosition.sub(selector.custom.state.p).distance() <\n            0.01) {\n            return;\n        }\n        if (target._line1.color[3] === 0 &&\n            selector.custom.state.p\n                .sub(selector.custom.startMovePosition)\n                .distance() >\n                o.width / 3) {\n            target._line1.setColor([1, 1, 1, 0.9]);\n            target._line2.setColor([1, 1, 1, 0.9]);\n            target._line3.setColor([0.5, 0.5, 0.5, 0.9]);\n            target._line4.setColor([0.5, 0.5, 0.5, 0.9]);\n            target.pulse({ scale: 1.4, duration: 0.4 });\n        }\n        var selectPosition = selector.custom.state.p.add(new Fig.parsePoint(o.selectPosition));\n        selector.custom.lastPosition = selector.custom.state.p;\n        for (var i = selector.parent.drawOrder.length - 1; i >= 0; i -= 1) {\n            var element = selector.parent.elements[selector.parent.drawOrder[i]];\n            if (element.custom.manipulativeType == null ||\n                (!Array.isArray(o.select) &&\n                    element.custom.manipulativeType !== o.select) ||\n                (Array.isArray(o.select) &&\n                    o.select.indexOf(element.custom.manipulativeType) == -1)) {\n                continue;\n            }\n            if (!element.custom.worksWith || !element.custom.worksWith[o.method]) {\n                continue;\n            }\n            var bounds = element.custom.getBoundingRect();\n            if (bounds.isPointInside(selectPosition)) {\n                if (selector.custom.highlighted) {\n                    selector.custom.highlighted.unhighlight();\n                }\n                element.highlight();\n                selector.custom.highlighted = element;\n                return;\n            }\n        }\n        if (selector.custom.highlighted) {\n            selector.custom.highlighted.unhighlight();\n            selector.custom.highlighted = null;\n        }\n    });\n    selector.executedMethod = function (result) {\n        if (result != null && result.disable) {\n            selector.unhighlightWorksWith();\n            selector.custom.deselect();\n            selector.isTouchable = false;\n            selector.hasTouchableElements = false;\n            selector.setOpacity(0.3);\n        }\n    };\n    selector.checkDeselect = function () {\n        var manipulatives = getManipulatives(false, null, fig, o.method, true);\n        if (manipulatives.length === 0) {\n            selector.custom.deselect();\n            selector.unhighlightWorksWith();\n        }\n    };\n    selector.custom.method = o.method;\n    selector.custom.secondaryTouchBounds = 0.1;\n    selector.highlightWorksWith = function () {\n        var manipulatives = getManipulatives(false, null, fig);\n        for (var i = 0; i < manipulatives.length; i += 1) {\n            var manipulative = manipulatives[i];\n            if (manipulative.custom.worksWith == null ||\n                manipulative.custom.worksWith[o.method] == null ||\n                manipulative.custom.worksWith[o.method] === false) {\n                manipulative.dim();\n            }\n        }\n        var manipulativeControls = getManipulativeControls(false, null, fig);\n        for (var i = 0; i < manipulativeControls.length; i += 1) {\n            var manipulative = manipulativeControls[i];\n            manipulative.dim();\n        }\n    };\n    selector.unhighlightWorksWith = function () {\n        var manipulatives = getManipulatives(false, toAdd, fig);\n        for (var i = 0; i < manipulatives.length; i += 1) {\n            var manipulative = manipulatives[i];\n            if (manipulative.custom.worksWith == null ||\n                manipulative.custom.worksWith[o.method] == null ||\n                manipulative.custom.worksWith[o.method] === false) {\n                manipulative.unhighlight();\n            }\n        }\n        var manipulativeControls = getManipulativeControls();\n        for (var i = 0; i < manipulativeControls.length; i += 1) {\n            var manipulative = manipulativeControls[i];\n            manipulative.unhighlight();\n        }\n    };\n    selector.notificationHelper.add(selector._container, 'onClick', function () {\n        var selectors = getSelectors(false, null, false, fig);\n        selector.parent.toFront(selector.name);\n        for (var i = 0; i < selectors.length; i += 1) {\n            if (selectors[i] != selector &&\n                selectors[i].custom.deselect != null &&\n                selectors[i].custom.selected) {\n                selectors[i].unhighlightWorksWith();\n                selectors[i].custom.deselect();\n            }\n        }\n        selector.custom.startMoveSelect = selector.custom.selected;\n        if (selector.custom.selected) {\n            selector.custom.deselect();\n        }\n        if (selector.custom.isS)\n            selector.custom.clickStart = performance.now();\n        selector.startBeingMoved();\n        selector.custom.startMove = performance.now();\n        selector.custom.startMovePosition = selector.getPosition();\n        selector.parent.toFront(selector);\n        window.clickHandled = true;\n        selector.highlightWorksWith();\n        // t1.show();\n        // t2.show();\n        // target._line1.setColor([1, 1, 1, 1]);\n        // target._line2.setColor([1, 1, 1, 1]);\n        // target._line3.setColor([0.5, 0.5, 0.5, 1]);\n        // target._line4.setColor([0.5, 0.5, 0.5, 1]);\n        // target.pulse({scale: 1.4, duration: 0.4});\n        // const manipulatives = getManipulatives();\n        // for (let i = 0; i < manipulatives.length; i += 1) {\n        //   const manipulative = manipulatives[i];\n        //   if (\n        //     manipulative.custom.worksWith == null ||\n        //     manipulative.custom.worksWith[o.method] == null ||\n        //     manipulative.custom.worksWith[o.method] === false\n        //   ) {\n        //     manipulative.dim();\n        //   }\n        // }\n    });\n    selector.notificationHelper.add(selector, 'stopBeingMoved', function () {\n        selector.unhighlightWorksWith();\n        if (selector.custom.highlighted) {\n            fig.answerChanged();\n            selector.executedMethod(selector.custom.highlighted[o.method]());\n            selector.custom.highlighted.unhighlight();\n            selector.custom.highlighted = null;\n        }\n        selector.custom.state.p = selector.getPosition();\n        target._line1.setColor([1, 1, 1, 0]);\n        target._line2.setColor([1, 1, 1, 0]);\n        target._line3.setColor([0.5, 0.5, 0.5, 0]);\n        target._line4.setColor([0.5, 0.5, 0.5, 0]);\n        if (performance.now() - selector.custom.startMove < 200 &&\n            !selector.custom.startMoveSelect\n        // || selector.custom.startMovePosition.sub(selector.getPosition()).distance() < o.width\n        ) {\n            selector.custom.select();\n            selector.highlightWorksWith();\n            // return;\n        }\n        // if (selector.custom.initialPosition.sub(selector.custom.state.p).distance() < o.width / 3) {\n        //   toAdd.animations.new()\n        //     .position({element: selector, target: selector.custom.initialPosition, duration: 0.3})\n        //     .start();\n        //   return;\n        // }\n        // if (\n        //   performance.now() - selector.custom.startMove < 200\n        //   && selector.custom.startMoveSelect\n        //   // || selector.custom.startMovePosition.sub(selector.getPosition()).distance() < o.width\n        // ) {\n        //   return;\n        // }\n        // t1.hide();\n        // t2.hide();\n        toAdd.animations\n            .new()\n            .position({\n            element: selector,\n            target: selector.custom.initialPosition,\n            duration: 0.3,\n            beforeFrame: function () {\n                selector.custom.state.p = selector.getPosition();\n            },\n        })\n            .trigger(function () {\n            selector.custom.state.p = selector.getPosition();\n        })\n            .start();\n        // toAdd.animations.new()\n        //   .dissolveOut({element: selector, duration: 0.01})\n        //   .delay(0.4)\n        //   .trigger(() => {\n        //     selector.setPosition(selector.custom.initialPosition);\n        //     selector.custom.state.p = selector.custom.initialPosition;\n        //   })\n        //   .dissolveIn({element: selector, duration: 0.5})\n        //   .start();\n        // // selector.hide();\n        // // setTimeout(() => {\n        // //   selector.parent.remove(selector);\n        // // }, 5);\n    });\n    if (o.isTouchable === false) {\n        selector.hasTouchableElements = false;\n    }\n    // selector.custom.manipulativeType = 'manipulative_selector';\n    selector.custom.selectorType = o.method;\n    container.setMove({ freely: false, element: selector });\n    selector.move.freely = false;\n    return selector;\n};\nexport { selectorManipulative, };\n","// Resolve a positioning keyword (or raw coordinate) to an x value on the bbox.\nfunction resolveX(v, b) {\n    if (typeof v === 'number')\n        return v;\n    if (v === 'left')\n        return b.left;\n    if (v === 'right')\n        return b.right;\n    return (b.left + b.right) / 2; // 'center' or default\n}\nfunction resolveY(v, b) {\n    if (typeof v === 'number')\n        return v;\n    if (v === 'bottom')\n        return b.bottom;\n    if (v === 'top')\n        return b.top;\n    return (b.bottom + b.top) / 2; // 'middle' or default\n}\n// Align keyword -> a [0, 1] fraction (0 = left/bottom line on the anchor, growing\n// up; 1 = right/top line on the anchor, growing down; 0.5 = centred).\nfunction alignFrac(v) {\n    if (typeof v === 'number')\n        return v;\n    if (v === 'left' || v === 'bottom')\n        return 0;\n    if (v === 'right' || v === 'top')\n        return 1;\n    return 0.5; // 'center' / 'middle' / default\n}\n// Build the snap lines for one axis. `spacing` 0 -> a single line at `anchor`;\n// > 0 -> every `spacing`, phased through `anchor`, within [min, max] inclusive.\nfunction buildLines(spacing, anchor, min, max) {\n    if (spacing === 0)\n        return [anchor];\n    var lines = [];\n    var lo = Math.min(min, max);\n    var hi = Math.max(min, max);\n    var kMin = Math.ceil((lo - anchor) / spacing - 1e-9);\n    var kMax = Math.floor((hi - anchor) / spacing + 1e-9);\n    for (var k = kMin; k <= kMax; k += 1)\n        lines.push(anchor + k * spacing);\n    return lines;\n}\n// Nearest line value to `c`, plus its distance. Caller guarantees lines.length > 0.\nfunction nearest(c, lines) {\n    var best = lines[0];\n    var bestD = Math.abs(c - best);\n    for (var i = 1; i < lines.length; i += 1) {\n        var d = Math.abs(c - lines[i]);\n        if (d < bestD) {\n            bestD = d;\n            best = lines[i];\n        }\n    }\n    return { value: best, dist: bestD };\n}\nvar makeSnapGrid = function (anchorEl, spec, bbox) {\n    // Reference node (the lattice passes through it on each non-free axis).\n    var ax;\n    var ay;\n    if (spec.origin != null) {\n        var o = Fig.getPoint(spec.origin);\n        ax = o.x;\n        ay = o.y;\n    }\n    else {\n        ax = resolveX(spec.xPosition, bbox);\n        ay = resolveY(spec.yPosition, bbox);\n    }\n    if (spec.offset != null) {\n        var off = Fig.getPoint(spec.offset);\n        ax += off.x;\n        ay += off.y;\n    }\n    // Extent: explicit bounds, else width/height placed around the anchor per the\n    // alignment, else the host bounding box.\n    var xMin;\n    var xMax;\n    var yMin;\n    var yMax;\n    if (spec.bounds != null) {\n        xMin = spec.bounds.left;\n        xMax = spec.bounds.right;\n        yMin = spec.bounds.bottom;\n        yMax = spec.bounds.top;\n    }\n    else if (spec.width != null || spec.height != null) {\n        var w = spec.width != null ? spec.width : bbox.right - bbox.left;\n        var h = spec.height != null ? spec.height : bbox.top - bbox.bottom;\n        var fx = alignFrac(spec.xAlign);\n        var fy = alignFrac(spec.yAlign);\n        xMin = ax - fx * w;\n        xMax = ax + (1 - fx) * w;\n        yMin = ay - fy * h;\n        yMax = ay + (1 - fy) * h;\n    }\n    else {\n        xMin = bbox.left;\n        xMax = bbox.right;\n        yMin = bbox.bottom;\n        yMax = bbox.top;\n    }\n    var extent = { left: xMin, bottom: yMin, right: xMax, top: yMax };\n    // null = free axis; 0 = single line; > 0 = spacing.\n    var sx = spec.x == null || spec.x === false ? null : spec.x;\n    var sy = spec.y == null || spec.y === false ? null : spec.y;\n    var xLines = sx == null ? [] : buildLines(sx, ax, xMin, xMax);\n    var yLines = sy == null ? [] : buildLines(sy, ay, yMin, yMax);\n    var hard = spec.hard === true;\n    var clamp = spec.clamp === true;\n    var threshold = spec.threshold != null ? spec.threshold : null;\n    var clampInto = function (v, lo, hi) {\n        return Math.max(Math.min(lo, hi), Math.min(Math.max(lo, hi), v));\n    };\n    // Snap to the nearest node. A free axis keeps its coordinate; `clamp` (applied\n    // first, independent of `threshold`) constrains it into the extent. With a\n    // `threshold` set, if the nearest node is farther than the pull radius (measured\n    // on the SNAPPING axes only, from the clamped point) the point does not snap — it\n    // stays at its clamped position. Without a threshold this always lands on the\n    // nearest node, however far (the classic behaviour).\n    var snapDraw = function (p) {\n        var cx = clamp ? clampInto(p.x, xMin, xMax) : p.x;\n        var cy = clamp ? clampInto(p.y, yMin, yMax) : p.y;\n        var sx = xLines.length ? nearest(cx, xLines).value : cx;\n        var sy = yLines.length ? nearest(cy, yLines).value : cy;\n        if (threshold != null) {\n            var dx = xLines.length ? sx - cx : 0;\n            var dy = yLines.length ? sy - cy : 0;\n            if (Math.sqrt(dx * dx + dy * dy) > threshold)\n                return Fig.getPoint([cx, cy]);\n        }\n        return Fig.getPoint([sx, sy]);\n    };\n    var snapFigure = function (p) {\n        var draw = anchorEl.pointFromSpaceToSpace(p, 'figure', 'draw');\n        return anchorEl.pointFromSpaceToSpace(snapDraw(draw), 'draw', 'figure');\n    };\n    var nodeDistanceFigure = function (p) {\n        if (xLines.length === 0 && yLines.length === 0)\n            return Infinity;\n        var d = anchorEl.pointFromSpaceToSpace(p, 'figure', 'draw');\n        var dx = xLines.length ? nearest(d.x, xLines).dist : 0;\n        var dy = yLines.length ? nearest(d.y, yLines).dist : 0;\n        return Math.sqrt(dx * dx + dy * dy);\n    };\n    // Faint debug overlay: dots at every node when both axes snap; otherwise the\n    // full snap lines for whichever single axis is active. The grid is a decoration —\n    // it must NOT affect the host's layout, so each element's `drawBorder` is nulled,\n    // which excludes it from the parent collection's bounding box (a collection only\n    // counts a non-collection child whose drawBorder is non-null) while it still draws.\n    var debugRender = function (parent) {\n        var color = [1, 0, 0, 0.35];\n        var decorate = function (opts) {\n            var el = parent.add(opts);\n            el.drawBorder = null; // omit from the host's bounding box / layout\n            el.isTouchable = false;\n        };\n        if (xLines.length && yLines.length) {\n            for (var i = 0; i < xLines.length; i += 1) {\n                for (var j = 0; j < yLines.length; j += 1) {\n                    decorate({\n                        name: \"snapNode_\".concat(i, \"_\").concat(j),\n                        make: 'polygon',\n                        sides: 10,\n                        radius: 0.012,\n                        position: [xLines[i], yLines[j]],\n                        color: color,\n                    });\n                }\n            }\n        }\n        else if (xLines.length) {\n            for (var i = 0; i < xLines.length; i += 1) {\n                decorate({\n                    name: \"snapLineX_\".concat(i),\n                    make: 'polyline',\n                    points: [[xLines[i], yMin], [xLines[i], yMax]],\n                    width: 0.004,\n                    color: color,\n                });\n            }\n        }\n        else if (yLines.length) {\n            for (var j = 0; j < yLines.length; j += 1) {\n                decorate({\n                    name: \"snapLineY_\".concat(j),\n                    make: 'polyline',\n                    points: [[xMin, yLines[j]], [xMax, yLines[j]]],\n                    width: 0.004,\n                    color: color,\n                });\n            }\n        }\n    };\n    return {\n        xLines: xLines,\n        yLines: yLines,\n        extent: extent,\n        hard: hard,\n        threshold: threshold,\n        snapFigure: snapFigure,\n        snapDraw: snapDraw,\n        nodeDistanceFigure: nodeDistanceFigure,\n        debugRender: debugRender,\n    };\n};\nexport { makeSnapGrid };\n","// interface ManipulativeElement extends FigureOneCollection {\n//   _selectBorder: FigureOneElement;\n// }\nfunction setupManipulative(element, selectBorder, options) {\n    if (selectBorder === void 0) { selectBorder = null; }\n    if (options.preserveChildColor != null) {\n        element.preserveChildColor = options.preserveChildColor;\n    }\n    else {\n        element.preserveChildColor = true;\n    }\n    if (options.isShowable == null || options.isShowable === true) {\n        element.custom.isShowable = true;\n    }\n    else {\n        element.custom.isShowable = false;\n    }\n    if (selectBorder != null) {\n        element.custom.selected = false;\n        element.custom.select = function () {\n            selectBorder.show();\n            selectBorder.color[3] = 1;\n            element.custom.selected = true;\n        };\n        element.custom.deselect = function () {\n            selectBorder.hide();\n            selectBorder.color[3] = 0;\n            element.custom.selected = false;\n        };\n        element.custom.toggleSelect = function () {\n            if (element.custom.selected) {\n                element.custom.deselect();\n            }\n            else {\n                element.custom.select();\n            }\n        };\n    }\n    element.custom.showBounds = function () {\n        if (element.custom.boundsShown) {\n            return;\n        }\n        if (element.custom.neverShowBounds != null && !element.custom.neverShowBounds) {\n            element.custom.boundsShown = true;\n            element\n                .getCanvas()\n                .parentElement.getElementsByClassName('figureone__html')[0]\n                .classList.add('figureone_shaddow');\n        }\n    };\n    element.custom.hideBounds = function () {\n        if (element.custom.boundsShown === false) {\n            return;\n        }\n        if (element.custom.neverShowBounds != null && !element.custom.neverShowBounds) {\n            element.custom.boundsShown = false;\n            element\n                .getCanvas()\n                .parentElement.getElementsByClassName('figureone__html')[0]\n                .classList.remove('figureone_shaddow');\n        }\n    };\n    element.setMoveBounds = function () {\n        if (options.boundMove) {\n            if (element.parent == null) {\n                return;\n            }\n            var scene = element.parent.getScene();\n            var f1 = element.parent.pointFromSpaceToSpace([scene.left, scene.bottom], 'figure', 'draw');\n            var f2 = element.parent.pointFromSpaceToSpace([scene.right, scene.top], 'figure', 'draw');\n            var bounds = void 0;\n            if (element.custom.getBoundingRect != null) {\n                bounds = element.custom.getBoundingRect('local');\n            }\n            else {\n                bounds = element.getBoundingRect('local');\n            }\n            element.move.bounds = new Fig.RectBounds({\n                position: [0, 0],\n                topDirection: [0, 1],\n                rightDirection: [1, 0],\n                left: f1.x,\n                top: f2.y - bounds.height,\n                bottom: f1.y,\n                right: f2.x - bounds.width,\n            });\n        }\n    };\n    element.trash = function () {\n        element.stop();\n        element.hide();\n        element.isTouchable = false;\n        if (element.notificationHelper) {\n            element.notificationHelper.cleanup();\n        }\n        element.parent.remove(element.name);\n    };\n    // Only need to see the shadow if not in workPad\n    if (options.boundMove && !element.getPath().includes('workPad')) {\n        element.notifications.add('setTransform', function () {\n            if (element.custom.boundsShown === true) {\n                return;\n            }\n            var p = element.getPosition();\n            var bounds = element.move.bounds;\n            if (bounds != null &&\n                (p.x <= bounds.left + 0.1 ||\n                    p.x >= bounds.right - 0.1 ||\n                    p.y <= bounds.bottom + 0.1 ||\n                    p.y >= bounds.top - 0.1)) {\n                // figure.htmlCanvas.classList.add('figureone_shaddow');\n                element.custom.showBounds();\n            }\n        });\n        element.notifications.add('stopBeingMoved', function () {\n            element.custom.hideBounds();\n        });\n    }\n}\nfunction getAllLinearBlocksSlots(toAdd) {\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'linearBlocksSlot') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction getAllBaseTenBlocksSlots(toAdd) {\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'baseTenBlocksSlot') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction getAllSimpleBlockSlots(toAdd, includeFill) {\n    if (includeFill === void 0) { includeFill = true; }\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'simpleBlockSlot') {\n                out.push(element);\n            }\n            if (includeFill &&\n                element.custom.manipulativeType == 'simpleBlockFillSlot') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction getAllSimpleBlockFillSlots(toAdd) {\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'simpleBlockFillSlot') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction getAllManipulativeTileSlots(toAdd) {\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'manipulativeTileSlot') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction getAllAnswerContainers(toAdd) {\n    var out = [];\n    Object.keys(toAdd.elements).forEach(function (elementName) {\n        var element = toAdd.elements[elementName];\n        if (element.custom != null && element.custom.manipulativeType != null) {\n            if (element.custom.manipulativeType == 'answerContainer') {\n                out.push(element);\n            }\n        }\n    });\n    return out;\n}\nfunction checkAnswerContainers(options, element) {\n    if (options.snapTo == null ||\n        options.snapTo.indexOf('answer_container') === -1) {\n        return 'notConfigured';\n    }\n    var toAdd = element.parent;\n    var answerContainers = getAllAnswerContainers(toAdd);\n    // Of the containers the tile is over, prefer the closest one with free\n    // capacity. Only return 'full' if every container the tile is over is at\n    // capacity — that's the signal for the caller to send the tile home.\n    var closestWithCapacity;\n    var closestWithCapacityDist;\n    var closestFull;\n    var closestFullDist;\n    var elementCenter = element.getBoundingRect().center();\n    for (var i = 0; i < answerContainers.length; i += 1) {\n        var container = answerContainers[i];\n        if (!container.doesContain(element))\n            continue;\n        var d = container.getBoundingRect().center().sub(elementCenter).distance();\n        var isFull = (container.snapToMode !== 'container'\n            && container.snaps.length > 0\n            && container.contained.length >= container.snaps.length);\n        if (isFull) {\n            if (closestFull == null || d < closestFullDist) {\n                closestFull = container;\n                closestFullDist = d;\n            }\n        }\n        else if (closestWithCapacity == null || d < closestWithCapacityDist) {\n            closestWithCapacity = container;\n            closestWithCapacityDist = d;\n        }\n    }\n    if (closestWithCapacity) {\n        if (closestWithCapacity.contained.indexOf(element) !== -1) {\n            return 'placed';\n        }\n        element.answerContainers.push(closestWithCapacity);\n        closestWithCapacity.addToContainer(element);\n        closestWithCapacity.moveInside(element);\n        // Remember where the most recent snap landed so tap-to-place ('snap_last')\n        // can send the next tapped tile to the same container.\n        toAdd.custom.lastSnapContainer = closestWithCapacity;\n        return 'placed';\n    }\n    if (closestFull) {\n        return 'full';\n    }\n    return 'noTarget';\n}\nfunction highlightAnswerContainer(options, element) {\n    if (options.snapTo == null ||\n        options.snapTo.indexOf('answer_container') === -1) {\n        return;\n    }\n    var toAdd = element.parent;\n    var answerContainers = getAllAnswerContainers(toAdd);\n    var closestContainer;\n    var closestDistance;\n    answerContainers.forEach(function (container) {\n        if (container.doesContain(element)) {\n            var distance = container\n                .getCenterFigurePosition()\n                .sub(element.getCenterFigurePosition())\n                .distance();\n            if (closestDistance == null || distance < closestDistance) {\n                closestDistance = distance;\n                closestContainer = container;\n            }\n        }\n        container.unhighlight();\n    });\n    if (closestContainer != null) {\n        closestContainer.highlight();\n    }\n}\nfunction removeFromContainer(options, element) {\n    if (options.snapTo == null ||\n        options.snapTo.indexOf('answer_container') === -1) {\n        return;\n    }\n    for (var i = 0; i < element.answerContainers.length; i += 1) {\n        var container = element.answerContainers[i];\n        container.removeFromContainer(element);\n    }\n    element.answerContainers = [];\n}\nfunction setupManipulativeIndex(style, name) {\n    if (window.grokkoliManipulatives == null) {\n        window.grokkoliManipulatives = {};\n    }\n    if (window.grokkoliManipulatives[style] == null) {\n        window.grokkoliManipulatives[style] = {};\n    }\n    if (window.grokkoliManipulatives[style][name] == null) {\n        window.grokkoliManipulatives[style][name] = 0;\n    }\n}\nfunction incrementManipulativeIndex(style, name) {\n    setupManipulativeIndex(style, name);\n    window.grokkoliManipulatives[style][name] += 1;\n    return window.grokkoliManipulatives[style][name];\n}\nfunction getManipulativeIndex(style, name) {\n    setupManipulativeIndex(style, name);\n    return window.grokkoliManipulatives[style][name];\n}\nvar TRASH_MANIPULATIVES = [\n    'b10_blocks',\n    'linear_blocks',\n    'keypad',\n    'times_table',\n    'rekenrek',\n];\n// Where a slot's add-a-block button pool parks a block once it has been\n// removed: far enough off-figure that it can't be seen or touched. Shared so\n// the park site and the code that recognises a parked block (baseTenBlocks'\n// setState, restoring pre-`sh` states) can't drift apart.\nvar POOL_PARK_POSITION = [100, 100];\n// Counter-based touch suppression. Multiple overlapping animations on the\n// same manipulative each push and pop. Touch is restored to whatever it was\n// before the *first* push, only once the last push is released. Avoids the\n// race where two overlapping captures of `hasTouchableElements` both record\n// `false` and \"restore\" the element to permanently untouchable.\nfunction suppressManipulativeTouch(manipulative) {\n    var depth = manipulative.custom.touchSuppressionDepth || 0;\n    if (depth === 0) {\n        manipulative.custom.touchableBeforeSuppression =\n            manipulative.hasTouchableElements;\n    }\n    manipulative.custom.touchSuppressionDepth = depth + 1;\n    manipulative.hasTouchableElements = false;\n}\nfunction releaseManipulativeTouch(manipulative) {\n    var depth = manipulative.custom.touchSuppressionDepth || 0;\n    var next = depth - 1;\n    manipulative.custom.touchSuppressionDepth = next > 0 ? next : 0;\n    if (next <= 0) {\n        manipulative.hasTouchableElements =\n            manipulative.custom.touchableBeforeSuppression !== false;\n    }\n}\n// Trace an edge-walk outline into vertices. `moves` are [heading°, length] on an\n// absolute compass (0 = +x, 90 = +y, CCW positive), stepped from `start`. If the\n// walk returns to its start the duplicate closing point is dropped, so a closed\n// shape draws a clean last->first edge rather than a zero-length one over a\n// doubled vertex; an open walk is left as-is. Shared by poly and splittable_shape.\nfunction outlineVertices(moves, start) {\n    if (start === void 0) { start = [0, 0]; }\n    var s = Fig.getPoint(start != null ? start : [0, 0]);\n    var verts = [Fig.getPoint([s.x, s.y])];\n    var x = s.x;\n    var y = s.y;\n    var list = moves || [];\n    for (var i = 0; i < list.length; i += 1) {\n        var a = (list[i][0] * Math.PI) / 180;\n        x += list[i][1] * Math.cos(a);\n        y += list[i][1] * Math.sin(a);\n        verts.push(Fig.getPoint([x, y]));\n    }\n    var last = verts[verts.length - 1];\n    if (Math.hypot(last.x - s.x, last.y - s.y) <= 1e-4) {\n        verts.pop(); // drop the closure point (it duplicates the start).\n    }\n    return verts;\n}\nexport { setupManipulative, getAllLinearBlocksSlots, getAllBaseTenBlocksSlots, getAllSimpleBlockSlots, getAllAnswerContainers, checkAnswerContainers, highlightAnswerContainer, removeFromContainer, setupManipulativeIndex, incrementManipulativeIndex, getManipulativeIndex, getAllManipulativeTileSlots, getAllSimpleBlockFillSlots, TRASH_MANIPULATIVES, POOL_PARK_POSITION, suppressManipulativeTouch, releaseManipulativeTouch, outlineVertices, };\n"],"names":["samePositionAsSaved","live","saved","a","Fig","parsePoint","b","round","x","y","createBaseTenBlocks","fig","eqn_name","toElement","o","boundMove","newO","joinObjects","name","concat","n","scale","createScale","fromPalette","to","baseTenBlocks","options","toAdd","get","elements","Array","isArray","size","color","line","createdFrom","xAlign","appear","orientation","border","canRotate","yAlign","yOffset","preserveChildColor","isSelectable","isTouchable","snap","selectLine","width","colors","COLOR_GROKKOLI_BLUE","space","debug","returnToInitial","maxBreaks","maxBreaksTotal","radius","dimension","position","borderEnabled","borderOpts","lineEnabled","lineOpts","lineWidth","lineColor","s","height","is3D","depthCells","depth","visualHeight","yBorderDelta","colorHighlight","colorDim","hBorder","Point","vBorder","fw","fh","cubeBorder","element","add","make","custom","notificationHelper","container","setRotation","Math","PI","block","topFace","rightFace","selectBorder","linesY","linesX","borderLine","frontRect","corner","sides","borderWidth","borderColor","shade3D","W","H","Dx_1","Dy_1","wCells","hCells","FL","FR","TR","TL","back_1","p","gridSegs_1","addFace","p1","p2","baseCells","gridColor","face","points","drawType","i","t","push","j","light","dark","lightLine","darkLine","length","cubeGrid_1","forEach","_a","cubeEdges","backPath","interior","base","setColor","computeState","e_name","getPosition","r","getRotation","getPath","regex","RegExp","c","replace","slice","e","sel","selected","sh","isShown","hide","copy","along","step","num","snaps","isSnapped","getState","setState","stats","setPosition","setBlockRotation","state","moved","select","shown","undefined","buttonSourced","initial","initialPosition","inferShownFromPosition","show","setMoveBounds","breakBaseTenBlocks","break","blockRotation","getBlockRotation","_loop_1","oneBlock","showAll","setPositionToElement","setTimeout","trash","_loop_2","tenBlock","_loop_3","hundredBlock","manipulatives","totalBreaks","N","m","manipulativeType","worksWith","checkBreakCount","breaks","disable","getContainerBounds","rect","getBoundingRect","bounds","Rect","left","bottom","ignoreSetColor","setTouchable","setMove","freely","move","manipulativeAid","style","highlightContainer","_container","_block","secondaryTouchBounds","selector","clickStart","method","highlightWorksWith","checkDeselect","snappedSlot","setAsToSnap","performance","now","startBeingMoved","parent","toFront","window","clickHandled","toggleSelect","workPad","_controls","_delete","hideAll","remove","answerContainers","checkAnswerContainers","removeFromContainer","snapPositionDelta","wantsSlotSnap","snapTo","indexOf","unsnap","slot","checkSlotSnaps","slots","attempted","tryAutoSnap","inBounds","accepted","commitSnap","startMovePosition","stopAnimating","animations","new","target","duration","trigger","start","bringUnsnappedBlocksToFront","all","walk","root","names","Object","keys","el","sub","distance","tryTapSlotSnap","preferred","toSnapBaseTenBlocksSlot","tryTapSlotReturn","opacity","snappedAtMoveStart","unhighlight","disabled","highlight","dim","answerContainerMoved","wasTap","wasSnappedAtMoveStart","result","executedMethod","rotation","startMove","reflowAfterRemove","orient","setBorder","hasTouchableElements","colsAtMax","mode","unitWidth","cell","max","cellsPerBlock","type","ceil","offsetX","mps","maxPerStack","sg","stackGap","widthAtMax","floor","makeContainer","groupSize","groupSpace","blocks","subOffset","splice","canAdd","widthIfAdded","positionFor","originX","originY","nextPosition","orderedBlocks","cols","colsIfAdded","colOf","nextCol","makeRowContainer","cells","Map","cellsPerCol","subCols","col","columnHeights","h","cur","row","numCols","findNextCell","used","set","delete","remaining","blk","sort","clear","idx","arr","map","makePackContainer","offsetY","infinite","per","Number","MAX_SAFE_INTEGER","fullStackWidth","offsetFor","oy","abs","stack","pos","widthForN","lastIdx","makeDiagonalContainer","baseTenBlocksSlot","defaults","fill","label","xLabelOffset","yLabelOffset","font","family","defaultFontFamilyMath","dash","snapBorder","borderInSize","correctness","animationDuration","orderSpace","depthSeparation","grid","group","stylePresets","normal","flat","spaced","stacked","hundreds","thousands","console","log","styleOrderSpace","rawOrderSpace","alwaysCenter","diagonalHundreds","cubeDepthOffset","diagonalThousands","groupedRow","plainRow","onesPack","defaultModes","tens","ones","normalizeSpec","spec","enabledByDefault","defaultMode","assign","thousandsMode","hundredsMode","tensMode","onesMode","unitWidthFor","colsList","reduce","groupNum","groupSpaceVal","nameRegex","borderDefaults","correct","COLOR_GROKKOLI_GREEN","incorrect","COLOR_GROKKOLI_ORANGE","fillDefaults","gridDefaults","hl","border_1","fb","onHl","onBorder","onGrid","numGroups","gapSpacing","renderedWidth","slotBaseHeight","padBelow","padAbove","accumulatePad","blockH","bidirectional","blockHeight","below","above","min","mag","downPad","upPad","verticalPadFor","mayContain3D","slotYBase","borderOffset","borderSpace","groupXAt","g","singleGroupX","fills","borders","toSnapFills","toSnapBorders","toSnapDisabled","toSnapSlot","toSnapOpt","toSnapFillColor","fillColor","toSnapBorderColor","regularBorderWidth","regularBorderDash","toSnapBorderWidth","toSnapBorderSpace","toSnapBorderRadius","toSnapBorderDash","tapCaptures","startCol","endCol","colsInGroup","groupW","groupX","nameSuffix","f","tc","touch","tsf","numY","vCount","hCount","initialColor","tsbSpace","tsb","toString","slotFont","render","forms","formDefaults","alignment","groupIdx","xCell","thousandsContainer","hundredsContainer","tensContainer","onesContainer","containers","snappedBlocks","refreshButtons","getSiblingSlots","out","els","refreshToSnapHighlight","isToSnap","visible","showingCorrectness","siblings","notifications","defineProperty","containerFor","blockType","contentOrigin","colGapAt","absCol","containerStartCol","hypothetical","containerDepth","b0","containerPlace","gapAfter","prevPlace","prevDepth","place","v","default","orderSpaceFor","containerOriginX","w","prevNonEmpty","contentWidth","effW","centerOffsetX","blockWorldPosition","baseY","extra","animateBlockTo","onArrive","arriveKey","fnMap","beforeFrame","callback","drawsBackToFront","modeOf","layoutAll","slotPos","order","reverse","expression","getTargetPositionFor","totalCols","containerNextWorldPosition","insertBlock","blockBounds","refreshSnaps","toPulse","pulseOptions","pulse","pulsePlace","opts","pointFromSpaceToSpace","delta","translation","angle","frequency","full","ordered","partial","walkAll","allBlocksOfType","test","findAvailableBlockOfType","buttonsOpt","buttons","buttonsEnabled","buttonsInteractive","buttonOverrides","b_1","spacing","offset","xPosition","yPosition","layout","inSize","backgroundColor","disabledBackgroundColor","disabledColor","disabledLineColor","labelFont","enabledKeys_1","key","enabled","filter","buttons_1","xPosFrac","yPosFrac","xAlignFrac","yAlignFrac","isCol","stripW","stripH","anchorY","stripLeft","stripBottom","bx","by","btn","bg","iconBorder","labelText","lbl","dflt","perType","labelFor","text","weight","cCell","fSize","d_1","ox","back","topFace_1","rightFace_1","edgeColor","setFaceColor","rows","iconW","iconH","iconX","iconY","claimForPool_1","setOpacity","cleanup","removeKey","isMovable","onButtonPress_1","bl","available","faceColor","fc","animateBlock","nameOrN","toOrDuration","legacy","destination","resolvedDuration","findBlockByName","findLastSnappedBlockOfType","findNextAvailableBlock","findLastSnappedBlock","d","d_2","hideKey","target_1","ip","th","o_1","counts","k","reset","showAnswer","showOptions","values","current","evict","showCorrectness","_b","correctColor","colorCorrect","incorrectColor","colorIncorrect","borderTarget","fillTarget","siblingsNow","baseTenBlocksControl","controlOptions","appearSpace","maxNum","blockOptions","controlOnly","manipulativeControlType","count","create","customN","new_element","beingMovedElement","new_element_p","newR","t1","t2","progression","baseTenBlocksMenu","justify","upScale","controls","control","setScale","right","controlElements","scene","getScene","createLinearBlock","linearBlocks","BLOCK_COLORS","OFFSET","countColor","isCountable","countDirection","continueAt","countUpColor","countDownColor","countElement","countElementValue","showSnap","getSnapPosition","index","getLocalPosition","slotSnapIndex","isPrimarySnap","startPoints","endPoints","midPoints","unitPoints","getRectPoints","grokkoli","globalBlockCounter","blockCountElements","figure","_expression","resetCount","startCount","countUp","countDown","countElements","countState","updateCount","setText","snapIndex","leftSpace","rightSpace","leftSpc","c_1","transform","_cross","_fill","blockCounter","_continue_button","stop","countCallback","nMod","textP","labelColor","labelSize","blockFont","split","at","n1","n2","second_element","afterSnapChange","animateToPosition","animateAndSnapToSlot","stopBeingMovedProcessing","answerChanged","tryTapSnap","linearBlocksSlots","autoSnap","anchor","findFirstAvailableAnchor","reservePendingPlacement","getTargetForAnchor","tryTapReturn","hasAnyAutoSnapSlot","autoSnapWinnerSlot","autoSnapWinnerDelta","autoSnapAttempted","findAutoSnapPlacement","smallestDelta","slotIndex","checkSnaps","setPositionToSlot","oOffset","slotSnapPos","blockSnapOffset","tTarget","_text","toColor","targetColor","countOrIndexes","startColor","indexes","steps","inParallel","resetColors","linearBlocksControl","new_p","linearBlocksMenu","drawNumber","linearBlocksSlot","numX","showBlocks","enforceOrder","stateOrder","autoSnapFit","lineDefaults","showBlocksDefaults","snapPositions","snapPosition","getManipulativeBaseSnap","fullBlocks","partialBlocks","blockSnap","blockIndexes","primaryBlock","primaryBlockSnapIndex","pendingBlock","slotSnap","getSnapFromPosition","clearPendingPlacement","slotSnaps","index_1","slotPosition","getSlotBorderBounds","slotBounds","getOccupiedSnapsForAnchor","anchorIndex","blockSnap0Pos","anchorPos","occupied","targetPos","matched","blockedBy","animateLinearBlock","outbound","elementNames_1","best","bestAnchor","isPendingInSlot","elementNames","findLinearBlock","anchorToReserve","found","slotSnapPosition","del","manipulativeTile","onClick","textFont","defaultFontFamily","labelColors","isShowable","COLOR_GROKKOLI_LIGHT_GREY","tile","parseFloat","parseInt","updatePoints","child","_CHILD","readyPosition","center","slotOnClick","startPosition","wasInContainer","wasSnapped","tileSlots","snappedTile","slotSnappedTile","moveTo","refresh","toArray","moveToContainer","cont","moveTile","contained","moveToRegion","regionName","moveTileToRegion","moveHome","isQuickClick","last","lastSnapContainer","includes","addToContainer","placeTapped","labelElements","getAllElements","_c","_d","correctLabelColor","colorCorrectLabel","incorrectLabelColor","colorIncorrectLabel","manipulativeTileSlot","colorSnapped","COLOR_GROKKOLI_MEDIUM_GREY","tp","_dup","tileBounds","slotBorderBounds","simpleBlock","styleDefaults","static","glyphs","snapStyle","labelOffset","snapped","snapFail","numSnaps","o_offset","getFirstSpace","allSnapped","snappedFillSlot","simpleBlockSlots","snapToGrid","setColors","except","_border","_label","setupLabel","labelOptions","symbol","__symbol__","side","symbolHeight","labelYOffset","content","topComment","ascent","comment","commentSpace","contentSpace","bottomComment","descent","simpleBlockSlot","tileLineWidth","correctnessBorder","technicallyCorrect","invalid","correctnessBorderDefaults","COLOR_GROKKOLI_GOLD","COLOR_GROKKOLI_GREY","cBorder","cSpace","cRadius","lineRadius","sideExtent","borderOuter","cOuter","totalW","totalH","labelRect","labelLeft","labelShift","labelRight","top","simpleBlockFillSlot","s1","maxY","lastBlock","elementRectWidth","elementRectRight","blockRect","blockWidth","lastX","snappedBlockRect","fullSnap","enable","firstSpace","numberlineManipulative","hopManipulative","arrow","xOffset","defaultArrowOptions","head","tailLength","hopElement","selectorControlManipulative","newSelector","trashManipulative","icon","selectPosition","texture","src","location","origin","mapFrom","mapTo","loadColor","lastPosition","highlighted","drawOrder","worksWithTrash","isPointInside","_line1","_line2","_line3","_line4","dissolveOut","delay","dissolveIn","RATIO","timesTable","ratio","tailWidth","tail","dimRect","controlElement","getElement","snapshot","publish","showArrow","operand","moveArrow","hideArrow","_line","rekenrek","single10","beads","barOverhang","double10","triple10","quadruple10","double20","fill1","fill2","line1","line2","barColor","rightFill1","rightFill2","rod","muted","barWidth","neverShowBounds","colorRight","prefix","intendedTouchable","touchLeft","priority","touchRight","resetButton","resetFont","colorFill","touchBorder","toLeftCount","toRightCount","stopGroupMove","allBeads","bead","widthIs","bounceLoss","deceleration","Line","bounce","moveGroup","ii","pp","groupDirection","_count","getCount","toLeft","velocity","toEnd","toRight","end","boundary","afterFrame","rightPosition","isLeft","totalMoves","startGroupMove","bead_1","jj","startLeft","direction","leftBead","rightBead","leftBeadP","rightBeadP","isSlot","rowsState","beadsState","p_1","left_count","right_count","enableBeads","_reset","showIn","enableTouch","beadAnimations","answerAnim","toPos","makeTouchable","touchable","makeNotTouchable","colorStyle","_leftBar","_rightBar","fill_1","disableInteraction","enableInteraction","disableInteractionCallbacks","wasDisabled","minuteAngleToAngle","minuteAngle","hourAngleToAngle","hourAngle","hourAngleToHourTime","hour","angleToTime","minute","timeToAngle","hourMinute","angleToMinuteAngle","angleToHourAngle","getColor","option","colorName","clock","minuteHand","controlsHour","hourHand","small","minuteLabels","minuteTicks","hourTicks","hourLabels","fontSize","HoursOnly","baseline","markerLines","arc","helper","subslots","setMarkerLine","hideMarkerLine","hideMarkerLines","fillCenter","startAngle","setArc","setArcOptions","endAngle","followHour","startTime","endTime","endMinute","startMinute","hideArc","length_1","cos","sin","length_2","angle_1","length_3","r_1","hourFont","minuteFont","hourHandMover","length_4","snapNum","moving","time","controlsMinute","setTime","snapAngle","thisHour","lastHour","unhighlightHour","highlightHour","minuteHandMover","length_5","colorHourHand","colorMinuteHand","goToTime","gtto","startAngle_1","targetAngle","delta_1","percent","pow","targetAngleM","targetAngleH","deltaM_1","deltaH_1","startAngleM_1","startAngleH_1","getTime","mh","minuteAngleToMinuteTime","hh","updateRotation","hourTick","minuteTick","hourLabel","minuteLabel","_center","shakeMinuteHand","centerOn","shakeHourHand","highlightHourHand","unhighlightHourHand","highlightMinuteHand","unhighlightMinuteHand","shakeHands","pulseHour","hourElem","tickScale","hourScale","hourTicksColor","hourLabelsColor","getCorrectnessColor","section","enableHelper","disableHelper","event","_debugPoint","toPolar","angleDelta","tools","g2","getDeltaAngle","deltaMinutes","minutes","addMinutesToTime","arcGoTo","fromMinute","toMinute","from","getRoundedTime","entryField","single","multi","fixed","close_button","fixedSpace","charset","max_char","max_char_nest","max_nest","init","endCursor","font_size","hide_keyboard_on_click","hide_keyboard_on_submit","enter_key_submit","init_label","x_buffer","keyboardDef","INT_STACK","INT_FLAT","INT_ARROW_FLAT","INT_HARROWS","INT_ARROWS","DEC","DEC_FLAT","FRAC","FRAC_FLAT","REPEATER","POW","PHRASE","PHRASE_TIMES","PHRASE_TIMES_FLAT","validKeys","button","keyboardKeys","maxChars","setWidth","setHeight","autoWidth","maxCharNest","maxNest","scaleIn","addTo","valid_keys","scenarios","expectedAnswer","appearIn","honing","forSlides","eqnOptions","enterKeySubmit","hideKeyboardOnClick","hideKeyboardOnSubmit","xBuffer","initLabel","closeButton","onSubmit","getAnswerInput","click","_entryField","summarize","_keyboard_div","visibility","locate","_keyboard_input","uid","hideCursor","rekenrekControl","buffer","resetSpace","hidden","createRekenrek","isHidden","rectBottomLeft","rectTopRight","newRect","midY","midX","localScene","deltaX","deltaY","showTable","_dim","hideTable","rekenrekMenu","autoShow","edgeSpace","timesTableControl","table","createTimesTable","timesTableMenu","tables","trashControlManipulative","customSlot","createdFromRegex","_e","figAny","customSlots","userGetState","configurable","enumerable","data","fn","args","_i","arguments","apply","templateManipulative","__spreadArray","pack","ar","l","prototype","call","poly","HL","close","alignTo","touchBorderBuffer","lines","angles","pad","selectable","selectCircle","selectShape","shape","movable","press","corners","squareAngles","growLines","pressPreset","isFormIgnored","padsLayer","selectLayer","baseLineLayer","fillLayer","overlaysLayer","anglesLayer","squaresLayer","squaresFrontLayer","growLinesLayer","growLinesFrontLayer","curvesLayer","curvesFrontLayer","sidesLayer","gridLayer","vertices","resolveDefinition","dx","dy","getPoint","applyGridSnap","baseLine","fillElement","counterEl","debugLine","cornerPads","sidePads","cornerDragPads","sideDragPads","activeDragPad","sidePadFull","sidePadBaseW","sideDragFull","sideDragBaseW","sideEls","sideOffsets","sideValueFmt","braceEls","braceOffsets","sideMarkEls","sideMarksHidden","suppressPad","overlayEls","selectShapeEls","selectShapeMeta","angleEls","angleMarkHidden","angleSelectCircles","angleSelectVertices","angleSelectCorners","angleSelectCornerLen","angleSelectMarks","squareEls","squareFillEls","squareLineEls","squareSizes","squareAligns","squareHidden","growLineEls","growLineAnchors","growLineExts","growLinePlacing","growLineHidden","growLineHideOnSelect","growLineSelHidden","growLinePressShown","growLineGrown","growLineOrder","curveSides","curveClosed","curveEls","curveLineEls","curveCapEls","curveHidden","cornerSelectPads","sideSelectPads","sideSelectFull","sideSelectBaseW","cornerPressesSquare","selectedAngles","Set","selectedSides","selectedVertices","selectedCorners","highlightedAngles","highlightedSides","allSelectionSets","selectionSetForKind","kind","applySelectMode","on","stateFadeDuration","indicatorShown","indicatorFading","applyIndicator","changed","dissolveDecoration","applyStatesFading","applyStates","sideCount","angleCount","sideEndIndex","angleVertexIndices","p3","angleIndexForVertex","cornerBracketPoints","q","len","hypot","squarePoints","align","dir","dPrev","dNext","axisOffset","quarter","atan2","other","sign","perp","squareTriangles","pts","normalizeSide","growLinePoints","ext0","ext1","ux","uy","e0","e1","total","pull","curvePoints","pop","curveRunOf","wrap","prev","next","curveBandTriangles","margin","unit","u","mx","my","mLen","cv","run","outline","tris","regularVertices","defaultRegularRotation","def","resolveMorphShape","reg","morphs","warn","excludeFromSize","layer","anyPad","resolveAngleSpec","resolveLineSpec","padMovable","parseRange","addDebugBorder","host","initRef","dbg","debugBorder","addDragPad","onMove","dragPad","setMovable","cfg","xr","yr","constrain","fnName","setTransformCallback","updateGeometry","addTapPad","selectPad","has","pressSquare","pressExtend","padVisual","counterText","counter","of","suffix","positionCounter","Infinity","off","buildCounter","each","resolveSquareSpec","growLineCount","isNaN","resolveGrowLineSpec","resolveCurveSpec","curves","baseStroke","formatLength","valueScale","dec","toFixed","forceDec","String","mapArrows","arrows","fillTriangles","area2","ring","cross","inTriangle","d1","d2","d3","guard","clipped","iPrev","iCur","iNext","contains","createAngle","specOverride","rightAngle","interiorDir","isCCW","baseArcs","arcs","baseWidth","baseRadius","baseSpacing","arcSpacing","arcSidesForRadius","useFill","outside","curve","autoRightAngle","startHidden","selState","states","selFill","selArcs","selWidth","selSpacing","mark","sc","hasFill","circle","selectVertex","sv","marker","selectCorner","cc","cap","bracket","roundEnds","refreshCurve","caps","refreshGrowLine","outsetPolygon","ccw","sqrt","e1x","e1y","e2x","e2y","n1x","n1y","mlen","syncDebugBorder","getScale","refreshCornerPressTouchBorder","disc","drawBorder","ai","square","debugPressSquare","syncPressSquareDebug","stateFor","anySelected","angleRestingColor","angleStateColor","applyOverlayState","overlay","stateOverride","look","hasSelMark","_curve","refreshGrowLineSelection","hideZero","updateCounter","onSelection","onSelectionApplied","outset","setEndPoints","setLabel","mid","edgeAngle","edgeLen","banded","geom","setAngle","moveCorner","moveSide","sa","ss","stroke","toggleInto","cancel","settleGrowLine","animateGrowLine","growTargetExts","value","gap","rest","lenFig","lenDraw","reach","px","py","isFinite","growLineBoundsExts","half","pressOpt","touchGrowLine","unshift","showSquareAngle","revealForPress","grow","growDuration","leastUsedGrowLine","placeDuration","fromExt","resolveTarget","builder","moveAndGrowLine","selectAngle","selectSide","highlightAngle","highlightSide","showSideMarks","hideSideMarks","showAngleMark","hideAngleMark","hideSquareAngle","showCurve","hideCurve","curveCount","curveInfo","closed","growLine","placeLine","pointIndex","showGrowLine","hideGrowLine","pressCorner","pressSide","growLineInfo","ext","grown","clearSelection","countAngle","counterElement","counterOptions","angleIndex","padOptions","touchR","touchRadius","selShape","createCornerSelectPad","pulseTarget","morph","arg","getBorder","setBorderFixed","fixBorder","segCount","segLen","rep","resampleToCount","done","whenFinished","lens","dirs","perimeter","maxLength","tolerance","maxAngle","minSides","short","joins","longer","turn","linked","record","every","continued","detectCurves","needPads","needSelectShapes","needSelectCircles","needOverlays","needAngles","needSides","needSquares","needSquaresFront","needGrowLines","needGrowLinesFront","needCurves","needCurvesFront","annotation","marks","sq","front","addLayer","createLayers","buildGrid","initMid","initEdgeLen","fullLength","padLength","padWidth","dragFull","touchLength","dragBaseW","dragShape","touchWidth","selFull","selBaseW","buildSidePads","hasAngle","selects","buildCornerPads","interiorLoc","flip","loc","labelLocation","isValue","len0","ann","sideSign","buildSides","tan","buildSideMarks","buildAngles","buildSquares","inset","hideWhenSelected","buildGrowLines","capped","buildCurves","buildOverlays","isRect","buildSelectShapes","applyAlignment","baseShowAll","bind","tag","rotateSplitterStyle","degrees","pads","relative","rotateButton","LINE_STYLES","rotate_splitter","rotate_splitter_30","rotate_splitter_45","rotate_splitter_90","lineManipulative","lineP1","lineP2","styledOptions","minWidth","optPads","endEnabled","centerEnabled","endOpt","centerOpt","endOffset","endIsRect","endMovable","endRelative","centerRelative","snapEnabled","snapPads","point","ang","midpoint","endPadPos","endFromPad","clampMinWidth","lineEl","makeControl","cosmeticShape","moveShape","hugLine","cosmetic","rectHug","halfLen","halfAcross","makeEndControl","centerControl","end1Control","end2Control","updateLine","placeControl","ctrl","includeMove","alignControls","L","lineLength","cutBtn","anchoredButtons","placeAnchoredButtons","offX","offY","updatePadsFromLine","wirePad","settling","commit","targetP1","targetP2","refLocal","clampCenterIntoFigure","snapLocal","clampPointIntoFigure","local","gridForPad","hard","padGridIsSoft","animateToLine","SNAP_SETTLE_DURATION","snapLineForRelease","snapGridOf","snapGrid","nearestSnapGrid","figurePt","bestD","isSplittable","nodeDistanceFigure","overlap","resolveSplittable","primarySnapGrid","force","snapFigure","pLocal","cx","cy","mLocal","insetX","insetY","mFig","f1","f2","lx","ly","clampAxis","lo","hi","ins","snappedEnd","rawEnd","figClamped","clamped","nodeWithin","threshold","centre","e2","getLinePoints","getFigureLine","setLine","startP1","startP2","endP1","endP2","finish","ease","shapeArg","neg","splitShape","pieceIndex","splitByLine","animateReflect","cutButton","cb","btnPieceIndex_1","splitOpts_1","pause","ambient","backColor","perspective","lockSeconds_1","iconColor","iconScale","cutTouch","alpha","shade","S","spineTop","spineBot","leftQuad","rightQuad","pw","triPts","tStart","tEnd","arcPts","hw","addCutIcon","cutBusy_1","rb","rotRad_1","rotDuration_1","rotBtn_1","rotTouch","sweep","t0","ex","ey","tx","ty","tl","addRotateIcon","roff","hideRotateButton","showRotateButton","rotateAbout_1","ca","rotBusy_1","finalized","EPS","MANIPULATIVE_COLS","EXTRA_PIECE_COLORS","splittableShape","splitColors","maxPieces","reportIgnoreAreaFrac","shapePoints","sideOf","segLineIntersect","rx","ry","sx","sy","denom","clipHalfPlane","nxt","dCur","dNxt","triangulate","cleanPolygon","minX","minY","maxX","diag","tol","l1","l2","polyCentroid","buildGroup","fullGroup","palette","pieceColors","pieceColorAt","pieceGroups","splitsShown","_outline","debugRender","lastCut","lastHalves","lastPieces","lastCutLines","resolvedSplitLines","lineToLocal","figurePts","splitByLines","cuts","ln","pieces","polyArea","worthy","setTransform","Transform","splitShapes","drivePieces","clearSplit","theta","axisX","axisY","strength","sigma","maxR","camZ","applyFold","phi","components","cosPhi","bright","anim","animateRotateOnto","onLine","applyRot","pr","polyAngles","angs","polyEdges","cornerAlign","A","B","aDir","bDir","nA","nB","a0","aNext","aPrev","bNext","bPrev","outDx","outDy","inDx","inDy","ax","ay","det","makeRigid","matchProper","angA","angB","lenA","lenB","perimA","perimB","charLen","wA","wB","pairCost","bestK","bestCost","den","cost","bestI","bestScore","cutSum","score","map_1","exact","err","pinA","pinB","pinEdges","apexOf","cut","bi","bj","rigidMap","proper","aRef","refl","tpx","tpy","cosp","sinp","beta","glide","gx","gy","reflected","p0x","p0y","animateRotateOntoPiece","fromIndex","toIndex","bestErr","r3","phiDeg","pinFrom","pinTo","pivot","foldLine","p0","startDelay","hold","fillFront","foldBack","foldCamZ","phiFold","cosF","animateRotateOntoPieceAll","r3_1","fallback","delayTo","delayFrom","eligible","fromStart","animated","separateSplit","splitIndexes","fixedDir","separateOne","splitIndex","piece","pc","separated","animateCongruent","congruentIndex","congruenceGroups","setPieceDim","dimmed","fillBase","outBase","outTarget","indexOrIndexes","idxs","showEqualSplit","cutLines","outlineEl","norm180","fp","mean","targets","angDist","lineOrder","_","sortedTargets","bestShift","pending","toLineDraw","lp","figPt","answerSpecPoints","showAnswerLines","resolved","al","answerLines","freeRotation","list","resolveAnswerTargets","targetPairs","dist","ci","straight","flipped","rotAbout","co","phis","deg","perms","build_1","chosen","pi","rt","usedT","bt","bc","bf","asn","tp1","tp2","glideToTargets","getSplitReport","getSplitLines","a2","groups","placed","maxCongruenceError","ref","refArea","worst","cutLineAnglesDeg","answerPointDistances","answerPoints","localLines","dists","fl","distanceToPoint","ignoreAreaFrac","maxNegArea","maxNegligibleArea","areas_1","total0","areas","equalArea","congruentGroups","congruent","lineAngles","minAreaFrac","negligibleCount","mainCount","areaSpread","congruenceError","pointDistances","areaList","spread","mainPieces","mainMin","mainMax","mainTotal","mainMean","mainSpread","snapFigurePoint","splitLines","specs_1","resolve_1","specPoints_1","outline_1","placeLine_1","wired_1","resplit","padNames","_loop_4","resplitOnRelease","payload","SOLID3D_BASE_DEFAULTS","cameraPosition","isRotatable","autoRotate","layoutBox","sensitivity","edgeWidth","edgeSides","hiddenLine","silhouette","annotationColor","annotationFaceColor","annotationEdgeColor","annotationVertexColor","annotationEdgeWidth","annotationEdgeOvershoot","annotationVertexRadius","REAL_CAMERA","LOOK_AT","UP","PROJ_SCALE","EDGE_SCALE","HL_AXIS_TOL","scaleEdgePoints","z","edgeTubePoints","overshoot","over","line3","normals","addLineEdges","build","raw","glPrimitive","setEdgePoints","updateGeneric3","prismOutline","cz","latheMesh","profile","segMode","dr","sl","ny","nr","horizontal","capSign","aj","aj1","B0","B1","T0","T1","tri","nrm","normalize","nj","nj1","crossProduct","solidGeometryAt","R_1","aCut","profile_1","R","isFaceted","SQRT1_2","topY","ringSegments","d0","solidEdgesAt","R_2","sides_1","topR","nSides","rot","SILHOUETTE_TYPES","solidHiddenLineOn","SIL_CIRCLE_SAMPLES","solidFeatureParams","sweepWallPoint","proud","nR","nY","addColorableShape","classify","geometryAt","faceOf","faceSum","nx","nz","faceNormals","colorFace","faceIndex","cullToFront","frontColor","m3","transformVector","faceNormal","faceIndices","faceTriangles","makeSolid3d","config","boxW","boxH","boxXAlign","boxX","boxY","sceneX","handleX","handleY","cameraMatrix0","lookAt","viewToMatrix","cam","up","mul","inverse","modelMatrix","tapers","transformBy","projectedFootprint","HANDLE_SIZE","Scene","camera","near","far","directional","solidScene","addShape","hiddenLineOn","hlInput","topCap","botCap","ringPt","segTotal","n_1","corner_1","pAt","wall_1","n0","slope","wall_2","s0","sTotal","wall_3","apex","slantN","v1","v2","wall","solidHiddenLineEdges","silhouetteOn","edges","addEdges","isCylinderHL","isConeHL","isSphereHL","freezeFill","hlEdges","hlSolidArc","hlSilhouette","updateHiddenLine","updateSilhouette","opaqueFill","opaqueEdges","wireframeOn","wireAnimating","ec_1","TRANSPARENT_1","EPS_1","FACE_TINT_1","hlWidth_1","hlSides_1","hlThick_1","cellPoints_1","vpc_1","DASH_1","pushCell_1","points_1","colors_1","cellEdge_1","cellInk_1","edgeN0_1","edgeN1_1","ei","EPS_T","ink","hiddenLineDashCells","c0","norm3_1","cross3_1","axisOf_1","av","axisStill_1","reorientFill_1","Rc_1","Lc_1","TWO_PI_1","buildArc_1","rims","capFront","aPoints","aColors","radial","rim","C","r0","r1","rm","restA","arc0","arcEl_1","lastArcA_1","lastVis_1","lastFillA_1","vis","visChanged","buildSil_1","sil","segments","R_3","norm","rho","degenerate","acos","solidSilhouetteSegments","sPoints","sColors","restSilA","sil0","silEl_1","lastSilA_1","og","opaqueColor","wireEls_1","Boolean","solidEls_1","setWireframe","wire","showEls","hideEls","animateNextFrame","BASE_LIGHT","annElements","restMatrixInv","viewUp","applyView","viewCam","faceZ","setLight","featureVerts","solidFeatureVertices","featureEdges","solidFeatureEdges","faceIdx","faces","faceAnn","edgeAnn","vertAnn","FACE_PROUD","annColor","faceColorDefault","edgeColorDefault","vertColorDefault","registerAnn","showFace","f_1","pz","hideFace","hideSweep","sweepFill","sweepLine","sweepable","sweepFace","sweepWall","toView","samples","viewN","sweepStart","fillPoints","segs","span","sweepFillPoints","edgeW","linePoints","sweepLineEnds","fillCol","lineCol","fillEl","showEdge","sd","globalOver","ov","pairs","hideEdge","showVertex","v_1","sphere","hideVertex","showFaces","showEdges","showVertices","hideAnnotations","EL_MAX","POLE_EPS","azOf","elOf","asin","DEG","animateThrough","stops","onFinish","camAt","az","pole","upForEl","startDir","fromAz","fromEl","tEl","dAz","dEl","legDur","legPause","viewFrom","azimuth","elevation","spinPaused","resetOrientation","resumeAutoRotate","highlightFace","entries","entry","faceN","geometryAt_1","setGrowth","edgesAt","localPointToExpression","p3d","isInteractive","handle_1","handle","P","U","deltaAz","deltaEl","panAxis","tiltAxis","toPole","dotProduct","Pn","getTransform","matrix","rotateView_1","updateTranslation","speed_1","U_1","L_1","last_1","ease_1","tiltReveal","angleDeg","holdSec","riseSec","tilt","spinStopped","rise","restCam","axis","maxEl","dt","frac","advanceTilt_1","holder","solid3dStack","depthOffset","updateDepth","myIdx","inFront","sib","setCamera","cubeFaceOf","_p","cube","faceLight","cylinderFaceOf","cylinder","coneFaceOf","cone","coneTip","sphereFaceOf","pyramidFaceOf","pyramid","pyramidTip","prism","TWO_PI","faceAz","prismPolygonFaceOf","rel","SQRT3_2","regularUnitEdge","CLASSIC","triangle","verts","hexagon","blueRhombus","tanRhombus","trapezoid","TRI_COUNT","SYMMETRY_ANGLE","deg2rad","wrapAngle","rotatePoint","convexOverlap","eps","polys","aMin","aMax","bMin","bMax","copyToClipboard","ta","document","createElement","body","appendChild","execCommand","removeChild","navigator","clipboard","writeText","catch","patternBlocks","rotateStep","snapOn","snapCfg","posTol","angTol","angleTolerance","initialRotation","fan","centroidWorld","worldVertsAt","getOtherBlocks","bestMate","sources","isPatternSlot","mySegs","getWorldSegments","nbPolys","getWorldVertices","candidates","oi","nbSegs","aMine","dTheta","rotMid","cand","newTheta","newCx","newCy","myPoly","covers","snapToNeighbors","overlappingNeighbors","clusterRing","kz","blockSegs","selfIndex","owners","dk","inCluster","queue","shift","nb","startKeys","rev","some","sk","areaOf","loops","visited","si","loop","seg","cornerTol","getOutline","moves","heading","join","pulseBlockers","blockers","flashBlocked","vs","borderEl","rotTarget","rotAnimating","pendingMate","commitRotation","settleRotation","rotateTap","patternYOffset","rotateByStep","getPoints","decimals","getOutlines","rings","vq","vk","vOwners","blockVKeys","seen","reachable","rq","comp","nc","cq","clusterOutlineRings","weldTol","welded","shifted","round4","startX","startY","triCount","symmetryAngle","placeAt","tgt","animate","placeKey","returnHome","home","pressPos","S6","S3","S12","SHAPE_OFFSETS","SHAPE_ORDER","angDelta","prefThetasByShape","orientNearCurrent","sym","takeBestForTheta","bestIdx","msg","signedArea","x0","y0","x1","resolveOutline","closeErr","pointInPolygon","pt","inside","xi","yi","xj","yj","patternBlocksSlot","rawRings","outlines","ringSpec","resolveOutlines","localRings","minX_1","maxX_1","minY_1","maxY_1","dx_1","dy_1","unitTriArea","areaTol","nudge","borderOptions","getWorldRings","getBlocks","blockInside","bverts","computeFill","area","covered","filled","tryPlace","offs","empty","lat","ros","claimed","id","keyToId","cellCorners","solveCells","inventory","repByShape","prefByShape","thetas","thetaOrder","prefs","nearestPref_1","symDist","sortedIds","assignments","nodes","recurse","ti","sig","buildInventory","inv","vertsMatch","playAuthoredSolution","solutions","placements","centroid","placementWorld","taken","bv","kept","pools","pl","solveAndShow","authored","sol","solution","force_solution","O","amin","amax","bmin","bmax","ab","toAB","expected","buildLattice","i_1","pool","keepFixed","allEmpty","asg","getSolution","UNIT_DEFAULTS","metric","divisions","unitLength","imperial","cssColor","SVG_NS","htmlRuler","units","unitDefaults","labels","labelStart","rotate","shadow","zIndex","tickInset","tick","primary","minor","tickLength","tickW","secondary","tickWidth","halfEndLabel","bodyLength","xZero","xOf","tickSteps","levels","levelOf","lengthOfLevel","level","drawTop","drawBottom","shadowCss","rotateOpts","panel","className","transformOrigin","pointerEvents","touchAction","userSelect","webkitUserSelect","markColor","bodyDiv","background","overflow","boxShadow","cursor","addBar","totalMarks","labelTop","labelBoxW","textContent","fontFamily","edge","textAlign","outlineDiv","boxSizing","borderStyle","knob","knobDir","knobBorder","borderRadius","HW","svg","createElementNS","setAttribute","display","rotateIconSvg","laidOutAt","htmlLayer","htmlCanvas","layerRect","getBoundingClientRect","drawScale","figureToClient","widthNear","heightNear","clientToFigure","rawRotation","snapStep","followAnchor","anchorCentre","sync","pxPerFigureUnit","dpr","devicePixelRatio","snapW","lineHeight","bw","firstElementChild","bounded","clamp","doc","documentElement","clientWidth","innerWidth","clientHeight","innerHeight","boxes","kx","boxes_1","y1","panelExtent","clampToPage","onResize","addEventListener","onScroll","scrollOpts","capture","passive","_docListeners","handler","vv","visualViewport","getAngle","getEnds","zero","getPivot","pivotPoint","getPanel","getKnob","drag","pivotLocalX","pivotOffset","angleAbout","clientX","clientY","onPointerDown","grabX","grabY","pv","startRotation","currentTarget","setPointerCapture","pointerId","stopPropagation","preventDefault","onPointerMove","onPointerUp","parentNode","STOP_SCROLL_BOUNDS","SECONDARY_TOUCH_BOUNDS","distToSegment","len2","polygonDepth","teardownNearTouch","stored","__nearTouchListeners","stored_1","canvas","event_1","removeEventListener","setupNearTouch","startIndex","figureOneFigures","beingTouchedElement","pixelPoint","touches","clientToPixel","closestElement","closestDistance","stopScroll","getTouchableElements","collection","poly_1","drawPoint","s_1","priorities","selectElement","manipulativeOptions","answerContainer","selectorManipulative","manipulative","eqn","createManipulativeControl","figureWP","_tiles","Item","updateOptions","classes","onToggle","nativeEvent","stopImmediatePropagation","paletteTouchStart","_controlTiles","_controlTilesFill","_cursor","startBlinking","showHighlight","action","cursorAnimateFrom","dispatchEvent","CustomEvent","stopBlinking","_controlsFill","onTouchStart","onMouseDown","Palette","paletteOptions","numRows","yNum","xNum","columns","addPalette","paletteContainer","getElementById","useState","initialSelect","setOptions","newOptions","_grokkoliReactRoots","createPalette","makeSnapGrid","gridOffset","xSeparation","ySeparation","topLeft","fillOrder","polygonArea","resolveAnchor","colorSelect","borderSides","onRemove","regionDefs","regions","gridGeom","g_1","sp","spaceX_1","spaceY_1","cellW_1","cellWidth","cellH_1","cellHeight","blockW","gridPos_1","measureTextWidth","hf","alignLeft","overhang","rowHeadings","rr","leftEdge","colHeadings","leftX","bottomY","defs","cellColor","cellFill","colFill","rowFill","gridPos","spaceX","spaceY","cellW","cellH","region","regionStyle","regionSides","regionDebug","regionBorder","layouts","adaptive","fillOpts","lineOpts_1","defaultColor","lblOffset","anchorX","labelEl","rowTol","minDy","occupants","snapToMode","tiles","bx_1","by_1","separators","colLine","rowLine","frame","addHeading","bandOx","bandOy","bandW","bandH","defXPos","defYPos","defXAlign","defYAlign","hc","snapOccupants","getNextFreeSnapPoint","placeAtSnap","manipSnapPoint","snapWorld","snapOffset","snapElement","staticSnapElement","showList","wanted","previous","homeKey","applyDrawOrderTo","moveTileToLocalSnap","localSnap","animName","acSuppressed","reflowKey","reflowPool","snapsSorted","tilesSorted","pa","pb","bringToFrontInOrder","parent_1","occ","poolIsFull","placeInPool","bestIndex","bestDist","isInBorder","elementBorder","elementRect","elementCenter","pos_1","rectBorder","pos_2","doesContain","answerContainerOrigin","occIndex","tapPlacement","moveInside","swap","targetPool","targetIndex","swapOnDrop","containedIndex","manipulativeCenter","furthestPoint","is","deltaFromBottomLeft","insideKey","homeArea","regionPools_1","swapTiles","tileA","tileB","find","currentPosition","createManipulativeAnswerInput","autoSetup","answer_input_type","answer_input","_answer_input","answerToShow","submitButton","getCorrectnessElements","elementNameOrNames","name_1","getElements","setupSubmitClicked","bubble","answer","getSubmittedAnswer","helpAnswerYes","submit","help","showAnswerInfo","continueButton","continueOffset","canBeDisabled","removeManipulative","fromList","createManipulativeSlotAnswerInput","finishShow","_submit","_continue","disableBackgroundGesture","showContinue","answer_info","showManipulativeResults","slots_1","manipulativesMap_1","slotsState_1","show_1","slotsState","manipulativeMap","manipulativeValueMap","slotName","getSnappedManipulatives","manipulativeNames","cleanShow","availableManipulatives","manipulatives_1","getAvailableManipulatives","showManipulatives","manipulativeDef","snappedManipulative","snappedValue","getShow","usedManipulatives_1","manipulativeDefs","manipulativeName","nextSnap","toShow","nameOrValue","blockSnapPosition","deltaPosition","slotState","allBlocks","blockName","block_1","continueDelay","continue_delay","isPlaying","isGuide","input_results","correctnessElements","c1","slotTypes","combinedSlotTypes","getManipulatives","asMap","withParent","inFigure","onlyShown","getManipulativeControls","getSelectors","selectedOnly","selectorType","getSelectedSelector","selectors","getManipulativesMap","getManipulativesValueMap","getManipulativesState","getManipulativeSlots","getManipulativeSlotsMap","objOut","getManipulativeSlotsState","manipulativesToRecord","i_2","i_3","manips","refreshManipulativeSlots","setManipulatives","allElements","elementMap","figureStates","restoredLines","ICONS","SCALE","BACKGROUND","negativeIcon","deselect","unhighlightWorksWith","manipulativeControls","startMoveSelect","isS","alignFrac","buildLines","kMin","kMax","nearest","anchorEl","bbox","xMin","xMax","yMin","yMax","resolveY","fx","fy","extent","xLines","yLines","clampInto","snapDraw","draw","decorate","setupManipulative","showBounds","boundsShown","getCanvas","parentElement","getElementsByClassName","classList","hideBounds","RectBounds","topDirection","rightDirection","getAllLinearBlocksSlots","elementName","getAllBaseTenBlocksSlots","getAllSimpleBlockSlots","includeFill","getAllManipulativeTileSlots","getAllAnswerContainers","closestWithCapacity","closestWithCapacityDist","closestFull","closestFullDist","highlightAnswerContainer","closestContainer","getCenterFigurePosition","setupManipulativeIndex","grokkoliManipulatives","incrementManipulativeIndex","getManipulativeIndex","TRASH_MANIPULATIVES","POOL_PARK_POSITION","suppressManipulativeTouch","touchSuppressionDepth","touchableBeforeSuppression","releaseManipulativeTouch","outlineVertices"],"sourceRoot":""}