@ai-matrx/design-system 0.86.368 → 0.86.369
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -2
- package/dist/accents.cjs +2 -2
- package/dist/accents.cjs.map +1 -1
- package/dist/accents.js +2 -2
- package/dist/accents.js.map +1 -1
- package/dist/carousel.js +5 -5
- package/dist/{chunk-SOCDBDFS.js → chunk-2HB65PD6.js} +2 -2
- package/dist/{chunk-KOUHF4JC.js → chunk-345ESUIP.js} +4 -4
- package/dist/{chunk-LS3C7IUV.js → chunk-ASDPMZNP.js} +2 -2
- package/dist/{chunk-WLKHQGX5.js → chunk-CFFRMRWJ.js} +2 -2
- package/dist/{chunk-TBWKBTPM.js → chunk-F7IUBABK.js} +3 -3
- package/dist/{chunk-3JEAXZKX.js → chunk-FLYZSVTR.js} +2 -2
- package/dist/{chunk-UAIBCPMB.js → chunk-RLTTLDWU.js} +4 -4
- package/dist/{chunk-VG765KBC.js → chunk-U3SUPYNT.js} +2 -2
- package/dist/{chunk-QEQDJBNK.js → chunk-WSEZDHLA.js} +2 -2
- package/dist/{chunk-3YTF4MH2.js → chunk-YA3DNAAC.js} +2 -2
- package/dist/clipboard-fallback-dialog.js +2 -2
- package/dist/controls.css +7 -0
- package/dist/controls.js +5 -5
- package/dist/data-table/data-row-inspector.js +5 -5
- package/dist/data-table/data-row-window.js +6 -6
- package/dist/data-table/index.js +8 -8
- package/dist/data-table/pagination.js +3 -3
- package/dist/data-table/uuid-cell.js +3 -3
- package/dist/desktop.js +4 -4
- package/dist/index.cjs +20 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +27 -19
- package/dist/index.js.map +1 -1
- package/dist/item.js +3 -3
- package/dist/lite-table.js +2 -2
- package/dist/record-list.js +3 -3
- package/dist/settings.js +3 -3
- package/dist/swipe-deck-tree.cjs +238 -0
- package/dist/swipe-deck-tree.cjs.map +1 -0
- package/dist/swipe-deck-tree.d.cts +202 -0
- package/dist/swipe-deck-tree.d.ts +202 -0
- package/dist/swipe-deck-tree.js +208 -0
- package/dist/swipe-deck-tree.js.map +1 -0
- package/dist/swipe-deck.cjs.map +1 -1
- package/dist/swipe-deck.d.cts +5 -0
- package/dist/swipe-deck.d.ts +5 -0
- package/dist/swipe-deck.js.map +1 -1
- package/dist/text-input-dialog.js +1 -1
- package/dist/tokens.css +23 -23
- package/dist/web-theme.css +20 -20
- package/dist/writing-field.js +3 -3
- package/package.json +12 -2
- /package/dist/{chunk-SOCDBDFS.js.map → chunk-2HB65PD6.js.map} +0 -0
- /package/dist/{chunk-KOUHF4JC.js.map → chunk-345ESUIP.js.map} +0 -0
- /package/dist/{chunk-LS3C7IUV.js.map → chunk-ASDPMZNP.js.map} +0 -0
- /package/dist/{chunk-WLKHQGX5.js.map → chunk-CFFRMRWJ.js.map} +0 -0
- /package/dist/{chunk-TBWKBTPM.js.map → chunk-F7IUBABK.js.map} +0 -0
- /package/dist/{chunk-3JEAXZKX.js.map → chunk-FLYZSVTR.js.map} +0 -0
- /package/dist/{chunk-UAIBCPMB.js.map → chunk-RLTTLDWU.js.map} +0 -0
- /package/dist/{chunk-VG765KBC.js.map → chunk-U3SUPYNT.js.map} +0 -0
- /package/dist/{chunk-QEQDJBNK.js.map → chunk-WSEZDHLA.js.map} +0 -0
- /package/dist/{chunk-3YTF4MH2.js.map → chunk-YA3DNAAC.js.map} +0 -0
package/dist/swipe-deck.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/swipe-deck/SwipeDeck.tsx","../src/swipe-deck/chrome.tsx","../src/swipe-deck/visual.ts","../src/swipe-deck/controller.ts","../src/swipe-deck/model.ts","../src/swipe-deck/gesture.ts","../src/swipe-deck/labels.ts","../src/swipe-deck/PartScreen.tsx","../src/swipe-deck/ExpandableSwipeDeck.tsx","../src/swipe-deck/kind-value.ts","../src/swipe-deck/logic.ts"],"sourcesContent":["\"use client\";\n\n/**\n * SwipeDeck — THE full-screen swipe deck: a deck of items a person answers by swiping.\n *\n * right Yes! · up Sort of · left No · down Not sure (every part configurable)\n *\n * The whole screen is the card; its text fits to the largest size the space allows. Each answer is\n * a large button on the edge it swipes toward; the corners are exit, ?, undo and copy. The moment a\n * drag starts the screen takes the answer's color and name; a flick commits too. The suggested\n * answer's button is filled and pulses and the card leans toward it. Undo is unlimited and the card\n * returns from the side it left. Items can expose parts (spans of their words), each answered on the\n * part screen (hold, or double-click); categories' answers flow down to the parts they tag.\n *\n * TWO MODES. Controlled: pass `items` and read answers back through `onAnswer` / `onChange` /\n * `onComplete`. Bound: pass a `binding` (see `controller.ts`) and the deck persists every change\n * through it, optimistically, showing the connection's own refusal sentence inline.\n *\n * Structural CSS: `swipe-deck.css` (imported by `styles.css`); colors are design-system tokens.\n */\nimport * as React from \"react\";\n\nimport { copyText as copyToClipboard } from \"@ai-matrx/kit/clipboard\";\n\nimport { ErrorBox } from \"../error-box\";\nimport { CheckIcon, CircleHelpIcon, CopyIcon, ListChecksIcon, Loader2Icon, Maximize2Icon, Minimize2Icon, PencilIcon, Undo2Icon, XIcon } from \"../icons\";\nimport { AnswerGlyph, CornerButton, EdgeButtons, setHot, Wash, type EdgeRefs, type WashHandle } from \"./chrome\";\nimport { useDeckController, type DeckController, type SwipeDeckBinding } from \"./controller\";\nimport { attachSwipe } from \"./gesture\";\nimport { DEFAULT_SWIPE_DECK_LABELS, type SwipeDeckLabels } from \"./labels\";\nimport {\n DECK_DIRECTIONS,\n DEFAULT_DECK_KEY,\n DEFAULT_KEEP_ANSWER,\n answerChange,\n answerDetail,\n answerOf,\n applyOps,\n findAnswer,\n membersOff,\n moreFor,\n currentStepIndex,\n deckCopyText,\n deckResult,\n deckSteps,\n directionOf,\n forgetSpan,\n itemCopyText,\n keyFor,\n knownCategories,\n makeChange,\n mergeKey,\n partAnswer,\n partsOf,\n partText,\n placePart,\n tokenize,\n type CategoryConflict,\n type DeckCategoryRow,\n type DeckAnswer,\n type DeckChange,\n type DeckDetail,\n type DeckDirection,\n type DeckOp,\n type DeckItem,\n type DeckMedia,\n type DeckKey,\n type DeckKeyOverride,\n type DeckPart,\n type DeckResult,\n type DeckRules,\n type DeckState,\n type DeckStep,\n type DeckTone,\n} from \"./model\";\nimport { PartScreen } from \"./PartScreen\";\nimport { VECTOR, buzz, enter, finePointer, fitText, flyOut, follow, heroMax, keepFitted, markOverflow, nudge, prefersReducedMotion, snapBack } from \"./visual\";\n\nexport interface SwipeDeckCopyContext {\n readonly item: DeckItem | null;\n readonly state: DeckState;\n readonly result: DeckResult;\n}\n\n/** What a card's own slots (`renderCardBody`, `renderCardActions`) can do. */\nexport interface SwipeDeckCardContext {\n readonly item: DeckItem;\n /** What will ride with this card's answer: the members switched off, a value typed on the card. */\n readonly detail: DeckDetail | null;\n /** Replace what rides with this card's next answer (any route: swipe, edge, key, button). */\n setDetail(detail: DeckDetail | null): void;\n /** Answer the card now, by answer id (on an edge or off it), optionally with what rides along. */\n answer(answerId: string, detail?: DeckDetail | null): void;\n /** While locked (a field being typed in), the card never swipes and the arrows and shortcuts do nothing. */\n lock(locked: boolean): void;\n}\n\nexport interface SwipeDeckProps {\n /** Controlled mode: the items. Ignored when `binding` is given (the binding brings its items). */\n readonly items?: readonly DeckItem[];\n /** Bound mode: the connection the deck persists through. */\n readonly binding?: SwipeDeckBinding;\n /** The deck's key, over the default (Yes! / Sort of / No / Not sure); `null` turns an edge off. */\n readonly answers?: DeckKeyOverride;\n /** Answers off the edges, offered on every card as a row of buttons (an item's own `more` replaces them). */\n readonly more?: readonly DeckAnswer[];\n /** Drawn on the card under its text: the host's own controls (a field to correct a value, a person's name). */\n readonly renderCardBody?: (context: SwipeDeckCardContext) => React.ReactNode;\n /** Drawn in the card's top row, at the end: small actions (open the source, see where it was found). */\n readonly renderCardActions?: (context: SwipeDeckCardContext) => React.ReactNode;\n /** The part screen's key, over the deck's (its down edge defaults to Keep as is). */\n readonly partAnswers?: DeckKeyOverride;\n /** The category rows offered on the part screen. */\n readonly categories?: readonly string[];\n /** Labelled chip rows on the part screen (\"Who\", \"Cares about\"), each with its own \"+\"; a category added there carries the row's id on its op. */\n readonly categoryRows?: readonly DeckCategoryRow[];\n /** When two categories' answers disagree on a part. Default: the worse answer wins. */\n readonly categoryConflict?: CategoryConflict;\n readonly allowNewCategories?: boolean;\n /** Turn the part screen off (parts still show and tap). */\n readonly editParts?: boolean;\n /** Groups that end in a pick-one screen (`true` = every group). */\n readonly pickOne?: boolean | readonly string[];\n /** The answer that makes an item a contender for its group's pick (default: the right edge's). */\n readonly pickAnswer?: string;\n /** What each group is called on its pick screen and at the end. */\n readonly groupLabels?: Readonly<Record<string, string>>;\n /** Controlled mode: answers, picks, parts and categories to start from. */\n readonly initialState?: Partial<DeckState>;\n readonly labels?: Partial<SwipeDeckLabels>;\n readonly onAnswer?: (item: DeckItem, answer: DeckAnswer, state: DeckState) => void;\n /** Every change, undo included (`undo` true), with the state after it. */\n readonly onChange?: (state: DeckState, change: DeckChange, undo: boolean) => void;\n /** The person reached the end; `result` holds every answer, pick, part and category. */\n readonly onComplete?: (result: DeckResult) => void;\n /** The exit corner; omitted, the corner is empty (or holds Full screen when `onExpand` is given). */\n readonly onExit?: () => void;\n /** What the exit corner means: `close` (an X) or `collapse` (leave full screen). */\n readonly exitKind?: \"close\" | \"collapse\";\n /** The full-screen corner (top left), for a deck drawn inline: open this deck full screen. */\n readonly onExpand?: () => void;\n /** Share another deck's controller (state AND undo), e.g. the inline and full-screen views of one deck. */\n readonly controller?: DeckController;\n /** Show each item's choices on the card, by their direction (a quiz). Default: when the item has its own answers. */\n readonly choicesOnCard?: boolean | \"auto\";\n /**\n * How big the card's own text is: `fit` (default) grows it to fill the card (a word, a short line);\n * `page` holds it at a page-title size in a reading-width column, for a card whose body is the point\n * (evidence to read before answering).\n */\n readonly titleSize?: \"fit\" | \"page\";\n /**\n * Draw the answers off the edges (`more`) as the card's row of buttons (default true). `false` when the\n * host draws every answer itself in its body through `context.answer`; their keyboard shortcuts stay.\n */\n readonly moreOnCard?: boolean;\n /** The copy corner's text (default: the item, or the whole deck at a pick or the end). */\n readonly copyText?: (context: SwipeDeckCopyContext) => string;\n /** Where \"the walkthrough already played\" is remembered; `null` never plays it on its own. */\n readonly tourKey?: string | null;\n /** Arrows, Z (undo) and ? (default on). */\n readonly keyboard?: boolean;\n /**\n * `fullscreen` covers the viewport; `fill` fills the nearest positioned parent; `inline` is a box in\n * the flow (a chat message): its height is `--sd-inline-height`, and its keys answer only while it\n * holds focus or the pointer.\n */\n readonly layout?: \"fullscreen\" | \"fill\" | \"inline\";\n readonly renderEnd?: (result: DeckResult) => React.ReactNode;\n /** The host's own buttons on the finish screen (back to the page, the next step). */\n readonly endActions?: React.ReactNode;\n /** The screen when there is nothing to answer: its words and the host's way on. */\n readonly empty?: { readonly title?: string; readonly line?: string; readonly action?: React.ReactNode };\n readonly className?: string;\n}\n\nconst KEYS: Readonly<Record<string, DeckDirection>> = { ArrowRight: \"right\", ArrowLeft: \"left\", ArrowUp: \"up\", ArrowDown: \"down\" };\nconst DEFAULT_TOUR_KEY = \"matrx.swipe-deck.tour\";\n\nfunction readFlag(key: string): boolean {\n try {\n return globalThis.localStorage?.getItem(key) === \"1\";\n } catch {\n return false;\n }\n}\nfunction writeFlag(key: string): void {\n try {\n globalThis.localStorage?.setItem(key, \"1\");\n } catch {\n /* storage blocked: the walkthrough may play again next visit */\n }\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport function SwipeDeck(props: SwipeDeckProps) {\n const labels = React.useMemo<SwipeDeckLabels>(() => ({ ...DEFAULT_SWIPE_DECK_LABELS, ...props.labels }), [props.labels]);\n const deckKey = React.useMemo(() => mergeKey(DEFAULT_DECK_KEY, props.answers), [props.answers]);\n const partKeyBase = React.useMemo(() => mergeKey({ ...deckKey, down: DEFAULT_KEEP_ANSWER }, props.partAnswers), [deckKey, props.partAnswers]);\n const rules = React.useMemo<DeckRules>(\n () => ({\n key: deckKey,\n ...(props.pickOne !== undefined ? { pickOne: props.pickOne } : {}),\n ...(props.pickAnswer ? { pickAnswer: props.pickAnswer } : {}),\n ...(props.more ? { more: props.more } : {}),\n }),\n [deckKey, props.pickOne, props.pickAnswer, props.more],\n );\n const conflict = props.categoryConflict;\n const own = useDeckController({ items: props.items, binding: props.binding, initialState: props.initialState, onChange: props.onChange });\n const controller = props.controller ?? own;\n const layout = props.layout ?? \"fullscreen\";\n const { items, state } = controller;\n const steps = React.useMemo(() => deckSteps(items, state, rules), [items, state, rules]);\n const stepIndex = currentStepIndex(steps, state);\n const step: DeckStep = steps[stepIndex] ?? { kind: \"end\", id: \"end\" };\n const ready = controller.status === \"ready\";\n const stateRef = React.useRef(state);\n stateRef.current = state;\n // Timers (pick, walkthrough, lean) never act on a deck that has closed.\n const alive = React.useRef(true);\n React.useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n /** Set when the deck itself moved to the next card (an answer here), so only that card change takes focus back. */\n const answeredHere = React.useRef(false);\n const frameRef = React.useRef<HTMLDivElement>(null);\n const layerRef = React.useRef<HTMLDivElement | null>(null);\n const edgeRefs = React.useRef<EdgeRefs>({});\n const wash = React.useRef<WashHandle>(null);\n const busy = React.useRef(false);\n const enterFrom = React.useRef<DeckDirection | \"stay\" | null>(null);\n const nudgeAnim = React.useRef<Animation | null>(null);\n const [touring, setTouring] = React.useState(false);\n const touringRef = React.useRef(false);\n const tourStop = React.useRef(false);\n const [part, setPart] = React.useState<{ itemId: string; start: number; end: number } | null>(null);\n const [bubble, setBubble] = React.useState<{ text: string; x: number; top: number; bottom: number } | null>(null);\n const [toast, setToast] = React.useState<string | null>(null);\n const [said, setSaid] = React.useState(\"\");\n\n // THE ANSWERED LIST, mid-deck: every answer so far, each one tap from changing it (the finish screen's list,\n // reachable at any point). While it is open the card does not take answers.\n const [reviewing, setReviewing] = React.useState(false);\n const reviewingRef = React.useRef(false);\n reviewingRef.current = reviewing;\n const cardItem = step.kind === \"card\" && !reviewing ? step.item : null;\n const cardKey = cardItem ? keyFor(rules, cardItem) : deckKey;\n const cardMore = React.useMemo(() => (cardItem ? moreFor(rules, cardItem) : []), [cardItem, rules]);\n // The buttons drawn under the card: a hidden answer is reached only through the card's own controls.\n const cardMoreShown = React.useMemo(() => cardMore.filter((a) => !a.hidden), [cardMore]);\n const suggestedDir = cardItem ? directionOf(cardKey, cardItem.suggested) : null;\n // What rides with the card in front's answer, set by its members and its own slots; starts from what was saved.\n const [cardDetail, setCardDetail] = React.useState<{ id: string; detail: DeckDetail | null } | null>(null);\n const detailNow = cardItem ? (cardDetail?.id === cardItem.id ? cardDetail.detail : (state.details?.[cardItem.id] ?? null)) : null;\n const detailRef = React.useRef(detailNow);\n detailRef.current = detailNow;\n const [locked, setLocked] = React.useState<string | null>(null);\n const lockedNow = !!cardItem && locked === cardItem.id;\n const lockedRef = React.useRef(lockedNow);\n lockedRef.current = lockedNow;\n\n const stopNudge = () => {\n try {\n nudgeAnim.current?.cancel();\n } catch {\n /* already finished */\n }\n nudgeAnim.current = null;\n };\n\n const flash = React.useCallback((text: string) => setToast(text), []);\n React.useEffect(() => {\n if (!toast) return;\n const t = setTimeout(() => setToast(null), 1400);\n return () => clearTimeout(t);\n }, [toast]);\n React.useEffect(() => {\n if (!bubble) return;\n const t = setTimeout(() => setBubble(null), 2200);\n return () => clearTimeout(t);\n }, [bubble]);\n\n // ─── answering ───────────────────────────────────────────────────────────\n const act = (dir: DeckDirection, speed = 0) => {\n const answer = cardKey[dir];\n if (answer) void give(answer, dir, speed);\n };\n /** Answer the card in front: by an edge (`dir`) or off the edges (`dir` null: it drops away). */\n const give = async (answer: DeckAnswer, dir: DeckDirection | null, speed = 0, detail?: DeckDetail | null) => {\n if (!cardItem || busy.current || touringRef.current || part) return;\n busy.current = true;\n stopNudge();\n setBubble(null);\n wash.current?.show(answer, dir, 1);\n setHot(edgeRefs.current, dir);\n buzz(globalThis.navigator, 8);\n await flyOut(layerRef.current, dir ?? \"down\", speed);\n const now = stateRef.current;\n const rides = answerDetail(cardItem, detail === undefined ? detailRef.current : detail);\n const made = answerChange(now, cardItem, answer.id, rules, items, dir, rides);\n // \"Skip for now\": the connection sends the card to the back of the line and keeps no answer.\n const change = answer.requeue && props.binding ? { ...made, transient: true } : made;\n enterFrom.current = null;\n setCardDetail(null);\n setLocked(null);\n answeredHere.current = true;\n controller.commit(change);\n busy.current = false;\n setHot(edgeRefs.current, null);\n wash.current?.hide();\n const after = applyOps(now, change.ops);\n props.onAnswer?.(cardItem, answer, after);\n const nextSteps = deckSteps(items, after, rules);\n const next = nextSteps[currentStepIndex(nextSteps, after)];\n setSaid(`${answer.label}.${next && next.kind === \"card\" ? ` ${labels.next}: ${next.item.text}` : \"\"}`);\n };\n const actRef = React.useRef(act);\n actRef.current = act;\n const giveRef = React.useRef(give);\n giveRef.current = give;\n\n const cardContext = React.useMemo<SwipeDeckCardContext | null>(\n () =>\n cardItem\n ? {\n item: cardItem,\n detail: detailNow,\n setDetail: (detail) => setCardDetail({ id: cardItem.id, detail }),\n answer: (answerId, detail) => {\n const a = findAnswer(rules, cardItem, answerId);\n if (a) void giveRef.current(a, directionOf(cardKey, answerId), 0, detail);\n },\n lock: (on) => setLocked(on ? cardItem.id : null),\n }\n : null,\n [cardItem, detailNow, rules, cardKey],\n );\n\n const undo = () => {\n if (busy.current || touringRef.current) return;\n if (part) setPart(null);\n setCardDetail(null);\n setLocked(null);\n const change = controller.undo();\n if (!change) return;\n enterFrom.current = change.from ?? \"stay\";\n // The card comes back as she left it: what rode with the answer (her switches, a typed value) is on it again.\n const answered = change.ops.find((o): o is Extract<DeckOp, { kind: \"answer\" }> => o.kind === \"answer\" && !!o.detail);\n if (answered?.detail) setCardDetail({ id: answered.itemId, detail: answered.detail });\n const touched = change.ops.find((o) => o.kind === \"answer\" || o.kind === \"parts\");\n const item = touched && \"itemId\" in touched ? items.find((i) => i.id === touched.itemId) : undefined;\n setSaid(`${labels.undone}.${item ? ` ${item.text}` : \"\"}`);\n };\n const undoRef = React.useRef(undo);\n undoRef.current = undo;\n\n const pick = (group: string, item: DeckItem) => {\n if (busy.current) return;\n busy.current = true;\n setTimeout(\n () => {\n busy.current = false;\n if (!alive.current) return;\n enterFrom.current = null;\n controller.commit(makeChange(stateRef.current, [{ kind: \"pick\", group, itemId: item.id }], items));\n setSaid(`${props.groupLabels?.[group] ?? group}: ${item.text}`);\n },\n prefersReducedMotion() ? 0 : 260,\n );\n };\n\n // ─── parts ───────────────────────────────────────────────────────────────\n const openPart = (item: DeckItem, index: number) => {\n if (props.editParts === false || busy.current || touringRef.current) return;\n stopNudge();\n setBubble(null);\n if (layerRef.current) snapBack(layerRef.current);\n wash.current?.hide();\n setPart({ itemId: item.id, start: index, end: index });\n };\n const openPartRef = React.useRef(openPart);\n openPartRef.current = openPart;\n\n const partItem = part ? (items.find((i) => i.id === part.itemId) ?? null) : null;\n const partKey = React.useMemo(\n () => (partItem ? mergeKey({ ...keyFor(rules, partItem), down: DEFAULT_KEEP_ANSWER }, props.partAnswers) : partKeyBase),\n [partItem, rules, props.partAnswers, partKeyBase],\n );\n const allCategories = React.useMemo(() => knownCategories(props.categories ?? [], items, state), [props.categories, items, state]);\n\n const placeOnItem = (item: DeckItem, next: DeckPart) => {\n enterFrom.current = \"stay\";\n const now = stateRef.current;\n controller.commit(makeChange(now, [{ kind: \"parts\", itemId: item.id, parts: placePart(partsOf(now, item), next) }], items));\n };\n const forgetOnItem = (item: DeckItem, span: { start: number; end: number }) => {\n enterFrom.current = \"stay\";\n const now = stateRef.current;\n controller.commit(makeChange(now, [{ kind: \"parts\", itemId: item.id, parts: forgetSpan(partsOf(now, item), span) }], items));\n flash(labels.forgotten);\n };\n\n // ─── the swipe on the card ───────────────────────────────────────────────\n // Set from the first move of a press until the next press: a press that dragged is never a choice's tap.\n const dragged = React.useRef(false);\n const live = React.useRef({ cardKey, enabled: false });\n live.current = { cardKey, enabled: !!cardItem && !part && !touring && !lockedNow };\n\n React.useEffect(() => {\n const root = frameRef.current;\n if (!root) return;\n return attachSwipe(root, {\n enabled: () => live.current.enabled && !busy.current && !touringRef.current,\n directions: () => live.current.cardKey,\n start: () => {\n dragged.current = false;\n stopNudge();\n setBubble(null);\n },\n move: (dx, dy, dir, amount) => {\n dragged.current = true;\n const answer = dir ? live.current.cardKey[dir] : undefined;\n follow(layerRef.current, dx, dy, dir && answer ? amount : 0);\n if (dir && answer) {\n wash.current?.show(answer, dir, amount);\n setHot(edgeRefs.current, amount >= 1 ? dir : null);\n } else {\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n }\n },\n release: () => {\n snapBack(layerRef.current);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n },\n commit: (dir, speed) => actRef.current(dir, speed),\n tap: (target) => {\n const span = target.closest<HTMLElement>(\"[data-sd-part]\");\n if (!span) {\n setBubble(null);\n return;\n }\n const r = span.getBoundingClientRect();\n setBubble({ text: span.getAttribute(\"data-sd-part-label\") ?? \"\", x: r.left + r.width / 2, top: r.top, bottom: r.bottom });\n },\n hold: (target) => {\n const i = Number(target.getAttribute(\"data-sd-t\"));\n const item = itemsRef.current.find((x) => x.id === target.closest(\"[data-sd-item]\")?.getAttribute(\"data-sd-item\"));\n if (item && Number.isFinite(i)) openPartRef.current(item, i);\n },\n holdSelector: \"[data-sd-t]\",\n // A swipe may start on a choice (it fills much of a quiz card); other buttons never swipe.\n ignoreSelector: \"button:not([data-sd-choice]), a, input, textarea, [data-sd-noswipe]\",\n });\n }, []);\n const itemsRef = React.useRef(items);\n itemsRef.current = items;\n\n // ─── keyboard ────────────────────────────────────────────────────────────\n const keyboard = props.keyboard !== false;\n // A key pressed during the walkthrough, done once it has stopped.\n const afterTour = React.useRef<string | null>(null);\n /** What a key does on the deck; true when it did something (its default is then prevented). */\n const runKeyRef = React.useRef<(key: string, target: Element | null) => boolean>(() => false);\n runKeyRef.current = (key, target) => {\n if (reviewingRef.current) {\n if (key === \"Escape\") {\n setReviewing(false);\n return true;\n }\n if (key !== \"z\" && key !== \"Z\" && key !== \"Backspace\") return false;\n }\n const dir = KEYS[key];\n const shortcut = !dir && key.length === 1 ? shortcutRef.current(key) : null;\n if ((dir || shortcut) && lockedRef.current) return false;\n if (dir) {\n actRef.current(dir);\n return true;\n }\n if (shortcut) {\n void giveRef.current(shortcut.answer, shortcut.dir);\n return true;\n }\n if (key === \"z\" || key === \"Z\" || key === \"Backspace\") {\n undoRef.current();\n return true;\n }\n if (key === \"?\") {\n void tourRef.current();\n return true;\n }\n if (key === \"Escape\" && exitRef.current.kind === \"collapse\" && exitRef.current.onExit) {\n exitRef.current.onExit();\n return true;\n }\n // Enter on the card (not on one of its buttons) opens the part screen on its first marked words, or its first word.\n if (key === \"Enter\" && !target?.closest(\"button, a, [role='button']\") && cardItemRef.current && props.editParts !== false) {\n const item = cardItemRef.current;\n const first = partsOf(stateRef.current, item)[0];\n openPartRef.current(item, first ? first.start : 0);\n return true;\n }\n return false;\n };\n const cardItemRef = React.useRef(cardItem);\n cardItemRef.current = cardItem;\n // An answer's own key (\"Y\", \"3\"), on an edge or off it; it outranks Z and ? when an answer claims them.\n const shortcutRef = React.useRef<(key: string) => { answer: DeckAnswer; dir: DeckDirection | null } | null>(() => null);\n shortcutRef.current = (key) => {\n if (!cardItem || part) return null;\n const k = key.toLowerCase();\n for (const d of DECK_DIRECTIONS) {\n const a = cardKey[d];\n if (a?.shortcut?.toLowerCase() === k) return { answer: a, dir: d };\n }\n const a = cardMoreShown.find((x) => x.shortcut?.toLowerCase() === k);\n return a ? { answer: a, dir: null } : null;\n };\n const exitRef = React.useRef({ kind: props.exitKind, onExit: props.onExit });\n exitRef.current = { kind: props.exitKind, onExit: props.onExit };\n React.useEffect(() => {\n if (!keyboard) return;\n const view = rootRef.current?.ownerDocument.defaultView ?? window;\n const onKey = (e: KeyboardEvent) => {\n const root = rootRef.current;\n const doc = root?.ownerDocument;\n const active = doc?.activeElement;\n if (active && active !== doc.body && !root?.contains(active)) return;\n // An inline deck (one of many things on a page) answers only while it holds focus or the pointer.\n if (layout === \"inline\" && !(root && (root.contains(active ?? null) || root.matches(\":hover\")))) return;\n const t = e.target instanceof Element ? e.target : null;\n if (t?.closest(\"input, textarea, select, [contenteditable='true']\")) return;\n // Cmd+Z / Ctrl+Z is undo here too (a field's own undo keeps it: fields returned above).\n if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && (e.key === \"z\" || e.key === \"Z\") && !e.repeat) {\n e.preventDefault();\n undoRef.current();\n return;\n }\n // A held key answers one card, never several; a key with Alt, Ctrl or Cmd belongs to the browser or the host.\n if (e.altKey || e.ctrlKey || e.metaKey) return;\n if (e.repeat) {\n if (KEYS[e.key] || e.key === \"z\" || e.key === \"Z\" || e.key === \"Backspace\") e.preventDefault();\n return;\n }\n if (touringRef.current) {\n // A key during the walkthrough ends it AND does what it says: the first answer is never lost.\n tourStop.current = true;\n if (KEYS[e.key] || e.key === \"z\" || e.key === \"Z\" || e.key === \"Backspace\") {\n e.preventDefault();\n afterTour.current = e.key;\n }\n return;\n }\n if (runKeyRef.current(e.key, t)) e.preventDefault();\n };\n view.addEventListener(\"keydown\", onKey);\n return () => view.removeEventListener(\"keydown\", onKey);\n }, [keyboard, layout]);\n\n // The keys stay with the deck after every answer (P5, pool 2026-10-24: after some cards the arrows did nothing until\n // the page was clicked). An answer can leave focus on a control OUTSIDE the deck (a menu's or hover card's portal, a\n // host control that re-rendered, a toast), and the key handler ignores keys whose focus is elsewhere. So when the card\n // changes, a full deck (not inline: one of many things on a page) takes focus back — never from a field being typed\n // in, an open dialog or menu. REVIEW9 M-5: a card change the HOST made (items arriving, re-sorting) never takes focus\n // from a button or link the person is on — only nothing focused (the page itself) is taken then; and a deck that sits\n // inside a dialog takes it back within that dialog.\n const cardId = cardItem?.id ?? null;\n React.useEffect(() => {\n const fromAnswer = answeredHere.current;\n answeredHere.current = false;\n if (!keyboard || layout === \"inline\" || cardId === null) return;\n const root = rootRef.current;\n const doc = root?.ownerDocument;\n const active = doc?.activeElement ?? null;\n if (!root || (active && root.contains(active))) return;\n const idle = !active || active === doc?.body || active === doc?.documentElement;\n if (!idle && !fromAnswer) return;\n if (active?.closest(\"input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='combobox'], [role='textbox'], [role='menu'], [role='listbox']\")) return;\n const dialog = active?.closest(\"[role='dialog'], [role='alertdialog'], dialog\");\n if (dialog && !dialog.contains(root)) return;\n root.focus({ preventScroll: true });\n }, [cardId, keyboard, layout]);\n\n // ─── the walkthrough (?) ─────────────────────────────────────────────────\n const fingerRef = React.useRef<HTMLDivElement>(null);\n const ringRef = React.useRef<HTMLDivElement>(null);\n const capRef = React.useRef<HTMLDivElement>(null);\n const tour = async () => {\n const layer = layerRef.current;\n const stage = layer?.parentElement;\n const F = fingerRef.current;\n if (touringRef.current || !cardItem || busy.current || part || !layer || !stage || !F) return;\n touringRef.current = true;\n tourStop.current = false;\n setTouring(true);\n stopNudge();\n setBubble(null);\n const reduced = prefersReducedMotion();\n const tween = (ms: number, f: (p: number) => void) =>\n new Promise<void>((res) => {\n const t0 = performance.now();\n const frame = (t: number) => {\n if (tourStop.current) return res();\n const p = Math.min(1, (t - t0) / ms);\n f(p);\n if (p < 1) requestAnimationFrame(frame);\n else res();\n };\n requestAnimationFrame(frame);\n });\n const ease = (p: number) => (p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2);\n const place = (el: HTMLElement | null, x: number, y: number) => {\n if (!el) return;\n el.style.left = `${x}px`;\n el.style.top = `${y}px`;\n };\n const r = stage.getBoundingClientRect();\n const cx = r.left + r.width / 2;\n const cy = r.top + r.height / 2;\n const dist = Math.min(r.width, r.height) * 0.34;\n place(F, cx, cy);\n F.style.opacity = \"1\";\n const key = cardKey;\n const order = [...(suggestedDir ? [suggestedDir] : []), ...DECK_DIRECTIONS.filter((d) => d !== suggestedDir)];\n for (const dir of order) {\n if (tourStop.current) break;\n const answer = key[dir];\n if (!answer) continue;\n const [vx, vy] = VECTOR[dir];\n F.setAttribute(\"data-down\", \"\");\n await tween(reduced ? 1 : 620, (p) => {\n const e = ease(p);\n place(F, cx + vx * dist * e, cy + vy * dist * e);\n follow(layer, vx * dist * e, vy * dist * e, e * 1.05);\n wash.current?.show(answer, dir, e * 1.05);\n setHot(edgeRefs.current, p > 0.8 ? dir : null);\n });\n await wait(tourStop.current ? 0 : 420);\n await tween(reduced ? 1 : 240, (p) => {\n const e = 1 - p;\n place(F, cx + vx * dist * e, cy + vy * dist * e);\n follow(layer, vx * dist * e, vy * dist * e, e);\n wash.current?.show(answer, dir, e);\n });\n F.removeAttribute(\"data-down\");\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n follow(layer, 0, 0);\n await wait(tourStop.current ? 0 : 140);\n }\n const word = layer.querySelector<HTMLElement>(\"[data-sd-part] [data-sd-t]\") ?? layer.querySelector<HTMLElement>(\"[data-sd-t]\");\n if (!tourStop.current && word && props.editParts !== false) {\n const wr = word.getBoundingClientRect();\n const tx = wr.left + wr.width / 2;\n const ty = wr.top + wr.height / 2;\n await tween(reduced ? 1 : 420, (p) => {\n const e = ease(p);\n place(F, cx + (tx - cx) * e, cy + (ty - cy) * e);\n });\n const cap = capRef.current;\n if (cap) {\n cap.textContent = finePointer() ? labels.clickHint : labels.holdHint;\n const vw = cap.ownerDocument.defaultView?.innerWidth ?? 0;\n place(cap, Math.max(cap.offsetWidth / 2 + 12, Math.min(tx, vw - cap.offsetWidth / 2 - 12)), ty - 40);\n cap.style.opacity = \"1\";\n }\n F.setAttribute(\"data-down\", \"\");\n word.setAttribute(\"data-sd-press\", \"\");\n place(ringRef.current, tx, ty);\n if (!reduced) ringRef.current?.animate([{ opacity: 1, transform: \"scale(.6)\" }, { opacity: 0, transform: \"scale(1.9)\" }], { duration: 900, iterations: 2 });\n await wait(tourStop.current ? 0 : 1700);\n word.removeAttribute(\"data-sd-press\");\n F.removeAttribute(\"data-down\");\n if (cap) cap.style.opacity = \"0\";\n }\n F.style.opacity = \"0\";\n follow(layer, 0, 0);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n touringRef.current = false;\n setTouring(false);\n const pending = afterTour.current;\n afterTour.current = null;\n if (pending && alive.current) runKeyRef.current(pending, null);\n };\n const tourRef = React.useRef(tour);\n tourRef.current = tour;\n\n // ─── card arrival: enter, lean toward the suggestion, first-use walkthrough ─\n const tourKey = props.tourKey === undefined ? DEFAULT_TOUR_KEY : props.tourKey;\n const onCardMounted = React.useCallback(\n (layer: HTMLDivElement, dir: DeckDirection | null) => {\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer, from);\n if (tourKey && !readFlag(tourKey)) {\n writeFlag(tourKey);\n setTimeout(() => {\n if (alive.current && layerRef.current === layer) void tourRef.current();\n }, 700);\n return;\n }\n if (from === null && dir) {\n setTimeout(() => {\n if (!alive.current || layerRef.current !== layer || busy.current || touringRef.current) return;\n nudgeAnim.current = nudge(layer, dir);\n }, 420);\n }\n },\n [tourKey],\n );\n\n // ─── reaching the end ────────────────────────────────────────────────────\n const result = React.useMemo(() => deckResult(items, state, rules, conflict), [items, state, rules, conflict]);\n const atEnd = ready && items.length > 0 && step.kind === \"end\";\n const wasAtEnd = React.useRef(false);\n const onComplete = props.onComplete;\n React.useEffect(() => {\n if (atEnd && !wasAtEnd.current) {\n onComplete?.(result);\n // Arriving at the finish is said, as every answer is.\n setSaid(\n `${result.score ? `${labels.score}: ${result.score.right} / ${result.score.graded}` : labels.allDone}. ${labels.answeredOf.replace(\"{answered}\", String(result.answered)).replace(\"{total}\", String(result.total))}`,\n );\n }\n wasAtEnd.current = atEnd;\n }, [atEnd, result, onComplete, labels]);\n\n // ─── copy ────────────────────────────────────────────────────────────────\n const copy = async () => {\n const text = props.copyText\n ? props.copyText({ item: cardItem, state, result })\n : cardItem\n ? itemCopyText(cardItem, state, cardKey, labels, conflict, cardMoreShown)\n : deckCopyText(result, rules);\n const ok = await copyToClipboard(text);\n flash(ok ? labels.copied : labels.copyFailed);\n };\n\n // Drop the bubble's measured position into the viewport.\n const bubbleRef = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n const b = bubbleRef.current;\n if (!b || !bubble) return;\n const vw = b.ownerDocument.defaultView?.innerWidth ?? 0;\n const w = b.offsetWidth;\n const h = b.offsetHeight;\n b.style.left = `${Math.max(12, Math.min(bubble.x - w / 2, vw - w - 12))}px`;\n b.style.top = `${bubble.top - h - 10 < 8 ? bubble.bottom + 10 : bubble.top - h - 10}px`;\n }, [bubble]);\n\n const progress = steps.filter((s) => s.kind !== \"end\");\n\n return (\n <div\n ref={rootRef}\n className={[\"matrx-sd\", props.className].filter(Boolean).join(\" \")}\n data-layout={layout}\n data-touring={touring ? \"\" : undefined}\n {...(layout === \"inline\"\n ? {\n tabIndex: 0,\n role: \"group\",\n \"aria-roledescription\": \"swipe deck\",\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => {\n // Pressing the deck gives it the keys (it is one of many things in a chat).\n const root = e.currentTarget;\n if (!root.contains(root.ownerDocument.activeElement)) root.focus({ preventScroll: true });\n },\n }\n : { tabIndex: -1 })}\n >\n <div className=\"matrx-sd-progress\" aria-hidden=\"true\">\n {progress.map((s, k) => {\n const tone =\n k === stepIndex\n ? \"current\"\n : s.kind === \"card\"\n ? findAnswer(rules, s.item, state.answers[s.item.id])?.tone\n : s.kind === \"pick\" && state.picks[s.group]\n ? \"primary\"\n : undefined;\n return <i key={s.id} data-tone={tone} />;\n })}\n </div>\n\n <div\n ref={frameRef}\n className=\"matrx-sd-frame\"\n data-axis={!cardKey.up && !cardKey.down ? \"x\" : undefined}\n aria-hidden={part ? true : undefined}\n inert={part ? true : undefined}\n onPointerDownCapture={(e) => {\n // A press on the card away from the host's own controls (their field gone or left) ends a lock.\n if (!lockedRef.current) return;\n const inBody = (n: EventTarget | Element | null) => n instanceof Element && !!n.closest(\".matrx-sd-body\");\n if (inBody(e.target) || inBody(e.currentTarget.ownerDocument.activeElement)) return;\n lockedRef.current = false;\n live.current = { ...live.current, enabled: !!cardItem && !part && !touring };\n setLocked(null);\n }}\n >\n {props.onExpand ? (\n <CornerButton corner=\"tl\" label={labels.expand} onClick={props.onExpand}>\n <Maximize2Icon />\n </CornerButton>\n ) : props.onExit ? (\n <CornerButton corner=\"tl\" label={props.exitKind === \"collapse\" ? labels.collapse : labels.exit} {...(props.exitKind === \"collapse\" ? { shortcut: \"Escape\" } : {})} onClick={props.onExit}>\n {props.exitKind === \"collapse\" ? <Minimize2Icon /> : <XIcon />}\n </CornerButton>\n ) : null}\n <CornerButton corner=\"tr\" label={labels.answered} onClick={() => setReviewing((v) => !v)} disabled={!ready || !items.length || step.kind === \"end\"} pressed={reviewing}>\n <ListChecksIcon />\n {result.answered ? <span className=\"matrx-sd-corner-count\">{result.answered}</span> : null}\n </CornerButton>\n <CornerButton corner=\"bl\" label={labels.undo} shortcut=\"Z\" onClick={undo} disabled={!controller.canUndo}>\n <Undo2Icon />\n </CornerButton>\n <CornerButton corner=\"br\" label={labels.copy} onClick={() => void copy()} disabled={!ready || !items.length}>\n <CopyIcon />\n </CornerButton>\n\n {cardItem ? (\n <EdgeButtons keyMap={cardKey} suggested={suggestedDir} refs={edgeRefs} onAnswer={(d) => act(d)} suggestionLabel={labels.suggestion} />\n ) : null}\n\n <div className=\"matrx-sd-stage\">\n {!ready ? (\n <div className=\"matrx-sd-layer\" data-state={controller.status}>\n {controller.status === \"error\" ? (\n <ErrorBox className=\"matrx-sd-message\" message={controller.readError ?? \"\"} operation=\"Read the deck\" origin=\"design-system/SwipeDeck\" />\n ) : (\n <Loader2Icon className=\"matrx-spin matrx-sd-spinner\" />\n )}\n </div>\n ) : items.length === 0 ? (\n <EmptyView key=\"empty\" title={props.empty?.title ?? labels.emptyTitle} line={props.empty?.line} action={props.empty?.action} layerRef={layerRef} />\n ) : reviewing && step.kind !== \"end\" ? (\n <EndView\n key=\"review\"\n result={result}\n rules={rules}\n labels={labels}\n groupLabels={props.groupLabels}\n layerRef={layerRef}\n enterFrom={enterFrom}\n review={{\n onBack: () => setReviewing(false),\n onHelp: () => {\n setReviewing(false);\n void tour();\n },\n }}\n onChange={(item) => {\n enterFrom.current = null;\n const now = stateRef.current;\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: null }];\n if (item.group && now.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n controller.commit(makeChange(now, ops, items));\n setReviewing(false);\n setSaid(`${labels.change}: ${item.text}`);\n }}\n />\n ) : step.kind === \"card\" ? (\n <CardView\n key={step.id}\n item={step.item}\n keyMap={cardKey}\n state={state}\n conflict={conflict}\n labels={labels}\n suggestedDir={suggestedDir}\n more={props.moreOnCard === false ? [] : cardMoreShown}\n titleSize={props.titleSize ?? \"fit\"}\n detail={detailNow}\n onDetail={(d) => setCardDetail({ id: step.item.id, detail: d })}\n body={cardContext && props.renderCardBody ? props.renderCardBody(cardContext) : null}\n onBodyLeft={() => setLocked(null)}\n actions={cardContext && props.renderCardActions ? props.renderCardActions(cardContext) : null}\n showChoices={props.choicesOnCard === true || ((props.choicesOnCard ?? \"auto\") === \"auto\" && !!step.item.answers)}\n onChoose={(d) => {\n // A drag that started on a choice and snapped back still ends in a click: not an answer.\n if (dragged.current) dragged.current = false;\n else act(d);\n }}\n onChooseMore={(a) => {\n if (dragged.current) dragged.current = false;\n else void give(a, null);\n }}\n layerRef={layerRef}\n onMounted={onCardMounted}\n onDoubleClickWord={(i) => openPart(step.item, i)}\n />\n ) : step.kind === \"pick\" ? (\n <PickView key={step.id} step={step} label={props.groupLabels?.[step.group] ?? labels.pick} labels={labels} layerRef={layerRef} onPick={pick} enterFrom={enterFrom} />\n ) : (\n <EndView\n key=\"end\"\n result={result}\n rules={rules}\n labels={labels}\n groupLabels={props.groupLabels}\n layerRef={layerRef}\n enterFrom={enterFrom}\n actions={props.endActions}\n onChange={(item) => {\n // Taking an answer back is a change like any other (undo puts it back); the deck returns to that card.\n enterFrom.current = null;\n const now = stateRef.current;\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: null }];\n // A pick that named this item goes with its answer, as when the card is answered otherwise.\n if (item.group && now.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n controller.commit(makeChange(now, ops, items));\n setSaid(`${labels.change}: ${item.text}`);\n }}\n >\n {props.renderEnd?.(result)}\n </EndView>\n )}\n </div>\n <Wash ref={wash} />\n </div>\n\n {controller.writeError ? (\n <ErrorBox className=\"matrx-sd-error\" message={controller.writeError} operation=\"Save an answer\" origin=\"design-system/SwipeDeck\" />\n ) : null}\n\n {part && partItem ? (\n <PartScreen\n key={`${part.itemId}:${part.start}`}\n item={partItem}\n parts={partsOf(state, partItem)}\n initial={{ start: part.start, end: part.end }}\n keyMap={partKey}\n deckKey={keyFor(rules, partItem)}\n state={state}\n categories={allCategories}\n rows={props.categoryRows}\n allowNewCategories={props.allowNewCategories !== false}\n conflict={conflict}\n labels={labels}\n onClose={() => setPart(null)}\n onPlace={(p) => placeOnItem(partItem, p)}\n onForget={(span) => forgetOnItem(partItem, span)}\n onCategoryAnswer={(name, answer, row) => {\n enterFrom.current = \"stay\";\n controller.commit(makeChange(stateRef.current, [{ kind: \"category\", name, answer, ...(row ? { row } : {}) }], items));\n }}\n announce={setSaid}\n />\n ) : null}\n\n <div className=\"matrx-sd-tour\" hidden={!touring} onPointerDown={() => (tourStop.current = true)}>\n <div ref={ringRef} className=\"matrx-sd-ring\" />\n <div ref={fingerRef} className=\"matrx-sd-finger\" />\n <div ref={capRef} className=\"matrx-sd-tour-cap\" />\n </div>\n {bubble ? (\n <div ref={bubbleRef} className=\"matrx-sd-bubble\" role=\"status\">\n {bubble.text}\n </div>\n ) : null}\n <div className=\"matrx-sd-toast\" role=\"status\" aria-live=\"polite\" data-on={toast ? \"\" : undefined}>\n {toast}\n </div>\n <div className=\"matrx-sd-sr\" aria-live=\"polite\" aria-atomic=\"true\">\n {said}\n </div>\n </div>\n );\n}\n\n// ─── the card ──────────────────────────────────────────────────────────────\n\ninterface CardViewProps {\n readonly item: DeckItem;\n readonly keyMap: DeckKey;\n readonly state: DeckState;\n readonly conflict: CategoryConflict | undefined;\n readonly labels: SwipeDeckLabels;\n readonly suggestedDir: DeckDirection | null;\n /** Draw the item's choices on the card by direction (a quiz). */\n readonly showChoices: boolean;\n readonly onChoose: (dir: DeckDirection) => void;\n /** Answers off the edges: on the card as buttons (in the choices when they show). */\n readonly more: readonly DeckAnswer[];\n readonly onChooseMore: (answer: DeckAnswer) => void;\n /** `fit` grows the text to the card; `page` holds it at a page-title size. */\n readonly titleSize: \"fit\" | \"page\";\n readonly detail: DeckDetail | null;\n readonly onDetail: (detail: DeckDetail | null) => void;\n readonly body: React.ReactNode;\n /** Focus left the body slot: a lock it held is released. */\n readonly onBodyLeft: () => void;\n readonly actions: React.ReactNode;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly onMounted: (layer: HTMLDivElement, suggested: DeckDirection | null) => void;\n readonly onDoubleClickWord: (index: number) => void;\n}\n\n/** The order choices read on a card: clockwise from the top. */\nconst CHOICE_ORDER: readonly DeckDirection[] = [\"up\", \"right\", \"down\", \"left\"];\n\nfunction MediaView({ media, size }: { media: DeckMedia; size?: \"small\" }) {\n const shape = media.shape ?? \"square\";\n return (\n <span className=\"matrx-sd-media\" data-shape={shape} data-size={size}>\n {\"src\" in media ? <img src={media.src} alt={media.alt ?? \"\"} draggable={false} /> : media.node}\n </span>\n );\n}\n\nfunction CardView({\n item,\n keyMap,\n state,\n conflict,\n labels,\n suggestedDir,\n showChoices,\n onChoose,\n more,\n onChooseMore,\n titleSize,\n detail,\n onDetail,\n body,\n onBodyLeft,\n actions,\n layerRef,\n onMounted,\n onDoubleClickWord,\n}: CardViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n const inner = React.useRef<HTMLDivElement>(null);\n const hero = React.useRef<HTMLParagraphElement>(null);\n const tokens = React.useMemo(() => tokenize(item.text), [item.text]);\n const parts = partsOf(state, item);\n const suggested = answerOf(keyMap, item.suggested, more);\n const off = membersOff(item, detail);\n const toggle = (id: string) => {\n const next = off.includes(id) ? off.filter((x) => x !== id) : [...off, id];\n onDetail({ ...(detail ?? {}), off: next });\n };\n\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n if (layer.current) onMounted(layer.current, suggestedDir);\n return () => {\n if (layerRef.current === layer.current) layerRef.current = null;\n };\n // Mount only: a card arrives once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const partsKey = parts.map((p) => `${p.start}-${p.end}`).join(\",\");\n React.useLayoutEffect(() => {\n const box = layer.current;\n if (!box || !inner.current || !hero.current) return;\n return keepFitted(box, () => {\n if (!inner.current || !hero.current) return;\n if (titleSize === \"fit\") fitText(box, inner.current, hero.current, 20, heroMax(box));\n else markOverflow(box, inner.current);\n });\n }, [item.text, partsKey, item.members?.length, more.length, titleSize]);\n\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < tokens.length; ) {\n const p = parts.find((x) => x.start === i);\n if (p) {\n const a = answerOf(keyMap, partAnswer(p, state, keyMap, conflict));\n const words: React.ReactNode[] = [];\n for (let j = p.start; j <= p.end; j++) {\n words.push(\n <span key={j} className=\"matrx-sd-token\" data-sd-t={j}>\n {tokens[j]}\n </span>,\n );\n if (j < p.end) words.push(\" \");\n }\n nodes.push(\n <span key={`p${i}`} className=\"matrx-sd-part\" data-sd-part={i} data-tone={a?.tone} data-sd-part-label={[a?.label, ...p.categories].filter(Boolean).join(\" · \") || partText(item, p)}>\n {words}\n </span>,\n );\n i = p.end + 1;\n } else {\n nodes.push(\n <span key={i} className=\"matrx-sd-token\" data-sd-t={i}>\n {tokens[i]}\n </span>,\n );\n i++;\n }\n if (i < tokens.length) nodes.push(\" \");\n }\n\n return (\n <div\n ref={layer}\n className=\"matrx-sd-layer\"\n data-sd-item={item.id}\n data-sd-title={titleSize === \"page\" ? \"page\" : undefined}\n aria-label={[item.kicker, item.text].filter(Boolean).join(\": \")}\n onDoubleClick={(e) => {\n const t = e.target instanceof Element ? e.target.closest(\"[data-sd-t]\") : null;\n if (t) onDoubleClickWord(Number(t.getAttribute(\"data-sd-t\")));\n }}\n >\n <div ref={inner} className=\"matrx-sd-card\">\n {item.media ? <MediaView media={item.media} /> : null}\n {item.kicker || item.tag || actions ? (\n <div className=\"matrx-sd-kicker\">\n {item.kicker ? <span>{item.kicker}</span> : null}\n {item.tag ? (\n <span className=\"matrx-sd-tag\">\n <CheckIcon />\n {item.tag}\n </span>\n ) : null}\n {actions ? <span className=\"matrx-sd-actions\">{actions}</span> : null}\n </div>\n ) : null}\n <p ref={hero} className=\"matrx-sd-hero\" data-quoted={item.quoted ? \"\" : undefined}>\n {nodes}\n </p>\n {item.members?.length ? (\n <div className=\"matrx-sd-members\">\n {item.members.map((m) => {\n const isOff = off.includes(m.id);\n return (\n // ui-exception: a group card's member switch is part of the card (a swipe never starts on it)\n <button key={m.id} type=\"button\" className=\"matrx-sd-member\" aria-pressed={!isOff} data-off={isOff ? \"\" : undefined} onClick={() => toggle(m.id)}>\n {m.media ? <MediaView media={m.media} size=\"small\" /> : null}\n <span>{m.label}</span>\n </button>\n );\n })}\n </div>\n ) : null}\n {body ? (\n <div\n className=\"matrx-sd-body\"\n onBlur={(e) => {\n // Focus leaving the host's own controls (a field closed, a tap on the card) ends a lock: never stuck.\n const next = e.relatedTarget instanceof Node ? e.relatedTarget : null;\n // The window losing focus (another tab, another app) is not leaving the field.\n if (!e.currentTarget.ownerDocument.hasFocus()) return;\n if (!next || !e.currentTarget.contains(next)) onBodyLeft();\n }}\n >\n {body}\n </div>\n ) : null}\n {showChoices ? (\n <div className=\"matrx-sd-choices\">\n {CHOICE_ORDER.map((d) => {\n const a = keyMap[d];\n if (!a) return null;\n return (\n // ui-exception: a choice on the card is the card's own answer target (and a swipe can start on it)\n <button key={d} type=\"button\" className=\"matrx-sd-choice\" data-sd-choice=\"\" data-dir={d} data-tone={a.tone} onClick={() => onChoose(d)}>\n <AnswerGlyph answer={{ ...a, icon: undefined }} dir={d} />\n <span>{a.label}</span>\n </button>\n );\n })}\n {more.map((a) => (\n // ui-exception: an answer off the edges is the card's own answer target\n <button key={a.id} type=\"button\" className=\"matrx-sd-choice\" data-sd-choice=\"\" data-tone={a.tone} title={a.shortcut ? `${a.label} (${a.shortcut})` : a.label} onClick={() => onChooseMore(a)}>\n {a.icon ?? null}\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n ) : more.length ? (\n <div className=\"matrx-sd-more\">\n {more.map((a) => (\n // ui-exception: an answer off the edges is the card's own answer target\n <button\n key={a.id}\n type=\"button\"\n className=\"matrx-sd-more-answer\"\n data-sd-choice=\"\"\n data-tone={a.tone}\n data-suggested={item.suggested === a.id ? \"\" : undefined}\n aria-keyshortcuts={a.shortcut}\n title={a.shortcut ? `${a.label} (${a.shortcut})` : a.label}\n onClick={() => onChooseMore(a)}\n >\n {a.icon ?? null}\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n ) : null}\n {suggested || item.reason || item.fields?.length ? (\n <div className=\"matrx-sd-fields\">\n {suggested ? (\n <div>\n <div className=\"matrx-sd-label\">{labels.suggestion}</div>\n <div className=\"matrx-sd-suggested\" data-tone={suggested.tone}>\n <AnswerGlyph answer={suggested} dir={suggestedDir} />\n {item.suggestedLabel ?? suggested.label}\n </div>\n </div>\n ) : null}\n {item.reason ? (\n <div>\n <div className=\"matrx-sd-label\">{labels.reason}</div>\n <div className=\"matrx-sd-value\">{item.reason}</div>\n </div>\n ) : null}\n {item.fields?.map((f) => (\n <div key={f.label}>\n <div className=\"matrx-sd-label\">{f.label}</div>\n <div className=\"matrx-sd-value\">{f.value}</div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\n// ─── pick one ──────────────────────────────────────────────────────────────\n\ninterface PickViewProps {\n readonly step: Extract<DeckStep, { kind: \"pick\" }>;\n readonly label: string;\n readonly labels: SwipeDeckLabels;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly enterFrom: React.MutableRefObject<DeckDirection | \"stay\" | null>;\n readonly onPick: (group: string, item: DeckItem) => void;\n}\n\nfunction PickView({ step, label, labels, layerRef, enterFrom, onPick }: PickViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n const [chosen, setChosen] = React.useState<string | null>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer.current, from);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n React.useLayoutEffect(() => {\n const box = layer.current;\n if (!box) return;\n const run = () => {\n const buttons = Array.from(box.querySelectorAll<HTMLElement>(\".matrx-sd-option\"));\n let lo = 16;\n let hi = (box.ownerDocument.defaultView?.innerWidth ?? 0) >= 1024 ? 64 : 40;\n let best = lo;\n for (let k = 0; k < 9; k++) {\n const mid = (lo + hi) / 2;\n buttons.forEach((b) => (b.style.fontSize = `${mid}px`));\n const ok = buttons.every((b) => b.scrollHeight <= b.clientHeight + 1 && b.scrollWidth <= b.clientWidth + 1);\n if (ok) {\n best = mid;\n lo = mid;\n } else hi = mid;\n }\n buttons.forEach((b) => (b.style.fontSize = `${Math.floor(best)}px`));\n // Too many options for even the smallest size: the pick scrolls instead of clipping.\n const list = box.querySelector<HTMLElement>(\".matrx-sd-options\");\n if (list && list.scrollHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n };\n return keepFitted(box, run);\n }, [step.items.length]);\n return (\n <div ref={layer} className=\"matrx-sd-layer\">\n <div className=\"matrx-sd-options\" role=\"radiogroup\" aria-label={label}>\n {step.items.map((item) => (\n // ui-exception: a pick-one option fills its share of the full-screen deck\n <button\n key={item.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={chosen === item.id}\n className=\"matrx-sd-option\"\n data-suggested={item.pickSuggested ? \"\" : undefined}\n data-chosen={chosen === item.id ? \"\" : undefined}\n onClick={() => {\n setChosen(item.id);\n onPick(step.group, item);\n }}\n >\n {item.pickSuggested ? <span className=\"matrx-sd-label\">{labels.suggestion}</span> : null}\n <span>{item.text}</span>\n </button>\n ))}\n </div>\n </div>\n );\n}\n\n// ─── the end ───────────────────────────────────────────────────────────────\n\ninterface EndViewProps {\n readonly result: DeckResult;\n readonly rules: DeckRules;\n readonly labels: SwipeDeckLabels;\n readonly groupLabels: Readonly<Record<string, string>> | undefined;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly enterFrom: React.MutableRefObject<DeckDirection | \"stay\" | null>;\n /** The host's own buttons at the end (back to where the person came from, next step). */\n readonly actions?: React.ReactNode;\n /** Take an item's answer back: the deck returns to that card. */\n readonly onChange: (item: DeckItem) => void;\n readonly children?: React.ReactNode;\n /** Mid-deck: the same list titled \"Answered\", with the way back to the cards (and the walkthrough). */\n readonly review?: { readonly onBack: () => void; readonly onHelp?: () => void };\n}\n\ninterface EndGroup {\n readonly key: string;\n readonly label: string;\n readonly tone: DeckTone;\n readonly count: number;\n}\n\n/** How the answers split: right / wrong on a graded deck, else by answer (same words = one group). */\nfunction endGroups(result: DeckResult, labels: SwipeDeckLabels): EndGroup[] {\n const graded = result.entries.filter((e) => e.answer && e.right !== null);\n if (result.score && graded.length) {\n const right = graded.filter((e) => e.right).length;\n return [\n { key: \"right\", label: labels.right, tone: \"success\", count: right },\n { key: \"wrong\", label: labels.wrong, tone: \"destructive\", count: graded.length - right },\n ].filter((g) => g.count > 0) as EndGroup[];\n }\n const out = new Map<string, EndGroup>();\n for (const e of result.entries) {\n if (!e.answer) continue;\n const key = e.answer.label;\n const had = out.get(key);\n out.set(key, { key, label: e.answer.label, tone: had?.tone ?? e.answer.tone, count: (had?.count ?? 0) + 1 });\n }\n return [...out.values()];\n}\n\nfunction groupOf(entry: DeckResult[\"entries\"][number], graded: boolean): string | null {\n if (!entry.answer) return null;\n if (graded && entry.right !== null) return entry.right ? \"right\" : \"wrong\";\n return entry.answer.label;\n}\n\n/** The finish: a mark that draws itself, the headline (a pick, a score, or done), how the answers split, and every answer to look over and change. */\nfunction EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, actions, onChange, children, review }: EndViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer.current, from);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n const [filter, setFilter] = React.useState<string | null>(null);\n if (children) {\n return (\n <div ref={layer} className=\"matrx-sd-layer\">\n {children}\n </div>\n );\n }\n const picks = Object.entries(result.picks);\n const [first, ...rest] = picks;\n const score = result.score;\n const groups = endGroups(result, labels);\n const graded = !!score && groups.some((g) => g.key === \"right\" || g.key === \"wrong\");\n const answered = result.entries.filter((e) => e.answer);\n const shown = filter ? answered.filter((e) => groupOf(e, graded) === filter) : answered;\n const pct = score && score.graded ? score.right / score.graded : 1;\n const kicker = review ? null : first ? (groupLabels?.[first[0]] ?? first[0]) : score ? labels.score : null;\n const headline = review ? labels.answered : first ? first[1].text : score ? `${score.right} / ${score.graded}` : labels.allDone;\n const sub = labels.answeredOf.replace(\"{answered}\", String(result.answered)).replace(\"{total}\", String(result.total));\n return (\n <div ref={layer} className=\"matrx-sd-layer matrx-sd-endlayer\">\n <div className=\"matrx-sd-end\" data-graded={graded ? \"\" : undefined} data-review={review ? \"\" : undefined}>\n {review ? null : (\n <svg className=\"matrx-sd-mark\" viewBox=\"0 0 72 72\" aria-hidden=\"true\" data-tone={score ? (pct >= 0.5 ? \"success\" : \"warning\") : \"success\"}>\n <circle className=\"matrx-sd-mark-track\" cx=\"36\" cy=\"36\" r=\"32\" />\n <circle className=\"matrx-sd-mark-ring\" cx=\"36\" cy=\"36\" r=\"32\" pathLength={100} style={{ strokeDasharray: `${Math.round(pct * 100)} 100` }} />\n {!score || pct === 1 ? <path className=\"matrx-sd-mark-check\" d=\"M23 37.5l9 9 17-19\" pathLength={100} /> : null}\n </svg>\n )}\n {kicker ? <div className=\"matrx-sd-kicker\">{kicker}</div> : null}\n <h2 className=\"matrx-sd-end-hero\">{headline}</h2>\n <div className=\"matrx-sd-end-sub\">{sub}</div>\n {score && first && !review ? (\n <div className=\"matrx-sd-endline\">\n <div className=\"matrx-sd-label\">{labels.score}</div>\n <div className=\"matrx-sd-value\">{`${score.right} / ${score.graded}`}</div>\n </div>\n ) : null}\n {(review ? [] : rest).map(([group, item]) => (\n <div key={group} className=\"matrx-sd-endline\">\n <div className=\"matrx-sd-label\">{groupLabels?.[group] ?? group}</div>\n <div className=\"matrx-sd-value\">{item.text}</div>\n </div>\n ))}\n {groups.length ? (\n <>\n <div className=\"matrx-sd-split\" aria-hidden=\"true\">\n {groups.map((g) => (\n <i key={g.key} data-tone={g.tone} style={{ flexGrow: g.count }} />\n ))}\n </div>\n <div className=\"matrx-sd-legend\" role=\"group\" aria-label={labels.filterAnswers}>\n {groups.length > 1 ? (\n // ui-exception: the end's answer filter is part of the deck's own finish screen\n <button type=\"button\" className=\"matrx-sd-legend-chip\" aria-pressed={filter === null} onClick={() => setFilter(null)}>\n <span>{labels.showAll}</span>\n <b>{answered.length}</b>\n </button>\n ) : null}\n {groups.map((g) => (\n // ui-exception: the end's answer filter is part of the deck's own finish screen\n <button\n key={g.key}\n type=\"button\"\n className=\"matrx-sd-legend-chip\"\n data-tone={g.tone}\n aria-pressed={filter === g.key}\n onClick={() => setFilter((f) => (f === g.key ? null : g.key))}\n >\n <i aria-hidden=\"true\" />\n <span>{g.label}</span>\n <b>{g.count}</b>\n </button>\n ))}\n </div>\n </>\n ) : null}\n {shown.length ? (\n <ul className=\"matrx-sd-review\" aria-label={labels.yourAnswers}>\n {shown.map((e) => {\n const rightIds = e.item.correct === undefined ? [] : typeof e.item.correct === \"string\" ? [e.item.correct] : e.item.correct;\n // What rode with the answer reads in its place: the value typed on the card, the relationship picked.\n const said = typeof e.detail?.value === \"string\" && e.detail.value.trim() ? e.detail.value : e.item.text;\n const answerWords = typeof e.detail?.label === \"string\" && e.detail.label ? e.detail.label : e.answer?.label;\n const rightWords = rightIds.map((id) => findAnswer(rules, e.item, id)?.label).filter(Boolean).join(\", \");\n return (\n <li key={e.item.id}>\n {/* ui-exception: a reviewed answer is the end screen's own row (tap to change it) */}\n <button\n type=\"button\"\n className=\"matrx-sd-review-row\"\n onClick={() => onChange(e.item)}\n aria-label={[\n `${labels.change}: ${said}`,\n [answerWords, e.right === true ? labels.right : e.right === false ? labels.wrong : null].filter(Boolean).join(\", \"),\n e.right === false && rightWords ? `${labels.rightAnswer}: ${rightWords}` : null,\n ]\n .filter(Boolean)\n .join(\". \")}\n >\n <span className=\"matrx-sd-review-text\">\n {e.item.kicker ? <span className=\"matrx-sd-label\">{e.item.kicker}</span> : null}\n <span className=\"matrx-sd-review-item\">{said}</span>\n {e.right === false && rightWords ? (\n <span className=\"matrx-sd-review-right\">\n {labels.rightAnswer}: {rightWords}\n </span>\n ) : null}\n </span>\n <span className=\"matrx-sd-review-answer\" data-tone={e.right === null ? e.answer?.tone : e.right ? \"success\" : \"destructive\"}>\n {e.right === true ? <CheckIcon /> : e.right === false ? <XIcon /> : null}\n <span>{answerWords}</span>\n </span>\n <PencilIcon className=\"matrx-sd-review-change\" aria-hidden=\"true\" />\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n {review ? (\n <div className=\"matrx-sd-end-actions\">\n {/* ui-exception: the answered list's way back is the deck's own control, in its own geometry */}\n <button type=\"button\" className=\"matrx-sd-review-back\" onClick={review.onBack} autoFocus>\n {labels.backToCards}\n </button>\n {review.onHelp ? (\n // ui-exception: the walkthrough, from the answered list (the corner it had now opens this list)\n <button type=\"button\" className=\"matrx-sd-review-help\" onClick={review.onHelp}>\n <CircleHelpIcon aria-hidden=\"true\" />\n <span>{labels.help}</span>\n </button>\n ) : null}\n </div>\n ) : actions ? (\n <div className=\"matrx-sd-end-actions\">{actions}</div>\n ) : null}\n </div>\n </div>\n );\n}\n\n/** Nothing to answer: the deck's own quiet screen, never a blank. */\nfunction EmptyView({ title, line, action, layerRef }: { title: string; line?: string | undefined; action?: React.ReactNode; layerRef: React.MutableRefObject<HTMLDivElement | null> }) {\n const layer = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n enter(layer.current, null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n return (\n <div ref={layer} className=\"matrx-sd-layer matrx-sd-endlayer\" data-sd-empty=\"\">\n <div className=\"matrx-sd-end matrx-sd-empty\">\n <div className=\"matrx-sd-empty-stack\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n </div>\n <h2 className=\"matrx-sd-end-hero\">{title}</h2>\n {line ? <div className=\"matrx-sd-end-sub\">{line}</div> : null}\n {action ? <div className=\"matrx-sd-end-actions\">{action}</div> : null}\n </div>\n </div>\n );\n}\n\n\n","\"use client\";\n\n/**\n * The deck's chrome: the four edge buttons, the corner buttons, and the full-screen wash.\n * Hot / wash state is written straight to the DOM (no React render per pointer move).\n */\nimport * as React from \"react\";\n\nimport { ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon } from \"../icons\";\nimport { hideWash, showWash } from \"./visual\";\nimport type { DeckAnswer, DeckDirection, DeckKey } from \"./model\";\n\nconst ARROWS: Record<DeckDirection, React.ComponentType<React.SVGAttributes<SVGSVGElement>>> = {\n right: ArrowRightIcon,\n left: ArrowLeftIcon,\n up: ArrowUpIcon,\n down: ArrowDownIcon,\n};\n\nexport const KEY_GLYPH: Record<DeckDirection, string> = { right: \"→\", up: \"↑\", left: \"←\", down: \"↓\" };\n\n/** The answer's own icon, else the arrow of the edge it sits on (an answer off the edges has none). */\nexport function AnswerGlyph({ answer, dir }: { answer: DeckAnswer; dir: DeckDirection | null }) {\n if (answer.icon) return <>{answer.icon}</>;\n if (!dir) return null;\n const Arrow = ARROWS[dir];\n return <Arrow />;\n}\n\nexport type EdgeRefs = Partial<Record<DeckDirection, HTMLButtonElement | null>>;\n\nexport function setHot(refs: EdgeRefs, dir: DeckDirection | null): void {\n for (const d of Object.keys(refs) as DeckDirection[]) {\n const el = refs[d];\n if (!el) continue;\n if (d === dir) el.setAttribute(\"data-hot\", \"\");\n else el.removeAttribute(\"data-hot\");\n }\n}\n\nexport interface EdgeButtonsProps {\n readonly keyMap: DeckKey;\n readonly suggested: DeckDirection | null;\n readonly refs: React.MutableRefObject<EdgeRefs>;\n readonly onAnswer: (dir: DeckDirection) => void;\n readonly suggestionLabel: string;\n readonly disabled?: boolean;\n}\n\n/** One large button on each enabled edge, where its swipe goes. */\nexport function EdgeButtons({ keyMap, suggested, refs, onAnswer, suggestionLabel, disabled }: EdgeButtonsProps) {\n return (\n <>\n {([\"up\", \"left\", \"right\", \"down\"] as const).map((dir) => {\n const answer = keyMap[dir];\n if (!answer) return null;\n const isSuggested = dir === suggested;\n return (\n // ui-exception: the deck's edge targets are its own geometry (the swipe they mirror), not a form control\n <button\n key={dir}\n ref={(el) => {\n refs.current[dir] = el;\n }}\n type=\"button\"\n className=\"matrx-sd-edge\"\n data-dir={dir}\n data-tone={answer.tone}\n data-suggested={isSuggested ? \"\" : undefined}\n aria-label={isSuggested ? `${answer.label} (${suggestionLabel})` : answer.label}\n aria-keyshortcuts={{ right: \"ArrowRight\", left: \"ArrowLeft\", up: \"ArrowUp\", down: \"ArrowDown\" }[dir]}\n title={`${answer.label} ${KEY_GLYPH[dir]}`}\n disabled={disabled}\n onClick={() => onAnswer(dir)}\n >\n <AnswerGlyph answer={answer} dir={dir} />\n </button>\n );\n })}\n </>\n );\n}\n\nexport interface CornerButtonProps {\n readonly corner: \"tl\" | \"tr\" | \"bl\" | \"br\";\n readonly label: string;\n readonly shortcut?: string;\n readonly onClick: () => void;\n readonly disabled?: boolean;\n readonly pressed?: boolean;\n readonly children: React.ReactNode;\n}\n\nexport function CornerButton({ corner, label, shortcut, onClick, disabled, pressed, children }: CornerButtonProps) {\n return (\n // ui-exception: the deck's four corner targets sit in its own frame geometry\n <button\n type=\"button\"\n className=\"matrx-sd-corner\"\n data-corner={corner}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n aria-keyshortcuts={shortcut}\n disabled={disabled}\n aria-pressed={pressed}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\nexport interface WashHandle {\n show(answer: DeckAnswer, dir: DeckDirection | null, amount: number): void;\n hide(): void;\n}\n\n/** The whole screen takes the answer's color and shows its name big, the moment a drag starts. */\nexport const Wash = React.forwardRef<WashHandle>(function Wash(_props, ref) {\n const bg = React.useRef<HTMLDivElement>(null);\n const label = React.useRef<HTMLDivElement>(null);\n const [shown, setShown] = React.useState<{ answer: DeckAnswer; dir: DeckDirection | null } | null>(null);\n React.useImperativeHandle(\n ref,\n () => ({\n show(answer, dir, amount) {\n setShown((cur) => (cur && cur.answer.id === answer.id && cur.dir === dir ? cur : { answer, dir }));\n showWash(bg.current, label.current, amount);\n },\n hide() {\n hideWash(bg.current, label.current);\n },\n }),\n [],\n );\n return (\n <div className=\"matrx-sd-wash\" aria-hidden=\"true\" data-tone={shown?.answer.tone}>\n <div ref={bg} className=\"matrx-sd-wash-bg\" />\n <div ref={label} className=\"matrx-sd-wash-label\">\n {shown ? <AnswerGlyph answer={shown.answer} dir={shown.dir} /> : null}\n <b>{shown?.answer.label}</b>\n </div>\n </div>\n );\n});\n","/**\n * The deck's direct-to-DOM motion: card follow, snap back, fly out, enter, the full-screen wash,\n * and the text fit. Each writes `transform`/`opacity` only (compositor properties) and never\n * React state, so dragging stays on the 60fps path.\n */\nimport type { DeckDirection } from \"./model\";\n\nexport const VECTOR: Record<DeckDirection, readonly [number, number]> = {\n right: [1, 0],\n left: [-1, 0],\n up: [0, -1],\n down: [0, 1],\n};\n\n/** A short buzz, only once the page has had a tap (browsers refuse, and say so, before one). */\nexport function buzz(nav: Navigator | undefined, ms: number): void {\n try {\n const activation = (nav as (Navigator & { userActivation?: { hasBeenActive: boolean } }) | undefined)?.userActivation;\n if (activation && !activation.hasBeenActive) return;\n nav?.vibrate?.(ms);\n } catch {\n /* no haptics */\n }\n}\n\nexport function prefersReducedMotion(): boolean {\n try {\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n } catch {\n return false;\n }\n}\n\nexport function finePointer(): boolean {\n try {\n return typeof matchMedia === \"function\" && matchMedia(\"(hover: hover) and (pointer: fine)\").matches;\n } catch {\n return false;\n }\n}\n\n/**\n * The card follows the drag; `amount` (distance over the threshold) fades it, so the answer's big name\n * reads over a quiet card (full drag: 0.3), never two texts printed over each other.\n */\nexport function follow(el: HTMLElement | null, dx: number, dy: number, amount = 0): void {\n if (!el) return;\n el.style.transition = \"none\";\n el.style.transform = dx || dy ? `translate3d(${dx}px,${dy}px,0) rotate(${(dx / 28).toFixed(2)}deg)` : \"\";\n el.style.opacity = amount > 0 ? String(1 - 0.7 * Math.min(1, amount)) : \"\";\n}\n\nexport function snapBack(el: HTMLElement | null): void {\n if (!el) return;\n el.style.transition = \"transform 260ms cubic-bezier(.2,.8,.2,1), opacity 260ms ease\";\n el.style.transform = \"\";\n el.style.opacity = \"\";\n}\n\n/** Throw the card off the edge it went toward; faster throws leave faster. */\nexport function flyOut(el: HTMLElement | null, dir: DeckDirection, speed = 0): Promise<void> {\n if (!el || prefersReducedMotion()) return new Promise((r) => setTimeout(r, 90));\n const [vx, vy] = VECTOR[dir];\n const ms = Math.round(Math.max(150, Math.min(260, 260 - speed * 60)));\n el.style.transition = `transform ${ms}ms cubic-bezier(.4,0,1,1), opacity ${ms}ms linear`;\n el.style.transform = `translate3d(${vx * 120}vw,${vy * 110}vh,0) rotate(${vx * 14}deg)`;\n el.style.opacity = \"0\";\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** A new card arrives: from the edge it left by (undo), or rising in place. */\nexport function enter(el: HTMLElement | null, from: DeckDirection | null): void {\n if (!el || prefersReducedMotion() || typeof el.animate !== \"function\") return;\n if (from) {\n const [vx, vy] = VECTOR[from];\n el.animate(\n [\n { transform: `translate3d(${vx * 100}vw,${vy * 100}vh,0) rotate(${vx * 10}deg)`, opacity: 0.3 },\n { transform: \"none\", opacity: 1 },\n ],\n { duration: 320, easing: \"cubic-bezier(.2,.8,.2,1)\" },\n );\n } else {\n el.animate([{ transform: \"scale(.95)\", opacity: 0 }, { transform: \"none\", opacity: 1 }], { duration: 260, easing: \"cubic-bezier(.2,.8,.2,1)\" });\n }\n}\n\n/** The card leans toward its suggested answer once, then settles. */\nexport function nudge(el: HTMLElement | null, dir: DeckDirection): Animation | null {\n if (!el || prefersReducedMotion() || typeof el.animate !== \"function\") return null;\n const [vx, vy] = VECTOR[dir];\n return el.animate(\n [\n { transform: \"none\" },\n { transform: `translate3d(${vx * 24}px,${vy * 24}px,0) rotate(${vx * 1.2}deg)`, offset: 0.3 },\n { transform: \"none\", offset: 0.6 },\n { transform: `translate3d(${vx * 10}px,${vy * 10}px,0)`, offset: 0.8 },\n { transform: \"none\" },\n ],\n { duration: 1100, easing: \"ease-in-out\" },\n );\n}\n\n/** Fill the screen with the answer's color; `amount` 0..1+ is how far the drag has gone. */\nexport function showWash(bg: HTMLElement | null, label: HTMLElement | null, amount: number): void {\n if (!bg || !label) return;\n const a = Math.max(0, Math.min(1, amount));\n bg.style.opacity = String(Math.min(0.93, 0.2 + 0.73 * a));\n label.style.opacity = String(Math.min(1, 0.35 + a));\n label.style.transform = `scale(${0.82 + 0.22 * a})`;\n}\n\nexport function hideWash(bg: HTMLElement | null, label: HTMLElement | null): void {\n if (bg) bg.style.opacity = \"0\";\n if (label) label.style.opacity = \"0\";\n}\n\n/**\n * The largest font size (px) at which `text` fits: `inner` no taller than `box`, and no word wider\n * than the line. Binary search, ten measurements.\n */\nexport function fitText(box: HTMLElement, inner: HTMLElement, text: HTMLElement, min: number, max: number): number {\n let lo = min;\n let hi = Math.max(min, max);\n let best = lo;\n for (let k = 0; k < 10; k++) {\n const mid = (lo + hi) / 2;\n text.style.fontSize = `${mid}px`;\n const ok = inner.offsetHeight <= box.clientHeight && text.scrollWidth <= text.clientWidth + 1;\n if (ok) {\n best = mid;\n lo = mid;\n } else hi = mid;\n }\n const size = Math.floor(best);\n text.style.fontSize = `${size}px`;\n // Even the smallest size does not fit (a very long text, a narrow phone): this one screen scrolls, never clips.\n if (inner.offsetHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n return size;\n}\n\n/** The card's text at a fixed size: the one screen scrolls when the card is taller than the stage, never clips. */\nexport function markOverflow(box: HTMLElement, inner: HTMLElement): void {\n if (inner.offsetHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n}\n\n/** Run a fit now, again once the web font has loaded (it changes every measure), and on every resize. */\nexport function keepFitted(box: HTMLElement, run: () => void): () => void {\n run();\n let alive = true;\n box.ownerDocument.fonts?.ready.then(() => alive && run()).catch(() => undefined);\n if (typeof ResizeObserver === \"undefined\") return () => void (alive = false);\n const ro = new ResizeObserver(run);\n ro.observe(box);\n return () => {\n alive = false;\n ro.disconnect();\n };\n}\n\n/**\n * The largest the card's text may be. A phone (under 480px) goes by its text column (column / 2.6, so a\n * short line like \"junk\" goes huge and the height fills first); wider screens by the screen's width.\n */\nexport function heroMax(box: HTMLElement): number {\n const vw = box.ownerDocument.defaultView?.innerWidth ?? box.clientWidth;\n if (vw < 480) return Math.min(104, Math.max(36, box.clientWidth / 2.6));\n const wide = vw >= 1024;\n return Math.min(wide ? 132 : 104, Math.max(36, Math.min(vw, box.clientWidth * 1.6) / 3.2));\n}\n","/**\n * THE DECK CONTROLLER — the one place a deck's changes go, in either mode.\n *\n * CONTROLLED (no binding): the state lives here; every change is reported through `onChange`.\n * BOUND (a {@link SwipeDeckBinding}): the binding holds the truth (its store, its realtime); this\n * controller draws each change at once on top of it (optimistic), sends the ops, and when the\n * connection refuses, takes the change back and keeps the refusal's own sentence for the screen.\n * Undo in both modes is the change's inverse, sent the same way.\n */\nimport * as React from \"react\";\n\nimport { applyOps, deckState, type DeckChange, type DeckItem, type DeckOp, type DeckState } from \"./model\";\n\n/**\n * A connection a deck persists through: hand one to `SwipeDeck` and it saves every answer, pick,\n * part edit and category the moment it happens. `state` must follow the connection's truth\n * (including other devices' writes); `apply` resolves when the connection kept the ops and rejects\n * with an Error whose message is the connection's own refusal sentence.\n */\nexport interface SwipeDeckBinding {\n readonly status: \"loading\" | \"ready\" | \"error\";\n /** Why the connection cannot be read, in its own words. */\n readonly error: string | null;\n readonly items: readonly DeckItem[];\n readonly state: DeckState;\n apply(ops: readonly DeckOp[]): Promise<void>;\n /**\n * Optional: the undo history the connection kept (newest last). Given, the deck starts from it, so undo\n * still works after a reload or on another device; `saveHistory` is handed every change to it (at most\n * {@link UNDO_KEPT} steps).\n */\n readonly history?: readonly DeckChange[];\n saveHistory?(history: readonly DeckChange[]): void;\n}\n\n/** How many steps of undo a connection is asked to keep. */\nexport const UNDO_KEPT = 100;\n\ninterface Pending {\n readonly id: number;\n readonly ops: readonly DeckOp[];\n settledAt: number | null;\n /** Never kept by the connection (a requeue): dropped the moment it settles, not held until reflected. */\n readonly transient?: boolean;\n}\n\nexport interface DeckController {\n readonly items: readonly DeckItem[];\n readonly state: DeckState;\n readonly status: \"loading\" | \"ready\" | \"error\";\n readonly readError: string | null;\n /** The last refusal of a write, in the connection's words; cleared by the next write that lands. */\n readonly writeError: string | null;\n readonly canUndo: boolean;\n commit(change: DeckChange): void;\n /** Takes back the last change; returns it (its `from` is the edge the card comes back from). */\n undo(): DeckChange | null;\n}\n\nexport interface DeckControllerOptions {\n readonly items?: readonly DeckItem[] | undefined;\n readonly binding?: SwipeDeckBinding | undefined;\n readonly initialState?: Partial<DeckState> | undefined;\n readonly onChange?: ((state: DeckState, change: DeckChange, undo: boolean) => void) | undefined;\n}\n\nconst SETTLE_GRACE_MS = 6000;\n\n/** True when `state` already holds what `op` writes. */\nexport function reflects(state: DeckState, op: DeckOp): boolean {\n switch (op.kind) {\n case \"answer\":\n return (state.answers[op.itemId] ?? null) === op.answer;\n case \"pick\":\n return (state.picks[op.group] ?? null) === op.itemId;\n case \"parts\":\n return JSON.stringify(state.parts[op.itemId] ?? null) === JSON.stringify(op.parts);\n case \"category\":\n return op.remove ? !state.categories[op.name] : (state.categories[op.name]?.answer ?? null) === op.answer;\n }\n}\n\nexport function useDeckController({ items, binding, initialState, onChange }: DeckControllerOptions): DeckController {\n const [local, setLocal] = React.useState<DeckState>(() => deckState(initialState));\n const [history, setHistory] = React.useState<readonly DeckChange[]>([]);\n const [pending, setPending] = React.useState<readonly Pending[]>([]);\n const [writeError, setWriteError] = React.useState<string | null>(null);\n const seq = React.useRef(0);\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n\n // A connection's state is read through the one sanitizer: an old or broken shape never blanks the deck.\n const bound = binding?.state;\n const base = React.useMemo(() => (bound ? deckState(bound) : local), [bound, local]);\n\n // A connection that keeps the undo history: the deck takes the kept steps while she has done nothing here\n // yet (they may arrive after the deck draws), and hands the history back only after a change of hers, so\n // opening a deck never writes and kept steps are never replaced by none.\n const touched = React.useRef(false);\n const bindingRef = React.useRef(binding);\n bindingRef.current = binding;\n const kept = binding?.history;\n React.useEffect(() => {\n // Follows the kept steps (a later read may bring more, fewer or none) until she acts here.\n if (touched.current || !kept) return;\n setHistory(kept);\n }, [kept]);\n React.useEffect(() => {\n if (touched.current) bindingRef.current?.saveHistory?.(history.slice(-UNDO_KEPT));\n }, [history]);\n // A settled write stays drawn until the connection's state CARRIES it (an unrelated remote write arriving\n // first must not flicker it away), or until a grace passes (another device wrote over it meanwhile).\n React.useEffect(() => {\n setPending((list) => {\n const kept = list.filter((p) => p.settledAt === null || !p.ops.every((op) => reflects(base, op)));\n return kept.length === list.length ? list : kept;\n });\n }, [base]);\n React.useEffect(() => {\n if (!pending.some((p) => p.settledAt !== null)) return;\n const t = setTimeout(() => setPending((list) => list.filter((p) => p.settledAt === null || Date.now() - p.settledAt < SETTLE_GRACE_MS)), SETTLE_GRACE_MS);\n return () => clearTimeout(t);\n }, [pending]);\n\n const state = React.useMemo(() => pending.reduce((s, p) => applyOps(s, p.ops), base), [base, pending]);\n const stateRef = React.useRef(state);\n stateRef.current = state;\n\n const send = React.useCallback(\n (ops: readonly DeckOp[], onRefused: () => void, transient = false) => {\n if (!binding) {\n setLocal((s) => applyOps(s, ops));\n return;\n }\n const id = ++seq.current;\n setPending((list) => [...list, { id, ops, settledAt: null, ...(transient ? { transient } : {}) }]);\n binding.apply(ops).then(\n () => {\n setWriteError(null);\n // A transient change is never in the connection's state: it stops drawing the moment it lands.\n setPending((list) => (transient ? list.filter((p) => p.id !== id) : list.map((p) => (p.id === id ? { ...p, settledAt: Date.now() } : p))));\n },\n (err: unknown) => {\n setPending((list) => list.filter((p) => p.id !== id));\n setWriteError(err instanceof Error && err.message ? err.message : String(err));\n onRefused();\n },\n );\n },\n [binding],\n );\n\n const commit = React.useCallback(\n (change: DeckChange) => {\n touched.current = true;\n setHistory((h) => [...h, change]);\n send(change.ops, () => setHistory((h) => h.filter((c) => c !== change)), change.transient);\n onChangeRef.current?.(applyOps(stateRef.current, change.ops), change, false);\n },\n [send],\n );\n\n const historyRef = React.useRef(history);\n historyRef.current = history;\n const undo = React.useCallback((): DeckChange | null => {\n const last = historyRef.current[historyRef.current.length - 1];\n if (!last) return null;\n touched.current = true;\n setHistory((h) => h.slice(0, -1));\n // A refused undo puts the change back on the stack: the person can try again.\n send(last.inverse, () => setHistory((h) => [...h, last]), last.transient);\n onChangeRef.current?.(applyOps(stateRef.current, last.inverse), last, true);\n return last;\n }, [send]);\n\n return {\n items: binding ? binding.items : (items ?? []),\n state,\n status: binding ? binding.status : \"ready\",\n readError: binding ? binding.error : null,\n writeError,\n canUndo: history.length > 0,\n commit,\n undo,\n };\n}\n","/**\n * THE SWIPE DECK MODEL — everything the deck decides, with no DOM and no React.\n *\n * A deck is a list of items a person answers by swiping one of four ways. The deck never stores\n * anything itself: every change is a list of {@link DeckOp}s applied to a {@link DeckState}, and\n * every change carries its exact inverse, so undo is unlimited and covers every kind of change\n * (answers, picks, part edits, categories). A bound deck sends the same ops to its connection.\n *\n * WHERE THE PERSON IS IS DERIVED, never stored: the current step is the first one not yet done.\n * So a deck open on two devices stays in step by sharing state alone, and a reload resumes where\n * the person left off.\n */\nimport type { ReactNode } from \"react\";\n\nexport type DeckDirection = \"right\" | \"up\" | \"left\" | \"down\";\nexport const DECK_DIRECTIONS: readonly DeckDirection[] = [\"right\", \"up\", \"left\", \"down\"];\n\n/** Semantic color of an answer; each names a design-system token pair (`--success` / `--success-foreground`…). */\nexport type DeckTone = \"success\" | \"info\" | \"destructive\" | \"warning\" | \"primary\" | \"neutral\";\n\nexport interface DeckAnswer {\n /** Stable id: what results, callbacks and connections carry. */\n readonly id: string;\n readonly label: string;\n /**\n * Offered only through the card's own controls (`renderCardActions` / `renderCardBody` call\n * `answer(id)`), never drawn as a button: an answer that needs a choice first (\"Related ▸ Partner\").\n */\n readonly hidden?: boolean;\n /**\n * \"Skip for now\": in a bound deck the connection moves the card to the back of the line and keeps no\n * answer (it comes back once the rest are answered); undo brings it back to the front. In a deck with no\n * connection it is kept like any other answer.\n */\n readonly requeue?: boolean;\n readonly tone: DeckTone;\n /** Higher is better. Decides which answer wins when categories disagree (default by direction). */\n readonly rank?: number;\n /** Replaces the arrow on the edge button and the full-screen wash. */\n readonly icon?: ReactNode;\n /** One key that gives this answer (\"Y\", \"3\"), beside the arrows. Case does not matter. */\n readonly shortcut?: string;\n}\n\n/** The answer on each edge. A missing direction is disabled (two, three or four ways). */\nexport type DeckKey = Partial<Record<DeckDirection, DeckAnswer>>;\n/** An override: an answer replaces that edge, `null` turns the edge off. */\nexport type DeckKeyOverride = Partial<Record<DeckDirection, DeckAnswer | null>>;\n\nexport const DEFAULT_DECK_KEY: DeckKey = {\n right: { id: \"yes\", label: \"Yes!\", tone: \"success\", rank: 3 },\n up: { id: \"sort_of\", label: \"Sort of\", tone: \"info\", rank: 2 },\n left: { id: \"no\", label: \"No\", tone: \"destructive\", rank: 0 },\n down: { id: \"not_sure\", label: \"Not sure\", tone: \"warning\", rank: 1 },\n};\n\n/** The part screen's down edge: close it, changing no answer. */\nexport const KEEP_ANSWER_ID = \"__keep\";\nexport const DEFAULT_KEEP_ANSWER: DeckAnswer = { id: KEEP_ANSWER_ID, label: \"Keep as is\", tone: \"neutral\" };\n\nconst DIRECTION_RANK: Record<DeckDirection, number> = { right: 3, up: 2, down: 1, left: 0 };\n\nexport function mergeKey(base: DeckKey, override?: DeckKeyOverride | null): DeckKey {\n if (!override) return base;\n const out: DeckKey = { ...base };\n for (const dir of DECK_DIRECTIONS) {\n if (!(dir in override)) continue;\n const next = override[dir];\n if (next) out[dir] = next;\n else delete out[dir];\n }\n return out;\n}\n\nexport function directionOf(key: DeckKey, answerId: string | null | undefined): DeckDirection | null {\n if (!answerId) return null;\n for (const dir of DECK_DIRECTIONS) if (key[dir]?.id === answerId) return dir;\n return null;\n}\n\n/** The answer with this id: on an edge of `key`, else among `more` (the answers off the edges). */\nexport function answerOf(key: DeckKey, answerId: string | null | undefined, more?: readonly DeckAnswer[]): DeckAnswer | null {\n const dir = directionOf(key, answerId);\n if (dir) return key[dir] ?? null;\n if (!answerId || !more) return null;\n return more.find((a) => a.id === answerId) ?? null;\n}\n\nfunction rankOf(key: DeckKey, answerId: string): number {\n const dir = directionOf(key, answerId);\n if (!dir) return -1;\n return key[dir]?.rank ?? DIRECTION_RANK[dir];\n}\n\n// ─── items, parts, categories ─────────────────────────────────────────────\n\nexport interface DeckField {\n readonly label: string;\n readonly value: string;\n}\n\n/** A part as an item first offers it: by phrase (first match) or by token span. */\nexport interface DeckPartSeed {\n readonly phrase?: string;\n readonly start?: number;\n readonly end?: number;\n readonly categories?: readonly string[];\n /** The answer this part leans to before anyone answers it. */\n readonly suggested?: string | null;\n readonly answer?: string | null;\n}\n\n/** A span of the item's words [start, end] (token indexes, inclusive) with its own answer. */\nexport interface DeckPart {\n readonly start: number;\n readonly end: number;\n readonly categories: readonly string[];\n readonly suggested: string | null;\n readonly answer: string | null;\n}\n\nexport interface DeckCategory {\n readonly name: string;\n readonly answer: string | null;\n /** The chip row it was added in (see {@link DeckCategoryRow}), when the deck has rows. */\n readonly row?: string;\n}\n\n/** A labelled row of categories on the part screen (\"Who\", \"Cares about\"); a category added with its \"+\" carries the row's id. */\nexport interface DeckCategoryRow {\n readonly id: string;\n readonly label: string;\n readonly categories: readonly string[];\n}\n\n/** A picture on the card: an image by address, or anything the host draws (an avatar with its own fallback). */\nexport type DeckMedia =\n | { readonly src: string; readonly alt?: string; readonly shape?: \"circle\" | \"square\" | \"wide\" }\n | { readonly node: ReactNode; readonly shape?: \"circle\" | \"square\" | \"wide\" };\n\n/** One member of a group card (\"these four logos\"): each can be switched off before the card is answered. */\nexport interface DeckMember {\n readonly id: string;\n readonly label: string;\n readonly media?: DeckMedia;\n /** Starts switched off. */\n readonly off?: boolean;\n}\n\n/**\n * When a card is asked: about one earlier card's answer, or a combination. A leaf names the card (`item`)\n * and, optionally, the answers that count (`is`), the ones that must not (`isNot`), or whether it was\n * answered at all (`answered`, default true). A card only ever depends on cards BEFORE it (no loops);\n * a card that is not asked has no answer as far as later cards are concerned.\n */\nexport type DeckCondition =\n | {\n readonly item: string;\n readonly is?: string | readonly string[];\n readonly isNot?: string | readonly string[];\n readonly answered?: boolean;\n }\n | { readonly all: readonly DeckCondition[] }\n | { readonly any: readonly DeckCondition[] }\n | { readonly not: DeckCondition };\n\n/** What rides with an answer beyond its id: the members switched off, a value typed on the card. */\nexport type DeckDetail = Readonly<Record<string, unknown>>;\n\nexport interface DeckItem {\n readonly id: string;\n /** The main text: fitted to the largest size the screen allows. */\n readonly text: string;\n /** A small label above the text (what kind of item this is). */\n readonly kicker?: string;\n /** A small fact tag beside the kicker. */\n readonly tag?: string;\n /** The suggested answer id: its button is filled and pulses, and the card leans toward it. */\n readonly suggested?: string | null;\n /**\n * The suggestion in finer words than its answer's label, shown as the Suggestion (the card still leans to\n * `suggested`): an answer that merges two (\"Sustain or Accept\") can show the precise one (\"Accept\").\n */\n readonly suggestedLabel?: string;\n /** Shown under the text with the \"Reason\" label. */\n readonly reason?: string;\n /** More label/value lines under the text. */\n readonly fields?: readonly DeckField[];\n /** Draw the text in quotation marks. */\n readonly quoted?: boolean;\n readonly parts?: readonly DeckPartSeed[];\n /** This item's own key: replaces or turns off edges of the deck's key. */\n readonly answers?: DeckKeyOverride;\n /** Pick-one group: when every item of a pick-one group is answered, the person picks one of its Yes items. */\n readonly group?: string;\n /** The suggested pick of its group. */\n readonly pickSuggested?: boolean;\n /**\n * The right answer(s), by answer id, for a deck that is graded (a quiz). Never shown while she answers;\n * the result says which were right and the end shows the score. Absent: the item is not graded.\n */\n readonly correct?: string | readonly string[];\n /** Answers off the edges, as a row of buttons on the card; replaces the deck's own `more` for this item. */\n readonly more?: readonly DeckAnswer[];\n /** A picture above the text. */\n readonly media?: DeckMedia;\n /** A group card: its members, each switched on or off; the off ones ride with the answer as `detail.off`. */\n readonly members?: readonly DeckMember[];\n /**\n * Asked only when this holds (see {@link DeckCondition}). Not asked: skipped, and left out of progress,\n * counts, the score and the results; an answer it already had is KEPT but does not apply, and comes\n * back if the card is asked again.\n */\n readonly showIf?: DeckCondition;\n}\n\nexport interface DeckState {\n readonly answers: Readonly<Record<string, string>>;\n readonly picks: Readonly<Record<string, string>>;\n /** Parts as changed or loaded; an item absent here shows its seeds. */\n readonly parts: Readonly<Record<string, readonly DeckPart[]>>;\n readonly categories: Readonly<Record<string, DeckCategory>>;\n /** What rode with each answer (see {@link DeckDetail}); a binding that keeps none may leave it out. */\n readonly details?: Readonly<Record<string, DeckDetail>>;\n}\n\nexport const EMPTY_DECK_STATE: DeckState = { answers: {}, picks: {}, parts: {}, categories: {}, details: {} };\n\nconst plain = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst keep = <T,>(v: unknown, ok: (x: unknown) => x is T): Record<string, T> =>\n plain(v) ? Object.fromEntries(Object.entries(v).filter((e): e is [string, T] => ok(e[1]))) : {};\nconst isText = (x: unknown): x is string => typeof x === \"string\" && x.length > 0;\nconst isPart = (x: unknown): x is DeckPart => plain(x) && Number.isInteger(x.start) && Number.isInteger(x.end) && Array.isArray(x.categories);\nconst isParts = (x: unknown): x is readonly DeckPart[] => Array.isArray(x) && x.every(isPart);\nconst isCategory = (x: unknown): x is DeckCategory => plain(x) && typeof x.name === \"string\";\n\n/**\n * A full deck state from anything saved or handed in: missing parts start empty, and an entry of the\n * wrong shape (an old save, a hand-edited row) is left out, so a deck never draws blank over bad data.\n */\nexport function deckState(partial?: Partial<DeckState> | null): DeckState {\n const p: Record<string, unknown> = plain(partial) ? partial : {};\n return {\n answers: keep(p.answers, isText),\n picks: keep(p.picks, isText),\n parts: keep(p.parts, isParts),\n categories: keep(p.categories, isCategory),\n details: keep(p.details, plain) as Record<string, DeckDetail>,\n };\n}\n\nexport function tokenize(text: string): string[] {\n return text.split(/\\s+/).filter(Boolean);\n}\n\nfunction norm(token: string): string {\n return token.toLowerCase().replace(/[^\\p{L}\\p{N}+-]/gu, \"\");\n}\n\n/** The parts an item opens with: each seed placed on its tokens; seeds that match nothing are dropped. */\nexport function seedParts(item: DeckItem): DeckPart[] {\n const tokens = tokenize(item.text);\n const normed = tokens.map(norm);\n const out: DeckPart[] = [];\n for (const seed of item.parts ?? []) {\n let start = seed.start;\n let end = seed.end;\n if (seed.phrase !== undefined) {\n const want = tokenize(seed.phrase).map(norm);\n start = undefined;\n for (let i = 0; i + want.length <= normed.length && want.length; i++) {\n if (want.every((w, j) => normed[i + j] === w)) {\n start = i;\n end = i + want.length - 1;\n break;\n }\n }\n }\n if (start === undefined || start < 0 || start >= tokens.length) continue;\n const e = Math.min(tokens.length - 1, Math.max(start, end ?? start));\n out.push({ start, end: e, categories: seed.categories ?? [], suggested: seed.suggested ?? null, answer: seed.answer ?? null });\n }\n return withoutOverlaps(out);\n}\n\nfunction withoutOverlaps(parts: DeckPart[]): DeckPart[] {\n const sorted = [...parts].sort((a, b) => a.start - b.start);\n const out: DeckPart[] = [];\n for (const p of sorted) if (!out.some((q) => !(q.end < p.start || q.start > p.end))) out.push(p);\n return out;\n}\n\nexport function partsOf(state: DeckState, item: DeckItem): readonly DeckPart[] {\n return state.parts[item.id] ?? seedParts(item);\n}\n\nexport function partText(item: DeckItem, part: Pick<DeckPart, \"start\" | \"end\">): string {\n return tokenize(item.text)\n .slice(part.start, part.end + 1)\n .join(\" \")\n .replace(/^[“\"‘'(\\[]+|[”\"’'.,;:!?)\\]]+$/g, \"\");\n}\n\n/** Every category the deck knows: the configured rows, then any a part or the state names. */\nexport function knownCategories(configured: readonly string[], items: readonly DeckItem[], state: DeckState): string[] {\n const out: string[] = [];\n const add = (name: string) => {\n if (name && !out.includes(name)) out.push(name);\n };\n configured.forEach(add);\n for (const item of items) for (const part of partsOf(state, item)) part.categories.forEach(add);\n Object.keys(state.categories).forEach(add);\n return out;\n}\n\nexport type CategoryConflict = \"worse\" | \"better\" | ((answerIds: readonly string[]) => string);\n\n/** One answer from several categories' answers: by default the worse one wins. */\nexport function resolveConflict(answerIds: readonly string[], key: DeckKey, conflict: CategoryConflict = \"worse\"): string | null {\n if (!answerIds.length) return null;\n if (typeof conflict === \"function\") return conflict(answerIds);\n const sign = conflict === \"better\" ? -1 : 1;\n return [...answerIds].sort((a, b) => sign * (rankOf(key, a) - rankOf(key, b)))[0] ?? null;\n}\n\n/** What a part leans to: its categories' answers flow down to it; otherwise its own suggestion. */\nexport function partSuggestion(part: DeckPart, state: DeckState, key: DeckKey, conflict?: CategoryConflict): string | null {\n const flowed = part.categories.map((c) => state.categories[c]?.answer).filter((a): a is string => !!a);\n return resolveConflict(flowed, key, conflict) ?? part.suggested;\n}\n\n/** The answer a part shows: its own, else what flows down to it. */\nexport function partAnswer(part: DeckPart, state: DeckState, key: DeckKey, conflict?: CategoryConflict): string | null {\n return part.answer ?? partSuggestion(part, state, key, conflict);\n}\n\n/** Place a part on its span: every part it overlaps is replaced. */\nexport function placePart(parts: readonly DeckPart[], next: DeckPart): DeckPart[] {\n return [...parts.filter((p) => p.end < next.start || p.start > next.end), next].sort((a, b) => a.start - b.start);\n}\n\nexport function forgetSpan(parts: readonly DeckPart[], span: Pick<DeckPart, \"start\" | \"end\">): DeckPart[] {\n return parts.filter((p) => p.end < span.start || p.start > span.end);\n}\n\n// ─── steps ────────────────────────────────────────────────────────────────\n\nexport type DeckStep =\n | { readonly kind: \"card\"; readonly id: string; readonly item: DeckItem }\n | { readonly kind: \"pick\"; readonly id: string; readonly group: string; readonly items: readonly DeckItem[] }\n | { readonly kind: \"end\"; readonly id: \"end\" };\n\nexport interface DeckRules {\n readonly key: DeckKey;\n /** Groups that end in a pick-one screen: `true` = every group. */\n readonly pickOne?: boolean | readonly string[];\n /** The answer that makes an item a contender in its group's pick (default: the right edge's). */\n readonly pickAnswer?: string;\n /** Answers off the edges, offered on every card (an item's own `more` replaces them). */\n readonly more?: readonly DeckAnswer[];\n}\n\nexport function keyFor(rules: DeckRules, item: DeckItem): DeckKey {\n return mergeKey(rules.key, item.answers);\n}\n\n/** The answers off the edges for this item: its own, or the deck's; never one already on an edge. */\nexport function moreFor(rules: DeckRules, item: DeckItem): readonly DeckAnswer[] {\n const key = keyFor(rules, item);\n const list = item.more ?? rules.more ?? [];\n return list.filter((a) => !directionOf(key, a.id));\n}\n\n/** Every answer this item can take: the edges' (clockwise from the top), then the ones off the edges. */\nexport function answersFor(rules: DeckRules, item: DeckItem): readonly DeckAnswer[] {\n const key = keyFor(rules, item);\n const edges = ([\"up\", \"right\", \"down\", \"left\"] as const).map((d) => key[d]).filter((a): a is DeckAnswer => !!a);\n return [...edges, ...moreFor(rules, item)];\n}\n\n/** The answer with this id for this item, on an edge or off it. */\nexport function findAnswer(rules: DeckRules, item: DeckItem, answerId: string | null | undefined): DeckAnswer | null {\n return answerOf(keyFor(rules, item), answerId, moreFor(rules, item));\n}\n\n/**\n * What rides with an item's answer: the detail given, and on a group card always its members switched off\n * (`off`, the starting ones included), so a consumer never has to know the item's defaults.\n */\nexport function answerDetail(item: DeckItem, detail: DeckDetail | null | undefined): DeckDetail | null {\n if (!item.members?.length) return detail ?? null;\n return { ...(detail ?? {}), off: [...membersOff(item, detail)] };\n}\n\n/** The members switched off on a group card: what the person set, else what the item starts with. */\nexport function membersOff(item: DeckItem, detail: DeckDetail | null | undefined): readonly string[] {\n const off = detail?.off;\n if (Array.isArray(off)) return off.filter((x): x is string => typeof x === \"string\");\n return (item.members ?? []).filter((m) => m.off).map((m) => m.id);\n}\n\nfunction pickAnswerOf(rules: DeckRules): string | null {\n return rules.pickAnswer ?? rules.key.right?.id ?? null;\n}\n\nfunction isPickGroup(rules: DeckRules, group: string | undefined): group is string {\n if (!group || !rules.pickOne) return false;\n return rules.pickOne === true || rules.pickOne.includes(group);\n}\n\nconst asList = (v: string | readonly string[] | undefined): readonly string[] | null => (v === undefined ? null : typeof v === \"string\" ? [v] : v);\n\n/** Whether a condition holds, given the cards asked so far (`asked`: id → asked) and the answers. */\nexport function conditionHolds(cond: DeckCondition, state: DeckState, asked: ReadonlyMap<string, boolean>): boolean {\n if (\"all\" in cond) return cond.all.every((c) => conditionHolds(c, state, asked));\n if (\"any\" in cond) return cond.any.some((c) => conditionHolds(c, state, asked));\n if (\"not\" in cond) return !conditionHolds(cond.not, state, asked);\n // A card not (yet) asked — later, missing, or skipped by its own condition — has no answer.\n const answer = asked.get(cond.item) ? (state.answers[cond.item] ?? null) : null;\n const wantAnswered = cond.answered ?? true;\n if (!wantAnswered) return answer === null;\n if (answer === null) return false;\n const is = asList(cond.is);\n const isNot = asList(cond.isNot);\n if (is && !is.includes(answer)) return false;\n if (isNot && isNot.includes(answer)) return false;\n return true;\n}\n\n/** Which cards are asked, in order: a card with no condition always; one with a condition when it holds over the cards before it. */\nexport function askedItems(items: readonly DeckItem[], state: DeckState): ReadonlyMap<string, boolean> {\n const asked = new Map<string, boolean>();\n for (const item of items) asked.set(item.id, item.showIf ? conditionHolds(item.showIf, state, asked) : true);\n return asked;\n}\n\n/** The cards asked, in order. */\nexport function shownItems(items: readonly DeckItem[], state: DeckState): DeckItem[] {\n if (!items.some((i) => i.showIf)) return [...items];\n const asked = askedItems(items, state);\n return items.filter((i) => asked.get(i.id));\n}\n\n/** Every card id a condition names. */\nexport function conditionItems(cond: DeckCondition): string[] {\n if (\"all\" in cond) return cond.all.flatMap(conditionItems);\n if (\"any\" in cond) return cond.any.flatMap(conditionItems);\n if (\"not\" in cond) return conditionItems(cond.not);\n return [cond.item];\n}\n\n/**\n * THE ORDER A DECK WITH CONDITIONS IS ASKED IN, when its order is not authored (a table sorted any way):\n * the given order, except that a card always comes after every card its condition names. Stable — a\n * deck whose conditions already point backwards is returned unchanged. A loop (two cards naming each\n * other) is left in the given order, where `conditionProblems` says so.\n */\nexport function dependencyOrder<T extends DeckItem>(items: readonly T[]): T[] {\n const ids = new Set(items.map((i) => i.id));\n const needs = new Map(items.map((i) => [i.id, new Set(i.showIf ? conditionItems(i.showIf).filter((d) => ids.has(d) && d !== i.id) : [])]));\n const out: T[] = [];\n const placed = new Set<string>();\n const left = [...items];\n while (left.length) {\n const k = left.findIndex((i) => [...needs.get(i.id)!].every((d) => placed.has(d)));\n const [next] = left.splice(k < 0 ? 0 : k, 1);\n out.push(next!);\n placed.add(next!.id);\n }\n return out;\n}\n\n/**\n * What is wrong with the deck's conditions, in words (never silent): a condition naming a card that does\n * not exist, one that comes later (it could never be answered first), or an answer the card does not have.\n */\n/**\n * A condition as a person or an agent wrote it (`{item, is, is_not | isNot, answered}`, `{all}`, `{any}`,\n * `{not}`, or a list meaning all), with its card and answers resolved by the host: `ref` names the card\n * (an id, a position, its words), `answer(itemId, word)` the answer id. Null when nothing can be read.\n * The one reader for every source of conditions (a chat answer, a table column, a definition).\n */\nexport function readDeckCondition(\n raw: unknown,\n resolve: { ref: (v: unknown) => string; answer: (itemId: string, word: unknown) => string | null },\n): DeckCondition | null {\n const rec = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\n const read = (r: unknown): DeckCondition | null => {\n if (Array.isArray(r)) {\n const all = r.map(read).filter((c): c is DeckCondition => !!c);\n return all.length ? { all } : null;\n }\n if (!rec(r)) return null;\n if (Array.isArray(r.all)) return { all: r.all.map(read).filter((c): c is DeckCondition => !!c) };\n if (Array.isArray(r.any)) return { any: r.any.map(read).filter((c): c is DeckCondition => !!c) };\n if (r.not !== undefined) {\n const inner = read(r.not);\n return inner ? { not: inner } : null;\n }\n if (r.item === undefined || r.item === null) return null;\n const item = resolve.ref(r.item);\n const words = (v: unknown): string[] | undefined =>\n v === undefined || v === null ? undefined : (Array.isArray(v) ? v : [v]).map((w) => resolve.answer(item, w) ?? String(w).trim()).filter(Boolean);\n const is = words(r.is);\n const isNot = words(r.is_not ?? r.isNot);\n return {\n item,\n ...(is ? { is } : {}),\n ...(isNot ? { isNot } : {}),\n ...(typeof r.answered === \"boolean\" ? { answered: r.answered } : {}),\n };\n };\n return read(raw);\n}\n\nexport function conditionProblems(items: readonly DeckItem[], rules: DeckRules): string[] {\n const out: string[] = [];\n const index = new Map(items.map((i, k) => [i.id, k]));\n items.forEach((item, k) => {\n if (!item.showIf) return;\n const visit = (c: DeckCondition): void => {\n if (\"all\" in c) return c.all.forEach(visit);\n if (\"any\" in c) return c.any.forEach(visit);\n if (\"not\" in c) return visit(c.not);\n const at = index.get(c.item);\n if (at === undefined) {\n out.push(`\"${item.text}\" depends on a card that is not in the deck (${c.item}).`);\n return;\n }\n if (at >= k) {\n out.push(`\"${item.text}\" depends on \"${items[at]?.text ?? c.item}\", which comes after it, so it can never be asked.`);\n return;\n }\n const target = items[at];\n if (!target) return;\n for (const id of [...(asList(c.is) ?? []), ...(asList(c.isNot) ?? [])]) {\n if (!findAnswer(rules, target, id)) out.push(`\"${item.text}\" waits for an answer \"${id}\" that \"${target.text}\" does not have.`);\n }\n };\n visit(item.showIf);\n });\n return out;\n}\n\nexport function contenders(items: readonly DeckItem[], state: DeckState, rules: DeckRules, group: string): DeckItem[] {\n const yes = pickAnswerOf(rules);\n return shownItems(items, state).filter((i) => i.group === group && yes !== null && state.answers[i.id] === yes);\n}\n\n/** The picked item of a group: the person's pick while it still stands, or the only contender. */\nexport function pickedItem(items: readonly DeckItem[], state: DeckState, rules: DeckRules, group: string): DeckItem | null {\n const all = contenders(items, state, rules, group);\n const chosen = state.picks[group];\n const hit = chosen ? all.find((i) => i.id === chosen) : undefined;\n if (hit) return hit;\n return all.length === 1 ? (all[0] ?? null) : null;\n}\n\nexport function deckSteps(allItems: readonly DeckItem[], state: DeckState, rules: DeckRules): DeckStep[] {\n const out: DeckStep[] = [];\n // Only the cards that are asked are steps; a card whose condition does not hold is skipped.\n const items = shownItems(allItems, state);\n items.forEach((item, index) => {\n out.push({ kind: \"card\", id: `card:${item.id}`, item });\n const group = item.group;\n if (!isPickGroup(rules, group)) return;\n const isLast = !items.slice(index + 1).some((i) => i.group === group);\n if (!isLast) return;\n const members = items.filter((i) => i.group === group);\n const all = contenders(items, state, rules, group);\n if (all.length > 1 && members.every((i) => state.answers[i.id])) out.push({ kind: \"pick\", id: `pick:${group}`, group, items: all });\n });\n out.push({ kind: \"end\", id: \"end\" });\n return out;\n}\n\nexport function stepDone(step: DeckStep, state: DeckState): boolean {\n if (step.kind === \"card\") return !!state.answers[step.item.id];\n if (step.kind === \"pick\") return step.items.some((i) => i.id === state.picks[step.group]);\n return false;\n}\n\n/** Where the person is: the first step not done (the end when all are). */\nexport function currentStepIndex(steps: readonly DeckStep[], state: DeckState): number {\n const i = steps.findIndex((s) => !stepDone(s, state));\n return i < 0 ? steps.length - 1 : i;\n}\n\n// ─── ops, changes, undo ───────────────────────────────────────────────────\n\nexport type DeckOp =\n | { readonly kind: \"answer\"; readonly itemId: string; readonly answer: string | null; readonly detail?: DeckDetail | null }\n | { readonly kind: \"pick\"; readonly group: string; readonly itemId: string | null }\n | { readonly kind: \"parts\"; readonly itemId: string; readonly parts: readonly DeckPart[] }\n | { readonly kind: \"category\"; readonly name: string; readonly answer: string | null; readonly remove?: boolean; readonly row?: string };\n\n/** One thing the person did: its ops, their exact inverse, and the edge it left by. */\nexport interface DeckChange {\n readonly ops: readonly DeckOp[];\n readonly inverse: readonly DeckOp[];\n readonly from: DeckDirection | null;\n /**\n * The connection acts on it but never keeps it as an answer (a `requeue` answer: the card goes to the\n * back of the line): once the connection resolves, the deck stops drawing it, so the card is unanswered.\n */\n readonly transient?: boolean;\n}\n\nfunction omit<T>(record: Readonly<Record<string, T>>, k: string): Record<string, T> {\n const { [k]: _gone, ...rest } = record;\n return rest;\n}\n\nexport function applyOp(state: DeckState, op: DeckOp): DeckState {\n switch (op.kind) {\n case \"answer\": {\n const details = state.details ?? {};\n return {\n ...state,\n answers: op.answer ? { ...state.answers, [op.itemId]: op.answer } : omit(state.answers, op.itemId),\n details: op.answer && op.detail ? { ...details, [op.itemId]: op.detail } : omit(details, op.itemId),\n };\n }\n case \"pick\":\n return { ...state, picks: op.itemId ? { ...state.picks, [op.group]: op.itemId } : omit(state.picks, op.group) };\n case \"parts\":\n return { ...state, parts: { ...state.parts, [op.itemId]: op.parts } };\n case \"category\":\n return {\n ...state,\n categories: op.remove\n ? omit(state.categories, op.name)\n : { ...state.categories, [op.name]: { name: op.name, answer: op.answer, ...(op.row ? { row: op.row } : {}) } },\n };\n default:\n // An op this deck does not know (saved by a newer one): leave the state as it is.\n return state;\n }\n}\n\nexport function applyOps(state: DeckState, ops: readonly DeckOp[]): DeckState {\n return ops.reduce(applyOp, state);\n}\n\n/** The op that puts back what `op` changes, read from the state before it. */\nexport function invertOp(before: DeckState, op: DeckOp, items: readonly DeckItem[]): DeckOp {\n switch (op.kind) {\n case \"answer\":\n return { kind: \"answer\", itemId: op.itemId, answer: before.answers[op.itemId] ?? null, detail: before.details?.[op.itemId] ?? null };\n case \"pick\":\n return { kind: \"pick\", group: op.group, itemId: before.picks[op.group] ?? null };\n case \"parts\": {\n const item = items.find((i) => i.id === op.itemId);\n return { kind: \"parts\", itemId: op.itemId, parts: before.parts[op.itemId] ?? (item ? seedParts(item) : []) };\n }\n case \"category\": {\n const had = before.categories[op.name];\n return had ? { kind: \"category\", name: op.name, answer: had.answer } : { kind: \"category\", name: op.name, answer: null, remove: true };\n }\n }\n}\n\nexport function makeChange(before: DeckState, ops: readonly DeckOp[], items: readonly DeckItem[], from: DeckDirection | null = null): DeckChange {\n const inverse: DeckOp[] = [];\n let s = before;\n for (const op of ops) {\n inverse.unshift(invertOp(s, op, items));\n s = applyOp(s, op);\n }\n return { ops, inverse, from };\n}\n\n/** Answer an item; an answer that drops it out of its group's contenders also drops a pick that named it. */\nexport function answerChange(\n before: DeckState,\n item: DeckItem,\n answerId: string,\n rules: DeckRules,\n items: readonly DeckItem[],\n from: DeckDirection | null,\n detail?: DeckDetail | null,\n): DeckChange {\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: answerId, ...(detail ? { detail } : {}) }];\n if (item.group && answerId !== pickAnswerOf(rules) && before.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n return makeChange(before, ops, items, from);\n}\n\n// ─── results and copy ─────────────────────────────────────────────────────\n\nexport interface DeckResultPart {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n readonly categories: readonly string[];\n readonly answer: DeckAnswer | null;\n /** True when the person answered the part itself, false when its answer flowed down. */\n readonly own: boolean;\n}\n\nexport interface DeckResultEntry {\n readonly item: DeckItem;\n readonly answer: DeckAnswer | null;\n readonly parts: readonly DeckResultPart[];\n /** Graded items only: whether the answer given is a right one (null: not graded, or not answered). */\n readonly right: boolean | null;\n /** What rode with the answer (members switched off, a value typed on the card); null when nothing did. */\n readonly detail: DeckDetail | null;\n /** False when the card is not asked (its condition does not hold): its answer, if any, does not apply. */\n readonly shown: boolean;\n}\n\nexport interface DeckResult {\n readonly entries: readonly DeckResultEntry[];\n readonly answered: number;\n readonly total: number;\n readonly complete: boolean;\n /** Per answer id: how many items took it. */\n readonly counts: Readonly<Record<string, number>>;\n readonly picks: Readonly<Record<string, DeckItem>>;\n readonly categories: readonly DeckCategory[];\n readonly state: DeckState;\n /** When any item is graded: how many answered items were right, of how many graded items. */\n readonly score: { readonly right: number; readonly graded: number } | null;\n}\n\nexport function deckResult(items: readonly DeckItem[], state: DeckState, rules: DeckRules, conflict?: CategoryConflict): DeckResult {\n const counts: Record<string, number> = {};\n const asked = askedItems(items, state);\n const entries = items.map((item): DeckResultEntry => {\n const key = keyFor(rules, item);\n const more = moreFor(rules, item);\n const shown = asked.get(item.id) !== false;\n // A card not asked keeps its answer in the state, but the answer does not apply anywhere.\n const id = shown ? (state.answers[item.id] ?? null) : null;\n if (id) counts[id] = (counts[id] ?? 0) + 1;\n const parts = partsOf(state, item).map((p): DeckResultPart => {\n const pa = partAnswer(p, state, key, conflict);\n return { text: partText(item, p), start: p.start, end: p.end, categories: p.categories, answer: answerOf(key, pa), own: !!p.answer };\n });\n const correct = item.correct === undefined ? null : typeof item.correct === \"string\" ? [item.correct] : item.correct;\n const right = correct && id ? correct.includes(id) : null;\n return { item, answer: answerOf(key, id, more), parts, right, detail: (id && state.details?.[item.id]) || null, shown };\n });\n const picks: Record<string, DeckItem> = {};\n const groups = new Set(items.map((i) => i.group).filter((g): g is string => isPickGroup(rules, g)));\n for (const g of groups) {\n const p = pickedItem(items, state, rules, g);\n if (p) picks[g] = p;\n }\n const answered = entries.filter((e) => e.answer).length;\n const steps = deckSteps(items, state, rules);\n const complete = steps[currentStepIndex(steps, state)]?.kind === \"end\";\n const graded = entries.filter((e) => e.shown && e.item.correct !== undefined).length;\n const score = graded ? { right: entries.filter((e) => e.right === true).length, graded } : null;\n const total = entries.filter((e) => e.shown).length;\n return { entries, answered, total, complete, counts, picks, categories: Object.values(state.categories), state, score };\n}\n\nexport interface DeckCopyLabels {\n readonly suggestion: string;\n readonly reason: string;\n readonly answer: string;\n readonly unanswered: string;\n}\n\n/** One item as plain text for an AI or a note: what it says, what was suggested, and what the person answered. */\nexport function itemCopyText(\n item: DeckItem,\n state: DeckState,\n key: DeckKey,\n labels: DeckCopyLabels,\n conflict?: CategoryConflict,\n more?: readonly DeckAnswer[],\n): string {\n const lines = [[item.kicker, item.quoted ? `“${item.text}”` : item.text].filter(Boolean).join(\": \")];\n if (item.tag) lines.push(item.tag);\n const off = membersOff(item, state.details?.[item.id]);\n for (const m of item.members ?? []) lines.push(`- ${m.label}${off.includes(m.id) ? \" (off)\" : \"\"}`);\n const sug = answerOf(key, item.suggested, more);\n if (sug) lines.push(`${labels.suggestion}: ${item.suggestedLabel ?? sug.label}`);\n if (item.reason) lines.push(`${labels.reason}: ${item.reason}`);\n for (const f of item.fields ?? []) lines.push(`${f.label}: ${f.value}`);\n const parts = partsOf(state, item);\n for (const p of parts) {\n const a = answerOf(key, partAnswer(p, state, key, conflict));\n lines.push(`- ${partText(item, p)}: ${[a?.label, ...p.categories].filter(Boolean).join(\" · \")}`);\n }\n lines.push(`${labels.answer}: ${answerOf(key, state.answers[item.id], more)?.label ?? labels.unanswered}`);\n return lines.join(\"\\n\");\n}\n\nexport function deckCopyText(result: DeckResult, rules: DeckRules): string {\n const lines: string[] = [];\n for (const [group, item] of Object.entries(result.picks)) lines.push(`${group}: ${item.text}`);\n // Each answer given, in the deck's order (its edges, then the rest as they first appear).\n const order: DeckAnswer[] = DECK_DIRECTIONS.map((d) => rules.key[d]).filter((a): a is DeckAnswer => !!a);\n for (const e of result.entries) if (e.answer && !order.some((a) => a.id === e.answer?.id)) order.push(e.answer);\n for (const a of order) {\n const hits = result.entries.filter((e) => e.answer?.id === a.id);\n if (!hits.length) continue;\n if (lines.length) lines.push(\"\");\n lines.push(`${a.label}:`);\n for (const e of hits) lines.push(`- ${e.item.text}`);\n }\n const placed = result.entries.flatMap((e) => e.parts.filter((p) => p.own && p.answer).map((p) => `- ${p.text}: ${p.answer?.label ?? \"\"}`));\n if (placed.length) lines.push(\"\", ...placed);\n return lines.join(\"\\n\");\n}\n\n// ─── chained decks ────────────────────────────────────────────────────────\n\n/**\n * Feed one deck's answers into the next deck's suggestions: each next item names the earlier item it\n * follows (`link`), and the earlier answer maps to the next suggestion (`map`, identity by default).\n * An item that already carries a suggestion keeps it.\n */\nexport function chainSuggestions(\n next: readonly DeckItem[],\n previous: DeckResult | DeckState,\n link: (item: DeckItem) => string | null | undefined,\n map: (answerId: string, item: DeckItem) => string | null | undefined = (a) => a,\n): DeckItem[] {\n const answers = \"entries\" in previous ? previous.state.answers : previous.answers;\n return next.map((item) => {\n if (item.suggested) return item;\n const from = link(item);\n const prior = from ? answers[from] : undefined;\n const suggested = prior ? map(prior, item) : undefined;\n return suggested ? { ...item, suggested } : item;\n });\n}\n","/**\n * THE SWIPE GESTURE — one pointer, four ways, plus tap and hold.\n *\n * A press that moves more than a few pixels becomes a drag; the drag commits when it passes the\n * distance threshold OR when it is released as a flick (speed over the last ~100ms, so a short fast\n * throw counts the way it does on every phone). A press that never moves is a tap; held still over\n * a `holdSelector` element it becomes a hold. Nothing here renders: the caller moves the card through\n * `move`, which runs per pointer event without touching React state (60fps on a mid-range phone).\n */\nimport type { DeckDirection } from \"./model\";\nimport { buzz } from \"./visual\";\n\nexport interface SwipeHandlers {\n enabled(): boolean;\n directions(): Partial<Record<DeckDirection, unknown>>;\n start?(): void;\n /** `amount` is distance over the threshold: 1 means letting go here commits. */\n move(dx: number, dy: number, dir: DeckDirection | null, amount: number): void;\n release(): void;\n /** `speed` in px/ms, so the card can leave as fast as it was thrown. */\n commit(dir: DeckDirection, speed: number): void;\n tap?(target: Element): void;\n hold?(target: Element): void;\n holdSelector?: string;\n /** Presses starting inside these never swipe (buttons, inputs, chip rows). */\n ignoreSelector?: string;\n}\n\nexport const HOLD_MS = 450;\nconst DRAG_SLOP = 10;\nconst FLICK_MIN_DISTANCE = 40;\nconst FLICK_MIN_SPEED = 0.55;\n\nexport function swipeThreshold(width: number): number {\n return Math.max(70, Math.min(120, width * 0.2));\n}\n\nexport function dominantDirection(dx: number, dy: number): DeckDirection {\n return Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? \"right\" : \"left\") : dy < 0 ? \"up\" : \"down\";\n}\n\n/** Decide a release: commit a direction, or null to snap back. Pure, so it is tested alone. */\nexport function releaseDecision(\n dx: number,\n dy: number,\n speed: number,\n width: number,\n enabled: Partial<Record<DeckDirection, unknown>>,\n): DeckDirection | null {\n const dir = dominantDirection(dx, dy);\n if (!enabled[dir]) return null;\n const dist = Math.max(Math.abs(dx), Math.abs(dy));\n if (dist >= swipeThreshold(width)) return dir;\n if (dist > FLICK_MIN_DISTANCE && speed > FLICK_MIN_SPEED) return dir;\n return null;\n}\n\nexport function attachSwipe(root: HTMLElement, h: SwipeHandlers): () => void {\n let id: number | null = null;\n let sx = 0;\n let sy = 0;\n let dx = 0;\n let dy = 0;\n let mode: \"press\" | \"drag\" | \"held\" | null = null;\n let holdTimer: ReturnType<typeof setTimeout> | null = null;\n let downTarget: Element | null = null;\n let samples: { t: number; x: number; y: number }[] = [];\n const view = root.ownerDocument.defaultView ?? window;\n\n const clearHold = () => {\n if (holdTimer) clearTimeout(holdTimer);\n holdTimer = null;\n root.querySelectorAll(\"[data-sd-press]\").forEach((el) => el.removeAttribute(\"data-sd-press\"));\n };\n\n const width = () => root.getBoundingClientRect().width || view.innerWidth;\n\n const onDown = (e: PointerEvent) => {\n if (id !== null || e.button > 0 || !h.enabled()) return;\n const target = e.target instanceof Element ? e.target : null;\n if (!target || target.closest(h.ignoreSelector ?? \"button, a, input, textarea, [data-sd-noswipe]\")) return;\n id = e.pointerId;\n sx = e.clientX;\n sy = e.clientY;\n dx = dy = 0;\n mode = \"press\";\n downTarget = target;\n samples = [{ t: e.timeStamp, x: e.clientX, y: e.clientY }];\n h.start?.();\n const holdable = h.hold && h.holdSelector ? target.closest(h.holdSelector) : null;\n if (holdable) {\n holdable.setAttribute(\"data-sd-press\", \"\");\n holdTimer = setTimeout(() => {\n if (mode !== \"press\") return;\n mode = \"held\";\n clearHold();\n buzz(view.navigator, 10);\n h.hold?.(holdable);\n }, HOLD_MS);\n }\n view.addEventListener(\"pointermove\", onMove);\n view.addEventListener(\"pointerup\", onUp);\n view.addEventListener(\"pointercancel\", onCancel);\n };\n\n const onMove = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n dx = e.clientX - sx;\n dy = e.clientY - sy;\n samples.push({ t: e.timeStamp, x: e.clientX, y: e.clientY });\n if (samples.length > 8) samples.shift();\n if (mode === \"press\" && Math.hypot(dx, dy) > DRAG_SLOP) {\n clearHold();\n mode = \"drag\";\n }\n if (mode !== \"drag\") return;\n const dir = dominantDirection(dx, dy);\n const dist = Math.max(Math.abs(dx), Math.abs(dy));\n h.move(dx, dy, h.directions()[dir] ? dir : null, dist / swipeThreshold(width()));\n };\n\n const detach = () => {\n view.removeEventListener(\"pointermove\", onMove);\n view.removeEventListener(\"pointerup\", onUp);\n view.removeEventListener(\"pointercancel\", onCancel);\n };\n\n const speedNow = (t: number) => {\n const recent = samples.filter((s) => t - s.t <= 100);\n const first = recent[0];\n const last = samples[samples.length - 1];\n if (!first || !last || last.t === first.t) return 0;\n return Math.hypot(last.x - first.x, last.y - first.y) / (last.t - first.t);\n };\n\n const onUp = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n detach();\n clearHold();\n const m = mode;\n id = null;\n mode = null;\n if (m === \"drag\") {\n const speed = speedNow(e.timeStamp);\n const dir = releaseDecision(dx, dy, speed, width(), h.directions());\n if (dir) h.commit(dir, speed);\n else h.release();\n } else if (m === \"press\" && downTarget) h.tap?.(downTarget);\n };\n\n const onCancel = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n detach();\n clearHold();\n const m = mode;\n id = null;\n mode = null;\n if (m === \"drag\") h.release();\n };\n\n const onContext = (e: Event) => {\n if (h.hold) e.preventDefault();\n };\n\n // iOS Safari: a vertical swipe while the page under the deck can scroll is taken by the page (the swipe\n // is cancelled, so \"up\" never answered there) unless the touch's own move is refused. Refused only while\n // this deck holds a press, and a vertical move only when the deck answers up or down (a two-way deck in a\n // chat lets the chat scroll).\n let touchFrom: { x: number; y: number } | null = null;\n const onTouchStart = (e: TouchEvent) => {\n const t = e.touches[0];\n touchFrom = t ? { x: t.clientX, y: t.clientY } : null;\n };\n const onTouchMove = (e: TouchEvent) => {\n if (id === null || !e.cancelable) return;\n const t = e.touches[0];\n const mx = t && touchFrom ? t.clientX - touchFrom.x : dx;\n const my = t && touchFrom ? t.clientY - touchFrom.y : dy;\n const dirs = h.directions();\n if (Math.abs(my) > Math.abs(mx) && !dirs.up && !dirs.down) return;\n e.preventDefault();\n };\n\n root.addEventListener(\"pointerdown\", onDown);\n root.addEventListener(\"contextmenu\", onContext);\n root.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n root.addEventListener(\"touchmove\", onTouchMove, { passive: false });\n return () => {\n detach();\n clearHold();\n root.removeEventListener(\"pointerdown\", onDown);\n root.removeEventListener(\"contextmenu\", onContext);\n root.removeEventListener(\"touchstart\", onTouchStart);\n root.removeEventListener(\"touchmove\", onTouchMove);\n };\n}\n","/** Every word the deck draws: short, because in-app text is layout. A host overrides any of them. */\nexport interface SwipeDeckLabels {\n readonly suggestion: string;\n readonly reason: string;\n readonly exit: string;\n readonly help: string;\n readonly undo: string;\n readonly copy: string;\n readonly copied: string;\n readonly copyFailed: string;\n readonly part: string;\n readonly keep: string;\n readonly forget: string;\n readonly forgotten: string;\n readonly category: string;\n readonly addCategory: string;\n readonly newCategory: string;\n readonly done: string;\n readonly holdHint: string;\n readonly clickHint: string;\n readonly answer: string;\n readonly unanswered: string;\n readonly next: string;\n readonly undone: string;\n readonly pick: string;\n readonly expand: string;\n readonly collapse: string;\n readonly score: string;\n /** The end's headline when nothing else leads it. */\n readonly allDone: string;\n /** \"{answered} of {total} answered\". */\n readonly answeredOf: string;\n /** The end's list of answers. */\n readonly yourAnswers: string;\n /** On an answered item at the end: take this answer back and answer it again. */\n readonly change: string;\n readonly rightAnswer: string;\n readonly right: string;\n readonly wrong: string;\n readonly showAll: string;\n /** The finish's filter chips, by name. */\n readonly filterAnswers: string;\n /** The empty screen (no items). */\n readonly emptyTitle: string;\n /** The corner that opens every answer so far, and that list's title. */\n readonly answered: string;\n /** Leave the answered list for the card in focus. */\n readonly backToCards: string;\n}\n\nexport const DEFAULT_SWIPE_DECK_LABELS: SwipeDeckLabels = {\n suggestion: \"Suggestion\",\n reason: \"Reason\",\n exit: \"Exit\",\n help: \"Show me how\",\n undo: \"Undo\",\n copy: \"Copy\",\n copied: \"Copied\",\n copyFailed: \"Copy failed\",\n part: \"This part\",\n keep: \"Keep as is\",\n forget: \"Forget this\",\n forgotten: \"Forgotten\",\n category: \"Category\",\n addCategory: \"Add a category\",\n newCategory: \"New category\",\n done: \"Done\",\n holdHint: \"Hold any word\",\n clickHint: \"Double-click any word\",\n answer: \"Answer\",\n unanswered: \"Not answered\",\n next: \"Next\",\n undone: \"Undone\",\n pick: \"Pick one\",\n expand: \"Full screen\",\n collapse: \"Exit full screen\",\n score: \"Score\",\n allDone: \"All done\",\n answeredOf: \"{answered} of {total} answered\",\n yourAnswers: \"Your answers\",\n answered: \"Answered\",\n backToCards: \"Back to cards\",\n change: \"Change\",\n rightAnswer: \"Right answer\",\n right: \"Right\",\n wrong: \"Wrong\",\n showAll: \"All\",\n filterAnswers: \"Filter answers\",\n emptyTitle: \"Nothing to answer\",\n};\n","\"use client\";\n\n/**\n * THE PART SCREEN — one part of an item (a span of its words), answered with the same four swipes.\n *\n * Select the span by dragging either handle, sweeping across words, or tapping a word to grow or\n * shrink it; tag it from the category rows (\"+\" adds a missing category and gives that category its\n * own answer with the same swipe); place it; or forget it. Down keeps it as is.\n */\nimport * as React from \"react\";\n\nimport { Input } from \"../input\";\nimport { EraserIcon, PlusIcon, XIcon } from \"../icons\";\nimport { CornerButton, EdgeButtons, setHot, Wash, type EdgeRefs, type WashHandle } from \"./chrome\";\nimport { attachSwipe } from \"./gesture\";\nimport {\n answerOf,\n directionOf,\n KEEP_ANSWER_ID,\n partSuggestion,\n tokenize,\n type CategoryConflict,\n type DeckDirection,\n type DeckItem,\n type DeckKey,\n type DeckCategoryRow,\n type DeckPart,\n type DeckState,\n} from \"./model\";\nimport { fitText, flyOut, follow, keepFitted, snapBack } from \"./visual\";\nimport type { SwipeDeckLabels } from \"./labels\";\n\nexport interface PartScreenProps {\n readonly item: DeckItem;\n readonly parts: readonly DeckPart[];\n readonly initial: { start: number; end: number };\n readonly keyMap: DeckKey;\n /** The deck's key: what a category's answer means (flows down to parts). */\n readonly deckKey: DeckKey;\n readonly state: DeckState;\n readonly categories: readonly string[];\n /** Labelled chip rows (\"Who\", \"Cares about\"); each has its own \"+\". Absent: one row of every category. */\n readonly rows?: readonly DeckCategoryRow[] | undefined;\n readonly allowNewCategories: boolean;\n readonly conflict: CategoryConflict | undefined;\n readonly labels: SwipeDeckLabels;\n readonly onClose: () => void;\n readonly onPlace: (part: DeckPart) => void;\n readonly onForget: (span: { start: number; end: number }) => void;\n readonly onCategoryAnswer: (name: string, answer: string | null, row?: string) => void;\n readonly announce: (text: string) => void;\n}\n\nfunction overlapping(parts: readonly DeckPart[], s: number, e: number): DeckPart[] {\n return parts.filter((p) => !(p.end < s || p.start > e));\n}\n\nexport function PartScreen(props: PartScreenProps) {\n const { item, parts, keyMap, deckKey, state, labels, conflict } = props;\n const tokens = React.useMemo(() => tokenize(item.text), [item.text]);\n const exactAt = (s: number, e: number) => parts.find((p) => p.start === s && p.end === e) ?? null;\n const startPart = parts.find((p) => props.initial.start >= p.start && props.initial.start <= p.end) ?? null;\n const [sel, setSel] = React.useState(() => (startPart ? { s: startPart.start, e: startPart.end } : { s: props.initial.start, e: props.initial.end }));\n const [tagged, setTagged] = React.useState<readonly string[]>(() => startPart?.categories ?? []);\n /** The row whose \"+\" is open (\"\" when the deck has no rows), or null. */\n const [adding, setAdding] = React.useState<string | null>(null);\n const [draft, setDraft] = React.useState(\"\");\n /** Giving a just-added category its own answer: the phrase area shows the category instead. */\n const [categoryMode, setCategoryMode] = React.useState<string | null>(null);\n const [categoryModeRow, setCategoryModeRow] = React.useState<string | undefined>(undefined);\n const [extra, setExtra] = React.useState<readonly { name: string; row: string }[]>([]);\n const guard = React.useRef(true);\n const busy = React.useRef(false);\n\n React.useEffect(() => {\n const t = setTimeout(() => {\n guard.current = false;\n }, 350);\n return () => clearTimeout(t);\n }, []);\n\n const exact = exactAt(sel.s, sel.e);\n const draftPart: DeckPart = { start: sel.s, end: sel.e, categories: tagged, suggested: exact?.suggested ?? null, answer: exact?.answer ?? null };\n const suggestedId = categoryMode ? null : partSuggestion(draftPart, state, deckKey, conflict);\n const suggestedDir = directionOf(keyMap, suggestedId);\n const phrase = categoryMode ?? tokens.slice(sel.s, sel.e + 1).join(\" \").replace(/^[“\"‘'(\\[]+|[”\"’'.,;:!?)\\]]+$/g, \"\");\n const nowAnswer = exact ? answerOf(deckKey, exact.answer ?? partSuggestion(exact, state, deckKey, conflict)) : null;\n const allCategories = React.useMemo(\n () => [...props.categories, ...extra.map((x) => x.name).filter((c) => !props.categories.includes(c))],\n [props.categories, extra],\n );\n // The chip rows: the deck's rows (anything they do not name joins the first), or one row of every category.\n const chipRows = React.useMemo(() => {\n const given = props.rows?.length ? props.rows : null;\n if (!given) return [{ id: \"\", label: null as string | null, categories: allCategories }];\n const named = new Set(given.flatMap((r) => r.categories));\n const loose = allCategories.filter((c) => !named.has(c) && !extra.some((x) => x.name === c));\n return given.map((r, i) => ({\n id: r.id,\n label: r.label as string | null,\n categories: [...r.categories, ...(i === 0 ? loose : []), ...extra.filter((x) => x.row === r.id && !r.categories.includes(x.name)).map((x) => x.name)],\n }));\n }, [props.rows, allCategories, extra]);\n\n // ─── the swipe on the phrase ───────────────────────────────────────────\n const frameRef = React.useRef<HTMLDivElement>(null);\n const phraseRef = React.useRef<HTMLDivElement>(null);\n const edgeRefs = React.useRef<EdgeRefs>({});\n const wash = React.useRef<WashHandle>(null);\n\n const act = async (dir: DeckDirection, speed = 0) => {\n if (busy.current || guard.current) return;\n const answer = keyMap[dir];\n if (!answer) return;\n if (answer.id === KEEP_ANSWER_ID) {\n if (categoryMode) {\n setCategoryMode(null);\n return;\n }\n // Keep as is: the answer stays; a new span or a changed tag is still kept.\n const changed = !exact || exact.categories.join(\"\\u0000\") !== tagged.join(\"\\u0000\");\n if (changed && (exact || tagged.length)) props.onPlace(draftPart);\n props.onClose();\n return;\n }\n busy.current = true;\n wash.current?.show(answer, dir, 1);\n setHot(edgeRefs.current, dir);\n await flyOut(phraseRef.current, dir, speed);\n busy.current = false;\n if (categoryMode) {\n props.onCategoryAnswer(categoryMode, answer.id, categoryModeRow || undefined);\n props.announce(`${categoryMode}: ${answer.label}`);\n setCategoryMode(null);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n if (phraseRef.current) {\n phraseRef.current.style.transition = \"none\";\n phraseRef.current.style.transform = \"\";\n phraseRef.current.style.opacity = \"\";\n }\n return;\n }\n props.onPlace({ ...draftPart, answer: answer.id });\n props.announce(`${phrase}: ${answer.label}`);\n props.onClose();\n };\n const actRef = React.useRef(act);\n actRef.current = act;\n\n React.useEffect(() => {\n const root = frameRef.current;\n if (!root) return;\n return attachSwipe(root, {\n enabled: () => !busy.current && !guard.current,\n directions: () => keyMap,\n move: (dx, dy, dir, amount) => {\n const answer = dir ? keyMap[dir] : undefined;\n follow(phraseRef.current, dx, dy, dir && answer ? amount : 0);\n if (dir && answer) {\n wash.current?.show(answer, dir, amount);\n setHot(edgeRefs.current, amount >= 1 ? dir : null);\n } else {\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n }\n },\n release: () => {\n snapBack(phraseRef.current);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n },\n commit: (dir, speed) => void actRef.current(dir, speed),\n ignoreSelector: \"button, a, input, textarea, [data-sd-noswipe]\",\n });\n }, [keyMap]);\n\n // ─── selecting the span ────────────────────────────────────────────────\n const sentRef = React.useRef<HTMLDivElement>(null);\n const handleS = React.useRef<HTMLSpanElement>(null);\n const handleE = React.useRef<HTMLSpanElement>(null);\n const sweep = React.useRef<{ id: number; mode: \"s\" | \"e\" | \"sweep\"; anchor: number | null; moved: boolean } | null>(null);\n\n React.useLayoutEffect(() => {\n const box = sentRef.current;\n if (!box) return;\n const a = box.querySelector<HTMLElement>(`[data-sd-w=\"${sel.s}\"]`);\n const b = box.querySelector<HTMLElement>(`[data-sd-w=\"${sel.e}\"]`);\n const hs = handleS.current;\n const he = handleE.current;\n if (!a || !b || !hs || !he) return;\n const r = box.getBoundingClientRect();\n const ra = a.getBoundingClientRect();\n const rb = b.getBoundingClientRect();\n const st = box.scrollTop;\n hs.style.left = `${ra.left - r.left}px`;\n hs.style.top = `${ra.top - r.top + st - 12}px`;\n hs.style.height = `${ra.height + 22}px`;\n he.style.left = `${rb.right - r.left}px`;\n he.style.top = `${rb.top - r.top + st - 10}px`;\n he.style.height = `${rb.height + 22}px`;\n });\n\n const wordAt = (x: number, y: number): number | null => {\n const doc = sentRef.current?.ownerDocument;\n const el = doc?.elementFromPoint(x, y);\n const t = el?.closest(\"[data-sd-w], [data-sd-sp]\");\n if (!t || !sentRef.current?.contains(t)) return null;\n const v = t.getAttribute(\"data-sd-w\") ?? t.getAttribute(\"data-sd-sp\");\n return v === null ? null : Number(v);\n };\n\n const tapWord = (i: number) =>\n setSel(({ s, e }) => {\n if (i < s) return { s: i, e };\n if (i > e) return { s, e: i };\n if (s === e) return { s, e };\n if (i === s) return { s: s + 1, e };\n if (i === e) return { s, e: e - 1 };\n return { s: i, e: i };\n });\n\n const onSentDown = (ev: React.PointerEvent) => {\n if (guard.current || categoryMode) return;\n const target = ev.target instanceof Element ? ev.target : null;\n const handle = target?.closest(\"[data-sd-handle]\");\n const word = target?.closest(\"[data-sd-w]\");\n if (!handle && !word) return;\n ev.preventDefault();\n sweep.current = {\n id: ev.pointerId,\n mode: handle ? (handle.getAttribute(\"data-sd-handle\") === \"s\" ? \"s\" : \"e\") : \"sweep\",\n anchor: word ? Number(word.getAttribute(\"data-sd-w\")) : null,\n moved: false,\n };\n const view = sentRef.current?.ownerDocument.defaultView ?? window;\n const move = (e: PointerEvent) => {\n const sw = sweep.current;\n if (!sw || e.pointerId !== sw.id) return;\n const k = wordAt(e.clientX, e.clientY);\n if (k === null) return;\n if (sw.mode === \"s\") setSel(({ e: end }) => ({ s: Math.min(k, end), e: end }));\n else if (sw.mode === \"e\") setSel(({ s }) => ({ s, e: Math.max(k, s) }));\n else if (sw.anchor !== null && (k !== sw.anchor || sw.moved)) {\n sw.moved = true;\n const anchor = sw.anchor;\n setSel({ s: Math.min(k, anchor), e: Math.max(k, anchor) });\n }\n };\n const up = (e: PointerEvent) => {\n const sw = sweep.current;\n if (!sw || e.pointerId !== sw.id) return;\n view.removeEventListener(\"pointermove\", move);\n view.removeEventListener(\"pointerup\", up);\n view.removeEventListener(\"pointercancel\", up);\n if (sw.mode === \"sweep\" && !sw.moved && sw.anchor !== null) tapWord(sw.anchor);\n sweep.current = null;\n };\n view.addEventListener(\"pointermove\", move);\n view.addEventListener(\"pointerup\", up);\n view.addEventListener(\"pointercancel\", up);\n };\n\n // On open, the chosen words are in view (a late word in a long line sits below the capped box) and hold\n // the focus, so the keyboard can grow or shrink them at once.\n React.useEffect(() => {\n const word = sentRef.current?.querySelector<HTMLElement>(`[data-sd-w=\"${sel.s}\"]`);\n word?.scrollIntoView?.({ block: \"nearest\" });\n word?.focus({ preventScroll: true });\n // Open only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // When the span moves onto an existing part, its tags come with it.\n const lastSpan = React.useRef(`${sel.s}:${sel.e}`);\n React.useEffect(() => {\n const k = `${sel.s}:${sel.e}`;\n if (k === lastSpan.current) return;\n lastSpan.current = k;\n const hit = parts.find((p) => p.start === sel.s && p.end === sel.e);\n if (hit) setTagged(hit.categories);\n }, [sel, parts]);\n\n // ─── fit the phrase ────────────────────────────────────────────────────\n const stageRef = React.useRef<HTMLDivElement>(null);\n const pinRef = React.useRef<HTMLDivElement>(null);\n const textRef = React.useRef<HTMLParagraphElement>(null);\n React.useLayoutEffect(() => {\n const box = stageRef.current;\n if (!box || !pinRef.current || !textRef.current) return;\n return keepFitted(box, () => {\n if (pinRef.current && textRef.current) fitText(box, pinRef.current, textRef.current, 22, (box.ownerDocument.defaultView?.innerWidth ?? 0) >= 1024 ? 120 : 84);\n });\n }, [phrase, nowAnswer?.id, categoryMode]);\n\n const addCategory = () => {\n const name = draft.trim();\n const row = adding ?? \"\";\n setAdding(null);\n setDraft(\"\");\n if (!name) return;\n if (!allCategories.includes(name)) setExtra((x) => [...x, { name, row }]);\n setTagged((t) => (t.includes(name) ? t : [...t, name]));\n if (!state.categories[name]?.answer) {\n setCategoryMode(name);\n setCategoryModeRow(row);\n }\n };\n\n // Escape closes (keeping as is); the arrows answer.\n React.useEffect(() => {\n const view = frameRef.current?.ownerDocument.defaultView ?? window;\n const onKey = (e: KeyboardEvent) => {\n const t = e.target instanceof Element ? e.target : null;\n if (t?.closest(\"input, textarea, [contenteditable='true']\")) return;\n if (e.altKey || e.ctrlKey || e.metaKey) return;\n const dir = ({ ArrowRight: \"right\", ArrowLeft: \"left\", ArrowUp: \"up\", ArrowDown: \"down\" } as const)[e.key as \"ArrowRight\"];\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopImmediatePropagation();\n if (categoryMode) setCategoryMode(null);\n else props.onClose();\n } else if (dir) {\n e.preventDefault();\n e.stopImmediatePropagation();\n // A held arrow places the part once.\n if (!e.repeat) void actRef.current(dir);\n }\n };\n view.addEventListener(\"keydown\", onKey, true);\n return () => view.removeEventListener(\"keydown\", onKey, true);\n }, [categoryMode, props]);\n\n // The first tagged chip is in view when the screen opens or the tags move.\n const chipsRef = React.useRef<HTMLDivElement>(null);\n const firstTag = tagged[0];\n React.useEffect(() => {\n const on = chipsRef.current?.querySelector<HTMLElement>('[aria-pressed=\"true\"]');\n on?.scrollIntoView?.({ block: \"nearest\", inline: \"center\" });\n }, [firstTag]);\n\n const canForget = !categoryMode && overlapping(parts, sel.s, sel.e).length > 0;\n\n return (\n <div ref={frameRef} className=\"matrx-sd-frame matrx-sd-partscreen\" role=\"dialog\" aria-modal=\"true\" aria-label={labels.part}>\n <CornerButton corner=\"tl\" label={labels.keep} shortcut=\"Escape\" onClick={() => (categoryMode ? setCategoryMode(null) : props.onClose())}>\n <XIcon />\n </CornerButton>\n <div className=\"matrx-sd-partbody\">\n <div ref={sentRef} className=\"matrx-sd-sentence\" data-sd-noswipe=\"\" data-dim={categoryMode ? \"\" : undefined} onPointerDown={onSentDown}>\n {tokens.map((t, i) => (\n <React.Fragment key={i}>\n {i > 0 ? (\n <span className=\"matrx-sd-space\" data-sd-sp={i} data-sel={i > sel.s && i <= sel.e ? \"\" : undefined}>\n {\" \"}\n </span>\n ) : null}\n <span\n className=\"matrx-sd-word\"\n tabIndex={0}\n role=\"button\"\n aria-pressed={i >= sel.s && i <= sel.e}\n onKeyDown={(e) => {\n // The keyboard's way to grow or shrink the words: Enter or Space on a word, as a tap does.\n if ((e.key === \"Enter\" || e.key === \" \") && !e.repeat && !categoryMode) {\n e.preventDefault();\n tapWord(i);\n }\n }}\n data-sd-w={i}\n data-sel={i >= sel.s && i <= sel.e ? \"\" : undefined}\n data-first={i === sel.s ? \"\" : undefined}\n data-last={i === sel.e ? \"\" : undefined}\n >\n {t}\n </span>\n </React.Fragment>\n ))}\n <span ref={handleS} className=\"matrx-sd-handle\" data-sd-handle=\"s\" aria-hidden=\"true\" />\n <span ref={handleE} className=\"matrx-sd-handle\" data-sd-handle=\"e\" aria-hidden=\"true\" />\n </div>\n <div ref={stageRef} className=\"matrx-sd-phrase-stage\">\n <div ref={phraseRef} className=\"matrx-sd-phrase\">\n <div ref={pinRef}>\n {categoryMode ? <div className=\"matrx-sd-kicker\">{labels.category}</div> : null}\n <p ref={textRef} className=\"matrx-sd-phrase-text\" data-quoted={categoryMode ? undefined : \"\"}>\n {phrase}\n </p>\n {nowAnswer && !categoryMode ? (\n <div className=\"matrx-sd-now\" data-tone={nowAnswer.tone}>\n <i />\n <span>{[nowAnswer.label, ...(exact?.categories ?? [])].join(\" · \")}</span>\n </div>\n ) : null}\n </div>\n </div>\n </div>\n <div ref={chipsRef} className=\"matrx-sd-chip-rows\" data-sd-noswipe=\"\">\n {chipRows.map((row) => (\n <div key={row.id || \"all\"} className=\"matrx-sd-chips\" role=\"group\" aria-label={row.label ?? labels.category}>\n {row.label ? <span className=\"matrx-sd-chip-row-label\">{row.label}</span> : null}\n {row.categories.map((c) => {\n const on = tagged.includes(c);\n const ca = answerOf(deckKey, state.categories[c]?.answer);\n return (\n // ui-exception: category chips are the part screen's own toggle row\n <button\n key={c}\n type=\"button\"\n className=\"matrx-sd-chip\"\n aria-pressed={on}\n data-tone={ca?.tone}\n disabled={!!categoryMode}\n onClick={() => setTagged((t) => (on ? t.filter((x) => x !== c) : [...t, c]))}\n >\n {ca ? <i aria-hidden=\"true\" /> : null}\n {c}\n </button>\n );\n })}\n {props.allowNewCategories && !categoryMode ? (\n adding === row.id ? (\n <Input\n className=\"matrx-sd-chip-input\"\n autoFocus\n aria-label={labels.newCategory}\n enterKeyHint=\"done\"\n autoComplete=\"off\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={addCategory}\n onKeyDown={(e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") {\n e.preventDefault();\n addCategory();\n } else if (e.key === \"Escape\") {\n setAdding(null);\n setDraft(\"\");\n }\n }}\n />\n ) : (\n // ui-exception: the chip row's own add target\n <button\n type=\"button\"\n className=\"matrx-sd-chip\"\n data-add=\"\"\n aria-label={row.label ? `${labels.addCategory}: ${row.label}` : labels.addCategory}\n title={labels.addCategory}\n onClick={() => setAdding(row.id)}\n >\n <PlusIcon />\n </button>\n )\n ) : null}\n </div>\n ))}\n </div>\n </div>\n <EdgeButtons keyMap={keyMap} suggested={suggestedDir} refs={edgeRefs} onAnswer={(d) => void act(d)} suggestionLabel={labels.suggestion} />\n {canForget ? (\n <CornerButton\n corner=\"br\"\n label={labels.forget}\n onClick={() => {\n if (guard.current) return;\n props.onForget({ start: sel.s, end: sel.e });\n props.onClose();\n }}\n >\n <EraserIcon />\n </CornerButton>\n ) : null}\n <Wash ref={wash} />\n </div>\n );\n}\n","\"use client\";\n\n/**\n * ExpandableSwipeDeck — the deck as a box in the flow (a chat message), fully usable where it is\n * (swipe, keys while focused, buttons, undo), with a corner that opens the SAME deck full screen.\n * Both views share one controller, so answers AND the undo history carry across; leaving full\n * screen (the corner, or Escape) returns to the box exactly where the person is.\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { useDeckController } from \"./controller\";\nimport { SwipeDeck, type SwipeDeckProps } from \"./SwipeDeck\";\n\nexport type ExpandableSwipeDeckProps = Omit<SwipeDeckProps, \"layout\" | \"onExpand\" | \"controller\" | \"onExit\" | \"exitKind\"> & {\n /** Full screen from the start (a host that opened the deck from elsewhere). */\n readonly defaultExpanded?: boolean;\n /** Told when the person opens or leaves full screen (a host may prefer its own canvas: return true to take it over). */\n readonly onExpandChange?: (expanded: boolean) => boolean | void;\n};\n\nexport function ExpandableSwipeDeck({ defaultExpanded = false, onExpandChange, ...props }: ExpandableSwipeDeckProps) {\n const controller = useDeckController({ items: props.items, binding: props.binding, initialState: props.initialState, onChange: props.onChange });\n const [expanded, setExpanded] = React.useState(defaultExpanded);\n const boxRef = React.useRef<HTMLDivElement>(null);\n const open = () => {\n if (onExpandChange?.(true) === true) return;\n setExpanded(true);\n };\n const close = () => {\n onExpandChange?.(false);\n setExpanded(false);\n // Back in the chat, the box holds the keys again.\n requestAnimationFrame(() => boxRef.current?.querySelector<HTMLElement>(\".matrx-sd\")?.focus({ preventScroll: true }));\n };\n const doc = typeof document === \"undefined\" ? null : document;\n return (\n <div ref={boxRef} className=\"matrx-sd-inline-host\">\n {expanded ? (\n // The box keeps its height while the deck is full screen, so the chat never jumps.\n <div className=\"matrx-sd\" data-layout=\"inline\" aria-hidden=\"true\" />\n ) : (\n <SwipeDeck {...props} layout=\"inline\" controller={controller} onExpand={open} />\n )}\n {expanded && doc\n ? createPortal(<SwipeDeck {...props} layout=\"fullscreen\" controller={controller} onExit={close} exitKind=\"collapse\" tourKey={null} />, doc.body)\n : null}\n </div>\n );\n}\n","/**\n * THE ONE READER of a `swipe_deck` kind value (what an agent writes) into the deck's own terms.\n *\n * Only `items[].text` is required; every other field is optional and nothing is invented for what is\n * absent. Directions are the agent's words: `suggested: \"right\"`, `answers: { up: null }`, a mark's\n * `lean: \"left\"`. An item's `choices` (2 to 8) become that item's own answers: the first four placed\n * clockwise from the top (2: right, left; 3: up, right, left; 4: up, right, down, left), any more as\n * buttons on the card; `correct` names a choice by its words (or a direction). Server declaration: aidream `aidream/kinds/swipe_deck.py`.\n */\nimport { DEFAULT_DECK_KEY, DECK_DIRECTIONS, askedItems, conditionProblems, mergeKey, readDeckCondition, type DeckAnswer, type DeckDirection, type DeckItem, type DeckKey, type DeckKeyOverride, type DeckTone } from \"./model\";\n\nexport interface SwipeDeckKindDeck {\n readonly title: string | null;\n readonly items: DeckItem[];\n /** The deck's key over the default; undefined when the value names none. */\n readonly answers: DeckKeyOverride | undefined;\n readonly pickOne: boolean;\n readonly categories: string[];\n /** Every item carries its own choices: the deck is a quiz-like set of questions. */\n readonly everyItemHasChoices: boolean;\n /** What the agent wrote that could not be honored (a right answer naming no choice, extra choices). Never silent: the host reports them. */\n readonly problems: string[];\n}\n\nconst TONES: readonly DeckTone[] = [\"success\", \"info\", \"destructive\", \"warning\", \"primary\", \"neutral\"];\nconst CHOICE_PLACES: Record<number, readonly DeckDirection[]> = {\n 2: [\"right\", \"left\"],\n 3: [\"up\", \"right\", \"left\"],\n 4: [\"up\", \"right\", \"down\", \"left\"],\n};\n/** Choice tones read as distinct options, never as right/wrong (no green, no red). */\nconst CHOICE_TONES: Record<DeckDirection, DeckTone> = { up: \"primary\", right: \"info\", down: \"warning\", left: \"neutral\" };\n\n/** A card holds four answers on its edges and four more as buttons. */\nconst MAX_CHOICES = 8;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst text = (v: unknown): string => (typeof v === \"string\" ? v.trim() : typeof v === \"number\" ? String(v) : \"\");\nconst isDirection = (v: unknown): v is DeckDirection => typeof v === \"string\" && (DECK_DIRECTIONS as readonly string[]).includes(v);\n\nfunction answerOverride(raw: unknown): DeckKeyOverride | undefined {\n if (!isRecord(raw)) return undefined;\n const out: { -readonly [D in DeckDirection]?: DeckAnswer | null } = {};\n let any = false;\n for (const dir of DECK_DIRECTIONS) {\n if (!(dir in raw)) continue;\n const v = raw[dir];\n const base = DEFAULT_DECK_KEY[dir];\n if (v === null || v === false) {\n out[dir] = null;\n any = true;\n continue;\n }\n const label = isRecord(v) ? text(v.label) : text(v);\n if (!label || !base) continue;\n const tone = isRecord(v) && TONES.includes(v.tone as DeckTone) ? (v.tone as DeckTone) : base.tone;\n out[dir] = { ...base, label, tone };\n any = true;\n }\n return any ? out : undefined;\n}\n\nfunction norm(s: string): string {\n return s.trim().toLowerCase().replace(/\\s+/g, \" \");\n}\n\n/** Read a swipe_deck value; null when it holds no readable item (the host shows its stand-in). */\nexport function swipeDeckFromKindValue(value: unknown): SwipeDeckKindDeck | null {\n if (!isRecord(value)) return null;\n const answers = answerOverride(value.answers);\n const deckKey: DeckKey = mergeKey(DEFAULT_DECK_KEY, answers);\n const rawItems = Array.isArray(value.items) ? value.items : [];\n const items: DeckItem[] = [];\n const problems: string[] = [];\n const seenIds = new Set<string>();\n // Each item's own answer reader and its raw `show_if`, resolved once every item is known.\n const readers = new Map<string, (w: unknown) => string | undefined>();\n const rawShow = new Map<string, unknown>();\n const positions: string[] = [];\n let withChoices = 0;\n rawItems.forEach((raw, index) => {\n const r = isRecord(raw) ? raw : typeof raw === \"string\" ? { text: raw } : null;\n if (!r) return;\n const body = text(r.text) || text(r.statement) || text(r.question) || text(r.title);\n if (!body) return;\n const allChoices = (Array.isArray(r.choices) ? r.choices : Array.isArray(r.options) ? r.options : [])\n .map((c) => (isRecord(c) ? text(c.label) || text(c.text) : text(c)))\n .filter(Boolean);\n if (allChoices.length > MAX_CHOICES) problems.push(`Item ${index + 1} has ${allChoices.length} choices; a card holds ${MAX_CHOICES}, so the rest were left off.`);\n if (allChoices.length === 1) problems.push(`Item ${index + 1} has a single choice; the deck's own answers were used.`);\n const choiceWords = allChoices.slice(0, MAX_CHOICES);\n const places = choiceWords.length >= 2 ? CHOICE_PLACES[Math.min(4, choiceWords.length)] : undefined;\n let own: DeckKeyOverride | undefined;\n let more: DeckAnswer[] = [];\n let key = deckKey;\n if (places) {\n withChoices++;\n const o: { -readonly [D in DeckDirection]?: DeckAnswer | null } = { up: null, right: null, down: null, left: null };\n places.forEach((dir, i) => {\n o[dir] = { id: `choice_${i + 1}`, label: choiceWords[i] ?? \"\", tone: CHOICE_TONES[dir] };\n });\n own = o;\n key = mergeKey(deckKey, o);\n more = choiceWords.slice(4).map((label, i) => ({ id: `choice_${i + 5}`, label, tone: \"neutral\" as const }));\n }\n // An answer named by its words first (a choice may itself read \"left\"), then — for an item with\n // choices — by letter (\"B\", \"b)\") or number (1-based, or a 0-based number the agent counted from),\n // then by direction.\n const byWords = (w: unknown): string | undefined => {\n const t = text(w);\n if (!t) return undefined;\n for (const a of [...DECK_DIRECTIONS.map((d) => key[d]), ...more]) {\n if (a && (norm(a.label) === norm(t) || a.id === t)) return a.id;\n }\n if (places) {\n const stripped = norm(t.replace(/^\\(?[a-h1-8][).:]\\s+/i, \"\"));\n const byLabel = choiceWords.findIndex((c) => norm(c) === stripped);\n if (byLabel >= 0) return `choice_${byLabel + 1}`;\n const letter = /^\\(?([a-h])[).:]?$/i.exec(t);\n if (letter?.[1]) {\n const i = letter[1].toLowerCase().charCodeAt(0) - 97;\n if (i < choiceWords.length) return `choice_${i + 1}`;\n }\n const numeral = /^\\(?([1-8])[).:]?$/.exec(t);\n if (numeral?.[1] && Number(numeral[1]) <= choiceWords.length) return `choice_${numeral[1]}`;\n if (typeof w === \"number\" && Number.isInteger(w)) {\n if (w >= 1 && w <= choiceWords.length) return `choice_${w}`;\n if (w === 0) return \"choice_1\";\n }\n }\n if (isDirection(t)) return key[t]?.id;\n return undefined;\n };\n const correct = Array.isArray(r.correct) ? r.correct.map(byWords).filter((x): x is string => !!x) : byWords(r.correct);\n const correctGiven = Array.isArray(r.correct) ? r.correct.length > 0 : r.correct !== undefined && r.correct !== null && text(r.correct) !== \"\";\n if (correctGiven && (correct === undefined || (Array.isArray(correct) && !correct.length)))\n problems.push(`Item ${index + 1}'s right answer \"${Array.isArray(r.correct) ? r.correct.map(text).join(\", \") : text(r.correct)}\" names none of its choices, so it is not graded.`);\n const details = (Array.isArray(r.details) ? r.details : Array.isArray(r.fields) ? r.fields : [])\n .filter(isRecord)\n .map((d) => ({ label: text(d.label), value: text(d.value) }))\n .filter((d) => d.label && d.value);\n const marks = (Array.isArray(r.marks) ? r.marks : [])\n .filter(isRecord)\n .map((m) => ({\n phrase: text(m.phrase),\n categories: Array.isArray(m.categories) ? m.categories.map(text).filter(Boolean) : [],\n suggested: isDirection(m.lean) ? (key[m.lean]?.id ?? null) : null,\n }))\n .filter((m) => m.phrase);\n const suggested = byWords(r.suggested);\n let id = text(r.id) || `item_${index + 1}`;\n if (seenIds.has(id)) {\n problems.push(`Two items share the id \"${id}\"; the second was given its own.`);\n id = `${id}_${index + 1}`;\n }\n seenIds.add(id);\n readers.set(id, byWords);\n positions[index] = id;\n const show = r.show_if ?? r.showIf;\n if (show !== undefined && show !== null) rawShow.set(id, show);\n const item: DeckItem = {\n id,\n text: body,\n ...(text(r.kicker) ? { kicker: text(r.kicker) } : {}),\n ...(text(r.tag) ? { tag: text(r.tag) } : {}),\n ...(suggested ? { suggested } : {}),\n ...(text(r.reason) ? { reason: text(r.reason) } : {}),\n ...(details.length ? { fields: details } : {}),\n ...(own ? { answers: own } : {}),\n ...(more.length ? { more } : {}),\n ...(correct !== undefined && (typeof correct === \"string\" || correct.length) ? { correct } : {}),\n ...(text(r.group) ? { group: text(r.group) } : {}),\n ...(marks.length ? { parts: marks } : {}),\n };\n items.push(item);\n });\n if (!items.length) return null;\n // Conditions name a card by its id, its position (1-based) or its exact words, and its answers by\n // their words (or a letter, a number, a direction), as `correct` does.\n const byText = new Map(items.map((i) => [norm(i.text), i.id]));\n const refOf = (v: unknown): string => {\n const t = text(v);\n if (readers.has(t)) return t;\n if (typeof v === \"number\" && Number.isInteger(v) && positions[v - 1]) return positions[v - 1] ?? t;\n return byText.get(norm(t)) ?? t;\n };\n const shaped = items.map((item) => {\n const raw = rawShow.get(item.id);\n const showIf = raw === undefined ? null : readDeckCondition(raw, { ref: refOf, answer: (id, w) => readers.get(id)?.(w) ?? null });\n if (raw !== undefined && !showIf) problems.push(`\"${item.text}\" has a show_if the deck cannot read, so it is always asked.`);\n return showIf ? { ...item, showIf } : item;\n });\n problems.push(...conditionProblems(shaped, { key: deckKey }));\n return {\n title: text(value.title) || null,\n items: shaped,\n answers,\n pickOne: value.pick_one === true,\n categories: Array.isArray(value.categories) ? value.categories.map(text).filter(Boolean) : [],\n everyItemHasChoices: withChoices === items.length,\n problems,\n };\n}\n\n/** The deck's results as rows (one per item), for \"Save to a table\". Column names are words. */\nexport function swipeDeckResultRows(\n deck: SwipeDeckKindDeck,\n answers: Readonly<Record<string, string>>,\n): Record<string, string>[] {\n const deckKey = mergeKey(DEFAULT_DECK_KEY, deck.answers);\n const graded = deck.items.some((i) => i.correct !== undefined);\n // Only the cards that were asked: a card skipped by its condition has no row (its kept answer does not apply).\n const asked = askedItems(deck.items, { answers, picks: {}, parts: {}, categories: {} });\n return deck.items.filter((item) => asked.get(item.id)).map((item) => {\n const key = mergeKey(deckKey, item.answers);\n const all = [...DECK_DIRECTIONS.map((d) => key[d]), ...(item.more ?? [])];\n const id = answers[item.id];\n const answer = id ? all.find((a) => a?.id === id) : undefined;\n const row: Record<string, string> = {};\n if (deck.items.some((i) => i.kicker)) row.Kind = item.kicker ?? \"\";\n row.Item = item.text;\n row.Answer = answer?.label ?? \"\";\n if (graded) {\n const correct = item.correct === undefined ? [] : typeof item.correct === \"string\" ? [item.correct] : item.correct;\n row[\"Right answer\"] = correct.map((c) => all.find((a) => a?.id === c)?.label ?? \"\").filter(Boolean).join(\", \");\n row.Right = !id || !correct.length ? \"\" : correct.includes(id) ? \"Yes\" : \"No\";\n }\n return row;\n });\n}\n","/**\n * THE DECK'S LOGIC AS A GRAPH — and back. Cards are nodes; each condition is an arrow from the earlier\n * card whose answer it reads to the card it opens, labelled by the answers that open it. Editing the\n * graph (draw an arrow, delete one, pick its answers, choose whether a card needs ANY or ALL of its\n * arrows) rebuilds each card's `showIf`; reading it back gives the same graph. Pure data: any graph\n * editor (the diagram canvas, a test) works through these two functions.\n *\n * A condition the graph cannot draw (a `not`, a nested group) is kept exactly as written and the card is\n * marked `custom`: the graph shows it and leaves it alone until a person replaces it there.\n */\nimport { conditionProblems, findAnswer, keyFor, moreFor, type DeckAnswer, type DeckCondition, type DeckItem, type DeckRules } from \"./model\";\n\nexport interface DeckLogicEdge {\n /** Stable while the graph is edited: `from→to`. */\n readonly id: string;\n /** The earlier card whose answer is read. */\n readonly from: string;\n /** The card it opens. */\n readonly to: string;\n /** Answer ids that open it (empty with `isNot` empty: any answer at all). */\n readonly is: readonly string[];\n /** Answer ids that keep it closed. */\n readonly isNot: readonly string[];\n}\n\nexport interface DeckLogicCard {\n readonly id: string;\n readonly text: string;\n readonly kicker?: string;\n /** Every answer the card can take, edges first. */\n readonly answers: readonly DeckAnswer[];\n /** With two or more arrows in: does the card need any of them, or all? */\n readonly match: \"any\" | \"all\";\n /** Its condition is one the graph cannot draw; kept as written. */\n readonly custom: boolean;\n}\n\nexport interface DeckLogicGraph {\n readonly cards: readonly DeckLogicCard[];\n readonly edges: readonly DeckLogicEdge[];\n}\n\nconst list = (v: string | readonly string[] | undefined): string[] => (v === undefined ? [] : typeof v === \"string\" ? [v] : [...v]);\n\ntype Leaf = Extract<DeckCondition, { item: string }>;\nconst isLeaf = (c: DeckCondition): c is Leaf => \"item\" in c;\n\n/** The leaves of a drawable condition and how they combine, or null when it cannot be drawn. */\nfunction drawable(cond: DeckCondition): { match: \"any\" | \"all\"; leaves: Leaf[] } | null {\n const plain = (l: Leaf) => l.answered !== false;\n if (isLeaf(cond)) return plain(cond) ? { match: \"any\", leaves: [cond] } : null;\n // An empty group (never / always) and two leaves on the same earlier card cannot be drawn as\n // arrows without changing what they mean: kept as written (`custom`).\n const group = (list: readonly DeckCondition[], match: \"any\" | \"all\") => {\n if (!list.length || !list.every((c) => isLeaf(c) && plain(c))) return null;\n const leaves = list as Leaf[];\n return new Set(leaves.map((l) => l.item)).size === leaves.length ? { match, leaves } : null;\n };\n if (\"any\" in cond) return group(cond.any, \"any\");\n if (\"all\" in cond) return group(cond.all, \"all\");\n return null;\n}\n\nfunction answersOf(rules: DeckRules, item: DeckItem): DeckAnswer[] {\n const key = keyFor(rules, item);\n const edges = ([\"right\", \"up\", \"left\", \"down\"] as const).map((d) => key[d]).filter((a): a is DeckAnswer => !!a);\n return [...edges, ...moreFor(rules, item)];\n}\n\n/** The graph of a deck's logic. */\nexport function deckLogicGraph(items: readonly DeckItem[], rules: DeckRules): DeckLogicGraph {\n const edges: DeckLogicEdge[] = [];\n const cards = items.map((item): DeckLogicCard => {\n const drawn = item.showIf ? drawable(item.showIf) : { match: \"any\" as const, leaves: [] };\n if (drawn) {\n for (const leaf of drawn.leaves) {\n const id = `${leaf.item}→${item.id}`;\n const at = edges.findIndex((e) => e.id === id);\n const edge = { id, from: leaf.item, to: item.id, is: list(leaf.is), isNot: list(leaf.isNot) };\n // Two leaves on the same card pair (rare, hand-written) merge into one arrow.\n if (at >= 0) {\n const had = edges[at]!;\n edges[at] = { ...had, is: [...new Set([...had.is, ...edge.is])], isNot: [...new Set([...had.isNot, ...edge.isNot])] };\n } else edges.push(edge);\n }\n }\n return {\n id: item.id,\n text: item.text,\n ...(item.kicker ? { kicker: item.kicker } : {}),\n answers: answersOf(rules, item),\n match: drawn?.match ?? \"any\",\n custom: !drawn,\n };\n });\n return { cards, edges };\n}\n\n/**\n * The deck with each card's `showIf` rebuilt from the graph. A card with no arrows in is always asked;\n * one arrow is that leaf; more combine by the card's `match`. A `custom` card keeps its own condition.\n */\nexport function applyDeckLogic(items: readonly DeckItem[], graph: DeckLogicGraph): DeckItem[] {\n const byCard = new Map(graph.cards.map((c) => [c.id, c]));\n return items.map((item) => {\n const card = byCard.get(item.id);\n if (card?.custom) return item;\n const leaves: Leaf[] = graph.edges\n .filter((e) => e.to === item.id)\n .map((e) => ({ item: e.from, ...(e.is.length ? { is: [...e.is] } : {}), ...(e.isNot.length ? { isNot: [...e.isNot] } : {}) }));\n const { showIf: _old, ...rest } = item;\n if (!leaves.length) return rest;\n const showIf: DeckCondition = leaves.length === 1 ? leaves[0]! : card?.match === \"all\" ? { all: leaves } : { any: leaves };\n return { ...rest, showIf };\n });\n}\n\n/** An arrow's words: the answers that open the card (\"Yes · Sort of\", \"not No\", \"answered\"). */\nexport function logicEdgeLabel(edge: DeckLogicEdge, items: readonly DeckItem[], rules: DeckRules): string {\n const from = items.find((i) => i.id === edge.from);\n const words = (ids: readonly string[]) => ids.map((id) => (from ? (findAnswer(rules, from, id)?.label ?? id) : id));\n const parts = [...words(edge.is), ...words(edge.isNot).map((w) => `not ${w}`)];\n return parts.length ? parts.join(\" · \") : \"answered\";\n}\n\n/** Whether an arrow may be drawn: only from an EARLIER card (no loops), never onto itself or twice. */\nexport function canConnect(items: readonly DeckItem[], graph: DeckLogicGraph, from: string, to: string): string | null {\n const a = items.findIndex((i) => i.id === from);\n const b = items.findIndex((i) => i.id === to);\n if (a < 0 || b < 0) return \"That card is not in the deck.\";\n if (a === b) return \"A card cannot depend on itself.\";\n if (a > b) return \"A card can only depend on a card before it.\";\n if (graph.edges.some((e) => e.from === from && e.to === to)) return \"Those two cards are already joined.\";\n if (graph.cards.find((c) => c.id === to)?.custom) return \"This card has a rule the graph cannot draw. Select it and press Clear rule first.\";\n return null;\n}\n\n/** A new arrow, opened by the earlier card's first answer (its right edge's, usually Yes). */\nexport function newLogicEdge(items: readonly DeckItem[], rules: DeckRules, from: string, to: string): DeckLogicEdge {\n const source = items.find((i) => i.id === from);\n const first = source ? answersOf(rules, source)[0] : undefined;\n return { id: `${from}→${to}`, from, to, is: first ? [first.id] : [], isNot: [] };\n}\n\n/** What is wrong with the logic as drawn, in words (the deck's own checks). */\nexport function logicProblems(items: readonly DeckItem[], rules: DeckRules, graph: DeckLogicGraph): string[] {\n return conditionProblems(applyDeckLogic(items, graph), rules);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,YAAYA,YAAW;AAEvB,SAAS,YAAY,uBAAuB;;;AChB5C,YAAY,WAAW;;;ACChB,IAAM,SAA2D;AAAA,EACtE,OAAO,CAAC,GAAG,CAAC;AAAA,EACZ,MAAM,CAAC,IAAI,CAAC;AAAA,EACZ,IAAI,CAAC,GAAG,EAAE;AAAA,EACV,MAAM,CAAC,GAAG,CAAC;AACb;AAGO,SAAS,KAAK,KAA4B,IAAkB;AACjE,MAAI;AACF,UAAM,aAAc,KAAmF;AACvG,QAAI,cAAc,CAAC,WAAW,cAAe;AAC7C,SAAK,UAAU,EAAE;AAAA,EACnB,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,uBAAgC;AAC9C,MAAI;AACF,WAAO,OAAO,eAAe,cAAc,WAAW,kCAAkC,EAAE;AAAA,EAC5F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,cAAuB;AACrC,MAAI;AACF,WAAO,OAAO,eAAe,cAAc,WAAW,oCAAoC,EAAE;AAAA,EAC9F,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,OAAO,IAAwB,IAAY,IAAY,SAAS,GAAS;AACvF,MAAI,CAAC,GAAI;AACT,KAAG,MAAM,aAAa;AACtB,KAAG,MAAM,YAAY,MAAM,KAAK,eAAe,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,QAAQ,CAAC,CAAC,SAAS;AACtG,KAAG,MAAM,UAAU,SAAS,IAAI,OAAO,IAAI,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AAC1E;AAEO,SAAS,SAAS,IAA8B;AACrD,MAAI,CAAC,GAAI;AACT,KAAG,MAAM,aAAa;AACtB,KAAG,MAAM,YAAY;AACrB,KAAG,MAAM,UAAU;AACrB;AAGO,SAAS,OAAO,IAAwB,KAAoB,QAAQ,GAAkB;AAC3F,MAAI,CAAC,MAAM,qBAAqB,EAAG,QAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9E,QAAM,CAAC,IAAI,EAAE,IAAI,OAAO,GAAG;AAC3B,QAAM,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,MAAM,QAAQ,EAAE,CAAC,CAAC;AACpE,KAAG,MAAM,aAAa,aAAa,EAAE,sCAAsC,EAAE;AAC7E,KAAG,MAAM,YAAY,eAAe,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,KAAK,EAAE;AACjF,KAAG,MAAM,UAAU;AACnB,SAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC7C;AAGO,SAAS,MAAM,IAAwB,MAAkC;AAC9E,MAAI,CAAC,MAAM,qBAAqB,KAAK,OAAO,GAAG,YAAY,WAAY;AACvE,MAAI,MAAM;AACR,UAAM,CAAC,IAAI,EAAE,IAAI,OAAO,IAAI;AAC5B,OAAG;AAAA,MACD;AAAA,QACE,EAAE,WAAW,eAAe,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,KAAK,EAAE,QAAQ,SAAS,IAAI;AAAA,QAC9F,EAAE,WAAW,QAAQ,SAAS,EAAE;AAAA,MAClC;AAAA,MACA,EAAE,UAAU,KAAK,QAAQ,2BAA2B;AAAA,IACtD;AAAA,EACF,OAAO;AACL,OAAG,QAAQ,CAAC,EAAE,WAAW,cAAc,SAAS,EAAE,GAAG,EAAE,WAAW,QAAQ,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,QAAQ,2BAA2B,CAAC;AAAA,EAChJ;AACF;AAGO,SAAS,MAAM,IAAwB,KAAsC;AAClF,MAAI,CAAC,MAAM,qBAAqB,KAAK,OAAO,GAAG,YAAY,WAAY,QAAO;AAC9E,QAAM,CAAC,IAAI,EAAE,IAAI,OAAO,GAAG;AAC3B,SAAO,GAAG;AAAA,IACR;AAAA,MACE,EAAE,WAAW,OAAO;AAAA,MACpB,EAAE,WAAW,eAAe,KAAK,EAAE,MAAM,KAAK,EAAE,gBAAgB,KAAK,GAAG,QAAQ,QAAQ,IAAI;AAAA,MAC5F,EAAE,WAAW,QAAQ,QAAQ,IAAI;AAAA,MACjC,EAAE,WAAW,eAAe,KAAK,EAAE,MAAM,KAAK,EAAE,SAAS,QAAQ,IAAI;AAAA,MACrE,EAAE,WAAW,OAAO;AAAA,IACtB;AAAA,IACA,EAAE,UAAU,MAAM,QAAQ,cAAc;AAAA,EAC1C;AACF;AAGO,SAAS,SAAS,IAAwB,OAA2B,QAAsB;AAChG,MAAI,CAAC,MAAM,CAAC,MAAO;AACnB,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACzC,KAAG,MAAM,UAAU,OAAO,KAAK,IAAI,MAAM,MAAM,OAAO,CAAC,CAAC;AACxD,QAAM,MAAM,UAAU,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC;AAClD,QAAM,MAAM,YAAY,SAAS,OAAO,OAAO,CAAC;AAClD;AAEO,SAAS,SAAS,IAAwB,OAAiC;AAChF,MAAI,GAAI,IAAG,MAAM,UAAU;AAC3B,MAAI,MAAO,OAAM,MAAM,UAAU;AACnC;AAMO,SAAS,QAAQ,KAAkB,OAAoBC,OAAmB,KAAa,KAAqB;AACjH,MAAI,KAAK;AACT,MAAI,KAAK,KAAK,IAAI,KAAK,GAAG;AAC1B,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,OAAO,KAAK,MAAM;AACxB,IAAAA,MAAK,MAAM,WAAW,GAAG,GAAG;AAC5B,UAAM,KAAK,MAAM,gBAAgB,IAAI,gBAAgBA,MAAK,eAAeA,MAAK,cAAc;AAC5F,QAAI,IAAI;AACN,aAAO;AACP,WAAK;AAAA,IACP,MAAO,MAAK;AAAA,EACd;AACA,QAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,EAAAA,MAAK,MAAM,WAAW,GAAG,IAAI;AAE7B,MAAI,MAAM,eAAe,IAAI,eAAe,EAAG,KAAI,aAAa,oBAAoB,EAAE;AAAA,MACjF,KAAI,gBAAgB,kBAAkB;AAC3C,SAAO;AACT;AAGO,SAAS,aAAa,KAAkB,OAA0B;AACvE,MAAI,MAAM,eAAe,IAAI,eAAe,EAAG,KAAI,aAAa,oBAAoB,EAAE;AAAA,MACjF,KAAI,gBAAgB,kBAAkB;AAC7C;AAGO,SAAS,WAAW,KAAkB,KAA6B;AACxE,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI,cAAc,OAAO,MAAM,KAAK,MAAM,SAAS,IAAI,CAAC,EAAE,MAAM,MAAM,MAAS;AAC/E,MAAI,OAAO,mBAAmB,YAAa,QAAO,MAAM,MAAM,QAAQ;AACtE,QAAM,KAAK,IAAI,eAAe,GAAG;AACjC,KAAG,QAAQ,GAAG;AACd,SAAO,MAAM;AACX,YAAQ;AACR,OAAG,WAAW;AAAA,EAChB;AACF;AAMO,SAAS,QAAQ,KAA0B;AAChD,QAAM,KAAK,IAAI,cAAc,aAAa,cAAc,IAAI;AAC5D,MAAI,KAAK,IAAK,QAAO,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,cAAc,GAAG,CAAC;AACtE,QAAM,OAAO,MAAM;AACnB,SAAO,KAAK,IAAI,OAAO,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,cAAc,GAAG,IAAI,GAAG,CAAC;AAC3F;;;ADpJ0B,wBAmHpB,YAnHoB;AAX1B,IAAM,SAAyF;AAAA,EAC7F,OAAO;AAAA,EACP,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,MAAM;AACR;AAEO,IAAM,YAA2C,EAAE,OAAO,UAAK,IAAI,UAAK,MAAM,UAAK,MAAM,SAAI;AAG7F,SAAS,YAAY,EAAE,QAAQ,IAAI,GAAsD;AAC9F,MAAI,OAAO,KAAM,QAAO,gCAAG,iBAAO,MAAK;AACvC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,OAAO,GAAG;AACxB,SAAO,oBAAC,SAAM;AAChB;AAIO,SAAS,OAAO,MAAgB,KAAiC;AACtE,aAAW,KAAK,OAAO,KAAK,IAAI,GAAsB;AACpD,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,CAAC,GAAI;AACT,QAAI,MAAM,IAAK,IAAG,aAAa,YAAY,EAAE;AAAA,QACxC,IAAG,gBAAgB,UAAU;AAAA,EACpC;AACF;AAYO,SAAS,YAAY,EAAE,QAAQ,WAAW,MAAM,UAAU,iBAAiB,SAAS,GAAqB;AAC9G,SACE,gCACI,WAAC,MAAM,QAAQ,SAAS,MAAM,EAAY,IAAI,CAAC,QAAQ;AACvD,UAAM,SAAS,OAAO,GAAG;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,cAAc,QAAQ;AAC5B;AAAA;AAAA,MAEE;AAAA,QAAC;AAAA;AAAA,UAEC,KAAK,CAAC,OAAO;AACX,iBAAK,QAAQ,GAAG,IAAI;AAAA,UACtB;AAAA,UACA,MAAK;AAAA,UACL,WAAU;AAAA,UACV,YAAU;AAAA,UACV,aAAW,OAAO;AAAA,UAClB,kBAAgB,cAAc,KAAK;AAAA,UACnC,cAAY,cAAc,GAAG,OAAO,KAAK,KAAK,eAAe,MAAM,OAAO;AAAA,UAC1E,qBAAmB,EAAE,OAAO,cAAc,MAAM,aAAa,IAAI,WAAW,MAAM,YAAY,EAAE,GAAG;AAAA,UACnG,OAAO,GAAG,OAAO,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,UACzC;AAAA,UACA,SAAS,MAAM,SAAS,GAAG;AAAA,UAE3B,8BAAC,eAAY,QAAgB,KAAU;AAAA;AAAA,QAflC;AAAA,MAgBP;AAAA;AAAA,EAEJ,CAAC,GACH;AAEJ;AAYO,SAAS,aAAa,EAAE,QAAQ,OAAO,UAAU,SAAS,UAAU,SAAS,SAAS,GAAsB;AACjH;AAAA;AAAA,IAEE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,eAAa;AAAA,QACb,cAAY;AAAA,QACZ,OAAO,WAAW,GAAG,KAAK,KAAK,QAAQ,MAAM;AAAA,QAC7C,qBAAmB;AAAA,QACnB;AAAA,QACA,gBAAc;AAAA,QACd;AAAA,QAEC;AAAA;AAAA,IACH;AAAA;AAEJ;AAQO,IAAM,OAAa,iBAAuB,SAASC,MAAK,QAAQ,KAAK;AAC1E,QAAM,KAAW,aAAuB,IAAI;AAC5C,QAAM,QAAc,aAAuB,IAAI;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAmE,IAAI;AACvG,EAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,MACL,KAAK,QAAQ,KAAK,QAAQ;AACxB,iBAAS,CAAC,QAAS,OAAO,IAAI,OAAO,OAAO,OAAO,MAAM,IAAI,QAAQ,MAAM,MAAM,EAAE,QAAQ,IAAI,CAAE;AACjG,iBAAS,GAAG,SAAS,MAAM,SAAS,MAAM;AAAA,MAC5C;AAAA,MACA,OAAO;AACL,iBAAS,GAAG,SAAS,MAAM,OAAO;AAAA,MACpC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AACA,SACE,qBAAC,SAAI,WAAU,iBAAgB,eAAY,QAAO,aAAW,OAAO,OAAO,MACzE;AAAA,wBAAC,SAAI,KAAK,IAAI,WAAU,oBAAmB;AAAA,IAC3C,qBAAC,SAAI,KAAK,OAAO,WAAU,uBACxB;AAAA,cAAQ,oBAAC,eAAY,QAAQ,MAAM,QAAQ,KAAK,MAAM,KAAK,IAAK;AAAA,MACjE,oBAAC,OAAG,iBAAO,OAAO,OAAM;AAAA,OAC1B;AAAA,KACF;AAEJ,CAAC;;;AEvID,YAAYC,YAAW;;;ACMhB,IAAM,kBAA4C,CAAC,SAAS,MAAM,QAAQ,MAAM;AAkChF,IAAM,mBAA4B;AAAA,EACvC,OAAO,EAAE,IAAI,OAAO,OAAO,QAAQ,MAAM,WAAW,MAAM,EAAE;AAAA,EAC5D,IAAI,EAAE,IAAI,WAAW,OAAO,WAAW,MAAM,QAAQ,MAAM,EAAE;AAAA,EAC7D,MAAM,EAAE,IAAI,MAAM,OAAO,MAAM,MAAM,eAAe,MAAM,EAAE;AAAA,EAC5D,MAAM,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,WAAW,MAAM,EAAE;AACtE;AAGO,IAAM,iBAAiB;AACvB,IAAM,sBAAkC,EAAE,IAAI,gBAAgB,OAAO,cAAc,MAAM,UAAU;AAE1G,IAAM,iBAAgD,EAAE,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE;AAEnF,SAAS,SAAS,MAAe,UAA4C;AAClF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAAe,EAAE,GAAG,KAAK;AAC/B,aAAW,OAAO,iBAAiB;AACjC,QAAI,EAAE,OAAO,UAAW;AACxB,UAAM,OAAO,SAAS,GAAG;AACzB,QAAI,KAAM,KAAI,GAAG,IAAI;AAAA,QAChB,QAAO,IAAI,GAAG;AAAA,EACrB;AACA,SAAO;AACT;AAEO,SAAS,YAAY,KAAc,UAA2D;AACnG,MAAI,CAAC,SAAU,QAAO;AACtB,aAAW,OAAO,gBAAiB,KAAI,IAAI,GAAG,GAAG,OAAO,SAAU,QAAO;AACzE,SAAO;AACT;AAGO,SAAS,SAAS,KAAc,UAAqC,MAAiD;AAC3H,QAAM,MAAM,YAAY,KAAK,QAAQ;AACrC,MAAI,IAAK,QAAO,IAAI,GAAG,KAAK;AAC5B,MAAI,CAAC,YAAY,CAAC,KAAM,QAAO;AAC/B,SAAO,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,KAAK;AAChD;AAEA,SAAS,OAAO,KAAc,UAA0B;AACtD,QAAM,MAAM,YAAY,KAAK,QAAQ;AACrC,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,IAAI,GAAG,GAAG,QAAQ,eAAe,GAAG;AAC7C;AAsIO,IAAM,mBAA8B,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,YAAY,CAAC,GAAG,SAAS,CAAC,EAAE;AAE5G,IAAM,QAAQ,CAAC,MAA6C,CAAC,CAAC,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAC5G,IAAM,OAAO,CAAK,GAAY,OAC5B,MAAM,CAAC,IAAI,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAwB,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAChG,IAAM,SAAS,CAAC,MAA4B,OAAO,MAAM,YAAY,EAAE,SAAS;AAChF,IAAM,SAAS,CAAC,MAA8B,MAAM,CAAC,KAAK,OAAO,UAAU,EAAE,KAAK,KAAK,OAAO,UAAU,EAAE,GAAG,KAAK,MAAM,QAAQ,EAAE,UAAU;AAC5I,IAAM,UAAU,CAAC,MAAyC,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM;AAC5F,IAAM,aAAa,CAAC,MAAkC,MAAM,CAAC,KAAK,OAAO,EAAE,SAAS;AAM7E,SAAS,UAAU,SAAgD;AACxE,QAAM,IAA6B,MAAM,OAAO,IAAI,UAAU,CAAC;AAC/D,SAAO;AAAA,IACL,SAAS,KAAK,EAAE,SAAS,MAAM;AAAA,IAC/B,OAAO,KAAK,EAAE,OAAO,MAAM;AAAA,IAC3B,OAAO,KAAK,EAAE,OAAO,OAAO;AAAA,IAC5B,YAAY,KAAK,EAAE,YAAY,UAAU;AAAA,IACzC,SAAS,KAAK,EAAE,SAAS,KAAK;AAAA,EAChC;AACF;AAEO,SAAS,SAASC,OAAwB;AAC/C,SAAOA,MAAK,MAAM,KAAK,EAAE,OAAO,OAAO;AACzC;AAEA,SAAS,KAAK,OAAuB;AACnC,SAAO,MAAM,YAAY,EAAE,QAAQ,qBAAqB,EAAE;AAC5D;AAGO,SAAS,UAAU,MAA4B;AACpD,QAAM,SAAS,SAAS,KAAK,IAAI;AACjC,QAAM,SAAS,OAAO,IAAI,IAAI;AAC9B,QAAM,MAAkB,CAAC;AACzB,aAAW,QAAQ,KAAK,SAAS,CAAC,GAAG;AACnC,QAAI,QAAQ,KAAK;AACjB,QAAI,MAAM,KAAK;AACf,QAAI,KAAK,WAAW,QAAW;AAC7B,YAAM,OAAO,SAAS,KAAK,MAAM,EAAE,IAAI,IAAI;AAC3C,cAAQ;AACR,eAAS,IAAI,GAAG,IAAI,KAAK,UAAU,OAAO,UAAU,KAAK,QAAQ,KAAK;AACpE,YAAI,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG;AAC7C,kBAAQ;AACR,gBAAM,IAAI,KAAK,SAAS;AACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,UAAU,UAAa,QAAQ,KAAK,SAAS,OAAO,OAAQ;AAChE,UAAM,IAAI,KAAK,IAAI,OAAO,SAAS,GAAG,KAAK,IAAI,OAAO,OAAO,KAAK,CAAC;AACnE,QAAI,KAAK,EAAE,OAAO,KAAK,GAAG,YAAY,KAAK,cAAc,CAAC,GAAG,WAAW,KAAK,aAAa,MAAM,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA,EAC/H;AACA,SAAO,gBAAgB,GAAG;AAC5B;AAEA,SAAS,gBAAgB,OAA+B;AACtD,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC1D,QAAM,MAAkB,CAAC;AACzB,aAAW,KAAK,OAAQ,KAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAG,KAAI,KAAK,CAAC;AAC/F,SAAO;AACT;AAEO,SAAS,QAAQ,OAAkB,MAAqC;AAC7E,SAAO,MAAM,MAAM,KAAK,EAAE,KAAK,UAAU,IAAI;AAC/C;AAEO,SAAS,SAAS,MAAgB,MAA+C;AACtF,SAAO,SAAS,KAAK,IAAI,EACtB,MAAM,KAAK,OAAO,KAAK,MAAM,CAAC,EAC9B,KAAK,GAAG,EACR,QAAQ,kCAAkC,EAAE;AACjD;AAGO,SAAS,gBAAgB,YAA+B,OAA4B,OAA4B;AACrH,QAAM,MAAgB,CAAC;AACvB,QAAM,MAAM,CAAC,SAAiB;AAC5B,QAAI,QAAQ,CAAC,IAAI,SAAS,IAAI,EAAG,KAAI,KAAK,IAAI;AAAA,EAChD;AACA,aAAW,QAAQ,GAAG;AACtB,aAAW,QAAQ,MAAO,YAAW,QAAQ,QAAQ,OAAO,IAAI,EAAG,MAAK,WAAW,QAAQ,GAAG;AAC9F,SAAO,KAAK,MAAM,UAAU,EAAE,QAAQ,GAAG;AACzC,SAAO;AACT;AAKO,SAAS,gBAAgB,WAA8B,KAAc,WAA6B,SAAwB;AAC/H,MAAI,CAAC,UAAU,OAAQ,QAAO;AAC9B,MAAI,OAAO,aAAa,WAAY,QAAO,SAAS,SAAS;AAC7D,QAAM,OAAO,aAAa,WAAW,KAAK;AAC1C,SAAO,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM,QAAQ,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK;AACvF;AAGO,SAAS,eAAe,MAAgB,OAAkB,KAAc,UAA4C;AACzH,QAAM,SAAS,KAAK,WAAW,IAAI,CAAC,MAAM,MAAM,WAAW,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC;AACrG,SAAO,gBAAgB,QAAQ,KAAK,QAAQ,KAAK,KAAK;AACxD;AAGO,SAAS,WAAW,MAAgB,OAAkB,KAAc,UAA4C;AACrH,SAAO,KAAK,UAAU,eAAe,MAAM,OAAO,KAAK,QAAQ;AACjE;AAGO,SAAS,UAAU,OAA4B,MAA4B;AAChF,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,QAAQ,KAAK,GAAG,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAClH;AAEO,SAAS,WAAW,OAA4B,MAAmD;AACxG,SAAO,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,QAAQ,KAAK,GAAG;AACrE;AAmBO,SAAS,OAAO,OAAkB,MAAyB;AAChE,SAAO,SAAS,MAAM,KAAK,KAAK,OAAO;AACzC;AAGO,SAAS,QAAQ,OAAkB,MAAuC;AAC/E,QAAM,MAAM,OAAO,OAAO,IAAI;AAC9B,QAAMC,QAAO,KAAK,QAAQ,MAAM,QAAQ,CAAC;AACzC,SAAOA,MAAK,OAAO,CAAC,MAAM,CAAC,YAAY,KAAK,EAAE,EAAE,CAAC;AACnD;AAGO,SAAS,WAAW,OAAkB,MAAuC;AAClF,QAAM,MAAM,OAAO,OAAO,IAAI;AAC9B,QAAM,QAAS,CAAC,MAAM,SAAS,QAAQ,MAAM,EAAY,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAuB,CAAC,CAAC,CAAC;AAC9G,SAAO,CAAC,GAAG,OAAO,GAAG,QAAQ,OAAO,IAAI,CAAC;AAC3C;AAGO,SAAS,WAAW,OAAkB,MAAgB,UAAwD;AACnH,SAAO,SAAS,OAAO,OAAO,IAAI,GAAG,UAAU,QAAQ,OAAO,IAAI,CAAC;AACrE;AAMO,SAAS,aAAa,MAAgB,QAA0D;AACrG,MAAI,CAAC,KAAK,SAAS,OAAQ,QAAO,UAAU;AAC5C,SAAO,EAAE,GAAI,UAAU,CAAC,GAAI,KAAK,CAAC,GAAG,WAAW,MAAM,MAAM,CAAC,EAAE;AACjE;AAGO,SAAS,WAAW,MAAgB,QAA0D;AACnG,QAAM,MAAM,QAAQ;AACpB,MAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AACnF,UAAQ,KAAK,WAAW,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAClE;AAEA,SAAS,aAAa,OAAiC;AACrD,SAAO,MAAM,cAAc,MAAM,IAAI,OAAO,MAAM;AACpD;AAEA,SAAS,YAAY,OAAkB,OAA4C;AACjF,MAAI,CAAC,SAAS,CAAC,MAAM,QAAS,QAAO;AACrC,SAAO,MAAM,YAAY,QAAQ,MAAM,QAAQ,SAAS,KAAK;AAC/D;AAEA,IAAM,SAAS,CAAC,MAAyE,MAAM,SAAY,OAAO,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI;AAGzI,SAAS,eAAe,MAAqB,OAAkB,OAA8C;AAClH,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,KAAK,CAAC;AAC/E,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,KAAK,CAAC,MAAM,eAAe,GAAG,OAAO,KAAK,CAAC;AAC9E,MAAI,SAAS,KAAM,QAAO,CAAC,eAAe,KAAK,KAAK,OAAO,KAAK;AAEhE,QAAM,SAAS,MAAM,IAAI,KAAK,IAAI,IAAK,MAAM,QAAQ,KAAK,IAAI,KAAK,OAAQ;AAC3E,QAAM,eAAe,KAAK,YAAY;AACtC,MAAI,CAAC,aAAc,QAAO,WAAW;AACrC,MAAI,WAAW,KAAM,QAAO;AAC5B,QAAM,KAAK,OAAO,KAAK,EAAE;AACzB,QAAM,QAAQ,OAAO,KAAK,KAAK;AAC/B,MAAI,MAAM,CAAC,GAAG,SAAS,MAAM,EAAG,QAAO;AACvC,MAAI,SAAS,MAAM,SAAS,MAAM,EAAG,QAAO;AAC5C,SAAO;AACT;AAGO,SAAS,WAAW,OAA4B,OAAgD;AACrG,QAAM,QAAQ,oBAAI,IAAqB;AACvC,aAAW,QAAQ,MAAO,OAAM,IAAI,KAAK,IAAI,KAAK,SAAS,eAAe,KAAK,QAAQ,OAAO,KAAK,IAAI,IAAI;AAC3G,SAAO;AACT;AAGO,SAAS,WAAW,OAA4B,OAA8B;AACnF,MAAI,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,EAAG,QAAO,CAAC,GAAG,KAAK;AAClD,QAAM,QAAQ,WAAW,OAAO,KAAK;AACrC,SAAO,MAAM,OAAO,CAAC,MAAM,MAAM,IAAI,EAAE,EAAE,CAAC;AAC5C;AAGO,SAAS,eAAe,MAA+B;AAC5D,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,QAAQ,cAAc;AACzD,MAAI,SAAS,KAAM,QAAO,KAAK,IAAI,QAAQ,cAAc;AACzD,MAAI,SAAS,KAAM,QAAO,eAAe,KAAK,GAAG;AACjD,SAAO,CAAC,KAAK,IAAI;AACnB;AAQO,SAAS,gBAAoC,OAA0B;AAC5E,QAAM,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC1C,QAAM,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,SAAS,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACzI,QAAM,MAAW,CAAC;AAClB,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,OAAO,CAAC,GAAG,KAAK;AACtB,SAAO,KAAK,QAAQ;AAClB,UAAM,IAAI,KAAK,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,EAAE,CAAE,EAAE,MAAM,CAAC,MAAM,OAAO,IAAI,CAAC,CAAC,CAAC;AACjF,UAAM,CAAC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,IAAI,GAAG,CAAC;AAC3C,QAAI,KAAK,IAAK;AACd,WAAO,IAAI,KAAM,EAAE;AAAA,EACrB;AACA,SAAO;AACT;AAYO,SAAS,kBACd,KACA,SACsB;AACtB,QAAM,MAAM,CAAC,MAA6C,CAAC,CAAC,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAC1G,QAAM,OAAO,CAAC,MAAqC;AACjD,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,YAAM,MAAM,EAAE,IAAI,IAAI,EAAE,OAAO,CAAC,MAA0B,CAAC,CAAC,CAAC;AAC7D,aAAO,IAAI,SAAS,EAAE,IAAI,IAAI;AAAA,IAChC;AACA,QAAI,CAAC,IAAI,CAAC,EAAG,QAAO;AACpB,QAAI,MAAM,QAAQ,EAAE,GAAG,EAAG,QAAO,EAAE,KAAK,EAAE,IAAI,IAAI,IAAI,EAAE,OAAO,CAAC,MAA0B,CAAC,CAAC,CAAC,EAAE;AAC/F,QAAI,MAAM,QAAQ,EAAE,GAAG,EAAG,QAAO,EAAE,KAAK,EAAE,IAAI,IAAI,IAAI,EAAE,OAAO,CAAC,MAA0B,CAAC,CAAC,CAAC,EAAE;AAC/F,QAAI,EAAE,QAAQ,QAAW;AACvB,YAAM,QAAQ,KAAK,EAAE,GAAG;AACxB,aAAO,QAAQ,EAAE,KAAK,MAAM,IAAI;AAAA,IAClC;AACA,QAAI,EAAE,SAAS,UAAa,EAAE,SAAS,KAAM,QAAO;AACpD,UAAM,OAAO,QAAQ,IAAI,EAAE,IAAI;AAC/B,UAAM,QAAQ,CAAC,MACb,MAAM,UAAa,MAAM,OAAO,UAAa,MAAM,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,CAAC,KAAK,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACjJ,UAAM,KAAK,MAAM,EAAE,EAAE;AACrB,UAAM,QAAQ,MAAM,EAAE,UAAU,EAAE,KAAK;AACvC,WAAO;AAAA,MACL;AAAA,MACA,GAAI,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,MACnB,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MACzB,GAAI,OAAO,EAAE,aAAa,YAAY,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC;AAAA,IACpE;AAAA,EACF;AACA,SAAO,KAAK,GAAG;AACjB;AAEO,SAAS,kBAAkB,OAA4B,OAA4B;AACxF,QAAM,MAAgB,CAAC;AACvB,QAAM,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACpD,QAAM,QAAQ,CAAC,MAAM,MAAM;AACzB,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,QAAQ,CAAC,MAA2B;AACxC,UAAI,SAAS,EAAG,QAAO,EAAE,IAAI,QAAQ,KAAK;AAC1C,UAAI,SAAS,EAAG,QAAO,EAAE,IAAI,QAAQ,KAAK;AAC1C,UAAI,SAAS,EAAG,QAAO,MAAM,EAAE,GAAG;AAClC,YAAM,KAAK,MAAM,IAAI,EAAE,IAAI;AAC3B,UAAI,OAAO,QAAW;AACpB,YAAI,KAAK,IAAI,KAAK,IAAI,gDAAgD,EAAE,IAAI,IAAI;AAChF;AAAA,MACF;AACA,UAAI,MAAM,GAAG;AACX,YAAI,KAAK,IAAI,KAAK,IAAI,iBAAiB,MAAM,EAAE,GAAG,QAAQ,EAAE,IAAI,oDAAoD;AACpH;AAAA,MACF;AACA,YAAM,SAAS,MAAM,EAAE;AACvB,UAAI,CAAC,OAAQ;AACb,iBAAW,MAAM,CAAC,GAAI,OAAO,EAAE,EAAE,KAAK,CAAC,GAAI,GAAI,OAAO,EAAE,KAAK,KAAK,CAAC,CAAE,GAAG;AACtE,YAAI,CAAC,WAAW,OAAO,QAAQ,EAAE,EAAG,KAAI,KAAK,IAAI,KAAK,IAAI,0BAA0B,EAAE,WAAW,OAAO,IAAI,kBAAkB;AAAA,MAChI;AAAA,IACF;AACA,UAAM,KAAK,MAAM;AAAA,EACnB,CAAC;AACD,SAAO;AACT;AAEO,SAAS,WAAW,OAA4B,OAAkB,OAAkB,OAA2B;AACpH,QAAM,MAAM,aAAa,KAAK;AAC9B,SAAO,WAAW,OAAO,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,QAAQ,QAAQ,MAAM,QAAQ,EAAE,EAAE,MAAM,GAAG;AAChH;AAGO,SAAS,WAAW,OAA4B,OAAkB,OAAkB,OAAgC;AACzH,QAAM,MAAM,WAAW,OAAO,OAAO,OAAO,KAAK;AACjD,QAAM,SAAS,MAAM,MAAM,KAAK;AAChC,QAAM,MAAM,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,IAAI;AACxD,MAAI,IAAK,QAAO;AAChB,SAAO,IAAI,WAAW,IAAK,IAAI,CAAC,KAAK,OAAQ;AAC/C;AAEO,SAAS,UAAU,UAA+B,OAAkB,OAA8B;AACvG,QAAM,MAAkB,CAAC;AAEzB,QAAM,QAAQ,WAAW,UAAU,KAAK;AACxC,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,QAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,QAAQ,KAAK,EAAE,IAAI,KAAK,CAAC;AACtD,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,YAAY,OAAO,KAAK,EAAG;AAChC,UAAM,SAAS,CAAC,MAAM,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AACpE,QAAI,CAAC,OAAQ;AACb,UAAM,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK;AACrD,UAAM,MAAM,WAAW,OAAO,OAAO,OAAO,KAAK;AACjD,QAAI,IAAI,SAAS,KAAK,QAAQ,MAAM,CAAC,MAAM,MAAM,QAAQ,EAAE,EAAE,CAAC,EAAG,KAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,QAAQ,KAAK,IAAI,OAAO,OAAO,IAAI,CAAC;AAAA,EACpI,CAAC;AACD,MAAI,KAAK,EAAE,MAAM,OAAO,IAAI,MAAM,CAAC;AACnC,SAAO;AACT;AAEO,SAAS,SAAS,MAAgB,OAA2B;AAClE,MAAI,KAAK,SAAS,OAAQ,QAAO,CAAC,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAE;AAC7D,MAAI,KAAK,SAAS,OAAQ,QAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,MAAM,KAAK,KAAK,CAAC;AACxF,SAAO;AACT;AAGO,SAAS,iBAAiB,OAA4B,OAA0B;AACrF,QAAM,IAAI,MAAM,UAAU,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;AACpD,SAAO,IAAI,IAAI,MAAM,SAAS,IAAI;AACpC;AAsBA,SAAS,KAAQ,QAAqC,GAA8B;AAClF,QAAM,EAAE,CAAC,CAAC,GAAG,OAAO,GAAG,KAAK,IAAI;AAChC,SAAO;AACT;AAEO,SAAS,QAAQ,OAAkB,IAAuB;AAC/D,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK,UAAU;AACb,YAAM,UAAU,MAAM,WAAW,CAAC;AAClC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS,GAAG,SAAS,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,MAAM,SAAS,GAAG,MAAM;AAAA,QACjG,SAAS,GAAG,UAAU,GAAG,SAAS,EAAE,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,SAAS,GAAG,MAAM;AAAA,MACpG;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,GAAG,SAAS,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,KAAK,GAAG,GAAG,OAAO,IAAI,KAAK,MAAM,OAAO,GAAG,KAAK,EAAE;AAAA,IAChH,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,IACtE,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,GAAG,SACX,KAAK,MAAM,YAAY,GAAG,IAAI,IAC9B,EAAE,GAAG,MAAM,YAAY,CAAC,GAAG,IAAI,GAAG,EAAE,MAAM,GAAG,MAAM,QAAQ,GAAG,QAAQ,GAAI,GAAG,MAAM,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC,EAAG,EAAE;AAAA,MACjH;AAAA,IACF;AAEE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,SAAS,OAAkB,KAAmC;AAC5E,SAAO,IAAI,OAAO,SAAS,KAAK;AAClC;AAGO,SAAS,SAAS,QAAmB,IAAY,OAAoC;AAC1F,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AACH,aAAO,EAAE,MAAM,UAAU,QAAQ,GAAG,QAAQ,QAAQ,OAAO,QAAQ,GAAG,MAAM,KAAK,MAAM,QAAQ,OAAO,UAAU,GAAG,MAAM,KAAK,KAAK;AAAA,IACrI,KAAK;AACH,aAAO,EAAE,MAAM,QAAQ,OAAO,GAAG,OAAO,QAAQ,OAAO,MAAM,GAAG,KAAK,KAAK,KAAK;AAAA,IACjF,KAAK,SAAS;AACZ,YAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM;AACjD,aAAO,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,OAAO,OAAO,MAAM,GAAG,MAAM,MAAM,OAAO,UAAU,IAAI,IAAI,CAAC,GAAG;AAAA,IAC7G;AAAA,IACA,KAAK,YAAY;AACf,YAAM,MAAM,OAAO,WAAW,GAAG,IAAI;AACrC,aAAO,MAAM,EAAE,MAAM,YAAY,MAAM,GAAG,MAAM,QAAQ,IAAI,OAAO,IAAI,EAAE,MAAM,YAAY,MAAM,GAAG,MAAM,QAAQ,MAAM,QAAQ,KAAK;AAAA,IACvI;AAAA,EACF;AACF;AAEO,SAAS,WAAW,QAAmB,KAAwB,OAA4B,OAA6B,MAAkB;AAC/I,QAAM,UAAoB,CAAC;AAC3B,MAAI,IAAI;AACR,aAAW,MAAM,KAAK;AACpB,YAAQ,QAAQ,SAAS,GAAG,IAAI,KAAK,CAAC;AACtC,QAAI,QAAQ,GAAG,EAAE;AAAA,EACnB;AACA,SAAO,EAAE,KAAK,SAAS,KAAK;AAC9B;AAGO,SAAS,aACd,QACA,MACA,UACA,OACA,OACA,MACA,QACY;AACZ,QAAM,MAAgB,CAAC,EAAE,MAAM,UAAU,QAAQ,KAAK,IAAI,QAAQ,UAAU,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAC3G,MAAI,KAAK,SAAS,aAAa,aAAa,KAAK,KAAK,OAAO,MAAM,KAAK,KAAK,MAAM,KAAK,GAAI,KAAI,KAAK,EAAE,MAAM,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,CAAC;AACtJ,SAAO,WAAW,QAAQ,KAAK,OAAO,IAAI;AAC5C;AAwCO,SAAS,WAAW,OAA4B,OAAkB,OAAkB,UAAyC;AAClI,QAAM,SAAiC,CAAC;AACxC,QAAM,QAAQ,WAAW,OAAO,KAAK;AACrC,QAAM,UAAU,MAAM,IAAI,CAAC,SAA0B;AACnD,UAAM,MAAM,OAAO,OAAO,IAAI;AAC9B,UAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,UAAM,QAAQ,MAAM,IAAI,KAAK,EAAE,MAAM;AAErC,UAAM,KAAK,QAAS,MAAM,QAAQ,KAAK,EAAE,KAAK,OAAQ;AACtD,QAAI,GAAI,QAAO,EAAE,KAAK,OAAO,EAAE,KAAK,KAAK;AACzC,UAAM,QAAQ,QAAQ,OAAO,IAAI,EAAE,IAAI,CAAC,MAAsB;AAC5D,YAAM,KAAK,WAAW,GAAG,OAAO,KAAK,QAAQ;AAC7C,aAAO,EAAE,MAAM,SAAS,MAAM,CAAC,GAAG,OAAO,EAAE,OAAO,KAAK,EAAE,KAAK,YAAY,EAAE,YAAY,QAAQ,SAAS,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,EAAE,OAAO;AAAA,IACrI,CAAC;AACD,UAAM,UAAU,KAAK,YAAY,SAAY,OAAO,OAAO,KAAK,YAAY,WAAW,CAAC,KAAK,OAAO,IAAI,KAAK;AAC7G,UAAM,QAAQ,WAAW,KAAK,QAAQ,SAAS,EAAE,IAAI;AACrD,WAAO,EAAE,MAAM,QAAQ,SAAS,KAAK,IAAI,IAAI,GAAG,OAAO,OAAO,QAAS,MAAM,MAAM,UAAU,KAAK,EAAE,KAAM,MAAM,MAAM;AAAA,EACxH,CAAC;AACD,QAAM,QAAkC,CAAC;AACzC,QAAM,SAAS,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,MAAmB,YAAY,OAAO,CAAC,CAAC,CAAC;AAClG,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAI,WAAW,OAAO,OAAO,OAAO,CAAC;AAC3C,QAAI,EAAG,OAAM,CAAC,IAAI;AAAA,EACpB;AACA,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;AACjD,QAAM,QAAQ,UAAU,OAAO,OAAO,KAAK;AAC3C,QAAM,WAAW,MAAM,iBAAiB,OAAO,KAAK,CAAC,GAAG,SAAS;AACjE,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,YAAY,MAAS,EAAE;AAC9E,QAAM,QAAQ,SAAS,EAAE,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,IAAI,EAAE,QAAQ,OAAO,IAAI;AAC3F,QAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;AAC7C,SAAO,EAAE,SAAS,UAAU,OAAO,UAAU,QAAQ,OAAO,YAAY,OAAO,OAAO,MAAM,UAAU,GAAG,OAAO,MAAM;AACxH;AAUO,SAAS,aACd,MACA,OACA,KACA,QACA,UACA,MACQ;AACR,QAAM,QAAQ,CAAC,CAAC,KAAK,QAAQ,KAAK,SAAS,SAAI,KAAK,IAAI,WAAM,KAAK,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC;AACnG,MAAI,KAAK,IAAK,OAAM,KAAK,KAAK,GAAG;AACjC,QAAM,MAAM,WAAW,MAAM,MAAM,UAAU,KAAK,EAAE,CAAC;AACrD,aAAW,KAAK,KAAK,WAAW,CAAC,EAAG,OAAM,KAAK,KAAK,EAAE,KAAK,GAAG,IAAI,SAAS,EAAE,EAAE,IAAI,WAAW,EAAE,EAAE;AAClG,QAAM,MAAM,SAAS,KAAK,KAAK,WAAW,IAAI;AAC9C,MAAI,IAAK,OAAM,KAAK,GAAG,OAAO,UAAU,KAAK,KAAK,kBAAkB,IAAI,KAAK,EAAE;AAC/E,MAAI,KAAK,OAAQ,OAAM,KAAK,GAAG,OAAO,MAAM,KAAK,KAAK,MAAM,EAAE;AAC9D,aAAW,KAAK,KAAK,UAAU,CAAC,EAAG,OAAM,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE;AACtE,QAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,aAAW,KAAK,OAAO;AACrB,UAAM,IAAI,SAAS,KAAK,WAAW,GAAG,OAAO,KAAK,QAAQ,CAAC;AAC3D,UAAM,KAAK,KAAK,SAAS,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,CAAC,EAAE;AAAA,EACjG;AACA,QAAM,KAAK,GAAG,OAAO,MAAM,KAAK,SAAS,KAAK,MAAM,QAAQ,KAAK,EAAE,GAAG,IAAI,GAAG,SAAS,OAAO,UAAU,EAAE;AACzG,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,aAAa,QAAoB,OAA0B;AACzE,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,OAAO,KAAK,EAAG,OAAM,KAAK,GAAG,KAAK,KAAK,KAAK,IAAI,EAAE;AAE7F,QAAM,QAAsB,gBAAgB,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAuB,CAAC,CAAC,CAAC;AACvG,aAAW,KAAK,OAAO,QAAS,KAAI,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAG,OAAM,KAAK,EAAE,MAAM;AAC9G,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,QAAQ,OAAO,EAAE,EAAE;AAC/D,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,MAAM,OAAQ,OAAM,KAAK,EAAE;AAC/B,UAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AACxB,eAAW,KAAK,KAAM,OAAM,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE;AAAA,EACrD;AACA,QAAM,SAAS,OAAO,QAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,EAAE,QAAQ,SAAS,EAAE,EAAE,CAAC;AACzI,MAAI,OAAO,OAAQ,OAAM,KAAK,IAAI,GAAG,MAAM;AAC3C,SAAO,MAAM,KAAK,IAAI;AACxB;AASO,SAAS,iBACd,MACA,UACA,MACA,MAAuE,CAAC,MAAM,GAClE;AACZ,QAAM,UAAU,aAAa,WAAW,SAAS,MAAM,UAAU,SAAS;AAC1E,SAAO,KAAK,IAAI,CAAC,SAAS;AACxB,QAAI,KAAK,UAAW,QAAO;AAC3B,UAAM,OAAO,KAAK,IAAI;AACtB,UAAM,QAAQ,OAAO,QAAQ,IAAI,IAAI;AACrC,UAAM,YAAY,QAAQ,IAAI,OAAO,IAAI,IAAI;AAC7C,WAAO,YAAY,EAAE,GAAG,MAAM,UAAU,IAAI;AAAA,EAC9C,CAAC;AACH;;;AD1xBO,IAAM,YAAY;AA8BzB,IAAM,kBAAkB;AAGjB,SAAS,SAAS,OAAkB,IAAqB;AAC9D,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AACH,cAAQ,MAAM,QAAQ,GAAG,MAAM,KAAK,UAAU,GAAG;AAAA,IACnD,KAAK;AACH,cAAQ,MAAM,MAAM,GAAG,KAAK,KAAK,UAAU,GAAG;AAAA,IAChD,KAAK;AACH,aAAO,KAAK,UAAU,MAAM,MAAM,GAAG,MAAM,KAAK,IAAI,MAAM,KAAK,UAAU,GAAG,KAAK;AAAA,IACnF,KAAK;AACH,aAAO,GAAG,SAAS,CAAC,MAAM,WAAW,GAAG,IAAI,KAAK,MAAM,WAAW,GAAG,IAAI,GAAG,UAAU,UAAU,GAAG;AAAA,EACvG;AACF;AAEO,SAAS,kBAAkB,EAAE,OAAO,SAAS,cAAc,SAAS,GAA0C;AACnH,QAAM,CAAC,OAAO,QAAQ,IAAU,gBAAoB,MAAM,UAAU,YAAY,CAAC;AACjF,QAAM,CAAC,SAAS,UAAU,IAAU,gBAAgC,CAAC,CAAC;AACtE,QAAM,CAAC,SAAS,UAAU,IAAU,gBAA6B,CAAC,CAAC;AACnE,QAAM,CAAC,YAAY,aAAa,IAAU,gBAAwB,IAAI;AACtE,QAAM,MAAY,cAAO,CAAC;AAC1B,QAAM,cAAoB,cAAO,QAAQ;AACzC,cAAY,UAAU;AAGtB,QAAM,QAAQ,SAAS;AACvB,QAAM,OAAa,eAAQ,MAAO,QAAQ,UAAU,KAAK,IAAI,OAAQ,CAAC,OAAO,KAAK,CAAC;AAKnF,QAAM,UAAgB,cAAO,KAAK;AAClC,QAAM,aAAmB,cAAO,OAAO;AACvC,aAAW,UAAU;AACrB,QAAM,OAAO,SAAS;AACtB,EAAM,iBAAU,MAAM;AAEpB,QAAI,QAAQ,WAAW,CAAC,KAAM;AAC9B,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,IAAI,CAAC;AACT,EAAM,iBAAU,MAAM;AACpB,QAAI,QAAQ,QAAS,YAAW,SAAS,cAAc,QAAQ,MAAM,CAAC,SAAS,CAAC;AAAA,EAClF,GAAG,CAAC,OAAO,CAAC;AAGZ,EAAM,iBAAU,MAAM;AACpB,eAAW,CAACC,UAAS;AACnB,YAAMC,QAAOD,MAAK,OAAO,CAAC,MAAM,EAAE,cAAc,QAAQ,CAAC,EAAE,IAAI,MAAM,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC,CAAC;AAChG,aAAOC,MAAK,WAAWD,MAAK,SAASA,QAAOC;AAAA,IAC9C,CAAC;AAAA,EACH,GAAG,CAAC,IAAI,CAAC;AACT,EAAM,iBAAU,MAAM;AACpB,QAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,cAAc,IAAI,EAAG;AAChD,UAAM,IAAI,WAAW,MAAM,WAAW,CAACD,UAASA,MAAK,OAAO,CAAC,MAAM,EAAE,cAAc,QAAQ,KAAK,IAAI,IAAI,EAAE,YAAY,eAAe,CAAC,GAAG,eAAe;AACxJ,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,QAAc,eAAQ,MAAM,QAAQ,OAAO,CAAC,GAAG,MAAM,SAAS,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC;AACrG,QAAM,WAAiB,cAAO,KAAK;AACnC,WAAS,UAAU;AAEnB,QAAM,OAAa;AAAA,IACjB,CAAC,KAAwB,WAAuB,YAAY,UAAU;AACpE,UAAI,CAAC,SAAS;AACZ,iBAAS,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAChC;AAAA,MACF;AACA,YAAM,KAAK,EAAE,IAAI;AACjB,iBAAW,CAACA,UAAS,CAAC,GAAGA,OAAM,EAAE,IAAI,KAAK,WAAW,MAAM,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG,CAAC,CAAC;AACjG,cAAQ,MAAM,GAAG,EAAE;AAAA,QACjB,MAAM;AACJ,wBAAc,IAAI;AAElB,qBAAW,CAACA,UAAU,YAAYA,MAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAIA,MAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,EAAE,GAAG,GAAG,WAAW,KAAK,IAAI,EAAE,IAAI,CAAE,CAAE;AAAA,QAC3I;AAAA,QACA,CAAC,QAAiB;AAChB,qBAAW,CAACA,UAASA,MAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACpD,wBAAc,eAAe,SAAS,IAAI,UAAU,IAAI,UAAU,OAAO,GAAG,CAAC;AAC7E,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,SAAe;AAAA,IACnB,CAAC,WAAuB;AACtB,cAAQ,UAAU;AAClB,iBAAW,CAAC,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC;AAChC,WAAK,OAAO,KAAK,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,MAAM,MAAM,CAAC,GAAG,OAAO,SAAS;AACzF,kBAAY,UAAU,SAAS,SAAS,SAAS,OAAO,GAAG,GAAG,QAAQ,KAAK;AAAA,IAC7E;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,aAAmB,cAAO,OAAO;AACvC,aAAW,UAAU;AACrB,QAAM,OAAa,mBAAY,MAAyB;AACtD,UAAM,OAAO,WAAW,QAAQ,WAAW,QAAQ,SAAS,CAAC;AAC7D,QAAI,CAAC,KAAM,QAAO;AAClB,YAAQ,UAAU;AAClB,eAAW,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAEhC,SAAK,KAAK,SAAS,MAAM,WAAW,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,KAAK,SAAS;AACxE,gBAAY,UAAU,SAAS,SAAS,SAAS,KAAK,OAAO,GAAG,MAAM,IAAI;AAC1E,WAAO;AAAA,EACT,GAAG,CAAC,IAAI,CAAC;AAET,SAAO;AAAA,IACL,OAAO,UAAU,QAAQ,QAAS,SAAS,CAAC;AAAA,IAC5C;AAAA,IACA,QAAQ,UAAU,QAAQ,SAAS;AAAA,IACnC,WAAW,UAAU,QAAQ,QAAQ;AAAA,IACrC;AAAA,IACA,SAAS,QAAQ,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;;;AE7JO,IAAM,UAAU;AACvB,IAAM,YAAY;AAClB,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;AAEjB,SAAS,eAAe,OAAuB;AACpD,SAAO,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,QAAQ,GAAG,CAAC;AAChD;AAEO,SAAS,kBAAkB,IAAY,IAA2B;AACvE,SAAO,KAAK,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,IAAK,KAAK,IAAI,UAAU,SAAU,KAAK,IAAI,OAAO;AACtF;AAGO,SAAS,gBACd,IACA,IACA,OACA,OACA,SACsB;AACtB,QAAM,MAAM,kBAAkB,IAAI,EAAE;AACpC,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO;AAC1B,QAAM,OAAO,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;AAChD,MAAI,QAAQ,eAAe,KAAK,EAAG,QAAO;AAC1C,MAAI,OAAO,sBAAsB,QAAQ,gBAAiB,QAAO;AACjE,SAAO;AACT;AAEO,SAAS,YAAY,MAAmB,GAA8B;AAC3E,MAAI,KAAoB;AACxB,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,KAAK;AACT,MAAI,OAAyC;AAC7C,MAAI,YAAkD;AACtD,MAAI,aAA6B;AACjC,MAAI,UAAiD,CAAC;AACtD,QAAM,OAAO,KAAK,cAAc,eAAe;AAE/C,QAAM,YAAY,MAAM;AACtB,QAAI,UAAW,cAAa,SAAS;AACrC,gBAAY;AACZ,SAAK,iBAAiB,iBAAiB,EAAE,QAAQ,CAAC,OAAO,GAAG,gBAAgB,eAAe,CAAC;AAAA,EAC9F;AAEA,QAAM,QAAQ,MAAM,KAAK,sBAAsB,EAAE,SAAS,KAAK;AAE/D,QAAM,SAAS,CAAC,MAAoB;AAClC,QAAI,OAAO,QAAQ,EAAE,SAAS,KAAK,CAAC,EAAE,QAAQ,EAAG;AACjD,UAAM,SAAS,EAAE,kBAAkB,UAAU,EAAE,SAAS;AACxD,QAAI,CAAC,UAAU,OAAO,QAAQ,EAAE,kBAAkB,+CAA+C,EAAG;AACpG,SAAK,EAAE;AACP,SAAK,EAAE;AACP,SAAK,EAAE;AACP,SAAK,KAAK;AACV,WAAO;AACP,iBAAa;AACb,cAAU,CAAC,EAAE,GAAG,EAAE,WAAW,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,CAAC;AACzD,MAAE,QAAQ;AACV,UAAM,WAAW,EAAE,QAAQ,EAAE,eAAe,OAAO,QAAQ,EAAE,YAAY,IAAI;AAC7E,QAAI,UAAU;AACZ,eAAS,aAAa,iBAAiB,EAAE;AACzC,kBAAY,WAAW,MAAM;AAC3B,YAAI,SAAS,QAAS;AACtB,eAAO;AACP,kBAAU;AACV,aAAK,KAAK,WAAW,EAAE;AACvB,UAAE,OAAO,QAAQ;AAAA,MACnB,GAAG,OAAO;AAAA,IACZ;AACA,SAAK,iBAAiB,eAAe,MAAM;AAC3C,SAAK,iBAAiB,aAAa,IAAI;AACvC,SAAK,iBAAiB,iBAAiB,QAAQ;AAAA,EACjD;AAEA,QAAM,SAAS,CAAC,MAAoB;AAClC,QAAI,EAAE,cAAc,GAAI;AACxB,SAAK,EAAE,UAAU;AACjB,SAAK,EAAE,UAAU;AACjB,YAAQ,KAAK,EAAE,GAAG,EAAE,WAAW,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,CAAC;AAC3D,QAAI,QAAQ,SAAS,EAAG,SAAQ,MAAM;AACtC,QAAI,SAAS,WAAW,KAAK,MAAM,IAAI,EAAE,IAAI,WAAW;AACtD,gBAAU;AACV,aAAO;AAAA,IACT;AACA,QAAI,SAAS,OAAQ;AACrB,UAAM,MAAM,kBAAkB,IAAI,EAAE;AACpC,UAAM,OAAO,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;AAChD,MAAE,KAAK,IAAI,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,MAAM,MAAM,OAAO,eAAe,MAAM,CAAC,CAAC;AAAA,EACjF;AAEA,QAAM,SAAS,MAAM;AACnB,SAAK,oBAAoB,eAAe,MAAM;AAC9C,SAAK,oBAAoB,aAAa,IAAI;AAC1C,SAAK,oBAAoB,iBAAiB,QAAQ;AAAA,EACpD;AAEA,QAAM,WAAW,CAAC,MAAc;AAC9B,UAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,IAAI,EAAE,KAAK,GAAG;AACnD,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,QAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,MAAM,MAAM,EAAG,QAAO;AAClD,WAAO,KAAK,MAAM,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,MAAM;AAAA,EAC1E;AAEA,QAAM,OAAO,CAAC,MAAoB;AAChC,QAAI,EAAE,cAAc,GAAI;AACxB,WAAO;AACP,cAAU;AACV,UAAM,IAAI;AACV,SAAK;AACL,WAAO;AACP,QAAI,MAAM,QAAQ;AAChB,YAAM,QAAQ,SAAS,EAAE,SAAS;AAClC,YAAM,MAAM,gBAAgB,IAAI,IAAI,OAAO,MAAM,GAAG,EAAE,WAAW,CAAC;AAClE,UAAI,IAAK,GAAE,OAAO,KAAK,KAAK;AAAA,UACvB,GAAE,QAAQ;AAAA,IACjB,WAAW,MAAM,WAAW,WAAY,GAAE,MAAM,UAAU;AAAA,EAC5D;AAEA,QAAM,WAAW,CAAC,MAAoB;AACpC,QAAI,EAAE,cAAc,GAAI;AACxB,WAAO;AACP,cAAU;AACV,UAAM,IAAI;AACV,SAAK;AACL,WAAO;AACP,QAAI,MAAM,OAAQ,GAAE,QAAQ;AAAA,EAC9B;AAEA,QAAM,YAAY,CAAC,MAAa;AAC9B,QAAI,EAAE,KAAM,GAAE,eAAe;AAAA,EAC/B;AAMA,MAAI,YAA6C;AACjD,QAAM,eAAe,CAAC,MAAkB;AACtC,UAAM,IAAI,EAAE,QAAQ,CAAC;AACrB,gBAAY,IAAI,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,IAAI;AAAA,EACnD;AACA,QAAM,cAAc,CAAC,MAAkB;AACrC,QAAI,OAAO,QAAQ,CAAC,EAAE,WAAY;AAClC,UAAM,IAAI,EAAE,QAAQ,CAAC;AACrB,UAAM,KAAK,KAAK,YAAY,EAAE,UAAU,UAAU,IAAI;AACtD,UAAM,KAAK,KAAK,YAAY,EAAE,UAAU,UAAU,IAAI;AACtD,UAAM,OAAO,EAAE,WAAW;AAC1B,QAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,KAAM;AAC3D,MAAE,eAAe;AAAA,EACnB;AAEA,OAAK,iBAAiB,eAAe,MAAM;AAC3C,OAAK,iBAAiB,eAAe,SAAS;AAC9C,OAAK,iBAAiB,cAAc,cAAc,EAAE,SAAS,KAAK,CAAC;AACnE,OAAK,iBAAiB,aAAa,aAAa,EAAE,SAAS,MAAM,CAAC;AAClE,SAAO,MAAM;AACX,WAAO;AACP,cAAU;AACV,SAAK,oBAAoB,eAAe,MAAM;AAC9C,SAAK,oBAAoB,eAAe,SAAS;AACjD,SAAK,oBAAoB,cAAc,YAAY;AACnD,SAAK,oBAAoB,aAAa,WAAW;AAAA,EACnD;AACF;;;ACjJO,IAAM,4BAA6C;AAAA,EACxD,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AAAA,EACb,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,eAAe;AAAA,EACf,YAAY;AACd;;;AChFA,YAAYE,YAAW;AAiVf,gBAAAC,MAKI,QAAAC,aALJ;AArSR,SAAS,YAAY,OAA4B,GAAW,GAAuB;AACjF,SAAO,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,KAAK,EAAE,QAAQ,EAAE;AACxD;AAEO,SAAS,WAAW,OAAwB;AACjD,QAAM,EAAE,MAAM,OAAO,QAAQ,SAAS,OAAO,QAAQ,SAAS,IAAI;AAClE,QAAM,SAAe,eAAQ,MAAM,SAAS,KAAK,IAAI,GAAG,CAAC,KAAK,IAAI,CAAC;AACnE,QAAM,UAAU,CAAC,GAAW,MAAc,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,EAAE,QAAQ,CAAC,KAAK;AAC7F,QAAM,YAAY,MAAM,KAAK,CAAC,MAAM,MAAM,QAAQ,SAAS,EAAE,SAAS,MAAM,QAAQ,SAAS,EAAE,GAAG,KAAK;AACvG,QAAM,CAAC,KAAK,MAAM,IAAU,gBAAS,MAAO,YAAY,EAAE,GAAG,UAAU,OAAO,GAAG,UAAU,IAAI,IAAI,EAAE,GAAG,MAAM,QAAQ,OAAO,GAAG,MAAM,QAAQ,IAAI,CAAE;AACpJ,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAA4B,MAAM,WAAW,cAAc,CAAC,CAAC;AAE/F,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAwB,IAAI;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAU,gBAAS,EAAE;AAE3C,QAAM,CAAC,cAAc,eAAe,IAAU,gBAAwB,IAAI;AAC1E,QAAM,CAAC,iBAAiB,kBAAkB,IAAU,gBAA6B,MAAS;AAC1F,QAAM,CAAC,OAAO,QAAQ,IAAU,gBAAmD,CAAC,CAAC;AACrF,QAAM,QAAc,cAAO,IAAI;AAC/B,QAAM,OAAa,cAAO,KAAK;AAE/B,EAAM,iBAAU,MAAM;AACpB,UAAM,IAAI,WAAW,MAAM;AACzB,YAAM,UAAU;AAAA,IAClB,GAAG,GAAG;AACN,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ,QAAQ,IAAI,GAAG,IAAI,CAAC;AAClC,QAAM,YAAsB,EAAE,OAAO,IAAI,GAAG,KAAK,IAAI,GAAG,YAAY,QAAQ,WAAW,OAAO,aAAa,MAAM,QAAQ,OAAO,UAAU,KAAK;AAC/I,QAAM,cAAc,eAAe,OAAO,eAAe,WAAW,OAAO,SAAS,QAAQ;AAC5F,QAAM,eAAe,YAAY,QAAQ,WAAW;AACpD,QAAM,SAAS,gBAAgB,OAAO,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG,EAAE,QAAQ,kCAAkC,EAAE;AACpH,QAAM,YAAY,QAAQ,SAAS,SAAS,MAAM,UAAU,eAAe,OAAO,OAAO,SAAS,QAAQ,CAAC,IAAI;AAC/G,QAAM,gBAAsB;AAAA,IAC1B,MAAM,CAAC,GAAG,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,WAAW,SAAS,CAAC,CAAC,CAAC;AAAA,IACpG,CAAC,MAAM,YAAY,KAAK;AAAA,EAC1B;AAEA,QAAM,WAAiB,eAAQ,MAAM;AACnC,UAAM,QAAQ,MAAM,MAAM,SAAS,MAAM,OAAO;AAChD,QAAI,CAAC,MAAO,QAAO,CAAC,EAAE,IAAI,IAAI,OAAO,MAAuB,YAAY,cAAc,CAAC;AACvF,UAAM,QAAQ,IAAI,IAAI,MAAM,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;AACxD,UAAM,QAAQ,cAAc,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC3F,WAAO,MAAM,IAAI,CAAC,GAAG,OAAO;AAAA,MAC1B,IAAI,EAAE;AAAA,MACN,OAAO,EAAE;AAAA,MACT,YAAY,CAAC,GAAG,EAAE,YAAY,GAAI,MAAM,IAAI,QAAQ,CAAC,GAAI,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,WAAW,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,IACtJ,EAAE;AAAA,EACJ,GAAG,CAAC,MAAM,MAAM,eAAe,KAAK,CAAC;AAGrC,QAAM,WAAiB,cAAuB,IAAI;AAClD,QAAM,YAAkB,cAAuB,IAAI;AACnD,QAAM,WAAiB,cAAiB,CAAC,CAAC;AAC1C,QAAM,OAAa,cAAmB,IAAI;AAE1C,QAAM,MAAM,OAAO,KAAoB,QAAQ,MAAM;AACnD,QAAI,KAAK,WAAW,MAAM,QAAS;AACnC,UAAM,SAAS,OAAO,GAAG;AACzB,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO,OAAO,gBAAgB;AAChC,UAAI,cAAc;AAChB,wBAAgB,IAAI;AACpB;AAAA,MACF;AAEA,YAAM,UAAU,CAAC,SAAS,MAAM,WAAW,KAAK,IAAQ,MAAM,OAAO,KAAK,IAAQ;AAClF,UAAI,YAAY,SAAS,OAAO,QAAS,OAAM,QAAQ,SAAS;AAChE,YAAM,QAAQ;AACd;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS,KAAK,QAAQ,KAAK,CAAC;AACjC,WAAO,SAAS,SAAS,GAAG;AAC5B,UAAM,OAAO,UAAU,SAAS,KAAK,KAAK;AAC1C,SAAK,UAAU;AACf,QAAI,cAAc;AAChB,YAAM,iBAAiB,cAAc,OAAO,IAAI,mBAAmB,MAAS;AAC5E,YAAM,SAAS,GAAG,YAAY,KAAK,OAAO,KAAK,EAAE;AACjD,sBAAgB,IAAI;AACpB,WAAK,SAAS,KAAK;AACnB,aAAO,SAAS,SAAS,IAAI;AAC7B,UAAI,UAAU,SAAS;AACrB,kBAAU,QAAQ,MAAM,aAAa;AACrC,kBAAU,QAAQ,MAAM,YAAY;AACpC,kBAAU,QAAQ,MAAM,UAAU;AAAA,MACpC;AACA;AAAA,IACF;AACA,UAAM,QAAQ,EAAE,GAAG,WAAW,QAAQ,OAAO,GAAG,CAAC;AACjD,UAAM,SAAS,GAAG,MAAM,KAAK,OAAO,KAAK,EAAE;AAC3C,UAAM,QAAQ;AAAA,EAChB;AACA,QAAM,SAAe,cAAO,GAAG;AAC/B,SAAO,UAAU;AAEjB,EAAM,iBAAU,MAAM;AACpB,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,KAAM;AACX,WAAO,YAAY,MAAM;AAAA,MACvB,SAAS,MAAM,CAAC,KAAK,WAAW,CAAC,MAAM;AAAA,MACvC,YAAY,MAAM;AAAA,MAClB,MAAM,CAAC,IAAI,IAAI,KAAK,WAAW;AAC7B,cAAM,SAAS,MAAM,OAAO,GAAG,IAAI;AACnC,eAAO,UAAU,SAAS,IAAI,IAAI,OAAO,SAAS,SAAS,CAAC;AAC5D,YAAI,OAAO,QAAQ;AACjB,eAAK,SAAS,KAAK,QAAQ,KAAK,MAAM;AACtC,iBAAO,SAAS,SAAS,UAAU,IAAI,MAAM,IAAI;AAAA,QACnD,OAAO;AACL,eAAK,SAAS,KAAK;AACnB,iBAAO,SAAS,SAAS,IAAI;AAAA,QAC/B;AAAA,MACF;AAAA,MACA,SAAS,MAAM;AACb,iBAAS,UAAU,OAAO;AAC1B,aAAK,SAAS,KAAK;AACnB,eAAO,SAAS,SAAS,IAAI;AAAA,MAC/B;AAAA,MACA,QAAQ,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,KAAK,KAAK;AAAA,MACtD,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,UAAgB,cAAuB,IAAI;AACjD,QAAM,UAAgB,cAAwB,IAAI;AAClD,QAAM,UAAgB,cAAwB,IAAI;AAClD,QAAM,QAAc,cAAgG,IAAI;AAExH,EAAM,uBAAgB,MAAM;AAC1B,UAAM,MAAM,QAAQ;AACpB,QAAI,CAAC,IAAK;AACV,UAAM,IAAI,IAAI,cAA2B,eAAe,IAAI,CAAC,IAAI;AACjE,UAAM,IAAI,IAAI,cAA2B,eAAe,IAAI,CAAC,IAAI;AACjE,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,QAAQ;AACnB,QAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAI;AAC5B,UAAM,IAAI,IAAI,sBAAsB;AACpC,UAAM,KAAK,EAAE,sBAAsB;AACnC,UAAM,KAAK,EAAE,sBAAsB;AACnC,UAAM,KAAK,IAAI;AACf,OAAG,MAAM,OAAO,GAAG,GAAG,OAAO,EAAE,IAAI;AACnC,OAAG,MAAM,MAAM,GAAG,GAAG,MAAM,EAAE,MAAM,KAAK,EAAE;AAC1C,OAAG,MAAM,SAAS,GAAG,GAAG,SAAS,EAAE;AACnC,OAAG,MAAM,OAAO,GAAG,GAAG,QAAQ,EAAE,IAAI;AACpC,OAAG,MAAM,MAAM,GAAG,GAAG,MAAM,EAAE,MAAM,KAAK,EAAE;AAC1C,OAAG,MAAM,SAAS,GAAG,GAAG,SAAS,EAAE;AAAA,EACrC,CAAC;AAED,QAAM,SAAS,CAAC,GAAW,MAA6B;AACtD,UAAM,MAAM,QAAQ,SAAS;AAC7B,UAAM,KAAK,KAAK,iBAAiB,GAAG,CAAC;AACrC,UAAM,IAAI,IAAI,QAAQ,2BAA2B;AACjD,QAAI,CAAC,KAAK,CAAC,QAAQ,SAAS,SAAS,CAAC,EAAG,QAAO;AAChD,UAAM,IAAI,EAAE,aAAa,WAAW,KAAK,EAAE,aAAa,YAAY;AACpE,WAAO,MAAM,OAAO,OAAO,OAAO,CAAC;AAAA,EACrC;AAEA,QAAM,UAAU,CAAC,MACf,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM;AACnB,QAAI,IAAI,EAAG,QAAO,EAAE,GAAG,GAAG,EAAE;AAC5B,QAAI,IAAI,EAAG,QAAO,EAAE,GAAG,GAAG,EAAE;AAC5B,QAAI,MAAM,EAAG,QAAO,EAAE,GAAG,EAAE;AAC3B,QAAI,MAAM,EAAG,QAAO,EAAE,GAAG,IAAI,GAAG,EAAE;AAClC,QAAI,MAAM,EAAG,QAAO,EAAE,GAAG,GAAG,IAAI,EAAE;AAClC,WAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACtB,CAAC;AAEH,QAAM,aAAa,CAAC,OAA2B;AAC7C,QAAI,MAAM,WAAW,aAAc;AACnC,UAAM,SAAS,GAAG,kBAAkB,UAAU,GAAG,SAAS;AAC1D,UAAM,SAAS,QAAQ,QAAQ,kBAAkB;AACjD,UAAM,OAAO,QAAQ,QAAQ,aAAa;AAC1C,QAAI,CAAC,UAAU,CAAC,KAAM;AACtB,OAAG,eAAe;AAClB,UAAM,UAAU;AAAA,MACd,IAAI,GAAG;AAAA,MACP,MAAM,SAAU,OAAO,aAAa,gBAAgB,MAAM,MAAM,MAAM,MAAO;AAAA,MAC7E,QAAQ,OAAO,OAAO,KAAK,aAAa,WAAW,CAAC,IAAI;AAAA,MACxD,OAAO;AAAA,IACT;AACA,UAAM,OAAO,QAAQ,SAAS,cAAc,eAAe;AAC3D,UAAM,OAAO,CAAC,MAAoB;AAChC,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,EAAE,cAAc,GAAG,GAAI;AAClC,YAAM,IAAI,OAAO,EAAE,SAAS,EAAE,OAAO;AACrC,UAAI,MAAM,KAAM;AAChB,UAAI,GAAG,SAAS,IAAK,QAAO,CAAC,EAAE,GAAG,IAAI,OAAO,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE;AAAA,eACpE,GAAG,SAAS,IAAK,QAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,KAAK,IAAI,GAAG,CAAC,EAAE,EAAE;AAAA,eAC7D,GAAG,WAAW,SAAS,MAAM,GAAG,UAAU,GAAG,QAAQ;AAC5D,WAAG,QAAQ;AACX,cAAM,SAAS,GAAG;AAClB,eAAO,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,GAAG,GAAG,KAAK,IAAI,GAAG,MAAM,EAAE,CAAC;AAAA,MAC3D;AAAA,IACF;AACA,UAAM,KAAK,CAAC,MAAoB;AAC9B,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,EAAE,cAAc,GAAG,GAAI;AAClC,WAAK,oBAAoB,eAAe,IAAI;AAC5C,WAAK,oBAAoB,aAAa,EAAE;AACxC,WAAK,oBAAoB,iBAAiB,EAAE;AAC5C,UAAI,GAAG,SAAS,WAAW,CAAC,GAAG,SAAS,GAAG,WAAW,KAAM,SAAQ,GAAG,MAAM;AAC7E,YAAM,UAAU;AAAA,IAClB;AACA,SAAK,iBAAiB,eAAe,IAAI;AACzC,SAAK,iBAAiB,aAAa,EAAE;AACrC,SAAK,iBAAiB,iBAAiB,EAAE;AAAA,EAC3C;AAIA,EAAM,iBAAU,MAAM;AACpB,UAAM,OAAO,QAAQ,SAAS,cAA2B,eAAe,IAAI,CAAC,IAAI;AACjF,UAAM,iBAAiB,EAAE,OAAO,UAAU,CAAC;AAC3C,UAAM,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EAGrC,GAAG,CAAC,CAAC;AAGL,QAAM,WAAiB,cAAO,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;AACjD,EAAM,iBAAU,MAAM;AACpB,UAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC;AAC3B,QAAI,MAAM,SAAS,QAAS;AAC5B,aAAS,UAAU;AACnB,UAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,EAAE,QAAQ,IAAI,CAAC;AAClE,QAAI,IAAK,WAAU,IAAI,UAAU;AAAA,EACnC,GAAG,CAAC,KAAK,KAAK,CAAC;AAGf,QAAM,WAAiB,cAAuB,IAAI;AAClD,QAAM,SAAe,cAAuB,IAAI;AAChD,QAAM,UAAgB,cAA6B,IAAI;AACvD,EAAM,uBAAgB,MAAM;AAC1B,UAAM,MAAM,SAAS;AACrB,QAAI,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,QAAQ,QAAS;AACjD,WAAO,WAAW,KAAK,MAAM;AAC3B,UAAI,OAAO,WAAW,QAAQ,QAAS,SAAQ,KAAK,OAAO,SAAS,QAAQ,SAAS,KAAK,IAAI,cAAc,aAAa,cAAc,MAAM,OAAO,MAAM,EAAE;AAAA,IAC9J,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,WAAW,IAAI,YAAY,CAAC;AAExC,QAAM,cAAc,MAAM;AACxB,UAAM,OAAO,MAAM,KAAK;AACxB,UAAM,MAAM,UAAU;AACtB,cAAU,IAAI;AACd,aAAS,EAAE;AACX,QAAI,CAAC,KAAM;AACX,QAAI,CAAC,cAAc,SAAS,IAAI,EAAG,UAAS,CAAC,MAAM,CAAC,GAAG,GAAG,EAAE,MAAM,IAAI,CAAC,CAAC;AACxE,cAAU,CAAC,MAAO,EAAE,SAAS,IAAI,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAE;AACtD,QAAI,CAAC,MAAM,WAAW,IAAI,GAAG,QAAQ;AACnC,sBAAgB,IAAI;AACpB,yBAAmB,GAAG;AAAA,IACxB;AAAA,EACF;AAGA,EAAM,iBAAU,MAAM;AACpB,UAAM,OAAO,SAAS,SAAS,cAAc,eAAe;AAC5D,UAAM,QAAQ,CAAC,MAAqB;AAClC,YAAM,IAAI,EAAE,kBAAkB,UAAU,EAAE,SAAS;AACnD,UAAI,GAAG,QAAQ,2CAA2C,EAAG;AAC7D,UAAI,EAAE,UAAU,EAAE,WAAW,EAAE,QAAS;AACxC,YAAM,MAAO,EAAE,YAAY,SAAS,WAAW,QAAQ,SAAS,MAAM,WAAW,OAAO,EAAY,EAAE,GAAmB;AACzH,UAAI,EAAE,QAAQ,UAAU;AACtB,UAAE,eAAe;AACjB,UAAE,yBAAyB;AAC3B,YAAI,aAAc,iBAAgB,IAAI;AAAA,YACjC,OAAM,QAAQ;AAAA,MACrB,WAAW,KAAK;AACd,UAAE,eAAe;AACjB,UAAE,yBAAyB;AAE3B,YAAI,CAAC,EAAE,OAAQ,MAAK,OAAO,QAAQ,GAAG;AAAA,MACxC;AAAA,IACF;AACA,SAAK,iBAAiB,WAAW,OAAO,IAAI;AAC5C,WAAO,MAAM,KAAK,oBAAoB,WAAW,OAAO,IAAI;AAAA,EAC9D,GAAG,CAAC,cAAc,KAAK,CAAC;AAGxB,QAAM,WAAiB,cAAuB,IAAI;AAClD,QAAM,WAAW,OAAO,CAAC;AACzB,EAAM,iBAAU,MAAM;AACpB,UAAM,KAAK,SAAS,SAAS,cAA2B,uBAAuB;AAC/E,QAAI,iBAAiB,EAAE,OAAO,WAAW,QAAQ,SAAS,CAAC;AAAA,EAC7D,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,YAAY,CAAC,gBAAgB,YAAY,OAAO,IAAI,GAAG,IAAI,CAAC,EAAE,SAAS;AAE7E,SACE,gBAAAA,MAAC,SAAI,KAAK,UAAU,WAAU,sCAAqC,MAAK,UAAS,cAAW,QAAO,cAAY,OAAO,MACpH;AAAA,oBAAAD,KAAC,gBAAa,QAAO,MAAK,OAAO,OAAO,MAAM,UAAS,UAAS,SAAS,MAAO,eAAe,gBAAgB,IAAI,IAAI,MAAM,QAAQ,GACnI,0BAAAA,KAAC,SAAM,GACT;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,qBACb;AAAA,sBAAAA,MAAC,SAAI,KAAK,SAAS,WAAU,qBAAoB,mBAAgB,IAAG,YAAU,eAAe,KAAK,QAAW,eAAe,YACzH;AAAA,eAAO,IAAI,CAAC,GAAG,MACd,gBAAAA,MAAO,iBAAN,EACE;AAAA,cAAI,IACH,gBAAAD,KAAC,UAAK,WAAU,kBAAiB,cAAY,GAAG,YAAU,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,QACtF,eACH,IACE;AAAA,UACJ,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,UAAU;AAAA,cACV,MAAK;AAAA,cACL,gBAAc,KAAK,IAAI,KAAK,KAAK,IAAI;AAAA,cACrC,WAAW,CAAC,MAAM;AAEhB,qBAAK,EAAE,QAAQ,WAAW,EAAE,QAAQ,QAAQ,CAAC,EAAE,UAAU,CAAC,cAAc;AACtE,oBAAE,eAAe;AACjB,0BAAQ,CAAC;AAAA,gBACX;AAAA,cACF;AAAA,cACA,aAAW;AAAA,cACX,YAAU,KAAK,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK;AAAA,cAC1C,cAAY,MAAM,IAAI,IAAI,KAAK;AAAA,cAC/B,aAAW,MAAM,IAAI,IAAI,KAAK;AAAA,cAE7B;AAAA;AAAA,UACH;AAAA,aAxBmB,CAyBrB,CACD;AAAA,QACD,gBAAAA,KAAC,UAAK,KAAK,SAAS,WAAU,mBAAkB,kBAAe,KAAI,eAAY,QAAO;AAAA,QACtF,gBAAAA,KAAC,UAAK,KAAK,SAAS,WAAU,mBAAkB,kBAAe,KAAI,eAAY,QAAO;AAAA,SACxF;AAAA,MACA,gBAAAA,KAAC,SAAI,KAAK,UAAU,WAAU,yBAC5B,0BAAAA,KAAC,SAAI,KAAK,WAAW,WAAU,mBAC7B,0BAAAC,MAAC,SAAI,KAAK,QACP;AAAA,uBAAe,gBAAAD,KAAC,SAAI,WAAU,mBAAmB,iBAAO,UAAS,IAAS;AAAA,QAC3E,gBAAAA,KAAC,OAAE,KAAK,SAAS,WAAU,wBAAuB,eAAa,eAAe,SAAY,IACvF,kBACH;AAAA,QACC,aAAa,CAAC,eACb,gBAAAC,MAAC,SAAI,WAAU,gBAAe,aAAW,UAAU,MACjD;AAAA,0BAAAD,KAAC,OAAE;AAAA,UACH,gBAAAA,KAAC,UAAM,WAAC,UAAU,OAAO,GAAI,OAAO,cAAc,CAAC,CAAE,EAAE,KAAK,QAAK,GAAE;AAAA,WACrE,IACE;AAAA,SACN,GACF,GACF;AAAA,MACA,gBAAAA,KAAC,SAAI,KAAK,UAAU,WAAU,sBAAqB,mBAAgB,IAChE,mBAAS,IAAI,CAAC,QACb,gBAAAC,MAAC,SAA0B,WAAU,kBAAiB,MAAK,SAAQ,cAAY,IAAI,SAAS,OAAO,UAChG;AAAA,YAAI,QAAQ,gBAAAD,KAAC,UAAK,WAAU,2BAA2B,cAAI,OAAM,IAAU;AAAA,QAC3E,IAAI,WAAW,IAAI,CAAC,MAAM;AACzB,gBAAM,KAAK,OAAO,SAAS,CAAC;AAC5B,gBAAM,KAAK,SAAS,SAAS,MAAM,WAAW,CAAC,GAAG,MAAM;AACxD;AAAA;AAAA,YAEE,gBAAAC;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,gBAAc;AAAA,gBACd,aAAW,IAAI;AAAA,gBACf,UAAU,CAAC,CAAC;AAAA,gBACZ,SAAS,MAAM,UAAU,CAAC,MAAO,KAAK,EAAE,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAE;AAAA,gBAE1E;AAAA,uBAAK,gBAAAD,KAAC,OAAE,eAAY,QAAO,IAAK;AAAA,kBAChC;AAAA;AAAA;AAAA,cATI;AAAA,YAUP;AAAA;AAAA,QAEJ,CAAC;AAAA,QACA,MAAM,sBAAsB,CAAC,eAC5B,WAAW,IAAI,KACb,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,WAAS;AAAA,YACT,cAAY,OAAO;AAAA,YACnB,cAAa;AAAA,YACb,cAAa;AAAA,YACb,OAAO;AAAA,YACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,YACxC,QAAQ;AAAA,YACR,WAAW,CAAC,MAAM;AAChB,gBAAE,gBAAgB;AAClB,kBAAI,EAAE,QAAQ,SAAS;AACrB,kBAAE,eAAe;AACjB,4BAAY;AAAA,cACd,WAAW,EAAE,QAAQ,UAAU;AAC7B,0BAAU,IAAI;AACd,yBAAS,EAAE;AAAA,cACb;AAAA,YACF;AAAA;AAAA,QACF;AAAA;AAAA,UAGA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,YAAS;AAAA,cACT,cAAY,IAAI,QAAQ,GAAG,OAAO,WAAW,KAAK,IAAI,KAAK,KAAK,OAAO;AAAA,cACvE,OAAO,OAAO;AAAA,cACd,SAAS,MAAM,UAAU,IAAI,EAAE;AAAA,cAE/B,0BAAAA,KAAC,YAAS;AAAA;AAAA,UACZ;AAAA,YAEA;AAAA,WAxDI,IAAI,MAAM,KAyDpB,CACD,GACH;AAAA,OACF;AAAA,IACA,gBAAAA,KAAC,eAAY,QAAgB,WAAW,cAAc,MAAM,UAAU,UAAU,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,iBAAiB,OAAO,YAAY;AAAA,IACvI,YACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,OAAO,OAAO;AAAA,QACd,SAAS,MAAM;AACb,cAAI,MAAM,QAAS;AACnB,gBAAM,SAAS,EAAE,OAAO,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;AAC3C,gBAAM,QAAQ;AAAA,QAChB;AAAA,QAEA,0BAAAA,KAAC,cAAW;AAAA;AAAA,IACd,IACE;AAAA,IACJ,gBAAAA,KAAC,QAAK,KAAK,MAAM;AAAA,KACnB;AAEJ;;;AP2TiB,SA+mBP,YAAAE,WA/mBO,OAAAC,MA6BT,QAAAC,aA7BS;AAxmBjB,IAAM,OAAgD,EAAE,YAAY,SAAS,WAAW,QAAQ,SAAS,MAAM,WAAW,OAAO;AACjI,IAAM,mBAAmB;AAEzB,SAAS,SAAS,KAAsB;AACtC,MAAI;AACF,WAAO,WAAW,cAAc,QAAQ,GAAG,MAAM;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AACA,SAAS,UAAU,KAAmB;AACpC,MAAI;AACF,eAAW,cAAc,QAAQ,KAAK,GAAG;AAAA,EAC3C,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,KAAK,IAA2B;AACvC,SAAO,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC7C;AAEO,SAAS,UAAU,OAAuB;AAC/C,QAAM,SAAe,eAAyB,OAAO,EAAE,GAAG,2BAA2B,GAAG,MAAM,OAAO,IAAI,CAAC,MAAM,MAAM,CAAC;AACvH,QAAM,UAAgB,eAAQ,MAAM,SAAS,kBAAkB,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC;AAC9F,QAAM,cAAoB,eAAQ,MAAM,SAAS,EAAE,GAAG,SAAS,MAAM,oBAAoB,GAAG,MAAM,WAAW,GAAG,CAAC,SAAS,MAAM,WAAW,CAAC;AAC5I,QAAM,QAAc;AAAA,IAClB,OAAO;AAAA,MACL,KAAK;AAAA,MACL,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,MAChE,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,MAC3D,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,IAC3C;AAAA,IACA,CAAC,SAAS,MAAM,SAAS,MAAM,YAAY,MAAM,IAAI;AAAA,EACvD;AACA,QAAM,WAAW,MAAM;AACvB,QAAM,MAAM,kBAAkB,EAAE,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,cAAc,MAAM,cAAc,UAAU,MAAM,SAAS,CAAC;AACxI,QAAM,aAAa,MAAM,cAAc;AACvC,QAAM,SAAS,MAAM,UAAU;AAC/B,QAAM,EAAE,OAAO,MAAM,IAAI;AACzB,QAAM,QAAc,eAAQ,MAAM,UAAU,OAAO,OAAO,KAAK,GAAG,CAAC,OAAO,OAAO,KAAK,CAAC;AACvF,QAAM,YAAY,iBAAiB,OAAO,KAAK;AAC/C,QAAM,OAAiB,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,IAAI,MAAM;AACpE,QAAM,QAAQ,WAAW,WAAW;AACpC,QAAM,WAAiB,cAAO,KAAK;AACnC,WAAS,UAAU;AAEnB,QAAM,QAAc,cAAO,IAAI;AAC/B,EAAM,iBAAU,MAAM;AACpB,UAAM,UAAU;AAChB,WAAO,MAAM;AACX,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAgB,cAAuB,IAAI;AAEjD,QAAM,eAAqB,cAAO,KAAK;AACvC,QAAM,WAAiB,cAAuB,IAAI;AAClD,QAAM,WAAiB,cAA8B,IAAI;AACzD,QAAM,WAAiB,cAAiB,CAAC,CAAC;AAC1C,QAAM,OAAa,cAAmB,IAAI;AAC1C,QAAM,OAAa,cAAO,KAAK;AAC/B,QAAM,YAAkB,cAAsC,IAAI;AAClE,QAAM,YAAkB,cAAyB,IAAI;AACrD,QAAM,CAAC,SAAS,UAAU,IAAU,gBAAS,KAAK;AAClD,QAAM,aAAmB,cAAO,KAAK;AACrC,QAAM,WAAiB,cAAO,KAAK;AACnC,QAAM,CAAC,MAAM,OAAO,IAAU,gBAAgE,IAAI;AAClG,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAA0E,IAAI;AAChH,QAAM,CAAC,OAAO,QAAQ,IAAU,gBAAwB,IAAI;AAC5D,QAAM,CAAC,MAAM,OAAO,IAAU,gBAAS,EAAE;AAIzC,QAAM,CAAC,WAAW,YAAY,IAAU,gBAAS,KAAK;AACtD,QAAM,eAAqB,cAAO,KAAK;AACvC,eAAa,UAAU;AACvB,QAAM,WAAW,KAAK,SAAS,UAAU,CAAC,YAAY,KAAK,OAAO;AAClE,QAAM,UAAU,WAAW,OAAO,OAAO,QAAQ,IAAI;AACrD,QAAM,WAAiB,eAAQ,MAAO,WAAW,QAAQ,OAAO,QAAQ,IAAI,CAAC,GAAI,CAAC,UAAU,KAAK,CAAC;AAElG,QAAM,gBAAsB,eAAQ,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,QAAQ,CAAC;AACvF,QAAM,eAAe,WAAW,YAAY,SAAS,SAAS,SAAS,IAAI;AAE3E,QAAM,CAAC,YAAY,aAAa,IAAU,gBAA2D,IAAI;AACzG,QAAM,YAAY,WAAY,YAAY,OAAO,SAAS,KAAK,WAAW,SAAU,MAAM,UAAU,SAAS,EAAE,KAAK,OAAS;AAC7H,QAAM,YAAkB,cAAO,SAAS;AACxC,YAAU,UAAU;AACpB,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAwB,IAAI;AAC9D,QAAM,YAAY,CAAC,CAAC,YAAY,WAAW,SAAS;AACpD,QAAM,YAAkB,cAAO,SAAS;AACxC,YAAU,UAAU;AAEpB,QAAM,YAAY,MAAM;AACtB,QAAI;AACF,gBAAU,SAAS,OAAO;AAAA,IAC5B,QAAQ;AAAA,IAER;AACA,cAAU,UAAU;AAAA,EACtB;AAEA,QAAM,QAAc,mBAAY,CAACC,UAAiB,SAASA,KAAI,GAAG,CAAC,CAAC;AACpE,EAAM,iBAAU,MAAM;AACpB,QAAI,CAAC,MAAO;AACZ,UAAM,IAAI,WAAW,MAAM,SAAS,IAAI,GAAG,IAAI;AAC/C,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,KAAK,CAAC;AACV,EAAM,iBAAU,MAAM;AACpB,QAAI,CAAC,OAAQ;AACb,UAAM,IAAI,WAAW,MAAM,UAAU,IAAI,GAAG,IAAI;AAChD,WAAO,MAAM,aAAa,CAAC;AAAA,EAC7B,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,MAAM,CAAC,KAAoB,QAAQ,MAAM;AAC7C,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,OAAQ,MAAK,KAAK,QAAQ,KAAK,KAAK;AAAA,EAC1C;AAEA,QAAM,OAAO,OAAO,QAAoB,KAA2B,QAAQ,GAAG,WAA+B;AAC3G,QAAI,CAAC,YAAY,KAAK,WAAW,WAAW,WAAW,KAAM;AAC7D,SAAK,UAAU;AACf,cAAU;AACV,cAAU,IAAI;AACd,SAAK,SAAS,KAAK,QAAQ,KAAK,CAAC;AACjC,WAAO,SAAS,SAAS,GAAG;AAC5B,SAAK,WAAW,WAAW,CAAC;AAC5B,UAAM,OAAO,SAAS,SAAS,OAAO,QAAQ,KAAK;AACnD,UAAM,MAAM,SAAS;AACrB,UAAM,QAAQ,aAAa,UAAU,WAAW,SAAY,UAAU,UAAU,MAAM;AACtF,UAAM,OAAO,aAAa,KAAK,UAAU,OAAO,IAAI,OAAO,OAAO,KAAK,KAAK;AAE5E,UAAM,SAAS,OAAO,WAAW,MAAM,UAAU,EAAE,GAAG,MAAM,WAAW,KAAK,IAAI;AAChF,cAAU,UAAU;AACpB,kBAAc,IAAI;AAClB,cAAU,IAAI;AACd,iBAAa,UAAU;AACvB,eAAW,OAAO,MAAM;AACxB,SAAK,UAAU;AACf,WAAO,SAAS,SAAS,IAAI;AAC7B,SAAK,SAAS,KAAK;AACnB,UAAM,QAAQ,SAAS,KAAK,OAAO,GAAG;AACtC,UAAM,WAAW,UAAU,QAAQ,KAAK;AACxC,UAAM,YAAY,UAAU,OAAO,OAAO,KAAK;AAC/C,UAAM,OAAO,UAAU,iBAAiB,WAAW,KAAK,CAAC;AACzD,YAAQ,GAAG,OAAO,KAAK,IAAI,QAAQ,KAAK,SAAS,SAAS,IAAI,OAAO,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,EAAE,EAAE;AAAA,EACvG;AACA,QAAM,SAAe,cAAO,GAAG;AAC/B,SAAO,UAAU;AACjB,QAAM,UAAgB,cAAO,IAAI;AACjC,UAAQ,UAAU;AAElB,QAAM,cAAoB;AAAA,IACxB,MACE,WACI;AAAA,MACE,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,CAAC,WAAW,cAAc,EAAE,IAAI,SAAS,IAAI,OAAO,CAAC;AAAA,MAChE,QAAQ,CAAC,UAAU,WAAW;AAC5B,cAAM,IAAI,WAAW,OAAO,UAAU,QAAQ;AAC9C,YAAI,EAAG,MAAK,QAAQ,QAAQ,GAAG,YAAY,SAAS,QAAQ,GAAG,GAAG,MAAM;AAAA,MAC1E;AAAA,MACA,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,KAAK,IAAI;AAAA,IACjD,IACA;AAAA,IACN,CAAC,UAAU,WAAW,OAAO,OAAO;AAAA,EACtC;AAEA,QAAM,OAAO,MAAM;AACjB,QAAI,KAAK,WAAW,WAAW,QAAS;AACxC,QAAI,KAAM,SAAQ,IAAI;AACtB,kBAAc,IAAI;AAClB,cAAU,IAAI;AACd,UAAM,SAAS,WAAW,KAAK;AAC/B,QAAI,CAAC,OAAQ;AACb,cAAU,UAAU,OAAO,QAAQ;AAEnC,UAAM,WAAW,OAAO,IAAI,KAAK,CAAC,MAAgD,EAAE,SAAS,YAAY,CAAC,CAAC,EAAE,MAAM;AACnH,QAAI,UAAU,OAAQ,eAAc,EAAE,IAAI,SAAS,QAAQ,QAAQ,SAAS,OAAO,CAAC;AACpF,UAAM,UAAU,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,OAAO;AAChF,UAAM,OAAO,WAAW,YAAY,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,MAAM,IAAI;AAC3F,YAAQ,GAAG,OAAO,MAAM,IAAI,OAAO,IAAI,KAAK,IAAI,KAAK,EAAE,EAAE;AAAA,EAC3D;AACA,QAAM,UAAgB,cAAO,IAAI;AACjC,UAAQ,UAAU;AAElB,QAAM,OAAO,CAAC,OAAe,SAAmB;AAC9C,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf;AAAA,MACE,MAAM;AACJ,aAAK,UAAU;AACf,YAAI,CAAC,MAAM,QAAS;AACpB,kBAAU,UAAU;AACpB,mBAAW,OAAO,WAAW,SAAS,SAAS,CAAC,EAAE,MAAM,QAAQ,OAAO,QAAQ,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;AACjG,gBAAQ,GAAG,MAAM,cAAc,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI,EAAE;AAAA,MAChE;AAAA,MACA,qBAAqB,IAAI,IAAI;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,WAAW,CAAC,MAAgB,UAAkB;AAClD,QAAI,MAAM,cAAc,SAAS,KAAK,WAAW,WAAW,QAAS;AACrE,cAAU;AACV,cAAU,IAAI;AACd,QAAI,SAAS,QAAS,UAAS,SAAS,OAAO;AAC/C,SAAK,SAAS,KAAK;AACnB,YAAQ,EAAE,QAAQ,KAAK,IAAI,OAAO,OAAO,KAAK,MAAM,CAAC;AAAA,EACvD;AACA,QAAM,cAAoB,cAAO,QAAQ;AACzC,cAAY,UAAU;AAEtB,QAAM,WAAW,OAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,KAAK,OAAQ;AAC5E,QAAM,UAAgB;AAAA,IACpB,MAAO,WAAW,SAAS,EAAE,GAAG,OAAO,OAAO,QAAQ,GAAG,MAAM,oBAAoB,GAAG,MAAM,WAAW,IAAI;AAAA,IAC3G,CAAC,UAAU,OAAO,MAAM,aAAa,WAAW;AAAA,EAClD;AACA,QAAM,gBAAsB,eAAQ,MAAM,gBAAgB,MAAM,cAAc,CAAC,GAAG,OAAO,KAAK,GAAG,CAAC,MAAM,YAAY,OAAO,KAAK,CAAC;AAEjI,QAAM,cAAc,CAAC,MAAgB,SAAmB;AACtD,cAAU,UAAU;AACpB,UAAM,MAAM,SAAS;AACrB,eAAW,OAAO,WAAW,KAAK,CAAC,EAAE,MAAM,SAAS,QAAQ,KAAK,IAAI,OAAO,UAAU,QAAQ,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;AAAA,EAC5H;AACA,QAAM,eAAe,CAAC,MAAgB,SAAyC;AAC7E,cAAU,UAAU;AACpB,UAAM,MAAM,SAAS;AACrB,eAAW,OAAO,WAAW,KAAK,CAAC,EAAE,MAAM,SAAS,QAAQ,KAAK,IAAI,OAAO,WAAW,QAAQ,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;AAC3H,UAAM,OAAO,SAAS;AAAA,EACxB;AAIA,QAAM,UAAgB,cAAO,KAAK;AAClC,QAAM,OAAa,cAAO,EAAE,SAAS,SAAS,MAAM,CAAC;AACrD,OAAK,UAAU,EAAE,SAAS,SAAS,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,UAAU;AAEjF,EAAM,iBAAU,MAAM;AACpB,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,KAAM;AACX,WAAO,YAAY,MAAM;AAAA,MACvB,SAAS,MAAM,KAAK,QAAQ,WAAW,CAAC,KAAK,WAAW,CAAC,WAAW;AAAA,MACpE,YAAY,MAAM,KAAK,QAAQ;AAAA,MAC/B,OAAO,MAAM;AACX,gBAAQ,UAAU;AAClB,kBAAU;AACV,kBAAU,IAAI;AAAA,MAChB;AAAA,MACA,MAAM,CAAC,IAAI,IAAI,KAAK,WAAW;AAC7B,gBAAQ,UAAU;AAClB,cAAM,SAAS,MAAM,KAAK,QAAQ,QAAQ,GAAG,IAAI;AACjD,eAAO,SAAS,SAAS,IAAI,IAAI,OAAO,SAAS,SAAS,CAAC;AAC3D,YAAI,OAAO,QAAQ;AACjB,eAAK,SAAS,KAAK,QAAQ,KAAK,MAAM;AACtC,iBAAO,SAAS,SAAS,UAAU,IAAI,MAAM,IAAI;AAAA,QACnD,OAAO;AACL,eAAK,SAAS,KAAK;AACnB,iBAAO,SAAS,SAAS,IAAI;AAAA,QAC/B;AAAA,MACF;AAAA,MACA,SAAS,MAAM;AACb,iBAAS,SAAS,OAAO;AACzB,aAAK,SAAS,KAAK;AACnB,eAAO,SAAS,SAAS,IAAI;AAAA,MAC/B;AAAA,MACA,QAAQ,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,KAAK;AAAA,MACjD,KAAK,CAAC,WAAW;AACf,cAAM,OAAO,OAAO,QAAqB,gBAAgB;AACzD,YAAI,CAAC,MAAM;AACT,oBAAU,IAAI;AACd;AAAA,QACF;AACA,cAAM,IAAI,KAAK,sBAAsB;AACrC,kBAAU,EAAE,MAAM,KAAK,aAAa,oBAAoB,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,QAAQ,EAAE,OAAO,CAAC;AAAA,MAC1H;AAAA,MACA,MAAM,CAAC,WAAW;AAChB,cAAM,IAAI,OAAO,OAAO,aAAa,WAAW,CAAC;AACjD,cAAM,OAAO,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO,QAAQ,gBAAgB,GAAG,aAAa,cAAc,CAAC;AACjH,YAAI,QAAQ,OAAO,SAAS,CAAC,EAAG,aAAY,QAAQ,MAAM,CAAC;AAAA,MAC7D;AAAA,MACA,cAAc;AAAA;AAAA,MAEd,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AACL,QAAM,WAAiB,cAAO,KAAK;AACnC,WAAS,UAAU;AAGnB,QAAM,WAAW,MAAM,aAAa;AAEpC,QAAM,YAAkB,cAAsB,IAAI;AAElD,QAAM,YAAkB,cAAyD,MAAM,KAAK;AAC5F,YAAU,UAAU,CAAC,KAAK,WAAW;AACnC,QAAI,aAAa,SAAS;AACxB,UAAI,QAAQ,UAAU;AACpB,qBAAa,KAAK;AAClB,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,OAAO,QAAQ,OAAO,QAAQ,YAAa,QAAO;AAAA,IAChE;AACA,UAAM,MAAM,KAAK,GAAG;AACpB,UAAM,WAAW,CAAC,OAAO,IAAI,WAAW,IAAI,YAAY,QAAQ,GAAG,IAAI;AACvE,SAAK,OAAO,aAAa,UAAU,QAAS,QAAO;AACnD,QAAI,KAAK;AACP,aAAO,QAAQ,GAAG;AAClB,aAAO;AAAA,IACT;AACA,QAAI,UAAU;AACZ,WAAK,QAAQ,QAAQ,SAAS,QAAQ,SAAS,GAAG;AAClD,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,OAAO,QAAQ,OAAO,QAAQ,aAAa;AACrD,cAAQ,QAAQ;AAChB,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,KAAK;AACf,WAAK,QAAQ,QAAQ;AACrB,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,YAAY,QAAQ,QAAQ,SAAS,cAAc,QAAQ,QAAQ,QAAQ;AACrF,cAAQ,QAAQ,OAAO;AACvB,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,4BAA4B,KAAK,YAAY,WAAW,MAAM,cAAc,OAAO;AACzH,YAAM,OAAO,YAAY;AACzB,YAAM,QAAQ,QAAQ,SAAS,SAAS,IAAI,EAAE,CAAC;AAC/C,kBAAY,QAAQ,MAAM,QAAQ,MAAM,QAAQ,CAAC;AACjD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACA,QAAM,cAAoB,cAAO,QAAQ;AACzC,cAAY,UAAU;AAEtB,QAAM,cAAoB,cAAkF,MAAM,IAAI;AACtH,cAAY,UAAU,CAAC,QAAQ;AAC7B,QAAI,CAAC,YAAY,KAAM,QAAO;AAC9B,UAAM,IAAI,IAAI,YAAY;AAC1B,eAAW,KAAK,iBAAiB;AAC/B,YAAMC,KAAI,QAAQ,CAAC;AACnB,UAAIA,IAAG,UAAU,YAAY,MAAM,EAAG,QAAO,EAAE,QAAQA,IAAG,KAAK,EAAE;AAAA,IACnE;AACA,UAAM,IAAI,cAAc,KAAK,CAAC,MAAM,EAAE,UAAU,YAAY,MAAM,CAAC;AACnE,WAAO,IAAI,EAAE,QAAQ,GAAG,KAAK,KAAK,IAAI;AAAA,EACxC;AACA,QAAM,UAAgB,cAAO,EAAE,MAAM,MAAM,UAAU,QAAQ,MAAM,OAAO,CAAC;AAC3E,UAAQ,UAAU,EAAE,MAAM,MAAM,UAAU,QAAQ,MAAM,OAAO;AAC/D,EAAM,iBAAU,MAAM;AACpB,QAAI,CAAC,SAAU;AACf,UAAM,OAAO,QAAQ,SAAS,cAAc,eAAe;AAC3D,UAAM,QAAQ,CAAC,MAAqB;AAClC,YAAM,OAAO,QAAQ;AACrB,YAAM,MAAM,MAAM;AAClB,YAAM,SAAS,KAAK;AACpB,UAAI,UAAU,WAAW,IAAI,QAAQ,CAAC,MAAM,SAAS,MAAM,EAAG;AAE9D,UAAI,WAAW,YAAY,EAAE,SAAS,KAAK,SAAS,UAAU,IAAI,KAAK,KAAK,QAAQ,QAAQ,IAAK;AACjG,YAAM,IAAI,EAAE,kBAAkB,UAAU,EAAE,SAAS;AACnD,UAAI,GAAG,QAAQ,mDAAmD,EAAG;AAErE,WAAK,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,UAAU,CAAC,EAAE,aAAa,EAAE,QAAQ,OAAO,EAAE,QAAQ,QAAQ,CAAC,EAAE,QAAQ;AACzG,UAAE,eAAe;AACjB,gBAAQ,QAAQ;AAChB;AAAA,MACF;AAEA,UAAI,EAAE,UAAU,EAAE,WAAW,EAAE,QAAS;AACxC,UAAI,EAAE,QAAQ;AACZ,YAAI,KAAK,EAAE,GAAG,KAAK,EAAE,QAAQ,OAAO,EAAE,QAAQ,OAAO,EAAE,QAAQ,YAAa,GAAE,eAAe;AAC7F;AAAA,MACF;AACA,UAAI,WAAW,SAAS;AAEtB,iBAAS,UAAU;AACnB,YAAI,KAAK,EAAE,GAAG,KAAK,EAAE,QAAQ,OAAO,EAAE,QAAQ,OAAO,EAAE,QAAQ,aAAa;AAC1E,YAAE,eAAe;AACjB,oBAAU,UAAU,EAAE;AAAA,QACxB;AACA;AAAA,MACF;AACA,UAAI,UAAU,QAAQ,EAAE,KAAK,CAAC,EAAG,GAAE,eAAe;AAAA,IACpD;AACA,SAAK,iBAAiB,WAAW,KAAK;AACtC,WAAO,MAAM,KAAK,oBAAoB,WAAW,KAAK;AAAA,EACxD,GAAG,CAAC,UAAU,MAAM,CAAC;AASrB,QAAM,SAAS,UAAU,MAAM;AAC/B,EAAM,iBAAU,MAAM;AACpB,UAAM,aAAa,aAAa;AAChC,iBAAa,UAAU;AACvB,QAAI,CAAC,YAAY,WAAW,YAAY,WAAW,KAAM;AACzD,UAAM,OAAO,QAAQ;AACrB,UAAM,MAAM,MAAM;AAClB,UAAM,SAAS,KAAK,iBAAiB;AACrC,QAAI,CAAC,QAAS,UAAU,KAAK,SAAS,MAAM,EAAI;AAChD,UAAM,OAAO,CAAC,UAAU,WAAW,KAAK,QAAQ,WAAW,KAAK;AAChE,QAAI,CAAC,QAAQ,CAAC,WAAY;AAC1B,QAAI,QAAQ,QAAQ,iJAAiJ,EAAG;AACxK,UAAM,SAAS,QAAQ,QAAQ,+CAA+C;AAC9E,QAAI,UAAU,CAAC,OAAO,SAAS,IAAI,EAAG;AACtC,SAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACpC,GAAG,CAAC,QAAQ,UAAU,MAAM,CAAC;AAG7B,QAAM,YAAkB,cAAuB,IAAI;AACnD,QAAM,UAAgB,cAAuB,IAAI;AACjD,QAAM,SAAe,cAAuB,IAAI;AAChD,QAAM,OAAO,YAAY;AACvB,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,OAAO;AACrB,UAAM,IAAI,UAAU;AACpB,QAAI,WAAW,WAAW,CAAC,YAAY,KAAK,WAAW,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,EAAG;AACvF,eAAW,UAAU;AACrB,aAAS,UAAU;AACnB,eAAW,IAAI;AACf,cAAU;AACV,cAAU,IAAI;AACd,UAAM,UAAU,qBAAqB;AACrC,UAAM,QAAQ,CAAC,IAAY,MACzB,IAAI,QAAc,CAAC,QAAQ;AACzB,YAAM,KAAK,YAAY,IAAI;AAC3B,YAAM,QAAQ,CAAC,MAAc;AAC3B,YAAI,SAAS,QAAS,QAAO,IAAI;AACjC,cAAM,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,EAAE;AACnC,UAAE,CAAC;AACH,YAAI,IAAI,EAAG,uBAAsB,KAAK;AAAA,YACjC,KAAI;AAAA,MACX;AACA,4BAAsB,KAAK;AAAA,IAC7B,CAAC;AACH,UAAM,OAAO,CAAC,MAAe,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI;AACjF,UAAM,QAAQ,CAAC,IAAwB,GAAW,MAAc;AAC9D,UAAI,CAAC,GAAI;AACT,SAAG,MAAM,OAAO,GAAG,CAAC;AACpB,SAAG,MAAM,MAAM,GAAG,CAAC;AAAA,IACrB;AACA,UAAM,IAAI,MAAM,sBAAsB;AACtC,UAAM,KAAK,EAAE,OAAO,EAAE,QAAQ;AAC9B,UAAM,KAAK,EAAE,MAAM,EAAE,SAAS;AAC9B,UAAM,OAAO,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI;AAC3C,UAAM,GAAG,IAAI,EAAE;AACf,MAAE,MAAM,UAAU;AAClB,UAAM,MAAM;AACZ,UAAM,QAAQ,CAAC,GAAI,eAAe,CAAC,YAAY,IAAI,CAAC,GAAI,GAAG,gBAAgB,OAAO,CAAC,MAAM,MAAM,YAAY,CAAC;AAC5G,eAAW,OAAO,OAAO;AACvB,UAAI,SAAS,QAAS;AACtB,YAAM,SAAS,IAAI,GAAG;AACtB,UAAI,CAAC,OAAQ;AACb,YAAM,CAAC,IAAI,EAAE,IAAI,OAAO,GAAG;AAC3B,QAAE,aAAa,aAAa,EAAE;AAC9B,YAAM,MAAM,UAAU,IAAI,KAAK,CAAC,MAAM;AACpC,cAAM,IAAI,KAAK,CAAC;AAChB,cAAM,GAAG,KAAK,KAAK,OAAO,GAAG,KAAK,KAAK,OAAO,CAAC;AAC/C,eAAO,OAAO,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AACpD,aAAK,SAAS,KAAK,QAAQ,KAAK,IAAI,IAAI;AACxC,eAAO,SAAS,SAAS,IAAI,MAAM,MAAM,IAAI;AAAA,MAC/C,CAAC;AACD,YAAM,KAAK,SAAS,UAAU,IAAI,GAAG;AACrC,YAAM,MAAM,UAAU,IAAI,KAAK,CAAC,MAAM;AACpC,cAAM,IAAI,IAAI;AACd,cAAM,GAAG,KAAK,KAAK,OAAO,GAAG,KAAK,KAAK,OAAO,CAAC;AAC/C,eAAO,OAAO,KAAK,OAAO,GAAG,KAAK,OAAO,GAAG,CAAC;AAC7C,aAAK,SAAS,KAAK,QAAQ,KAAK,CAAC;AAAA,MACnC,CAAC;AACD,QAAE,gBAAgB,WAAW;AAC7B,WAAK,SAAS,KAAK;AACnB,aAAO,SAAS,SAAS,IAAI;AAC7B,aAAO,OAAO,GAAG,CAAC;AAClB,YAAM,KAAK,SAAS,UAAU,IAAI,GAAG;AAAA,IACvC;AACA,UAAM,OAAO,MAAM,cAA2B,4BAA4B,KAAK,MAAM,cAA2B,aAAa;AAC7H,QAAI,CAAC,SAAS,WAAW,QAAQ,MAAM,cAAc,OAAO;AAC1D,YAAM,KAAK,KAAK,sBAAsB;AACtC,YAAM,KAAK,GAAG,OAAO,GAAG,QAAQ;AAChC,YAAM,KAAK,GAAG,MAAM,GAAG,SAAS;AAChC,YAAM,MAAM,UAAU,IAAI,KAAK,CAAC,MAAM;AACpC,cAAM,IAAI,KAAK,CAAC;AAChB,cAAM,GAAG,MAAM,KAAK,MAAM,GAAG,MAAM,KAAK,MAAM,CAAC;AAAA,MACjD,CAAC;AACD,YAAM,MAAM,OAAO;AACnB,UAAI,KAAK;AACP,YAAI,cAAc,YAAY,IAAI,OAAO,YAAY,OAAO;AAC5D,cAAM,KAAK,IAAI,cAAc,aAAa,cAAc;AACxD,cAAM,KAAK,KAAK,IAAI,IAAI,cAAc,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,cAAc,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE;AACnG,YAAI,MAAM,UAAU;AAAA,MACtB;AACA,QAAE,aAAa,aAAa,EAAE;AAC9B,WAAK,aAAa,iBAAiB,EAAE;AACrC,YAAM,QAAQ,SAAS,IAAI,EAAE;AAC7B,UAAI,CAAC,QAAS,SAAQ,SAAS,QAAQ,CAAC,EAAE,SAAS,GAAG,WAAW,YAAY,GAAG,EAAE,SAAS,GAAG,WAAW,aAAa,CAAC,GAAG,EAAE,UAAU,KAAK,YAAY,EAAE,CAAC;AAC1J,YAAM,KAAK,SAAS,UAAU,IAAI,IAAI;AACtC,WAAK,gBAAgB,eAAe;AACpC,QAAE,gBAAgB,WAAW;AAC7B,UAAI,IAAK,KAAI,MAAM,UAAU;AAAA,IAC/B;AACA,MAAE,MAAM,UAAU;AAClB,WAAO,OAAO,GAAG,CAAC;AAClB,SAAK,SAAS,KAAK;AACnB,WAAO,SAAS,SAAS,IAAI;AAC7B,eAAW,UAAU;AACrB,eAAW,KAAK;AAChB,UAAM,UAAU,UAAU;AAC1B,cAAU,UAAU;AACpB,QAAI,WAAW,MAAM,QAAS,WAAU,QAAQ,SAAS,IAAI;AAAA,EAC/D;AACA,QAAM,UAAgB,cAAO,IAAI;AACjC,UAAQ,UAAU;AAGlB,QAAM,UAAU,MAAM,YAAY,SAAY,mBAAmB,MAAM;AACvE,QAAM,gBAAsB;AAAA,IAC1B,CAAC,OAAuB,QAA8B;AACpD,YAAM,OAAO,UAAU;AACvB,gBAAU,UAAU;AACpB,UAAI,SAAS,OAAQ,OAAM,OAAO,IAAI;AACtC,UAAI,WAAW,CAAC,SAAS,OAAO,GAAG;AACjC,kBAAU,OAAO;AACjB,mBAAW,MAAM;AACf,cAAI,MAAM,WAAW,SAAS,YAAY,MAAO,MAAK,QAAQ,QAAQ;AAAA,QACxE,GAAG,GAAG;AACN;AAAA,MACF;AACA,UAAI,SAAS,QAAQ,KAAK;AACxB,mBAAW,MAAM;AACf,cAAI,CAAC,MAAM,WAAW,SAAS,YAAY,SAAS,KAAK,WAAW,WAAW,QAAS;AACxF,oBAAU,UAAU,MAAM,OAAO,GAAG;AAAA,QACtC,GAAG,GAAG;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAGA,QAAM,SAAe,eAAQ,MAAM,WAAW,OAAO,OAAO,OAAO,QAAQ,GAAG,CAAC,OAAO,OAAO,OAAO,QAAQ,CAAC;AAC7G,QAAM,QAAQ,SAAS,MAAM,SAAS,KAAK,KAAK,SAAS;AACzD,QAAM,WAAiB,cAAO,KAAK;AACnC,QAAM,aAAa,MAAM;AACzB,EAAM,iBAAU,MAAM;AACpB,QAAI,SAAS,CAAC,SAAS,SAAS;AAC9B,mBAAa,MAAM;AAEnB;AAAA,QACE,GAAG,OAAO,QAAQ,GAAG,OAAO,KAAK,KAAK,OAAO,MAAM,KAAK,MAAM,OAAO,MAAM,MAAM,KAAK,OAAO,OAAO,KAAK,OAAO,WAAW,QAAQ,cAAc,OAAO,OAAO,QAAQ,CAAC,EAAE,QAAQ,WAAW,OAAO,OAAO,KAAK,CAAC,CAAC;AAAA,MACpN;AAAA,IACF;AACA,aAAS,UAAU;AAAA,EACrB,GAAG,CAAC,OAAO,QAAQ,YAAY,MAAM,CAAC;AAGtC,QAAM,OAAO,YAAY;AACvB,UAAMD,QAAO,MAAM,WACf,MAAM,SAAS,EAAE,MAAM,UAAU,OAAO,OAAO,CAAC,IAChD,WACE,aAAa,UAAU,OAAO,SAAS,QAAQ,UAAU,aAAa,IACtE,aAAa,QAAQ,KAAK;AAChC,UAAM,KAAK,MAAM,gBAAgBA,KAAI;AACrC,UAAM,KAAK,OAAO,SAAS,OAAO,UAAU;AAAA,EAC9C;AAGA,QAAM,YAAkB,cAAuB,IAAI;AACnD,EAAM,uBAAgB,MAAM;AAC1B,UAAM,IAAI,UAAU;AACpB,QAAI,CAAC,KAAK,CAAC,OAAQ;AACnB,UAAM,KAAK,EAAE,cAAc,aAAa,cAAc;AACtD,UAAM,IAAI,EAAE;AACZ,UAAM,IAAI,EAAE;AACZ,MAAE,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC;AACvE,MAAE,MAAM,MAAM,GAAG,OAAO,MAAM,IAAI,KAAK,IAAI,OAAO,SAAS,KAAK,OAAO,MAAM,IAAI,EAAE;AAAA,EACrF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK;AAErD,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,CAAC,YAAY,MAAM,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACjE,eAAa;AAAA,MACb,gBAAc,UAAU,KAAK;AAAA,MAC5B,GAAI,WAAW,WACZ;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,wBAAwB;AAAA,QACxB,eAAe,CAAC,MAA0C;AAExD,gBAAM,OAAO,EAAE;AACf,cAAI,CAAC,KAAK,SAAS,KAAK,cAAc,aAAa,EAAG,MAAK,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,QAC1F;AAAA,MACF,IACA,EAAE,UAAU,GAAG;AAAA,MAEnB;AAAA,wBAAAD,KAAC,SAAI,WAAU,qBAAoB,eAAY,QAC5C,mBAAS,IAAI,CAAC,GAAG,MAAM;AACtB,gBAAM,OACJ,MAAM,YACF,YACA,EAAE,SAAS,SACT,WAAW,OAAO,EAAE,MAAM,MAAM,QAAQ,EAAE,KAAK,EAAE,CAAC,GAAG,OACrD,EAAE,SAAS,UAAU,MAAM,MAAM,EAAE,KAAK,IACtC,YACA;AACV,iBAAO,gBAAAA,KAAC,OAAa,aAAW,QAAjB,EAAE,EAAqB;AAAA,QACxC,CAAC,GACH;AAAA,QAEA,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAU;AAAA,YACV,aAAW,CAAC,QAAQ,MAAM,CAAC,QAAQ,OAAO,MAAM;AAAA,YAChD,eAAa,OAAO,OAAO;AAAA,YAC3B,OAAO,OAAO,OAAO;AAAA,YACrB,sBAAsB,CAAC,MAAM;AAE3B,kBAAI,CAAC,UAAU,QAAS;AACxB,oBAAM,SAAS,CAAC,MAAoC,aAAa,WAAW,CAAC,CAAC,EAAE,QAAQ,gBAAgB;AACxG,kBAAI,OAAO,EAAE,MAAM,KAAK,OAAO,EAAE,cAAc,cAAc,aAAa,EAAG;AAC7E,wBAAU,UAAU;AACpB,mBAAK,UAAU,EAAE,GAAG,KAAK,SAAS,SAAS,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ;AAC3E,wBAAU,IAAI;AAAA,YAChB;AAAA,YAEC;AAAA,oBAAM,WACL,gBAAAD,KAAC,gBAAa,QAAO,MAAK,OAAO,OAAO,QAAQ,SAAS,MAAM,UAC7D,0BAAAA,KAAC,iBAAc,GACjB,IACE,MAAM,SACR,gBAAAA,KAAC,gBAAa,QAAO,MAAK,OAAO,MAAM,aAAa,aAAa,OAAO,WAAW,OAAO,MAAO,GAAI,MAAM,aAAa,aAAa,EAAE,UAAU,SAAS,IAAI,CAAC,GAAI,SAAS,MAAM,QAC/K,gBAAM,aAAa,aAAa,gBAAAA,KAAC,iBAAc,IAAK,gBAAAA,KAAC,SAAM,GAC9D,IACE;AAAA,cACJ,gBAAAC,MAAC,gBAAa,QAAO,MAAK,OAAO,OAAO,UAAU,SAAS,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,UAAU,KAAK,SAAS,OAAO,SAAS,WAC3J;AAAA,gCAAAD,KAAC,kBAAe;AAAA,gBACf,OAAO,WAAW,gBAAAA,KAAC,UAAK,WAAU,yBAAyB,iBAAO,UAAS,IAAU;AAAA,iBACxF;AAAA,cACA,gBAAAA,KAAC,gBAAa,QAAO,MAAK,OAAO,OAAO,MAAM,UAAS,KAAI,SAAS,MAAM,UAAU,CAAC,WAAW,SAC9F,0BAAAA,KAAC,aAAU,GACb;AAAA,cACA,gBAAAA,KAAC,gBAAa,QAAO,MAAK,OAAO,OAAO,MAAM,SAAS,MAAM,KAAK,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,QACnG,0BAAAA,KAAC,YAAS,GACZ;AAAA,cAEC,WACC,gBAAAA,KAAC,eAAY,QAAQ,SAAS,WAAW,cAAc,MAAM,UAAU,UAAU,CAAC,MAAM,IAAI,CAAC,GAAG,iBAAiB,OAAO,YAAY,IAClI;AAAA,cAEJ,gBAAAA,KAAC,SAAI,WAAU,kBACZ,WAAC,QACA,gBAAAA,KAAC,SAAI,WAAU,kBAAiB,cAAY,WAAW,QACpD,qBAAW,WAAW,UACrB,gBAAAA,KAAC,YAAS,WAAU,oBAAmB,SAAS,WAAW,aAAa,IAAI,WAAU,iBAAgB,QAAO,2BAA0B,IAEvI,gBAAAA,KAAC,eAAY,WAAU,+BAA8B,GAEzD,IACE,MAAM,WAAW,IACnB,gBAAAA,KAAC,aAAsB,OAAO,MAAM,OAAO,SAAS,OAAO,YAAY,MAAM,MAAM,OAAO,MAAM,QAAQ,MAAM,OAAO,QAAQ,YAA9G,OAAkI,IAC/I,aAAa,KAAK,SAAS,QAC7B,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,aAAa,MAAM;AAAA,kBACnB;AAAA,kBACA;AAAA,kBACA,QAAQ;AAAA,oBACN,QAAQ,MAAM,aAAa,KAAK;AAAA,oBAChC,QAAQ,MAAM;AACZ,mCAAa,KAAK;AAClB,2BAAK,KAAK;AAAA,oBACZ;AAAA,kBACF;AAAA,kBACA,UAAU,CAAC,SAAS;AAClB,8BAAU,UAAU;AACpB,0BAAM,MAAM,SAAS;AACrB,0BAAM,MAAgB,CAAC,EAAE,MAAM,UAAU,QAAQ,KAAK,IAAI,QAAQ,KAAK,CAAC;AACxE,wBAAI,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,MAAM,KAAK,GAAI,KAAI,KAAK,EAAE,MAAM,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,CAAC;AAC/G,+BAAW,OAAO,WAAW,KAAK,KAAK,KAAK,CAAC;AAC7C,iCAAa,KAAK;AAClB,4BAAQ,GAAG,OAAO,MAAM,KAAK,KAAK,IAAI,EAAE;AAAA,kBAC1C;AAAA;AAAA,gBAtBI;AAAA,cAuBN,IACE,KAAK,SAAS,SAChB,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC,MAAM,KAAK;AAAA,kBACX,QAAQ;AAAA,kBACR;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,MAAM,MAAM,eAAe,QAAQ,CAAC,IAAI;AAAA,kBACxC,WAAW,MAAM,aAAa;AAAA,kBAC9B,QAAQ;AAAA,kBACR,UAAU,CAAC,MAAM,cAAc,EAAE,IAAI,KAAK,KAAK,IAAI,QAAQ,EAAE,CAAC;AAAA,kBAC9D,MAAM,eAAe,MAAM,iBAAiB,MAAM,eAAe,WAAW,IAAI;AAAA,kBAChF,YAAY,MAAM,UAAU,IAAI;AAAA,kBAChC,SAAS,eAAe,MAAM,oBAAoB,MAAM,kBAAkB,WAAW,IAAI;AAAA,kBACzF,aAAa,MAAM,kBAAkB,SAAU,MAAM,iBAAiB,YAAY,UAAU,CAAC,CAAC,KAAK,KAAK;AAAA,kBACxG,UAAU,CAAC,MAAM;AAEf,wBAAI,QAAQ,QAAS,SAAQ,UAAU;AAAA,wBAClC,KAAI,CAAC;AAAA,kBACZ;AAAA,kBACA,cAAc,CAAC,MAAM;AACnB,wBAAI,QAAQ,QAAS,SAAQ,UAAU;AAAA,wBAClC,MAAK,KAAK,GAAG,IAAI;AAAA,kBACxB;AAAA,kBACA;AAAA,kBACA,WAAW;AAAA,kBACX,mBAAmB,CAAC,MAAM,SAAS,KAAK,MAAM,CAAC;AAAA;AAAA,gBA1B1C,KAAK;AAAA,cA2BZ,IACE,KAAK,SAAS,SAChB,gBAAAA,KAAC,YAAuB,MAAY,OAAO,MAAM,cAAc,KAAK,KAAK,KAAK,OAAO,MAAM,QAAgB,UAAoB,QAAQ,MAAM,aAA9H,KAAK,EAA+I,IAEnK,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA,aAAa,MAAM;AAAA,kBACnB;AAAA,kBACA;AAAA,kBACA,SAAS,MAAM;AAAA,kBACf,UAAU,CAAC,SAAS;AAElB,8BAAU,UAAU;AACpB,0BAAM,MAAM,SAAS;AACrB,0BAAM,MAAgB,CAAC,EAAE,MAAM,UAAU,QAAQ,KAAK,IAAI,QAAQ,KAAK,CAAC;AAExE,wBAAI,KAAK,SAAS,IAAI,MAAM,KAAK,KAAK,MAAM,KAAK,GAAI,KAAI,KAAK,EAAE,MAAM,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,CAAC;AAC/G,+BAAW,OAAO,WAAW,KAAK,KAAK,KAAK,CAAC;AAC7C,4BAAQ,GAAG,OAAO,MAAM,KAAK,KAAK,IAAI,EAAE;AAAA,kBAC1C;AAAA,kBAEC,gBAAM,YAAY,MAAM;AAAA;AAAA,gBAnBrB;AAAA,cAoBN,GAEJ;AAAA,cACA,gBAAAA,KAAC,QAAK,KAAK,MAAM;AAAA;AAAA;AAAA,QACnB;AAAA,QAEC,WAAW,aACV,gBAAAA,KAAC,YAAS,WAAU,kBAAiB,SAAS,WAAW,YAAY,WAAU,kBAAiB,QAAO,2BAA0B,IAC/H;AAAA,QAEH,QAAQ,WACP,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,MAAM;AAAA,YACN,OAAO,QAAQ,OAAO,QAAQ;AAAA,YAC9B,SAAS,EAAE,OAAO,KAAK,OAAO,KAAK,KAAK,IAAI;AAAA,YAC5C,QAAQ;AAAA,YACR,SAAS,OAAO,OAAO,QAAQ;AAAA,YAC/B;AAAA,YACA,YAAY;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,oBAAoB,MAAM,uBAAuB;AAAA,YACjD;AAAA,YACA;AAAA,YACA,SAAS,MAAM,QAAQ,IAAI;AAAA,YAC3B,SAAS,CAAC,MAAM,YAAY,UAAU,CAAC;AAAA,YACvC,UAAU,CAAC,SAAS,aAAa,UAAU,IAAI;AAAA,YAC/C,kBAAkB,CAAC,MAAM,QAAQ,QAAQ;AACvC,wBAAU,UAAU;AACpB,yBAAW,OAAO,WAAW,SAAS,SAAS,CAAC,EAAE,MAAM,YAAY,MAAM,QAAQ,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC,EAAG,CAAC,GAAG,KAAK,CAAC;AAAA,YACtH;AAAA,YACA,UAAU;AAAA;AAAA,UAnBL,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK;AAAA,QAoBnC,IACE;AAAA,QAEJ,gBAAAC,MAAC,SAAI,WAAU,iBAAgB,QAAQ,CAAC,SAAS,eAAe,MAAO,SAAS,UAAU,MACxF;AAAA,0BAAAD,KAAC,SAAI,KAAK,SAAS,WAAU,iBAAgB;AAAA,UAC7C,gBAAAA,KAAC,SAAI,KAAK,WAAW,WAAU,mBAAkB;AAAA,UACjD,gBAAAA,KAAC,SAAI,KAAK,QAAQ,WAAU,qBAAoB;AAAA,WAClD;AAAA,QACC,SACC,gBAAAA,KAAC,SAAI,KAAK,WAAW,WAAU,mBAAkB,MAAK,UACnD,iBAAO,MACV,IACE;AAAA,QACJ,gBAAAA,KAAC,SAAI,WAAU,kBAAiB,MAAK,UAAS,aAAU,UAAS,WAAS,QAAQ,KAAK,QACpF,iBACH;AAAA,QACA,gBAAAA,KAAC,SAAI,WAAU,eAAc,aAAU,UAAS,eAAY,QACzD,gBACH;AAAA;AAAA;AAAA,EACF;AAEJ;AA+BA,IAAM,eAAyC,CAAC,MAAM,SAAS,QAAQ,MAAM;AAE7E,SAAS,UAAU,EAAE,OAAO,KAAK,GAAyC;AACxE,QAAM,QAAQ,MAAM,SAAS;AAC7B,SACE,gBAAAA,KAAC,UAAK,WAAU,kBAAiB,cAAY,OAAO,aAAW,MAC5D,mBAAS,QAAQ,gBAAAA,KAAC,SAAI,KAAK,MAAM,KAAK,KAAK,MAAM,OAAO,IAAI,WAAW,OAAO,IAAK,MAAM,MAC5F;AAEJ;AAEA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkB;AAChB,QAAM,QAAc,cAAuB,IAAI;AAC/C,QAAM,QAAc,cAAuB,IAAI;AAC/C,QAAM,OAAa,cAA6B,IAAI;AACpD,QAAM,SAAe,eAAQ,MAAM,SAAS,KAAK,IAAI,GAAG,CAAC,KAAK,IAAI,CAAC;AACnE,QAAM,QAAQ,QAAQ,OAAO,IAAI;AACjC,QAAM,YAAY,SAAS,QAAQ,KAAK,WAAW,IAAI;AACvD,QAAM,MAAM,WAAW,MAAM,MAAM;AACnC,QAAM,SAAS,CAAC,OAAe;AAC7B,UAAM,OAAO,IAAI,SAAS,EAAE,IAAI,IAAI,OAAO,CAAC,MAAM,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK,EAAE;AACzE,aAAS,EAAE,GAAI,UAAU,CAAC,GAAI,KAAK,KAAK,CAAC;AAAA,EAC3C;AAEA,EAAM,uBAAgB,MAAM;AAC1B,aAAS,UAAU,MAAM;AACzB,QAAI,MAAM,QAAS,WAAU,MAAM,SAAS,YAAY;AACxD,WAAO,MAAM;AACX,UAAI,SAAS,YAAY,MAAM,QAAS,UAAS,UAAU;AAAA,IAC7D;AAAA,EAGF,GAAG,CAAC,CAAC;AAEL,QAAM,WAAW,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,IAAI,EAAE,GAAG,EAAE,EAAE,KAAK,GAAG;AACjE,EAAM,uBAAgB,MAAM;AAC1B,UAAM,MAAM,MAAM;AAClB,QAAI,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,KAAK,QAAS;AAC7C,WAAO,WAAW,KAAK,MAAM;AAC3B,UAAI,CAAC,MAAM,WAAW,CAAC,KAAK,QAAS;AACrC,UAAI,cAAc,MAAO,SAAQ,KAAK,MAAM,SAAS,KAAK,SAAS,IAAI,QAAQ,GAAG,CAAC;AAAA,UAC9E,cAAa,KAAK,MAAM,OAAO;AAAA,IACtC,CAAC;AAAA,EACH,GAAG,CAAC,KAAK,MAAM,UAAU,KAAK,SAAS,QAAQ,KAAK,QAAQ,SAAS,CAAC;AAEtE,QAAM,QAA2B,CAAC;AAClC,WAAS,IAAI,GAAG,IAAI,OAAO,UAAU;AACnC,UAAM,IAAI,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;AACzC,QAAI,GAAG;AACL,YAAM,IAAI,SAAS,QAAQ,WAAW,GAAG,OAAO,QAAQ,QAAQ,CAAC;AACjE,YAAM,QAA2B,CAAC;AAClC,eAAS,IAAI,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK;AACrC,cAAM;AAAA,UACJ,gBAAAA,KAAC,UAAa,WAAU,kBAAiB,aAAW,GACjD,iBAAO,CAAC,KADA,CAEX;AAAA,QACF;AACA,YAAI,IAAI,EAAE,IAAK,OAAM,KAAK,GAAG;AAAA,MAC/B;AACA,YAAM;AAAA,QACJ,gBAAAA,KAAC,UAAmB,WAAU,iBAAgB,gBAAc,GAAG,aAAW,GAAG,MAAM,sBAAoB,CAAC,GAAG,OAAO,GAAG,EAAE,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK,SAAS,MAAM,CAAC,GAC/K,mBADQ,IAAI,CAAC,EAEhB;AAAA,MACF;AACA,UAAI,EAAE,MAAM;AAAA,IACd,OAAO;AACL,YAAM;AAAA,QACJ,gBAAAA,KAAC,UAAa,WAAU,kBAAiB,aAAW,GACjD,iBAAO,CAAC,KADA,CAEX;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,IAAI,OAAO,OAAQ,OAAM,KAAK,GAAG;AAAA,EACvC;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAU;AAAA,MACV,gBAAc,KAAK;AAAA,MACnB,iBAAe,cAAc,SAAS,SAAS;AAAA,MAC/C,cAAY,CAAC,KAAK,QAAQ,KAAK,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,MAC9D,eAAe,CAAC,MAAM;AACpB,cAAM,IAAI,EAAE,kBAAkB,UAAU,EAAE,OAAO,QAAQ,aAAa,IAAI;AAC1E,YAAI,EAAG,mBAAkB,OAAO,EAAE,aAAa,WAAW,CAAC,CAAC;AAAA,MAC9D;AAAA,MAEA,0BAAAC,MAAC,SAAI,KAAK,OAAO,WAAU,iBACxB;AAAA,aAAK,QAAQ,gBAAAD,KAAC,aAAU,OAAO,KAAK,OAAO,IAAK;AAAA,QAChD,KAAK,UAAU,KAAK,OAAO,UAC1B,gBAAAC,MAAC,SAAI,WAAU,mBACZ;AAAA,eAAK,SAAS,gBAAAD,KAAC,UAAM,eAAK,QAAO,IAAU;AAAA,UAC3C,KAAK,MACJ,gBAAAC,MAAC,UAAK,WAAU,gBACd;AAAA,4BAAAD,KAAC,aAAU;AAAA,YACV,KAAK;AAAA,aACR,IACE;AAAA,UACH,UAAU,gBAAAA,KAAC,UAAK,WAAU,oBAAoB,mBAAQ,IAAU;AAAA,WACnE,IACE;AAAA,QACJ,gBAAAA,KAAC,OAAE,KAAK,MAAM,WAAU,iBAAgB,eAAa,KAAK,SAAS,KAAK,QACrE,iBACH;AAAA,QACC,KAAK,SAAS,SACb,gBAAAA,KAAC,SAAI,WAAU,oBACZ,eAAK,QAAQ,IAAI,CAAC,MAAM;AACvB,gBAAM,QAAQ,IAAI,SAAS,EAAE,EAAE;AAC/B;AAAA;AAAA,YAEE,gBAAAC,MAAC,YAAkB,MAAK,UAAS,WAAU,mBAAkB,gBAAc,CAAC,OAAO,YAAU,QAAQ,KAAK,QAAW,SAAS,MAAM,OAAO,EAAE,EAAE,GAC5I;AAAA,gBAAE,QAAQ,gBAAAD,KAAC,aAAU,OAAO,EAAE,OAAO,MAAK,SAAQ,IAAK;AAAA,cACxD,gBAAAA,KAAC,UAAM,YAAE,OAAM;AAAA,iBAFJ,EAAE,EAGf;AAAA;AAAA,QAEJ,CAAC,GACH,IACE;AAAA,QACH,OACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,QAAQ,CAAC,MAAM;AAEb,oBAAM,OAAO,EAAE,yBAAyB,OAAO,EAAE,gBAAgB;AAEjE,kBAAI,CAAC,EAAE,cAAc,cAAc,SAAS,EAAG;AAC/C,kBAAI,CAAC,QAAQ,CAAC,EAAE,cAAc,SAAS,IAAI,EAAG,YAAW;AAAA,YAC3D;AAAA,YAEC;AAAA;AAAA,QACH,IACE;AAAA,QACH,cACC,gBAAAC,MAAC,SAAI,WAAU,oBACZ;AAAA,uBAAa,IAAI,CAAC,MAAM;AACvB,kBAAM,IAAI,OAAO,CAAC;AAClB,gBAAI,CAAC,EAAG,QAAO;AACf;AAAA;AAAA,cAEE,gBAAAA,MAAC,YAAe,MAAK,UAAS,WAAU,mBAAkB,kBAAe,IAAG,YAAU,GAAG,aAAW,EAAE,MAAM,SAAS,MAAM,SAAS,CAAC,GACnI;AAAA,gCAAAD,KAAC,eAAY,QAAQ,EAAE,GAAG,GAAG,MAAM,OAAU,GAAG,KAAK,GAAG;AAAA,gBACxD,gBAAAA,KAAC,UAAM,YAAE,OAAM;AAAA,mBAFJ,CAGb;AAAA;AAAA,UAEJ,CAAC;AAAA,UACA,KAAK,IAAI,CAAC;AAAA;AAAA,YAET,gBAAAC,MAAC,YAAkB,MAAK,UAAS,WAAU,mBAAkB,kBAAe,IAAG,aAAW,EAAE,MAAM,OAAO,EAAE,WAAW,GAAG,EAAE,KAAK,KAAK,EAAE,QAAQ,MAAM,EAAE,OAAO,SAAS,MAAM,aAAa,CAAC,GACxL;AAAA,gBAAE,QAAQ;AAAA,cACX,gBAAAD,KAAC,UAAM,YAAE,OAAM;AAAA,iBAFJ,EAAE,EAGf;AAAA,WACD;AAAA,WACH,IACE,KAAK,SACP,gBAAAA,KAAC,SAAI,WAAU,iBACZ,eAAK,IAAI,CAAC;AAAA;AAAA,UAET,gBAAAC;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,kBAAe;AAAA,cACf,aAAW,EAAE;AAAA,cACb,kBAAgB,KAAK,cAAc,EAAE,KAAK,KAAK;AAAA,cAC/C,qBAAmB,EAAE;AAAA,cACrB,OAAO,EAAE,WAAW,GAAG,EAAE,KAAK,KAAK,EAAE,QAAQ,MAAM,EAAE;AAAA,cACrD,SAAS,MAAM,aAAa,CAAC;AAAA,cAE5B;AAAA,kBAAE,QAAQ;AAAA,gBACX,gBAAAD,KAAC,UAAM,YAAE,OAAM;AAAA;AAAA;AAAA,YAXV,EAAE;AAAA,UAYT;AAAA,SACD,GACH,IACE;AAAA,QACH,aAAa,KAAK,UAAU,KAAK,QAAQ,SACxC,gBAAAC,MAAC,SAAI,WAAU,mBACZ;AAAA,sBACC,gBAAAA,MAAC,SACC;AAAA,4BAAAD,KAAC,SAAI,WAAU,kBAAkB,iBAAO,YAAW;AAAA,YACnD,gBAAAC,MAAC,SAAI,WAAU,sBAAqB,aAAW,UAAU,MACvD;AAAA,8BAAAD,KAAC,eAAY,QAAQ,WAAW,KAAK,cAAc;AAAA,cAClD,KAAK,kBAAkB,UAAU;AAAA,eACpC;AAAA,aACF,IACE;AAAA,UACH,KAAK,SACJ,gBAAAC,MAAC,SACC;AAAA,4BAAAD,KAAC,SAAI,WAAU,kBAAkB,iBAAO,QAAO;AAAA,YAC/C,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,eAAK,QAAO;AAAA,aAC/C,IACE;AAAA,UACH,KAAK,QAAQ,IAAI,CAAC,MACjB,gBAAAC,MAAC,SACC;AAAA,4BAAAD,KAAC,SAAI,WAAU,kBAAkB,YAAE,OAAM;AAAA,YACzC,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,YAAE,OAAM;AAAA,eAFjC,EAAE,KAGZ,CACD;AAAA,WACH,IACE;AAAA,SACN;AAAA;AAAA,EACF;AAEJ;AAaA,SAAS,SAAS,EAAE,MAAM,OAAO,QAAQ,UAAU,WAAW,OAAO,GAAkB;AACrF,QAAM,QAAc,cAAuB,IAAI;AAC/C,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAwB,IAAI;AAC9D,EAAM,uBAAgB,MAAM;AAC1B,aAAS,UAAU,MAAM;AACzB,UAAM,OAAO,UAAU;AACvB,cAAU,UAAU;AACpB,QAAI,SAAS,OAAQ,OAAM,MAAM,SAAS,IAAI;AAAA,EAEhD,GAAG,CAAC,CAAC;AACL,EAAM,uBAAgB,MAAM;AAC1B,UAAM,MAAM,MAAM;AAClB,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,MAAM;AAChB,YAAM,UAAU,MAAM,KAAK,IAAI,iBAA8B,kBAAkB,CAAC;AAChF,UAAI,KAAK;AACT,UAAI,MAAM,IAAI,cAAc,aAAa,cAAc,MAAM,OAAO,KAAK;AACzE,UAAI,OAAO;AACX,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,cAAM,OAAO,KAAK,MAAM;AACxB,gBAAQ,QAAQ,CAAC,MAAO,EAAE,MAAM,WAAW,GAAG,GAAG,IAAK;AACtD,cAAM,KAAK,QAAQ,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,eAAe,KAAK,EAAE,eAAe,EAAE,cAAc,CAAC;AAC1G,YAAI,IAAI;AACN,iBAAO;AACP,eAAK;AAAA,QACP,MAAO,MAAK;AAAA,MACd;AACA,cAAQ,QAAQ,CAAC,MAAO,EAAE,MAAM,WAAW,GAAG,KAAK,MAAM,IAAI,CAAC,IAAK;AAEnE,YAAMI,QAAO,IAAI,cAA2B,mBAAmB;AAC/D,UAAIA,SAAQA,MAAK,eAAe,IAAI,eAAe,EAAG,KAAI,aAAa,oBAAoB,EAAE;AAAA,UACxF,KAAI,gBAAgB,kBAAkB;AAAA,IAC7C;AACA,WAAO,WAAW,KAAK,GAAG;AAAA,EAC5B,GAAG,CAAC,KAAK,MAAM,MAAM,CAAC;AACtB,SACE,gBAAAJ,KAAC,SAAI,KAAK,OAAO,WAAU,kBACzB,0BAAAA,KAAC,SAAI,WAAU,oBAAmB,MAAK,cAAa,cAAY,OAC7D,eAAK,MAAM,IAAI,CAAC;AAAA;AAAA,IAEf,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,gBAAc,WAAW,KAAK;AAAA,QAC9B,WAAU;AAAA,QACV,kBAAgB,KAAK,gBAAgB,KAAK;AAAA,QAC1C,eAAa,WAAW,KAAK,KAAK,KAAK;AAAA,QACvC,SAAS,MAAM;AACb,oBAAU,KAAK,EAAE;AACjB,iBAAO,KAAK,OAAO,IAAI;AAAA,QACzB;AAAA,QAEC;AAAA,eAAK,gBAAgB,gBAAAD,KAAC,UAAK,WAAU,kBAAkB,iBAAO,YAAW,IAAU;AAAA,UACpF,gBAAAA,KAAC,UAAM,eAAK,MAAK;AAAA;AAAA;AAAA,MAbZ,KAAK;AAAA,IAcZ;AAAA,GACD,GACH,GACF;AAEJ;AA4BA,SAAS,UAAU,QAAoB,QAAqC;AAC1E,QAAM,SAAS,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,IAAI;AACxE,MAAI,OAAO,SAAS,OAAO,QAAQ;AACjC,UAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;AAC5C,WAAO;AAAA,MACL,EAAE,KAAK,SAAS,OAAO,OAAO,OAAO,MAAM,WAAW,OAAO,MAAM;AAAA,MACnE,EAAE,KAAK,SAAS,OAAO,OAAO,OAAO,MAAM,eAAe,OAAO,OAAO,SAAS,MAAM;AAAA,IACzF,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,EAC7B;AACA,QAAM,MAAM,oBAAI,IAAsB;AACtC,aAAW,KAAK,OAAO,SAAS;AAC9B,QAAI,CAAC,EAAE,OAAQ;AACf,UAAM,MAAM,EAAE,OAAO;AACrB,UAAM,MAAM,IAAI,IAAI,GAAG;AACvB,QAAI,IAAI,KAAK,EAAE,KAAK,OAAO,EAAE,OAAO,OAAO,MAAM,KAAK,QAAQ,EAAE,OAAO,MAAM,QAAQ,KAAK,SAAS,KAAK,EAAE,CAAC;AAAA,EAC7G;AACA,SAAO,CAAC,GAAG,IAAI,OAAO,CAAC;AACzB;AAEA,SAAS,QAAQ,OAAsC,QAAgC;AACrF,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,MAAI,UAAU,MAAM,UAAU,KAAM,QAAO,MAAM,QAAQ,UAAU;AACnE,SAAO,MAAM,OAAO;AACtB;AAGA,SAAS,QAAQ,EAAE,QAAQ,OAAO,QAAQ,aAAa,UAAU,WAAW,SAAS,UAAU,UAAU,OAAO,GAAiB;AAC/H,QAAM,QAAc,cAAuB,IAAI;AAC/C,EAAM,uBAAgB,MAAM;AAC1B,aAAS,UAAU,MAAM;AACzB,UAAM,OAAO,UAAU;AACvB,cAAU,UAAU;AACpB,QAAI,SAAS,OAAQ,OAAM,MAAM,SAAS,IAAI;AAAA,EAEhD,GAAG,CAAC,CAAC;AACL,QAAM,CAAC,QAAQ,SAAS,IAAU,gBAAwB,IAAI;AAC9D,MAAI,UAAU;AACZ,WACE,gBAAAA,KAAC,SAAI,KAAK,OAAO,WAAU,kBACxB,UACH;AAAA,EAEJ;AACA,QAAM,QAAQ,OAAO,QAAQ,OAAO,KAAK;AACzC,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,QAAM,QAAQ,OAAO;AACrB,QAAM,SAAS,UAAU,QAAQ,MAAM;AACvC,QAAM,SAAS,CAAC,CAAC,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,WAAW,EAAE,QAAQ,OAAO;AACnF,QAAM,WAAW,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM;AACtD,QAAM,QAAQ,SAAS,SAAS,OAAO,CAAC,MAAM,QAAQ,GAAG,MAAM,MAAM,MAAM,IAAI;AAC/E,QAAM,MAAM,SAAS,MAAM,SAAS,MAAM,QAAQ,MAAM,SAAS;AACjE,QAAM,SAAS,SAAS,OAAO,QAAS,cAAc,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,IAAK,QAAQ,OAAO,QAAQ;AACtG,QAAM,WAAW,SAAS,OAAO,WAAW,QAAQ,MAAM,CAAC,EAAE,OAAO,QAAQ,GAAG,MAAM,KAAK,MAAM,MAAM,MAAM,KAAK,OAAO;AACxH,QAAM,MAAM,OAAO,WAAW,QAAQ,cAAc,OAAO,OAAO,QAAQ,CAAC,EAAE,QAAQ,WAAW,OAAO,OAAO,KAAK,CAAC;AACpH,SACE,gBAAAA,KAAC,SAAI,KAAK,OAAO,WAAU,oCACzB,0BAAAC,MAAC,SAAI,WAAU,gBAAe,eAAa,SAAS,KAAK,QAAW,eAAa,SAAS,KAAK,QAC5F;AAAA,aAAS,OACV,gBAAAA,MAAC,SAAI,WAAU,iBAAgB,SAAQ,aAAY,eAAY,QAAO,aAAW,QAAS,OAAO,MAAM,YAAY,YAAa,WAC9H;AAAA,sBAAAD,KAAC,YAAO,WAAU,uBAAsB,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,MAC/D,gBAAAA,KAAC,YAAO,WAAU,sBAAqB,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,YAAY,KAAK,OAAO,EAAE,iBAAiB,GAAG,KAAK,MAAM,MAAM,GAAG,CAAC,OAAO,GAAG;AAAA,MAC1I,CAAC,SAAS,QAAQ,IAAI,gBAAAA,KAAC,UAAK,WAAU,uBAAsB,GAAE,sBAAqB,YAAY,KAAK,IAAK;AAAA,OAC5G;AAAA,IAEC,SAAS,gBAAAA,KAAC,SAAI,WAAU,mBAAmB,kBAAO,IAAS;AAAA,IAC5D,gBAAAA,KAAC,QAAG,WAAU,qBAAqB,oBAAS;AAAA,IAC5C,gBAAAA,KAAC,SAAI,WAAU,oBAAoB,eAAI;AAAA,IACtC,SAAS,SAAS,CAAC,SAClB,gBAAAC,MAAC,SAAI,WAAU,oBACb;AAAA,sBAAAD,KAAC,SAAI,WAAU,kBAAkB,iBAAO,OAAM;AAAA,MAC9C,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,aAAG,MAAM,KAAK,MAAM,MAAM,MAAM,IAAG;AAAA,OACtE,IACE;AAAA,KACF,SAAS,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,MACrC,gBAAAC,MAAC,SAAgB,WAAU,oBACzB;AAAA,sBAAAD,KAAC,SAAI,WAAU,kBAAkB,wBAAc,KAAK,KAAK,OAAM;AAAA,MAC/D,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,eAAK,MAAK;AAAA,SAFnC,KAGV,CACD;AAAA,IACA,OAAO,SACN,gBAAAC,MAAAF,WAAA,EACE;AAAA,sBAAAC,KAAC,SAAI,WAAU,kBAAiB,eAAY,QACzC,iBAAO,IAAI,CAAC,MACX,gBAAAA,KAAC,OAAc,aAAW,EAAE,MAAM,OAAO,EAAE,UAAU,EAAE,MAAM,KAArD,EAAE,GAAsD,CACjE,GACH;AAAA,MACA,gBAAAC,MAAC,SAAI,WAAU,mBAAkB,MAAK,SAAQ,cAAY,OAAO,eAC9D;AAAA,eAAO,SAAS;AAAA;AAAA,UAEf,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,gBAAc,WAAW,MAAM,SAAS,MAAM,UAAU,IAAI,GACjH;AAAA,4BAAAD,KAAC,UAAM,iBAAO,SAAQ;AAAA,YACtB,gBAAAA,KAAC,OAAG,mBAAS,QAAO;AAAA,aACtB;AAAA,YACE;AAAA,QACH,OAAO,IAAI,CAAC;AAAA;AAAA,UAEX,gBAAAC;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,aAAW,EAAE;AAAA,cACb,gBAAc,WAAW,EAAE;AAAA,cAC3B,SAAS,MAAM,UAAU,CAAC,MAAO,MAAM,EAAE,MAAM,OAAO,EAAE,GAAI;AAAA,cAE5D;AAAA,gCAAAD,KAAC,OAAE,eAAY,QAAO;AAAA,gBACtB,gBAAAA,KAAC,UAAM,YAAE,OAAM;AAAA,gBACf,gBAAAA,KAAC,OAAG,YAAE,OAAM;AAAA;AAAA;AAAA,YATP,EAAE;AAAA,UAUT;AAAA,SACD;AAAA,SACH;AAAA,OACF,IACE;AAAA,IACH,MAAM,SACL,gBAAAA,KAAC,QAAG,WAAU,mBAAkB,cAAY,OAAO,aAChD,gBAAM,IAAI,CAAC,MAAM;AAChB,YAAM,WAAW,EAAE,KAAK,YAAY,SAAY,CAAC,IAAI,OAAO,EAAE,KAAK,YAAY,WAAW,CAAC,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK;AAEpH,YAAM,OAAO,OAAO,EAAE,QAAQ,UAAU,YAAY,EAAE,OAAO,MAAM,KAAK,IAAI,EAAE,OAAO,QAAQ,EAAE,KAAK;AACpG,YAAM,cAAc,OAAO,EAAE,QAAQ,UAAU,YAAY,EAAE,OAAO,QAAQ,EAAE,OAAO,QAAQ,EAAE,QAAQ;AACvG,YAAM,aAAa,SAAS,IAAI,CAAC,OAAO,WAAW,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AACvG,aACE,gBAAAA,KAAC,QAEC,0BAAAC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM,SAAS,EAAE,IAAI;AAAA,UAC9B,cAAY;AAAA,YACV,GAAG,OAAO,MAAM,KAAK,IAAI;AAAA,YACzB,CAAC,aAAa,EAAE,UAAU,OAAO,OAAO,QAAQ,EAAE,UAAU,QAAQ,OAAO,QAAQ,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,YAClH,EAAE,UAAU,SAAS,aAAa,GAAG,OAAO,WAAW,KAAK,UAAU,KAAK;AAAA,UAC7E,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,UAEZ;AAAA,4BAAAA,MAAC,UAAK,WAAU,wBACb;AAAA,gBAAE,KAAK,SAAS,gBAAAD,KAAC,UAAK,WAAU,kBAAkB,YAAE,KAAK,QAAO,IAAU;AAAA,cAC3E,gBAAAA,KAAC,UAAK,WAAU,wBAAwB,gBAAK;AAAA,cAC5C,EAAE,UAAU,SAAS,aACpB,gBAAAC,MAAC,UAAK,WAAU,yBACb;AAAA,uBAAO;AAAA,gBAAY;AAAA,gBAAG;AAAA,iBACzB,IACE;AAAA,eACN;AAAA,YACA,gBAAAA,MAAC,UAAK,WAAU,0BAAyB,aAAW,EAAE,UAAU,OAAO,EAAE,QAAQ,OAAO,EAAE,QAAQ,YAAY,eAC3G;AAAA,gBAAE,UAAU,OAAO,gBAAAD,KAAC,aAAU,IAAK,EAAE,UAAU,QAAQ,gBAAAA,KAAC,SAAM,IAAK;AAAA,cACpE,gBAAAA,KAAC,UAAM,uBAAY;AAAA,eACrB;AAAA,YACA,gBAAAA,KAAC,cAAW,WAAU,0BAAyB,eAAY,QAAO;AAAA;AAAA;AAAA,MACpE,KA5BO,EAAE,KAAK,EA6BhB;AAAA,IAEJ,CAAC,GACH,IACE;AAAA,IACH,SACC,gBAAAC,MAAC,SAAI,WAAU,wBAEb;AAAA,sBAAAD,KAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,OAAO,QAAQ,WAAS,MACrF,iBAAO,aACV;AAAA,MACC,OAAO;AAAA;AAAA,QAEN,gBAAAC,MAAC,YAAO,MAAK,UAAS,WAAU,wBAAuB,SAAS,OAAO,QACrE;AAAA,0BAAAD,KAAC,kBAAe,eAAY,QAAO;AAAA,UACnC,gBAAAA,KAAC,UAAM,iBAAO,MAAK;AAAA,WACrB;AAAA,UACE;AAAA,OACN,IACE,UACF,gBAAAA,KAAC,SAAI,WAAU,wBAAwB,mBAAQ,IAC7C;AAAA,KACN,GACF;AAEJ;AAGA,SAAS,UAAU,EAAE,OAAO,MAAM,QAAQ,SAAS,GAAoI;AACrL,QAAM,QAAc,cAAuB,IAAI;AAC/C,EAAM,uBAAgB,MAAM;AAC1B,aAAS,UAAU,MAAM;AACzB,UAAM,MAAM,SAAS,IAAI;AAAA,EAE3B,GAAG,CAAC,CAAC;AACL,SACE,gBAAAA,KAAC,SAAI,KAAK,OAAO,WAAU,oCAAmC,iBAAc,IAC1E,0BAAAC,MAAC,SAAI,WAAU,+BACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,wBAAuB,eAAY,QAChD;AAAA,sBAAAD,KAAC,OAAE;AAAA,MACH,gBAAAA,KAAC,OAAE;AAAA,MACH,gBAAAA,KAAC,OAAE;AAAA,OACL;AAAA,IACA,gBAAAA,KAAC,QAAG,WAAU,qBAAqB,iBAAM;AAAA,IACxC,OAAO,gBAAAA,KAAC,SAAI,WAAU,oBAAoB,gBAAK,IAAS;AAAA,IACxD,SAAS,gBAAAA,KAAC,SAAI,WAAU,wBAAwB,kBAAO,IAAS;AAAA,KACnE,GACF;AAEJ;;;AQt/CA,YAAYK,YAAW;AACvB,SAAS,oBAAoB;AA4BzB,SAGI,OAAAC,MAHJ,QAAAC,aAAA;AAhBG,SAAS,oBAAoB,EAAE,kBAAkB,OAAO,gBAAgB,GAAG,MAAM,GAA6B;AACnH,QAAM,aAAa,kBAAkB,EAAE,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS,cAAc,MAAM,cAAc,UAAU,MAAM,SAAS,CAAC;AAC/I,QAAM,CAAC,UAAU,WAAW,IAAU,gBAAS,eAAe;AAC9D,QAAM,SAAe,cAAuB,IAAI;AAChD,QAAM,OAAO,MAAM;AACjB,QAAI,iBAAiB,IAAI,MAAM,KAAM;AACrC,gBAAY,IAAI;AAAA,EAClB;AACA,QAAM,QAAQ,MAAM;AAClB,qBAAiB,KAAK;AACtB,gBAAY,KAAK;AAEjB,0BAAsB,MAAM,OAAO,SAAS,cAA2B,WAAW,GAAG,MAAM,EAAE,eAAe,KAAK,CAAC,CAAC;AAAA,EACrH;AACA,QAAM,MAAM,OAAO,aAAa,cAAc,OAAO;AACrD,SACE,gBAAAA,MAAC,SAAI,KAAK,QAAQ,WAAU,wBACzB;AAAA;AAAA;AAAA,MAEC,gBAAAD,KAAC,SAAI,WAAU,YAAW,eAAY,UAAS,eAAY,QAAO;AAAA,QAElE,gBAAAA,KAAC,aAAW,GAAG,OAAO,QAAO,UAAS,YAAwB,UAAU,MAAM;AAAA,IAE/E,YAAY,MACT,aAAa,gBAAAA,KAAC,aAAW,GAAG,OAAO,QAAO,cAAa,YAAwB,QAAQ,OAAO,UAAS,YAAW,SAAS,MAAM,GAAI,IAAI,IAAI,IAC7I;AAAA,KACN;AAEJ;;;ACzBA,IAAM,QAA6B,CAAC,WAAW,QAAQ,eAAe,WAAW,WAAW,SAAS;AACrG,IAAM,gBAA0D;AAAA,EAC9D,GAAG,CAAC,SAAS,MAAM;AAAA,EACnB,GAAG,CAAC,MAAM,SAAS,MAAM;AAAA,EACzB,GAAG,CAAC,MAAM,SAAS,QAAQ,MAAM;AACnC;AAEA,IAAM,eAAgD,EAAE,IAAI,WAAW,OAAO,QAAQ,MAAM,WAAW,MAAM,UAAU;AAGvH,IAAM,cAAc;AAEpB,IAAM,WAAW,CAAC,MAA6C,CAAC,CAAC,KAAK,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAC/G,IAAM,OAAO,CAAC,MAAwB,OAAO,MAAM,WAAW,EAAE,KAAK,IAAI,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI;AAC7G,IAAM,cAAc,CAAC,MAAmC,OAAO,MAAM,YAAa,gBAAsC,SAAS,CAAC;AAElI,SAAS,eAAe,KAA2C;AACjE,MAAI,CAAC,SAAS,GAAG,EAAG,QAAO;AAC3B,QAAM,MAA8D,CAAC;AACrE,MAAI,MAAM;AACV,aAAW,OAAO,iBAAiB;AACjC,QAAI,EAAE,OAAO,KAAM;AACnB,UAAM,IAAI,IAAI,GAAG;AACjB,UAAM,OAAO,iBAAiB,GAAG;AACjC,QAAI,MAAM,QAAQ,MAAM,OAAO;AAC7B,UAAI,GAAG,IAAI;AACX,YAAM;AACN;AAAA,IACF;AACA,UAAM,QAAQ,SAAS,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,KAAK,CAAC;AAClD,QAAI,CAAC,SAAS,CAAC,KAAM;AACrB,UAAM,OAAO,SAAS,CAAC,KAAK,MAAM,SAAS,EAAE,IAAgB,IAAK,EAAE,OAAoB,KAAK;AAC7F,QAAI,GAAG,IAAI,EAAE,GAAG,MAAM,OAAO,KAAK;AAClC,UAAM;AAAA,EACR;AACA,SAAO,MAAM,MAAM;AACrB;AAEA,SAASE,MAAK,GAAmB;AAC/B,SAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,QAAQ,GAAG;AACnD;AAGO,SAAS,uBAAuB,OAA0C;AAC/E,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,UAAU,eAAe,MAAM,OAAO;AAC5C,QAAM,UAAmB,SAAS,kBAAkB,OAAO;AAC3D,QAAM,WAAW,MAAM,QAAQ,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC7D,QAAM,QAAoB,CAAC;AAC3B,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAAU,oBAAI,IAAY;AAEhC,QAAM,UAAU,oBAAI,IAAgD;AACpE,QAAM,UAAU,oBAAI,IAAqB;AACzC,QAAM,YAAsB,CAAC;AAC7B,MAAI,cAAc;AAClB,WAAS,QAAQ,CAAC,KAAK,UAAU;AAC/B,UAAM,IAAI,SAAS,GAAG,IAAI,MAAM,OAAO,QAAQ,WAAW,EAAE,MAAM,IAAI,IAAI;AAC1E,QAAI,CAAC,EAAG;AACR,UAAM,OAAO,KAAK,EAAE,IAAI,KAAK,KAAK,EAAE,SAAS,KAAK,KAAK,EAAE,QAAQ,KAAK,KAAK,EAAE,KAAK;AAClF,QAAI,CAAC,KAAM;AACX,UAAM,cAAc,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,UAAU,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,UAAU,CAAC,GAChG,IAAI,CAAC,MAAO,SAAS,CAAC,IAAI,KAAK,EAAE,KAAK,KAAK,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,CAAE,EAClE,OAAO,OAAO;AACjB,QAAI,WAAW,SAAS,YAAa,UAAS,KAAK,QAAQ,QAAQ,CAAC,QAAQ,WAAW,MAAM,0BAA0B,WAAW,8BAA8B;AAChK,QAAI,WAAW,WAAW,EAAG,UAAS,KAAK,QAAQ,QAAQ,CAAC,yDAAyD;AACrH,UAAM,cAAc,WAAW,MAAM,GAAG,WAAW;AACnD,UAAM,SAAS,YAAY,UAAU,IAAI,cAAc,KAAK,IAAI,GAAG,YAAY,MAAM,CAAC,IAAI;AAC1F,QAAI;AACJ,QAAI,OAAqB,CAAC;AAC1B,QAAI,MAAM;AACV,QAAI,QAAQ;AACV;AACA,YAAM,IAA4D,EAAE,IAAI,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM,KAAK;AAClH,aAAO,QAAQ,CAAC,KAAK,MAAM;AACzB,UAAE,GAAG,IAAI,EAAE,IAAI,UAAU,IAAI,CAAC,IAAI,OAAO,YAAY,CAAC,KAAK,IAAI,MAAM,aAAa,GAAG,EAAE;AAAA,MACzF,CAAC;AACD,YAAM;AACN,YAAM,SAAS,SAAS,CAAC;AACzB,aAAO,YAAY,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,OAAO,EAAE,IAAI,UAAU,IAAI,CAAC,IAAI,OAAO,MAAM,UAAmB,EAAE;AAAA,IAC5G;AAIA,UAAM,UAAU,CAAC,MAAmC;AAClD,YAAM,IAAI,KAAK,CAAC;AAChB,UAAI,CAAC,EAAG,QAAO;AACf,iBAAW,KAAK,CAAC,GAAG,gBAAgB,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG;AAChE,YAAI,MAAMA,MAAK,EAAE,KAAK,MAAMA,MAAK,CAAC,KAAK,EAAE,OAAO,GAAI,QAAO,EAAE;AAAA,MAC/D;AACA,UAAI,QAAQ;AACV,cAAM,WAAWA,MAAK,EAAE,QAAQ,yBAAyB,EAAE,CAAC;AAC5D,cAAM,UAAU,YAAY,UAAU,CAAC,MAAMA,MAAK,CAAC,MAAM,QAAQ;AACjE,YAAI,WAAW,EAAG,QAAO,UAAU,UAAU,CAAC;AAC9C,cAAM,SAAS,sBAAsB,KAAK,CAAC;AAC3C,YAAI,SAAS,CAAC,GAAG;AACf,gBAAM,IAAI,OAAO,CAAC,EAAE,YAAY,EAAE,WAAW,CAAC,IAAI;AAClD,cAAI,IAAI,YAAY,OAAQ,QAAO,UAAU,IAAI,CAAC;AAAA,QACpD;AACA,cAAM,UAAU,qBAAqB,KAAK,CAAC;AAC3C,YAAI,UAAU,CAAC,KAAK,OAAO,QAAQ,CAAC,CAAC,KAAK,YAAY,OAAQ,QAAO,UAAU,QAAQ,CAAC,CAAC;AACzF,YAAI,OAAO,MAAM,YAAY,OAAO,UAAU,CAAC,GAAG;AAChD,cAAI,KAAK,KAAK,KAAK,YAAY,OAAQ,QAAO,UAAU,CAAC;AACzD,cAAI,MAAM,EAAG,QAAO;AAAA,QACtB;AAAA,MACF;AACA,UAAI,YAAY,CAAC,EAAG,QAAO,IAAI,CAAC,GAAG;AACnC,aAAO;AAAA,IACT;AACA,UAAM,UAAU,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,QAAQ,IAAI,OAAO,EAAE,OAAO,CAAC,MAAmB,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,OAAO;AACrH,UAAM,eAAe,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,QAAQ,SAAS,IAAI,EAAE,YAAY,UAAa,EAAE,YAAY,QAAQ,KAAK,EAAE,OAAO,MAAM;AAC5I,QAAI,iBAAiB,YAAY,UAAc,MAAM,QAAQ,OAAO,KAAK,CAAC,QAAQ;AAChF,eAAS,KAAK,QAAQ,QAAQ,CAAC,oBAAoB,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,QAAQ,IAAI,IAAI,EAAE,KAAK,IAAI,IAAI,KAAK,EAAE,OAAO,CAAC,mDAAmD;AACnL,UAAM,WAAW,MAAM,QAAQ,EAAE,OAAO,IAAI,EAAE,UAAU,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS,CAAC,GAC3F,OAAO,QAAQ,EACf,IAAI,CAAC,OAAO,EAAE,OAAO,KAAK,EAAE,KAAK,GAAG,OAAO,KAAK,EAAE,KAAK,EAAE,EAAE,EAC3D,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK;AACnC,UAAM,SAAS,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,QAAQ,CAAC,GAChD,OAAO,QAAQ,EACf,IAAI,CAAC,OAAO;AAAA,MACX,QAAQ,KAAK,EAAE,MAAM;AAAA,MACrB,YAAY,MAAM,QAAQ,EAAE,UAAU,IAAI,EAAE,WAAW,IAAI,IAAI,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,MACpF,WAAW,YAAY,EAAE,IAAI,IAAK,IAAI,EAAE,IAAI,GAAG,MAAM,OAAQ;AAAA,IAC/D,EAAE,EACD,OAAO,CAAC,MAAM,EAAE,MAAM;AACzB,UAAM,YAAY,QAAQ,EAAE,SAAS;AACrC,QAAI,KAAK,KAAK,EAAE,EAAE,KAAK,QAAQ,QAAQ,CAAC;AACxC,QAAI,QAAQ,IAAI,EAAE,GAAG;AACnB,eAAS,KAAK,2BAA2B,EAAE,kCAAkC;AAC7E,WAAK,GAAG,EAAE,IAAI,QAAQ,CAAC;AAAA,IACzB;AACA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,IAAI,OAAO;AACvB,cAAU,KAAK,IAAI;AACnB,UAAM,OAAO,EAAE,WAAW,EAAE;AAC5B,QAAI,SAAS,UAAa,SAAS,KAAM,SAAQ,IAAI,IAAI,IAAI;AAC7D,UAAM,OAAiB;AAAA,MACrB;AAAA,MACA,MAAM;AAAA,MACN,GAAI,KAAK,EAAE,MAAM,IAAI,EAAE,QAAQ,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,MACnD,GAAI,KAAK,EAAE,GAAG,IAAI,EAAE,KAAK,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC;AAAA,MAC1C,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjC,GAAI,KAAK,EAAE,MAAM,IAAI,EAAE,QAAQ,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,MACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,IAAI,CAAC;AAAA,MAC5C,GAAI,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC;AAAA,MAC9B,GAAI,KAAK,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,MAC9B,GAAI,YAAY,WAAc,OAAO,YAAY,YAAY,QAAQ,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC9F,GAAI,KAAK,EAAE,KAAK,IAAI,EAAE,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,MAChD,GAAI,MAAM,SAAS,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,IACzC;AACA,UAAM,KAAK,IAAI;AAAA,EACjB,CAAC;AACD,MAAI,CAAC,MAAM,OAAQ,QAAO;AAG1B,QAAM,SAAS,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAACA,MAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;AAC7D,QAAM,QAAQ,CAAC,MAAuB;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,QAAQ,IAAI,CAAC,EAAG,QAAO;AAC3B,QAAI,OAAO,MAAM,YAAY,OAAO,UAAU,CAAC,KAAK,UAAU,IAAI,CAAC,EAAG,QAAO,UAAU,IAAI,CAAC,KAAK;AACjG,WAAO,OAAO,IAAIA,MAAK,CAAC,CAAC,KAAK;AAAA,EAChC;AACA,QAAM,SAAS,MAAM,IAAI,CAAC,SAAS;AACjC,UAAM,MAAM,QAAQ,IAAI,KAAK,EAAE;AAC/B,UAAM,SAAS,QAAQ,SAAY,OAAO,kBAAkB,KAAK,EAAE,KAAK,OAAO,QAAQ,CAAC,IAAI,MAAM,QAAQ,IAAI,EAAE,IAAI,CAAC,KAAK,KAAK,CAAC;AAChI,QAAI,QAAQ,UAAa,CAAC,OAAQ,UAAS,KAAK,IAAI,KAAK,IAAI,8DAA8D;AAC3H,WAAO,SAAS,EAAE,GAAG,MAAM,OAAO,IAAI;AAAA,EACxC,CAAC;AACD,WAAS,KAAK,GAAG,kBAAkB,QAAQ,EAAE,KAAK,QAAQ,CAAC,CAAC;AAC5D,SAAO;AAAA,IACL,OAAO,KAAK,MAAM,KAAK,KAAK;AAAA,IAC5B,OAAO;AAAA,IACP;AAAA,IACA,SAAS,MAAM,aAAa;AAAA,IAC5B,YAAY,MAAM,QAAQ,MAAM,UAAU,IAAI,MAAM,WAAW,IAAI,IAAI,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,IAC5F,qBAAqB,gBAAgB,MAAM;AAAA,IAC3C;AAAA,EACF;AACF;AAGO,SAAS,oBACd,MACA,SAC0B;AAC1B,QAAM,UAAU,SAAS,kBAAkB,KAAK,OAAO;AACvD,QAAM,SAAS,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,MAAS;AAE7D,QAAM,QAAQ,WAAW,KAAK,OAAO,EAAE,SAAS,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC;AACtF,SAAO,KAAK,MAAM,OAAO,CAAC,SAAS,MAAM,IAAI,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS;AACnE,UAAM,MAAM,SAAS,SAAS,KAAK,OAAO;AAC1C,UAAM,MAAM,CAAC,GAAG,gBAAgB,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,GAAI,KAAK,QAAQ,CAAC,CAAE;AACxE,UAAM,KAAK,QAAQ,KAAK,EAAE;AAC1B,UAAM,SAAS,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,EAAE,IAAI;AACpD,UAAM,MAA8B,CAAC;AACrC,QAAI,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,EAAG,KAAI,OAAO,KAAK,UAAU;AAChE,QAAI,OAAO,KAAK;AAChB,QAAI,SAAS,QAAQ,SAAS;AAC9B,QAAI,QAAQ;AACV,YAAM,UAAU,KAAK,YAAY,SAAY,CAAC,IAAI,OAAO,KAAK,YAAY,WAAW,CAAC,KAAK,OAAO,IAAI,KAAK;AAC3G,UAAI,cAAc,IAAI,QAAQ,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC7G,UAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,SAAS,KAAK,QAAQ,SAAS,EAAE,IAAI,QAAQ;AAAA,IAC3E;AACA,WAAO;AAAA,EACT,CAAC;AACH;;;AC3LA,IAAM,OAAO,CAAC,MAAyD,MAAM,SAAY,CAAC,IAAI,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAGjI,IAAM,SAAS,CAAC,MAAgC,UAAU;AAG1D,SAAS,SAAS,MAAsE;AACtF,QAAMC,SAAQ,CAAC,MAAY,EAAE,aAAa;AAC1C,MAAI,OAAO,IAAI,EAAG,QAAOA,OAAM,IAAI,IAAI,EAAE,OAAO,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI;AAG1E,QAAM,QAAQ,CAACC,OAAgC,UAAyB;AACtE,QAAI,CAACA,MAAK,UAAU,CAACA,MAAK,MAAM,CAAC,MAAM,OAAO,CAAC,KAAKD,OAAM,CAAC,CAAC,EAAG,QAAO;AACtE,UAAM,SAASC;AACf,WAAO,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,OAAO,SAAS,EAAE,OAAO,OAAO,IAAI;AAAA,EACzF;AACA,MAAI,SAAS,KAAM,QAAO,MAAM,KAAK,KAAK,KAAK;AAC/C,MAAI,SAAS,KAAM,QAAO,MAAM,KAAK,KAAK,KAAK;AAC/C,SAAO;AACT;AAEA,SAAS,UAAU,OAAkB,MAA8B;AACjE,QAAM,MAAM,OAAO,OAAO,IAAI;AAC9B,QAAM,QAAS,CAAC,SAAS,MAAM,QAAQ,MAAM,EAAY,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAuB,CAAC,CAAC,CAAC;AAC9G,SAAO,CAAC,GAAG,OAAO,GAAG,QAAQ,OAAO,IAAI,CAAC;AAC3C;AAGO,SAAS,eAAe,OAA4B,OAAkC;AAC3F,QAAM,QAAyB,CAAC;AAChC,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAwB;AAC/C,UAAM,QAAQ,KAAK,SAAS,SAAS,KAAK,MAAM,IAAI,EAAE,OAAO,OAAgB,QAAQ,CAAC,EAAE;AACxF,QAAI,OAAO;AACT,iBAAW,QAAQ,MAAM,QAAQ;AAC/B,cAAM,KAAK,GAAG,KAAK,IAAI,SAAI,KAAK,EAAE;AAClC,cAAM,KAAK,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAC7C,cAAM,OAAO,EAAE,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,GAAG,OAAO,KAAK,KAAK,KAAK,EAAE;AAE5F,YAAI,MAAM,GAAG;AACX,gBAAM,MAAM,MAAM,EAAE;AACpB,gBAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,EAAE;AAAA,QACtH,MAAO,OAAM,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AACA,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,MAC7C,SAAS,UAAU,OAAO,IAAI;AAAA,MAC9B,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,CAAC;AAAA,IACX;AAAA,EACF,CAAC;AACD,SAAO,EAAE,OAAO,MAAM;AACxB;AAMO,SAAS,eAAe,OAA4B,OAAmC;AAC5F,QAAM,SAAS,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACxD,SAAO,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,OAAO,OAAO,IAAI,KAAK,EAAE;AAC/B,QAAI,MAAM,OAAQ,QAAO;AACzB,UAAM,SAAiB,MAAM,MAC1B,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,EAC9B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAI,EAAE,GAAG,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAI,GAAI,EAAE,MAAM,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAG,EAAE;AAC/H,UAAM,EAAE,QAAQ,MAAM,GAAG,KAAK,IAAI;AAClC,QAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,UAAM,SAAwB,OAAO,WAAW,IAAI,OAAO,CAAC,IAAK,MAAM,UAAU,QAAQ,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK,OAAO;AACzH,WAAO,EAAE,GAAG,MAAM,OAAO;AAAA,EAC3B,CAAC;AACH;AAGO,SAAS,eAAe,MAAqB,OAA4B,OAA0B;AACxG,QAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;AACjD,QAAM,QAAQ,CAAC,QAA2B,IAAI,IAAI,CAAC,OAAQ,OAAQ,WAAW,OAAO,MAAM,EAAE,GAAG,SAAS,KAAM,EAAG;AAClH,QAAM,QAAQ,CAAC,GAAG,MAAM,KAAK,EAAE,GAAG,GAAG,MAAM,KAAK,KAAK,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,CAAC;AAC7E,SAAO,MAAM,SAAS,MAAM,KAAK,QAAK,IAAI;AAC5C;AAGO,SAAS,WAAW,OAA4B,OAAuB,MAAc,IAA2B;AACrH,QAAM,IAAI,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,IAAI;AAC9C,QAAM,IAAI,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAC5C,MAAI,IAAI,KAAK,IAAI,EAAG,QAAO;AAC3B,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,IAAI,EAAG,QAAO;AAClB,MAAI,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,OAAO,EAAE,EAAG,QAAO;AACpE,MAAI,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAQ,QAAO;AACzD,SAAO;AACT;AAGO,SAAS,aAAa,OAA4B,OAAkB,MAAc,IAA2B;AAClH,QAAM,SAAS,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI;AAC9C,QAAM,QAAQ,SAAS,UAAU,OAAO,MAAM,EAAE,CAAC,IAAI;AACrD,SAAO,EAAE,IAAI,GAAG,IAAI,SAAI,EAAE,IAAI,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE;AACjF;AAGO,SAAS,cAAc,OAA4B,OAAkB,OAAiC;AAC3G,SAAO,kBAAkB,eAAe,OAAO,KAAK,GAAG,KAAK;AAC9D;","names":["React","text","Wash","React","text","list","list","kept","React","jsx","jsxs","Fragment","jsx","jsxs","text","a","list","React","jsx","jsxs","norm","plain","list"]}
|
|
1
|
+
{"version":3,"sources":["../src/swipe-deck/SwipeDeck.tsx","../src/swipe-deck/chrome.tsx","../src/swipe-deck/visual.ts","../src/swipe-deck/controller.ts","../src/swipe-deck/model.ts","../src/swipe-deck/gesture.ts","../src/swipe-deck/labels.ts","../src/swipe-deck/PartScreen.tsx","../src/swipe-deck/ExpandableSwipeDeck.tsx","../src/swipe-deck/kind-value.ts","../src/swipe-deck/logic.ts"],"sourcesContent":["\"use client\";\n\n/**\n * SwipeDeck — THE full-screen swipe deck: a deck of items a person answers by swiping.\n *\n * right Yes! · up Sort of · left No · down Not sure (every part configurable)\n *\n * The whole screen is the card; its text fits to the largest size the space allows. Each answer is\n * a large button on the edge it swipes toward; the corners are exit, ?, undo and copy. The moment a\n * drag starts the screen takes the answer's color and name; a flick commits too. The suggested\n * answer's button is filled and pulses and the card leans toward it. Undo is unlimited and the card\n * returns from the side it left. Items can expose parts (spans of their words), each answered on the\n * part screen (hold, or double-click); categories' answers flow down to the parts they tag.\n *\n * TWO MODES. Controlled: pass `items` and read answers back through `onAnswer` / `onChange` /\n * `onComplete`. Bound: pass a `binding` (see `controller.ts`) and the deck persists every change\n * through it, optimistically, showing the connection's own refusal sentence inline.\n *\n * Structural CSS: `swipe-deck.css` (imported by `styles.css`); colors are design-system tokens.\n */\nimport * as React from \"react\";\n\nimport { copyText as copyToClipboard } from \"@ai-matrx/kit/clipboard\";\n\nimport { ErrorBox } from \"../error-box\";\nimport { CheckIcon, CircleHelpIcon, CopyIcon, ListChecksIcon, Loader2Icon, Maximize2Icon, Minimize2Icon, PencilIcon, Undo2Icon, XIcon } from \"../icons\";\nimport { AnswerGlyph, CornerButton, EdgeButtons, setHot, Wash, type EdgeRefs, type WashHandle } from \"./chrome\";\nimport { useDeckController, type DeckController, type SwipeDeckBinding } from \"./controller\";\nimport { attachSwipe } from \"./gesture\";\nimport { DEFAULT_SWIPE_DECK_LABELS, type SwipeDeckLabels } from \"./labels\";\nimport {\n DECK_DIRECTIONS,\n DEFAULT_DECK_KEY,\n DEFAULT_KEEP_ANSWER,\n answerChange,\n answerDetail,\n answerOf,\n applyOps,\n findAnswer,\n membersOff,\n moreFor,\n currentStepIndex,\n deckCopyText,\n deckResult,\n deckSteps,\n directionOf,\n forgetSpan,\n itemCopyText,\n keyFor,\n knownCategories,\n makeChange,\n mergeKey,\n partAnswer,\n partsOf,\n partText,\n placePart,\n tokenize,\n type CategoryConflict,\n type DeckCategoryRow,\n type DeckAnswer,\n type DeckChange,\n type DeckDetail,\n type DeckDirection,\n type DeckOp,\n type DeckItem,\n type DeckMedia,\n type DeckKey,\n type DeckKeyOverride,\n type DeckPart,\n type DeckResult,\n type DeckRules,\n type DeckState,\n type DeckStep,\n type DeckTone,\n} from \"./model\";\nimport { PartScreen } from \"./PartScreen\";\nimport { VECTOR, buzz, enter, finePointer, fitText, flyOut, follow, heroMax, keepFitted, markOverflow, nudge, prefersReducedMotion, snapBack } from \"./visual\";\n\nexport interface SwipeDeckCopyContext {\n readonly item: DeckItem | null;\n readonly state: DeckState;\n readonly result: DeckResult;\n}\n\n/** What a card's own slots (`renderCardBody`, `renderCardActions`) can do. */\nexport interface SwipeDeckCardContext {\n readonly item: DeckItem;\n /** What will ride with this card's answer: the members switched off, a value typed on the card. */\n readonly detail: DeckDetail | null;\n /** Replace what rides with this card's next answer (any route: swipe, edge, key, button). */\n setDetail(detail: DeckDetail | null): void;\n /** Answer the card now, by answer id (on an edge or off it), optionally with what rides along. */\n answer(answerId: string, detail?: DeckDetail | null): void;\n /** While locked (a field being typed in), the card never swipes and the arrows and shortcuts do nothing. */\n lock(locked: boolean): void;\n}\n\nexport interface SwipeDeckProps {\n /** Controlled mode: the items. Ignored when `binding` is given (the binding brings its items). */\n readonly items?: readonly DeckItem[];\n /** Bound mode: the connection the deck persists through. */\n readonly binding?: SwipeDeckBinding;\n /** The deck's key, over the default (Yes! / Sort of / No / Not sure); `null` turns an edge off. */\n readonly answers?: DeckKeyOverride;\n /** Answers off the edges, offered on every card as a row of buttons (an item's own `more` replaces them). */\n readonly more?: readonly DeckAnswer[];\n /** Drawn on the card under its text: the host's own controls (a field to correct a value, a person's name). */\n readonly renderCardBody?: (context: SwipeDeckCardContext) => React.ReactNode;\n /** Drawn in the card's top row, at the end: small actions (open the source, see where it was found). */\n readonly renderCardActions?: (context: SwipeDeckCardContext) => React.ReactNode;\n /** The part screen's key, over the deck's (its down edge defaults to Keep as is). */\n readonly partAnswers?: DeckKeyOverride;\n /** The category rows offered on the part screen. */\n readonly categories?: readonly string[];\n /** Labelled chip rows on the part screen (\"Who\", \"Cares about\"), each with its own \"+\"; a category added there carries the row's id on its op. */\n readonly categoryRows?: readonly DeckCategoryRow[];\n /** When two categories' answers disagree on a part. Default: the worse answer wins. */\n readonly categoryConflict?: CategoryConflict;\n readonly allowNewCategories?: boolean;\n /** Turn the part screen off (parts still show and tap). */\n readonly editParts?: boolean;\n /** Groups that end in a pick-one screen (`true` = every group). */\n readonly pickOne?: boolean | readonly string[];\n /** The answer that makes an item a contender for its group's pick (default: the right edge's). */\n readonly pickAnswer?: string;\n /** What each group is called on its pick screen and at the end. */\n readonly groupLabels?: Readonly<Record<string, string>>;\n /** Controlled mode: answers, picks, parts and categories to start from. */\n readonly initialState?: Partial<DeckState>;\n readonly labels?: Partial<SwipeDeckLabels>;\n readonly onAnswer?: (item: DeckItem, answer: DeckAnswer, state: DeckState) => void;\n /** Every change, undo included (`undo` true), with the state after it. */\n readonly onChange?: (state: DeckState, change: DeckChange, undo: boolean) => void;\n /** The person reached the end; `result` holds every answer, pick, part and category. */\n readonly onComplete?: (result: DeckResult) => void;\n /** The exit corner; omitted, the corner is empty (or holds Full screen when `onExpand` is given). */\n readonly onExit?: () => void;\n /** What the exit corner means: `close` (an X) or `collapse` (leave full screen). */\n readonly exitKind?: \"close\" | \"collapse\";\n /** The full-screen corner (top left), for a deck drawn inline: open this deck full screen. */\n readonly onExpand?: () => void;\n /** Share another deck's controller (state AND undo), e.g. the inline and full-screen views of one deck. */\n readonly controller?: DeckController;\n /** Show each item's choices on the card, by their direction (a quiz). Default: when the item has its own answers. */\n readonly choicesOnCard?: boolean | \"auto\";\n /**\n * How big the card's own text is: `fit` (default) grows it to fill the card (a word, a short line);\n * `page` holds it at a page-title size in a reading-width column, for a card whose body is the point\n * (evidence to read before answering).\n */\n readonly titleSize?: \"fit\" | \"page\";\n /**\n * Draw the answers off the edges (`more`) as the card's row of buttons (default true). `false` when the\n * host draws every answer itself in its body through `context.answer`; their keyboard shortcuts stay.\n */\n readonly moreOnCard?: boolean;\n /** The copy corner's text (default: the item, or the whole deck at a pick or the end). */\n readonly copyText?: (context: SwipeDeckCopyContext) => string;\n /** Where \"the walkthrough already played\" is remembered; `null` never plays it on its own. */\n readonly tourKey?: string | null;\n /** Arrows, Z (undo) and ? (default on). */\n readonly keyboard?: boolean;\n /**\n * `fullscreen` covers the viewport; `fill` fills the nearest positioned parent; `inline` is a box in\n * the flow (a chat message): its height is `--sd-inline-height`, and its keys answer only while it\n * holds focus or the pointer.\n */\n readonly layout?: \"fullscreen\" | \"fill\" | \"inline\";\n readonly renderEnd?: (result: DeckResult) => React.ReactNode;\n /** The host's own buttons on the finish screen (back to the page, the next step). */\n readonly endActions?: React.ReactNode;\n /** The screen when there is nothing to answer: its words and the host's way on. */\n readonly empty?: { readonly title?: string; readonly line?: string; readonly action?: React.ReactNode };\n readonly className?: string;\n}\n\nconst KEYS: Readonly<Record<string, DeckDirection>> = { ArrowRight: \"right\", ArrowLeft: \"left\", ArrowUp: \"up\", ArrowDown: \"down\" };\nconst DEFAULT_TOUR_KEY = \"matrx.swipe-deck.tour\";\n\nfunction readFlag(key: string): boolean {\n try {\n return globalThis.localStorage?.getItem(key) === \"1\";\n } catch {\n return false;\n }\n}\nfunction writeFlag(key: string): void {\n try {\n globalThis.localStorage?.setItem(key, \"1\");\n } catch {\n /* storage blocked: the walkthrough may play again next visit */\n }\n}\n\nfunction wait(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport function SwipeDeck(props: SwipeDeckProps) {\n const labels = React.useMemo<SwipeDeckLabels>(() => ({ ...DEFAULT_SWIPE_DECK_LABELS, ...props.labels }), [props.labels]);\n const deckKey = React.useMemo(() => mergeKey(DEFAULT_DECK_KEY, props.answers), [props.answers]);\n const partKeyBase = React.useMemo(() => mergeKey({ ...deckKey, down: DEFAULT_KEEP_ANSWER }, props.partAnswers), [deckKey, props.partAnswers]);\n const rules = React.useMemo<DeckRules>(\n () => ({\n key: deckKey,\n ...(props.pickOne !== undefined ? { pickOne: props.pickOne } : {}),\n ...(props.pickAnswer ? { pickAnswer: props.pickAnswer } : {}),\n ...(props.more ? { more: props.more } : {}),\n }),\n [deckKey, props.pickOne, props.pickAnswer, props.more],\n );\n const conflict = props.categoryConflict;\n const own = useDeckController({ items: props.items, binding: props.binding, initialState: props.initialState, onChange: props.onChange });\n const controller = props.controller ?? own;\n const layout = props.layout ?? \"fullscreen\";\n const { items, state } = controller;\n const steps = React.useMemo(() => deckSteps(items, state, rules), [items, state, rules]);\n const stepIndex = currentStepIndex(steps, state);\n const step: DeckStep = steps[stepIndex] ?? { kind: \"end\", id: \"end\" };\n const ready = controller.status === \"ready\";\n const stateRef = React.useRef(state);\n stateRef.current = state;\n // Timers (pick, walkthrough, lean) never act on a deck that has closed.\n const alive = React.useRef(true);\n React.useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n /** Set when the deck itself moved to the next card (an answer here), so only that card change takes focus back. */\n const answeredHere = React.useRef(false);\n const frameRef = React.useRef<HTMLDivElement>(null);\n const layerRef = React.useRef<HTMLDivElement | null>(null);\n const edgeRefs = React.useRef<EdgeRefs>({});\n const wash = React.useRef<WashHandle>(null);\n const busy = React.useRef(false);\n const enterFrom = React.useRef<DeckDirection | \"stay\" | null>(null);\n const nudgeAnim = React.useRef<Animation | null>(null);\n const [touring, setTouring] = React.useState(false);\n const touringRef = React.useRef(false);\n const tourStop = React.useRef(false);\n const [part, setPart] = React.useState<{ itemId: string; start: number; end: number } | null>(null);\n const [bubble, setBubble] = React.useState<{ text: string; x: number; top: number; bottom: number } | null>(null);\n const [toast, setToast] = React.useState<string | null>(null);\n const [said, setSaid] = React.useState(\"\");\n\n // THE ANSWERED LIST, mid-deck: every answer so far, each one tap from changing it (the finish screen's list,\n // reachable at any point). While it is open the card does not take answers.\n const [reviewing, setReviewing] = React.useState(false);\n const reviewingRef = React.useRef(false);\n reviewingRef.current = reviewing;\n const cardItem = step.kind === \"card\" && !reviewing ? step.item : null;\n const cardKey = cardItem ? keyFor(rules, cardItem) : deckKey;\n const cardMore = React.useMemo(() => (cardItem ? moreFor(rules, cardItem) : []), [cardItem, rules]);\n // The buttons drawn under the card: a hidden answer is reached only through the card's own controls.\n const cardMoreShown = React.useMemo(() => cardMore.filter((a) => !a.hidden), [cardMore]);\n const suggestedDir = cardItem ? directionOf(cardKey, cardItem.suggested) : null;\n // What rides with the card in front's answer, set by its members and its own slots; starts from what was saved.\n const [cardDetail, setCardDetail] = React.useState<{ id: string; detail: DeckDetail | null } | null>(null);\n const detailNow = cardItem ? (cardDetail?.id === cardItem.id ? cardDetail.detail : (state.details?.[cardItem.id] ?? null)) : null;\n const detailRef = React.useRef(detailNow);\n detailRef.current = detailNow;\n const [locked, setLocked] = React.useState<string | null>(null);\n const lockedNow = !!cardItem && locked === cardItem.id;\n const lockedRef = React.useRef(lockedNow);\n lockedRef.current = lockedNow;\n\n const stopNudge = () => {\n try {\n nudgeAnim.current?.cancel();\n } catch {\n /* already finished */\n }\n nudgeAnim.current = null;\n };\n\n const flash = React.useCallback((text: string) => setToast(text), []);\n React.useEffect(() => {\n if (!toast) return;\n const t = setTimeout(() => setToast(null), 1400);\n return () => clearTimeout(t);\n }, [toast]);\n React.useEffect(() => {\n if (!bubble) return;\n const t = setTimeout(() => setBubble(null), 2200);\n return () => clearTimeout(t);\n }, [bubble]);\n\n // ─── answering ───────────────────────────────────────────────────────────\n const act = (dir: DeckDirection, speed = 0) => {\n const answer = cardKey[dir];\n if (answer) void give(answer, dir, speed);\n };\n /** Answer the card in front: by an edge (`dir`) or off the edges (`dir` null: it drops away). */\n const give = async (answer: DeckAnswer, dir: DeckDirection | null, speed = 0, detail?: DeckDetail | null) => {\n if (!cardItem || busy.current || touringRef.current || part) return;\n busy.current = true;\n stopNudge();\n setBubble(null);\n wash.current?.show(answer, dir, 1);\n setHot(edgeRefs.current, dir);\n buzz(globalThis.navigator, 8);\n await flyOut(layerRef.current, dir ?? \"down\", speed);\n const now = stateRef.current;\n const rides = answerDetail(cardItem, detail === undefined ? detailRef.current : detail);\n const made = answerChange(now, cardItem, answer.id, rules, items, dir, rides);\n // \"Skip for now\": the connection sends the card to the back of the line and keeps no answer.\n const change = answer.requeue && props.binding ? { ...made, transient: true } : made;\n enterFrom.current = null;\n setCardDetail(null);\n setLocked(null);\n answeredHere.current = true;\n controller.commit(change);\n busy.current = false;\n setHot(edgeRefs.current, null);\n wash.current?.hide();\n const after = applyOps(now, change.ops);\n props.onAnswer?.(cardItem, answer, after);\n const nextSteps = deckSteps(items, after, rules);\n const next = nextSteps[currentStepIndex(nextSteps, after)];\n setSaid(`${answer.label}.${next && next.kind === \"card\" ? ` ${labels.next}: ${next.item.text}` : \"\"}`);\n };\n const actRef = React.useRef(act);\n actRef.current = act;\n const giveRef = React.useRef(give);\n giveRef.current = give;\n\n const cardContext = React.useMemo<SwipeDeckCardContext | null>(\n () =>\n cardItem\n ? {\n item: cardItem,\n detail: detailNow,\n setDetail: (detail) => setCardDetail({ id: cardItem.id, detail }),\n answer: (answerId, detail) => {\n const a = findAnswer(rules, cardItem, answerId);\n if (a) void giveRef.current(a, directionOf(cardKey, answerId), 0, detail);\n },\n lock: (on) => setLocked(on ? cardItem.id : null),\n }\n : null,\n [cardItem, detailNow, rules, cardKey],\n );\n\n const undo = () => {\n if (busy.current || touringRef.current) return;\n if (part) setPart(null);\n setCardDetail(null);\n setLocked(null);\n const change = controller.undo();\n if (!change) return;\n enterFrom.current = change.from ?? \"stay\";\n // The card comes back as she left it: what rode with the answer (her switches, a typed value) is on it again.\n const answered = change.ops.find((o): o is Extract<DeckOp, { kind: \"answer\" }> => o.kind === \"answer\" && !!o.detail);\n if (answered?.detail) setCardDetail({ id: answered.itemId, detail: answered.detail });\n const touched = change.ops.find((o) => o.kind === \"answer\" || o.kind === \"parts\");\n const item = touched && \"itemId\" in touched ? items.find((i) => i.id === touched.itemId) : undefined;\n setSaid(`${labels.undone}.${item ? ` ${item.text}` : \"\"}`);\n };\n const undoRef = React.useRef(undo);\n undoRef.current = undo;\n\n const pick = (group: string, item: DeckItem) => {\n if (busy.current) return;\n busy.current = true;\n setTimeout(\n () => {\n busy.current = false;\n if (!alive.current) return;\n enterFrom.current = null;\n controller.commit(makeChange(stateRef.current, [{ kind: \"pick\", group, itemId: item.id }], items));\n setSaid(`${props.groupLabels?.[group] ?? group}: ${item.text}`);\n },\n prefersReducedMotion() ? 0 : 260,\n );\n };\n\n // ─── parts ───────────────────────────────────────────────────────────────\n const openPart = (item: DeckItem, index: number) => {\n if (props.editParts === false || busy.current || touringRef.current) return;\n stopNudge();\n setBubble(null);\n if (layerRef.current) snapBack(layerRef.current);\n wash.current?.hide();\n setPart({ itemId: item.id, start: index, end: index });\n };\n const openPartRef = React.useRef(openPart);\n openPartRef.current = openPart;\n\n const partItem = part ? (items.find((i) => i.id === part.itemId) ?? null) : null;\n const partKey = React.useMemo(\n () => (partItem ? mergeKey({ ...keyFor(rules, partItem), down: DEFAULT_KEEP_ANSWER }, props.partAnswers) : partKeyBase),\n [partItem, rules, props.partAnswers, partKeyBase],\n );\n const allCategories = React.useMemo(() => knownCategories(props.categories ?? [], items, state), [props.categories, items, state]);\n\n const placeOnItem = (item: DeckItem, next: DeckPart) => {\n enterFrom.current = \"stay\";\n const now = stateRef.current;\n controller.commit(makeChange(now, [{ kind: \"parts\", itemId: item.id, parts: placePart(partsOf(now, item), next) }], items));\n };\n const forgetOnItem = (item: DeckItem, span: { start: number; end: number }) => {\n enterFrom.current = \"stay\";\n const now = stateRef.current;\n controller.commit(makeChange(now, [{ kind: \"parts\", itemId: item.id, parts: forgetSpan(partsOf(now, item), span) }], items));\n flash(labels.forgotten);\n };\n\n // ─── the swipe on the card ───────────────────────────────────────────────\n // Set from the first move of a press until the next press: a press that dragged is never a choice's tap.\n const dragged = React.useRef(false);\n const live = React.useRef({ cardKey, enabled: false });\n live.current = { cardKey, enabled: !!cardItem && !part && !touring && !lockedNow };\n\n React.useEffect(() => {\n const root = frameRef.current;\n if (!root) return;\n return attachSwipe(root, {\n enabled: () => live.current.enabled && !busy.current && !touringRef.current,\n directions: () => live.current.cardKey,\n start: () => {\n dragged.current = false;\n stopNudge();\n setBubble(null);\n },\n move: (dx, dy, dir, amount) => {\n dragged.current = true;\n const answer = dir ? live.current.cardKey[dir] : undefined;\n follow(layerRef.current, dx, dy, dir && answer ? amount : 0);\n if (dir && answer) {\n wash.current?.show(answer, dir, amount);\n setHot(edgeRefs.current, amount >= 1 ? dir : null);\n } else {\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n }\n },\n release: () => {\n snapBack(layerRef.current);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n },\n commit: (dir, speed) => actRef.current(dir, speed),\n tap: (target) => {\n const span = target.closest<HTMLElement>(\"[data-sd-part]\");\n if (!span) {\n setBubble(null);\n return;\n }\n const r = span.getBoundingClientRect();\n setBubble({ text: span.getAttribute(\"data-sd-part-label\") ?? \"\", x: r.left + r.width / 2, top: r.top, bottom: r.bottom });\n },\n hold: (target) => {\n const i = Number(target.getAttribute(\"data-sd-t\"));\n const item = itemsRef.current.find((x) => x.id === target.closest(\"[data-sd-item]\")?.getAttribute(\"data-sd-item\"));\n if (item && Number.isFinite(i)) openPartRef.current(item, i);\n },\n holdSelector: \"[data-sd-t]\",\n // A swipe may start on a choice (it fills much of a quiz card); other buttons never swipe.\n ignoreSelector: \"button:not([data-sd-choice]), a, input, textarea, [data-sd-noswipe]\",\n });\n }, []);\n const itemsRef = React.useRef(items);\n itemsRef.current = items;\n\n // ─── keyboard ────────────────────────────────────────────────────────────\n const keyboard = props.keyboard !== false;\n // A key pressed during the walkthrough, done once it has stopped.\n const afterTour = React.useRef<string | null>(null);\n /** What a key does on the deck; true when it did something (its default is then prevented). */\n const runKeyRef = React.useRef<(key: string, target: Element | null) => boolean>(() => false);\n runKeyRef.current = (key, target) => {\n if (reviewingRef.current) {\n if (key === \"Escape\") {\n setReviewing(false);\n return true;\n }\n if (key !== \"z\" && key !== \"Z\" && key !== \"Backspace\") return false;\n }\n const dir = KEYS[key];\n const shortcut = !dir && key.length === 1 ? shortcutRef.current(key) : null;\n if ((dir || shortcut) && lockedRef.current) return false;\n if (dir) {\n actRef.current(dir);\n return true;\n }\n if (shortcut) {\n void giveRef.current(shortcut.answer, shortcut.dir);\n return true;\n }\n if (key === \"z\" || key === \"Z\" || key === \"Backspace\") {\n undoRef.current();\n return true;\n }\n if (key === \"?\") {\n void tourRef.current();\n return true;\n }\n if (key === \"Escape\" && exitRef.current.kind === \"collapse\" && exitRef.current.onExit) {\n exitRef.current.onExit();\n return true;\n }\n // Enter on the card (not on one of its buttons) opens the part screen on its first marked words, or its first word.\n if (key === \"Enter\" && !target?.closest(\"button, a, [role='button']\") && cardItemRef.current && props.editParts !== false) {\n const item = cardItemRef.current;\n const first = partsOf(stateRef.current, item)[0];\n openPartRef.current(item, first ? first.start : 0);\n return true;\n }\n return false;\n };\n const cardItemRef = React.useRef(cardItem);\n cardItemRef.current = cardItem;\n // An answer's own key (\"Y\", \"3\"), on an edge or off it; it outranks Z and ? when an answer claims them.\n const shortcutRef = React.useRef<(key: string) => { answer: DeckAnswer; dir: DeckDirection | null } | null>(() => null);\n shortcutRef.current = (key) => {\n if (!cardItem || part) return null;\n const k = key.toLowerCase();\n for (const d of DECK_DIRECTIONS) {\n const a = cardKey[d];\n if (a?.shortcut?.toLowerCase() === k) return { answer: a, dir: d };\n }\n const a = cardMoreShown.find((x) => x.shortcut?.toLowerCase() === k);\n return a ? { answer: a, dir: null } : null;\n };\n const exitRef = React.useRef({ kind: props.exitKind, onExit: props.onExit });\n exitRef.current = { kind: props.exitKind, onExit: props.onExit };\n React.useEffect(() => {\n if (!keyboard) return;\n const view = rootRef.current?.ownerDocument.defaultView ?? window;\n const onKey = (e: KeyboardEvent) => {\n const root = rootRef.current;\n const doc = root?.ownerDocument;\n const active = doc?.activeElement;\n if (active && active !== doc.body && !root?.contains(active)) return;\n // An inline deck (one of many things on a page) answers only while it holds focus or the pointer.\n if (layout === \"inline\" && !(root && (root.contains(active ?? null) || root.matches(\":hover\")))) return;\n const t = e.target instanceof Element ? e.target : null;\n if (t?.closest(\"input, textarea, select, [contenteditable='true']\")) return;\n // Cmd+Z / Ctrl+Z is undo here too (a field's own undo keeps it: fields returned above).\n if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && (e.key === \"z\" || e.key === \"Z\") && !e.repeat) {\n e.preventDefault();\n undoRef.current();\n return;\n }\n // A held key answers one card, never several; a key with Alt, Ctrl or Cmd belongs to the browser or the host.\n if (e.altKey || e.ctrlKey || e.metaKey) return;\n if (e.repeat) {\n if (KEYS[e.key] || e.key === \"z\" || e.key === \"Z\" || e.key === \"Backspace\") e.preventDefault();\n return;\n }\n if (touringRef.current) {\n // A key during the walkthrough ends it AND does what it says: the first answer is never lost.\n tourStop.current = true;\n if (KEYS[e.key] || e.key === \"z\" || e.key === \"Z\" || e.key === \"Backspace\") {\n e.preventDefault();\n afterTour.current = e.key;\n }\n return;\n }\n if (runKeyRef.current(e.key, t)) e.preventDefault();\n };\n view.addEventListener(\"keydown\", onKey);\n return () => view.removeEventListener(\"keydown\", onKey);\n }, [keyboard, layout]);\n\n // The keys stay with the deck after every answer (P5, pool 2026-10-24: after some cards the arrows did nothing until\n // the page was clicked). An answer can leave focus on a control OUTSIDE the deck (a menu's or hover card's portal, a\n // host control that re-rendered, a toast), and the key handler ignores keys whose focus is elsewhere. So when the card\n // changes, a full deck (not inline: one of many things on a page) takes focus back — never from a field being typed\n // in, an open dialog or menu. REVIEW9 M-5: a card change the HOST made (items arriving, re-sorting) never takes focus\n // from a button or link the person is on — only nothing focused (the page itself) is taken then; and a deck that sits\n // inside a dialog takes it back within that dialog.\n const cardId = cardItem?.id ?? null;\n React.useEffect(() => {\n const fromAnswer = answeredHere.current;\n answeredHere.current = false;\n if (!keyboard || layout === \"inline\" || cardId === null) return;\n const root = rootRef.current;\n const doc = root?.ownerDocument;\n const active = doc?.activeElement ?? null;\n if (!root || (active && root.contains(active))) return;\n const idle = !active || active === doc?.body || active === doc?.documentElement;\n if (!idle && !fromAnswer) return;\n if (active?.closest(\"input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='combobox'], [role='textbox'], [role='menu'], [role='listbox']\")) return;\n const dialog = active?.closest(\"[role='dialog'], [role='alertdialog'], dialog\");\n if (dialog && !dialog.contains(root)) return;\n root.focus({ preventScroll: true });\n }, [cardId, keyboard, layout]);\n\n // ─── the walkthrough (?) ─────────────────────────────────────────────────\n const fingerRef = React.useRef<HTMLDivElement>(null);\n const ringRef = React.useRef<HTMLDivElement>(null);\n const capRef = React.useRef<HTMLDivElement>(null);\n const tour = async () => {\n const layer = layerRef.current;\n const stage = layer?.parentElement;\n const F = fingerRef.current;\n if (touringRef.current || !cardItem || busy.current || part || !layer || !stage || !F) return;\n touringRef.current = true;\n tourStop.current = false;\n setTouring(true);\n stopNudge();\n setBubble(null);\n const reduced = prefersReducedMotion();\n const tween = (ms: number, f: (p: number) => void) =>\n new Promise<void>((res) => {\n const t0 = performance.now();\n const frame = (t: number) => {\n if (tourStop.current) return res();\n const p = Math.min(1, (t - t0) / ms);\n f(p);\n if (p < 1) requestAnimationFrame(frame);\n else res();\n };\n requestAnimationFrame(frame);\n });\n const ease = (p: number) => (p < 0.5 ? 2 * p * p : 1 - Math.pow(-2 * p + 2, 2) / 2);\n const place = (el: HTMLElement | null, x: number, y: number) => {\n if (!el) return;\n el.style.left = `${x}px`;\n el.style.top = `${y}px`;\n };\n const r = stage.getBoundingClientRect();\n const cx = r.left + r.width / 2;\n const cy = r.top + r.height / 2;\n const dist = Math.min(r.width, r.height) * 0.34;\n place(F, cx, cy);\n F.style.opacity = \"1\";\n const key = cardKey;\n const order = [...(suggestedDir ? [suggestedDir] : []), ...DECK_DIRECTIONS.filter((d) => d !== suggestedDir)];\n for (const dir of order) {\n if (tourStop.current) break;\n const answer = key[dir];\n if (!answer) continue;\n const [vx, vy] = VECTOR[dir];\n F.setAttribute(\"data-down\", \"\");\n await tween(reduced ? 1 : 620, (p) => {\n const e = ease(p);\n place(F, cx + vx * dist * e, cy + vy * dist * e);\n follow(layer, vx * dist * e, vy * dist * e, e * 1.05);\n wash.current?.show(answer, dir, e * 1.05);\n setHot(edgeRefs.current, p > 0.8 ? dir : null);\n });\n await wait(tourStop.current ? 0 : 420);\n await tween(reduced ? 1 : 240, (p) => {\n const e = 1 - p;\n place(F, cx + vx * dist * e, cy + vy * dist * e);\n follow(layer, vx * dist * e, vy * dist * e, e);\n wash.current?.show(answer, dir, e);\n });\n F.removeAttribute(\"data-down\");\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n follow(layer, 0, 0);\n await wait(tourStop.current ? 0 : 140);\n }\n const word = layer.querySelector<HTMLElement>(\"[data-sd-part] [data-sd-t]\") ?? layer.querySelector<HTMLElement>(\"[data-sd-t]\");\n if (!tourStop.current && word && props.editParts !== false) {\n const wr = word.getBoundingClientRect();\n const tx = wr.left + wr.width / 2;\n const ty = wr.top + wr.height / 2;\n await tween(reduced ? 1 : 420, (p) => {\n const e = ease(p);\n place(F, cx + (tx - cx) * e, cy + (ty - cy) * e);\n });\n const cap = capRef.current;\n if (cap) {\n cap.textContent = finePointer() ? labels.clickHint : labels.holdHint;\n const vw = cap.ownerDocument.defaultView?.innerWidth ?? 0;\n place(cap, Math.max(cap.offsetWidth / 2 + 12, Math.min(tx, vw - cap.offsetWidth / 2 - 12)), ty - 40);\n cap.style.opacity = \"1\";\n }\n F.setAttribute(\"data-down\", \"\");\n word.setAttribute(\"data-sd-press\", \"\");\n place(ringRef.current, tx, ty);\n if (!reduced) ringRef.current?.animate([{ opacity: 1, transform: \"scale(.6)\" }, { opacity: 0, transform: \"scale(1.9)\" }], { duration: 900, iterations: 2 });\n await wait(tourStop.current ? 0 : 1700);\n word.removeAttribute(\"data-sd-press\");\n F.removeAttribute(\"data-down\");\n if (cap) cap.style.opacity = \"0\";\n }\n F.style.opacity = \"0\";\n follow(layer, 0, 0);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n touringRef.current = false;\n setTouring(false);\n const pending = afterTour.current;\n afterTour.current = null;\n if (pending && alive.current) runKeyRef.current(pending, null);\n };\n const tourRef = React.useRef(tour);\n tourRef.current = tour;\n\n // ─── card arrival: enter, lean toward the suggestion, first-use walkthrough ─\n const tourKey = props.tourKey === undefined ? DEFAULT_TOUR_KEY : props.tourKey;\n const onCardMounted = React.useCallback(\n (layer: HTMLDivElement, dir: DeckDirection | null) => {\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer, from);\n if (tourKey && !readFlag(tourKey)) {\n writeFlag(tourKey);\n setTimeout(() => {\n if (alive.current && layerRef.current === layer) void tourRef.current();\n }, 700);\n return;\n }\n if (from === null && dir) {\n setTimeout(() => {\n if (!alive.current || layerRef.current !== layer || busy.current || touringRef.current) return;\n nudgeAnim.current = nudge(layer, dir);\n }, 420);\n }\n },\n [tourKey],\n );\n\n // ─── reaching the end ────────────────────────────────────────────────────\n const result = React.useMemo(() => deckResult(items, state, rules, conflict), [items, state, rules, conflict]);\n const atEnd = ready && items.length > 0 && step.kind === \"end\";\n const wasAtEnd = React.useRef(false);\n const onComplete = props.onComplete;\n React.useEffect(() => {\n if (atEnd && !wasAtEnd.current) {\n onComplete?.(result);\n // Arriving at the finish is said, as every answer is.\n setSaid(\n `${result.score ? `${labels.score}: ${result.score.right} / ${result.score.graded}` : labels.allDone}. ${labels.answeredOf.replace(\"{answered}\", String(result.answered)).replace(\"{total}\", String(result.total))}`,\n );\n }\n wasAtEnd.current = atEnd;\n }, [atEnd, result, onComplete, labels]);\n\n // ─── copy ────────────────────────────────────────────────────────────────\n const copy = async () => {\n const text = props.copyText\n ? props.copyText({ item: cardItem, state, result })\n : cardItem\n ? itemCopyText(cardItem, state, cardKey, labels, conflict, cardMoreShown)\n : deckCopyText(result, rules);\n const ok = await copyToClipboard(text);\n flash(ok ? labels.copied : labels.copyFailed);\n };\n\n // Drop the bubble's measured position into the viewport.\n const bubbleRef = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n const b = bubbleRef.current;\n if (!b || !bubble) return;\n const vw = b.ownerDocument.defaultView?.innerWidth ?? 0;\n const w = b.offsetWidth;\n const h = b.offsetHeight;\n b.style.left = `${Math.max(12, Math.min(bubble.x - w / 2, vw - w - 12))}px`;\n b.style.top = `${bubble.top - h - 10 < 8 ? bubble.bottom + 10 : bubble.top - h - 10}px`;\n }, [bubble]);\n\n const progress = steps.filter((s) => s.kind !== \"end\");\n\n return (\n <div\n ref={rootRef}\n className={[\"matrx-sd\", props.className].filter(Boolean).join(\" \")}\n data-layout={layout}\n data-touring={touring ? \"\" : undefined}\n {...(layout === \"inline\"\n ? {\n tabIndex: 0,\n role: \"group\",\n \"aria-roledescription\": \"swipe deck\",\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => {\n // Pressing the deck gives it the keys (it is one of many things in a chat).\n const root = e.currentTarget;\n if (!root.contains(root.ownerDocument.activeElement)) root.focus({ preventScroll: true });\n },\n }\n : { tabIndex: -1 })}\n >\n <div className=\"matrx-sd-progress\" aria-hidden=\"true\">\n {progress.map((s, k) => {\n const tone =\n k === stepIndex\n ? \"current\"\n : s.kind === \"card\"\n ? findAnswer(rules, s.item, state.answers[s.item.id])?.tone\n : s.kind === \"pick\" && state.picks[s.group]\n ? \"primary\"\n : undefined;\n return <i key={s.id} data-tone={tone} />;\n })}\n </div>\n\n <div\n ref={frameRef}\n className=\"matrx-sd-frame\"\n data-axis={!cardKey.up && !cardKey.down ? \"x\" : undefined}\n aria-hidden={part ? true : undefined}\n inert={part ? true : undefined}\n onPointerDownCapture={(e) => {\n // A press on the card away from the host's own controls (their field gone or left) ends a lock.\n if (!lockedRef.current) return;\n const inBody = (n: EventTarget | Element | null) => n instanceof Element && !!n.closest(\".matrx-sd-body\");\n if (inBody(e.target) || inBody(e.currentTarget.ownerDocument.activeElement)) return;\n lockedRef.current = false;\n live.current = { ...live.current, enabled: !!cardItem && !part && !touring };\n setLocked(null);\n }}\n >\n {props.onExpand ? (\n <CornerButton corner=\"tl\" label={labels.expand} onClick={props.onExpand}>\n <Maximize2Icon />\n </CornerButton>\n ) : props.onExit ? (\n <CornerButton corner=\"tl\" label={props.exitKind === \"collapse\" ? labels.collapse : labels.exit} {...(props.exitKind === \"collapse\" ? { shortcut: \"Escape\" } : {})} onClick={props.onExit}>\n {props.exitKind === \"collapse\" ? <Minimize2Icon /> : <XIcon />}\n </CornerButton>\n ) : null}\n <CornerButton corner=\"tr\" label={labels.answered} onClick={() => setReviewing((v) => !v)} disabled={!ready || !items.length || step.kind === \"end\"} pressed={reviewing}>\n <ListChecksIcon />\n {result.answered ? <span className=\"matrx-sd-corner-count\">{result.answered}</span> : null}\n </CornerButton>\n <CornerButton corner=\"bl\" label={labels.undo} shortcut=\"Z\" onClick={undo} disabled={!controller.canUndo}>\n <Undo2Icon />\n </CornerButton>\n <CornerButton corner=\"br\" label={labels.copy} onClick={() => void copy()} disabled={!ready || !items.length}>\n <CopyIcon />\n </CornerButton>\n\n {cardItem ? (\n <EdgeButtons keyMap={cardKey} suggested={suggestedDir} refs={edgeRefs} onAnswer={(d) => act(d)} suggestionLabel={labels.suggestion} />\n ) : null}\n\n <div className=\"matrx-sd-stage\">\n {!ready ? (\n <div className=\"matrx-sd-layer\" data-state={controller.status}>\n {controller.status === \"error\" ? (\n <ErrorBox className=\"matrx-sd-message\" message={controller.readError ?? \"\"} operation=\"Read the deck\" origin=\"design-system/SwipeDeck\" />\n ) : (\n <Loader2Icon className=\"matrx-spin matrx-sd-spinner\" />\n )}\n </div>\n ) : items.length === 0 ? (\n <EmptyView key=\"empty\" title={props.empty?.title ?? labels.emptyTitle} line={props.empty?.line} action={props.empty?.action} layerRef={layerRef} />\n ) : reviewing && step.kind !== \"end\" ? (\n <EndView\n key=\"review\"\n result={result}\n rules={rules}\n labels={labels}\n groupLabels={props.groupLabels}\n layerRef={layerRef}\n enterFrom={enterFrom}\n review={{\n onBack: () => setReviewing(false),\n onHelp: () => {\n setReviewing(false);\n void tour();\n },\n }}\n onChange={(item) => {\n enterFrom.current = null;\n const now = stateRef.current;\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: null }];\n if (item.group && now.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n controller.commit(makeChange(now, ops, items));\n setReviewing(false);\n setSaid(`${labels.change}: ${item.text}`);\n }}\n />\n ) : step.kind === \"card\" ? (\n <CardView\n key={step.id}\n item={step.item}\n keyMap={cardKey}\n state={state}\n conflict={conflict}\n labels={labels}\n suggestedDir={suggestedDir}\n more={props.moreOnCard === false ? [] : cardMoreShown}\n titleSize={props.titleSize ?? \"fit\"}\n detail={detailNow}\n onDetail={(d) => setCardDetail({ id: step.item.id, detail: d })}\n body={cardContext && props.renderCardBody ? props.renderCardBody(cardContext) : null}\n onBodyLeft={() => setLocked(null)}\n actions={cardContext && props.renderCardActions ? props.renderCardActions(cardContext) : null}\n showChoices={props.choicesOnCard === true || ((props.choicesOnCard ?? \"auto\") === \"auto\" && !!step.item.answers)}\n onChoose={(d) => {\n // A drag that started on a choice and snapped back still ends in a click: not an answer.\n if (dragged.current) dragged.current = false;\n else act(d);\n }}\n onChooseMore={(a) => {\n if (dragged.current) dragged.current = false;\n else void give(a, null);\n }}\n layerRef={layerRef}\n onMounted={onCardMounted}\n onDoubleClickWord={(i) => openPart(step.item, i)}\n />\n ) : step.kind === \"pick\" ? (\n <PickView key={step.id} step={step} label={props.groupLabels?.[step.group] ?? labels.pick} labels={labels} layerRef={layerRef} onPick={pick} enterFrom={enterFrom} />\n ) : (\n <EndView\n key=\"end\"\n result={result}\n rules={rules}\n labels={labels}\n groupLabels={props.groupLabels}\n layerRef={layerRef}\n enterFrom={enterFrom}\n actions={props.endActions}\n onChange={(item) => {\n // Taking an answer back is a change like any other (undo puts it back); the deck returns to that card.\n enterFrom.current = null;\n const now = stateRef.current;\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: null }];\n // A pick that named this item goes with its answer, as when the card is answered otherwise.\n if (item.group && now.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n controller.commit(makeChange(now, ops, items));\n setSaid(`${labels.change}: ${item.text}`);\n }}\n >\n {props.renderEnd?.(result)}\n </EndView>\n )}\n </div>\n <Wash ref={wash} />\n </div>\n\n {controller.writeError ? (\n <ErrorBox className=\"matrx-sd-error\" message={controller.writeError} operation=\"Save an answer\" origin=\"design-system/SwipeDeck\" />\n ) : null}\n\n {part && partItem ? (\n <PartScreen\n key={`${part.itemId}:${part.start}`}\n item={partItem}\n parts={partsOf(state, partItem)}\n initial={{ start: part.start, end: part.end }}\n keyMap={partKey}\n deckKey={keyFor(rules, partItem)}\n state={state}\n categories={allCategories}\n rows={props.categoryRows}\n allowNewCategories={props.allowNewCategories !== false}\n conflict={conflict}\n labels={labels}\n onClose={() => setPart(null)}\n onPlace={(p) => placeOnItem(partItem, p)}\n onForget={(span) => forgetOnItem(partItem, span)}\n onCategoryAnswer={(name, answer, row) => {\n enterFrom.current = \"stay\";\n controller.commit(makeChange(stateRef.current, [{ kind: \"category\", name, answer, ...(row ? { row } : {}) }], items));\n }}\n announce={setSaid}\n />\n ) : null}\n\n <div className=\"matrx-sd-tour\" hidden={!touring} onPointerDown={() => (tourStop.current = true)}>\n <div ref={ringRef} className=\"matrx-sd-ring\" />\n <div ref={fingerRef} className=\"matrx-sd-finger\" />\n <div ref={capRef} className=\"matrx-sd-tour-cap\" />\n </div>\n {bubble ? (\n <div ref={bubbleRef} className=\"matrx-sd-bubble\" role=\"status\">\n {bubble.text}\n </div>\n ) : null}\n <div className=\"matrx-sd-toast\" role=\"status\" aria-live=\"polite\" data-on={toast ? \"\" : undefined}>\n {toast}\n </div>\n <div className=\"matrx-sd-sr\" aria-live=\"polite\" aria-atomic=\"true\">\n {said}\n </div>\n </div>\n );\n}\n\n// ─── the card ──────────────────────────────────────────────────────────────\n\ninterface CardViewProps {\n readonly item: DeckItem;\n readonly keyMap: DeckKey;\n readonly state: DeckState;\n readonly conflict: CategoryConflict | undefined;\n readonly labels: SwipeDeckLabels;\n readonly suggestedDir: DeckDirection | null;\n /** Draw the item's choices on the card by direction (a quiz). */\n readonly showChoices: boolean;\n readonly onChoose: (dir: DeckDirection) => void;\n /** Answers off the edges: on the card as buttons (in the choices when they show). */\n readonly more: readonly DeckAnswer[];\n readonly onChooseMore: (answer: DeckAnswer) => void;\n /** `fit` grows the text to the card; `page` holds it at a page-title size. */\n readonly titleSize: \"fit\" | \"page\";\n readonly detail: DeckDetail | null;\n readonly onDetail: (detail: DeckDetail | null) => void;\n readonly body: React.ReactNode;\n /** Focus left the body slot: a lock it held is released. */\n readonly onBodyLeft: () => void;\n readonly actions: React.ReactNode;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly onMounted: (layer: HTMLDivElement, suggested: DeckDirection | null) => void;\n readonly onDoubleClickWord: (index: number) => void;\n}\n\n/** The order choices read on a card: clockwise from the top. */\nconst CHOICE_ORDER: readonly DeckDirection[] = [\"up\", \"right\", \"down\", \"left\"];\n\nfunction MediaView({ media, size }: { media: DeckMedia; size?: \"small\" }) {\n const shape = media.shape ?? \"square\";\n return (\n <span className=\"matrx-sd-media\" data-shape={shape} data-size={size}>\n {\"src\" in media ? <img src={media.src} alt={media.alt ?? \"\"} draggable={false} /> : media.node}\n </span>\n );\n}\n\nfunction CardView({\n item,\n keyMap,\n state,\n conflict,\n labels,\n suggestedDir,\n showChoices,\n onChoose,\n more,\n onChooseMore,\n titleSize,\n detail,\n onDetail,\n body,\n onBodyLeft,\n actions,\n layerRef,\n onMounted,\n onDoubleClickWord,\n}: CardViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n const inner = React.useRef<HTMLDivElement>(null);\n const hero = React.useRef<HTMLParagraphElement>(null);\n const tokens = React.useMemo(() => tokenize(item.text), [item.text]);\n const parts = partsOf(state, item);\n const suggested = answerOf(keyMap, item.suggested, more);\n const off = membersOff(item, detail);\n const toggle = (id: string) => {\n const next = off.includes(id) ? off.filter((x) => x !== id) : [...off, id];\n onDetail({ ...(detail ?? {}), off: next });\n };\n\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n if (layer.current) onMounted(layer.current, suggestedDir);\n return () => {\n if (layerRef.current === layer.current) layerRef.current = null;\n };\n // Mount only: a card arrives once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const partsKey = parts.map((p) => `${p.start}-${p.end}`).join(\",\");\n React.useLayoutEffect(() => {\n const box = layer.current;\n if (!box || !inner.current || !hero.current) return;\n return keepFitted(box, () => {\n if (!inner.current || !hero.current) return;\n if (titleSize === \"fit\") fitText(box, inner.current, hero.current, 20, heroMax(box));\n else markOverflow(box, inner.current);\n });\n }, [item.text, partsKey, item.members?.length, more.length, titleSize]);\n\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < tokens.length; ) {\n const p = parts.find((x) => x.start === i);\n if (p) {\n const a = answerOf(keyMap, partAnswer(p, state, keyMap, conflict));\n const words: React.ReactNode[] = [];\n for (let j = p.start; j <= p.end; j++) {\n words.push(\n <span key={j} className=\"matrx-sd-token\" data-sd-t={j}>\n {tokens[j]}\n </span>,\n );\n if (j < p.end) words.push(\" \");\n }\n nodes.push(\n <span key={`p${i}`} className=\"matrx-sd-part\" data-sd-part={i} data-tone={a?.tone} data-sd-part-label={[a?.label, ...p.categories].filter(Boolean).join(\" · \") || partText(item, p)}>\n {words}\n </span>,\n );\n i = p.end + 1;\n } else {\n nodes.push(\n <span key={i} className=\"matrx-sd-token\" data-sd-t={i}>\n {tokens[i]}\n </span>,\n );\n i++;\n }\n if (i < tokens.length) nodes.push(\" \");\n }\n\n return (\n <div\n ref={layer}\n className=\"matrx-sd-layer\"\n data-sd-item={item.id}\n data-sd-title={titleSize === \"page\" ? \"page\" : undefined}\n aria-label={[item.kicker, item.text].filter(Boolean).join(\": \")}\n onDoubleClick={(e) => {\n const t = e.target instanceof Element ? e.target.closest(\"[data-sd-t]\") : null;\n if (t) onDoubleClickWord(Number(t.getAttribute(\"data-sd-t\")));\n }}\n >\n <div ref={inner} className=\"matrx-sd-card\">\n {item.media ? <MediaView media={item.media} /> : null}\n {item.kicker || item.tag || actions ? (\n <div className=\"matrx-sd-kicker\">\n {item.kicker ? <span>{item.kicker}</span> : null}\n {item.tag ? (\n <span className=\"matrx-sd-tag\">\n <CheckIcon />\n {item.tag}\n </span>\n ) : null}\n {actions ? <span className=\"matrx-sd-actions\">{actions}</span> : null}\n </div>\n ) : null}\n <p ref={hero} className=\"matrx-sd-hero\" data-quoted={item.quoted ? \"\" : undefined}>\n {nodes}\n </p>\n {item.members?.length ? (\n <div className=\"matrx-sd-members\">\n {item.members.map((m) => {\n const isOff = off.includes(m.id);\n return (\n // ui-exception: a group card's member switch is part of the card (a swipe never starts on it)\n <button key={m.id} type=\"button\" className=\"matrx-sd-member\" aria-pressed={!isOff} data-off={isOff ? \"\" : undefined} onClick={() => toggle(m.id)}>\n {m.media ? <MediaView media={m.media} size=\"small\" /> : null}\n <span>{m.label}</span>\n </button>\n );\n })}\n </div>\n ) : null}\n {body ? (\n <div\n className=\"matrx-sd-body\"\n onBlur={(e) => {\n // Focus leaving the host's own controls (a field closed, a tap on the card) ends a lock: never stuck.\n const next = e.relatedTarget instanceof Node ? e.relatedTarget : null;\n // The window losing focus (another tab, another app) is not leaving the field.\n if (!e.currentTarget.ownerDocument.hasFocus()) return;\n if (!next || !e.currentTarget.contains(next)) onBodyLeft();\n }}\n >\n {body}\n </div>\n ) : null}\n {showChoices ? (\n <div className=\"matrx-sd-choices\">\n {CHOICE_ORDER.map((d) => {\n const a = keyMap[d];\n if (!a) return null;\n return (\n // ui-exception: a choice on the card is the card's own answer target (and a swipe can start on it)\n <button key={d} type=\"button\" className=\"matrx-sd-choice\" data-sd-choice=\"\" data-dir={d} data-tone={a.tone} onClick={() => onChoose(d)}>\n <AnswerGlyph answer={{ ...a, icon: undefined }} dir={d} />\n <span>{a.label}</span>\n </button>\n );\n })}\n {more.map((a) => (\n // ui-exception: an answer off the edges is the card's own answer target\n <button key={a.id} type=\"button\" className=\"matrx-sd-choice\" data-sd-choice=\"\" data-tone={a.tone} title={a.shortcut ? `${a.label} (${a.shortcut})` : a.label} onClick={() => onChooseMore(a)}>\n {a.icon ?? null}\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n ) : more.length ? (\n <div className=\"matrx-sd-more\">\n {more.map((a) => (\n // ui-exception: an answer off the edges is the card's own answer target\n <button\n key={a.id}\n type=\"button\"\n className=\"matrx-sd-more-answer\"\n data-sd-choice=\"\"\n data-tone={a.tone}\n data-suggested={item.suggested === a.id ? \"\" : undefined}\n aria-keyshortcuts={a.shortcut}\n title={a.shortcut ? `${a.label} (${a.shortcut})` : a.label}\n onClick={() => onChooseMore(a)}\n >\n {a.icon ?? null}\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n ) : null}\n {suggested || item.reason || item.fields?.length ? (\n <div className=\"matrx-sd-fields\">\n {suggested ? (\n <div>\n <div className=\"matrx-sd-label\">{labels.suggestion}</div>\n <div className=\"matrx-sd-suggested\" data-tone={suggested.tone}>\n <AnswerGlyph answer={suggested} dir={suggestedDir} />\n {item.suggestedLabel ?? suggested.label}\n </div>\n </div>\n ) : null}\n {item.reason ? (\n <div>\n <div className=\"matrx-sd-label\">{labels.reason}</div>\n <div className=\"matrx-sd-value\">{item.reason}</div>\n </div>\n ) : null}\n {item.fields?.map((f) => (\n <div key={f.label}>\n <div className=\"matrx-sd-label\">{f.label}</div>\n <div className=\"matrx-sd-value\">{f.value}</div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\n// ─── pick one ──────────────────────────────────────────────────────────────\n\ninterface PickViewProps {\n readonly step: Extract<DeckStep, { kind: \"pick\" }>;\n readonly label: string;\n readonly labels: SwipeDeckLabels;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly enterFrom: React.MutableRefObject<DeckDirection | \"stay\" | null>;\n readonly onPick: (group: string, item: DeckItem) => void;\n}\n\nfunction PickView({ step, label, labels, layerRef, enterFrom, onPick }: PickViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n const [chosen, setChosen] = React.useState<string | null>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer.current, from);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n React.useLayoutEffect(() => {\n const box = layer.current;\n if (!box) return;\n const run = () => {\n const buttons = Array.from(box.querySelectorAll<HTMLElement>(\".matrx-sd-option\"));\n let lo = 16;\n let hi = (box.ownerDocument.defaultView?.innerWidth ?? 0) >= 1024 ? 64 : 40;\n let best = lo;\n for (let k = 0; k < 9; k++) {\n const mid = (lo + hi) / 2;\n buttons.forEach((b) => (b.style.fontSize = `${mid}px`));\n const ok = buttons.every((b) => b.scrollHeight <= b.clientHeight + 1 && b.scrollWidth <= b.clientWidth + 1);\n if (ok) {\n best = mid;\n lo = mid;\n } else hi = mid;\n }\n buttons.forEach((b) => (b.style.fontSize = `${Math.floor(best)}px`));\n // Too many options for even the smallest size: the pick scrolls instead of clipping.\n const list = box.querySelector<HTMLElement>(\".matrx-sd-options\");\n if (list && list.scrollHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n };\n return keepFitted(box, run);\n }, [step.items.length]);\n return (\n <div ref={layer} className=\"matrx-sd-layer\">\n <div className=\"matrx-sd-options\" role=\"radiogroup\" aria-label={label}>\n {step.items.map((item) => (\n // ui-exception: a pick-one option fills its share of the full-screen deck\n <button\n key={item.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={chosen === item.id}\n className=\"matrx-sd-option\"\n data-suggested={item.pickSuggested ? \"\" : undefined}\n data-chosen={chosen === item.id ? \"\" : undefined}\n onClick={() => {\n setChosen(item.id);\n onPick(step.group, item);\n }}\n >\n {item.pickSuggested ? <span className=\"matrx-sd-label\">{labels.suggestion}</span> : null}\n <span>{item.text}</span>\n </button>\n ))}\n </div>\n </div>\n );\n}\n\n// ─── the end ───────────────────────────────────────────────────────────────\n\ninterface EndViewProps {\n readonly result: DeckResult;\n readonly rules: DeckRules;\n readonly labels: SwipeDeckLabels;\n readonly groupLabels: Readonly<Record<string, string>> | undefined;\n readonly layerRef: React.MutableRefObject<HTMLDivElement | null>;\n readonly enterFrom: React.MutableRefObject<DeckDirection | \"stay\" | null>;\n /** The host's own buttons at the end (back to where the person came from, next step). */\n readonly actions?: React.ReactNode;\n /** Take an item's answer back: the deck returns to that card. */\n readonly onChange: (item: DeckItem) => void;\n readonly children?: React.ReactNode;\n /** Mid-deck: the same list titled \"Answered\", with the way back to the cards (and the walkthrough). */\n readonly review?: { readonly onBack: () => void; readonly onHelp?: () => void };\n}\n\ninterface EndGroup {\n readonly key: string;\n readonly label: string;\n readonly tone: DeckTone;\n readonly count: number;\n}\n\n/** How the answers split: right / wrong on a graded deck, else by answer (same words = one group). */\nfunction endGroups(result: DeckResult, labels: SwipeDeckLabels): EndGroup[] {\n const graded = result.entries.filter((e) => e.answer && e.right !== null);\n if (result.score && graded.length) {\n const right = graded.filter((e) => e.right).length;\n return [\n { key: \"right\", label: labels.right, tone: \"success\", count: right },\n { key: \"wrong\", label: labels.wrong, tone: \"destructive\", count: graded.length - right },\n ].filter((g) => g.count > 0) as EndGroup[];\n }\n const out = new Map<string, EndGroup>();\n for (const e of result.entries) {\n if (!e.answer) continue;\n const key = e.answer.label;\n const had = out.get(key);\n out.set(key, { key, label: e.answer.label, tone: had?.tone ?? e.answer.tone, count: (had?.count ?? 0) + 1 });\n }\n return [...out.values()];\n}\n\nfunction groupOf(entry: DeckResult[\"entries\"][number], graded: boolean): string | null {\n if (!entry.answer) return null;\n if (graded && entry.right !== null) return entry.right ? \"right\" : \"wrong\";\n return entry.answer.label;\n}\n\n/** The finish: a mark that draws itself, the headline (a pick, a score, or done), how the answers split, and every answer to look over and change. */\nfunction EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, actions, onChange, children, review }: EndViewProps) {\n const layer = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n const from = enterFrom.current;\n enterFrom.current = null;\n if (from !== \"stay\") enter(layer.current, from);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n const [filter, setFilter] = React.useState<string | null>(null);\n if (children) {\n return (\n <div ref={layer} className=\"matrx-sd-layer\">\n {children}\n </div>\n );\n }\n const picks = Object.entries(result.picks);\n const [first, ...rest] = picks;\n const score = result.score;\n const groups = endGroups(result, labels);\n const graded = !!score && groups.some((g) => g.key === \"right\" || g.key === \"wrong\");\n const answered = result.entries.filter((e) => e.answer);\n const shown = filter ? answered.filter((e) => groupOf(e, graded) === filter) : answered;\n const pct = score && score.graded ? score.right / score.graded : 1;\n const kicker = review ? null : first ? (groupLabels?.[first[0]] ?? first[0]) : score ? labels.score : null;\n const headline = review ? labels.answered : first ? first[1].text : score ? `${score.right} / ${score.graded}` : labels.allDone;\n const sub = labels.answeredOf.replace(\"{answered}\", String(result.answered)).replace(\"{total}\", String(result.total));\n return (\n <div ref={layer} className=\"matrx-sd-layer matrx-sd-endlayer\">\n <div className=\"matrx-sd-end\" data-graded={graded ? \"\" : undefined} data-review={review ? \"\" : undefined}>\n {review ? null : (\n <svg className=\"matrx-sd-mark\" viewBox=\"0 0 72 72\" aria-hidden=\"true\" data-tone={score ? (pct >= 0.5 ? \"success\" : \"warning\") : \"success\"}>\n <circle className=\"matrx-sd-mark-track\" cx=\"36\" cy=\"36\" r=\"32\" />\n <circle className=\"matrx-sd-mark-ring\" cx=\"36\" cy=\"36\" r=\"32\" pathLength={100} style={{ strokeDasharray: `${Math.round(pct * 100)} 100` }} />\n {!score || pct === 1 ? <path className=\"matrx-sd-mark-check\" d=\"M23 37.5l9 9 17-19\" pathLength={100} /> : null}\n </svg>\n )}\n {kicker ? <div className=\"matrx-sd-kicker\">{kicker}</div> : null}\n <h2 className=\"matrx-sd-end-hero\">{headline}</h2>\n <div className=\"matrx-sd-end-sub\">{sub}</div>\n {score && first && !review ? (\n <div className=\"matrx-sd-endline\">\n <div className=\"matrx-sd-label\">{labels.score}</div>\n <div className=\"matrx-sd-value\">{`${score.right} / ${score.graded}`}</div>\n </div>\n ) : null}\n {(review ? [] : rest).map(([group, item]) => (\n <div key={group} className=\"matrx-sd-endline\">\n <div className=\"matrx-sd-label\">{groupLabels?.[group] ?? group}</div>\n <div className=\"matrx-sd-value\">{item.text}</div>\n </div>\n ))}\n {groups.length ? (\n <>\n <div className=\"matrx-sd-split\" aria-hidden=\"true\">\n {groups.map((g) => (\n <i key={g.key} data-tone={g.tone} style={{ flexGrow: g.count }} />\n ))}\n </div>\n <div className=\"matrx-sd-legend\" role=\"group\" aria-label={labels.filterAnswers}>\n {groups.length > 1 ? (\n // ui-exception: the end's answer filter is part of the deck's own finish screen\n <button type=\"button\" className=\"matrx-sd-legend-chip\" aria-pressed={filter === null} onClick={() => setFilter(null)}>\n <span>{labels.showAll}</span>\n <b>{answered.length}</b>\n </button>\n ) : null}\n {groups.map((g) => (\n // ui-exception: the end's answer filter is part of the deck's own finish screen\n <button\n key={g.key}\n type=\"button\"\n className=\"matrx-sd-legend-chip\"\n data-tone={g.tone}\n aria-pressed={filter === g.key}\n onClick={() => setFilter((f) => (f === g.key ? null : g.key))}\n >\n <i aria-hidden=\"true\" />\n <span>{g.label}</span>\n <b>{g.count}</b>\n </button>\n ))}\n </div>\n </>\n ) : null}\n {shown.length ? (\n <ul className=\"matrx-sd-review\" aria-label={labels.yourAnswers}>\n {shown.map((e) => {\n const rightIds = e.item.correct === undefined ? [] : typeof e.item.correct === \"string\" ? [e.item.correct] : e.item.correct;\n // What rode with the answer reads in its place: the value typed on the card, the relationship picked.\n const said = typeof e.detail?.value === \"string\" && e.detail.value.trim() ? e.detail.value : e.item.text;\n const answerWords = typeof e.detail?.label === \"string\" && e.detail.label ? e.detail.label : e.answer?.label;\n const rightWords = rightIds.map((id) => findAnswer(rules, e.item, id)?.label).filter(Boolean).join(\", \");\n return (\n <li key={e.item.id}>\n {/* ui-exception: a reviewed answer is the end screen's own row (tap to change it) */}\n <button\n type=\"button\"\n className=\"matrx-sd-review-row\"\n onClick={() => onChange(e.item)}\n aria-label={[\n `${labels.change}: ${said}`,\n [answerWords, e.right === true ? labels.right : e.right === false ? labels.wrong : null].filter(Boolean).join(\", \"),\n e.right === false && rightWords ? `${labels.rightAnswer}: ${rightWords}` : null,\n ]\n .filter(Boolean)\n .join(\". \")}\n >\n <span className=\"matrx-sd-review-text\">\n {e.item.kicker ? <span className=\"matrx-sd-label\">{e.item.kicker}</span> : null}\n <span className=\"matrx-sd-review-item\">{said}</span>\n {e.right === false && rightWords ? (\n <span className=\"matrx-sd-review-right\">\n {labels.rightAnswer}: {rightWords}\n </span>\n ) : null}\n </span>\n <span className=\"matrx-sd-review-answer\" data-tone={e.right === null ? e.answer?.tone : e.right ? \"success\" : \"destructive\"}>\n {e.right === true ? <CheckIcon /> : e.right === false ? <XIcon /> : null}\n <span>{answerWords}</span>\n </span>\n <PencilIcon className=\"matrx-sd-review-change\" aria-hidden=\"true\" />\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n {review ? (\n <div className=\"matrx-sd-end-actions\">\n {/* ui-exception: the answered list's way back is the deck's own control, in its own geometry */}\n <button type=\"button\" className=\"matrx-sd-review-back\" onClick={review.onBack} autoFocus>\n {labels.backToCards}\n </button>\n {review.onHelp ? (\n // ui-exception: the walkthrough, from the answered list (the corner it had now opens this list)\n <button type=\"button\" className=\"matrx-sd-review-help\" onClick={review.onHelp}>\n <CircleHelpIcon aria-hidden=\"true\" />\n <span>{labels.help}</span>\n </button>\n ) : null}\n </div>\n ) : actions ? (\n <div className=\"matrx-sd-end-actions\">{actions}</div>\n ) : null}\n </div>\n </div>\n );\n}\n\n/** Nothing to answer: the deck's own quiet screen, never a blank. */\nfunction EmptyView({ title, line, action, layerRef }: { title: string; line?: string | undefined; action?: React.ReactNode; layerRef: React.MutableRefObject<HTMLDivElement | null> }) {\n const layer = React.useRef<HTMLDivElement>(null);\n React.useLayoutEffect(() => {\n layerRef.current = layer.current;\n enter(layer.current, null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n return (\n <div ref={layer} className=\"matrx-sd-layer matrx-sd-endlayer\" data-sd-empty=\"\">\n <div className=\"matrx-sd-end matrx-sd-empty\">\n <div className=\"matrx-sd-empty-stack\" aria-hidden=\"true\">\n <i />\n <i />\n <i />\n </div>\n <h2 className=\"matrx-sd-end-hero\">{title}</h2>\n {line ? <div className=\"matrx-sd-end-sub\">{line}</div> : null}\n {action ? <div className=\"matrx-sd-end-actions\">{action}</div> : null}\n </div>\n </div>\n );\n}\n\n\n","\"use client\";\n\n/**\n * The deck's chrome: the four edge buttons, the corner buttons, and the full-screen wash.\n * Hot / wash state is written straight to the DOM (no React render per pointer move).\n */\nimport * as React from \"react\";\n\nimport { ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon } from \"../icons\";\nimport { hideWash, showWash } from \"./visual\";\nimport type { DeckAnswer, DeckDirection, DeckKey } from \"./model\";\n\nconst ARROWS: Record<DeckDirection, React.ComponentType<React.SVGAttributes<SVGSVGElement>>> = {\n right: ArrowRightIcon,\n left: ArrowLeftIcon,\n up: ArrowUpIcon,\n down: ArrowDownIcon,\n};\n\nexport const KEY_GLYPH: Record<DeckDirection, string> = { right: \"→\", up: \"↑\", left: \"←\", down: \"↓\" };\n\n/** The answer's own icon, else the arrow of the edge it sits on (an answer off the edges has none). */\nexport function AnswerGlyph({ answer, dir }: { answer: DeckAnswer; dir: DeckDirection | null }) {\n if (answer.icon) return <>{answer.icon}</>;\n if (!dir) return null;\n const Arrow = ARROWS[dir];\n return <Arrow />;\n}\n\nexport type EdgeRefs = Partial<Record<DeckDirection, HTMLButtonElement | null>>;\n\nexport function setHot(refs: EdgeRefs, dir: DeckDirection | null): void {\n for (const d of Object.keys(refs) as DeckDirection[]) {\n const el = refs[d];\n if (!el) continue;\n if (d === dir) el.setAttribute(\"data-hot\", \"\");\n else el.removeAttribute(\"data-hot\");\n }\n}\n\nexport interface EdgeButtonsProps {\n readonly keyMap: DeckKey;\n readonly suggested: DeckDirection | null;\n readonly refs: React.MutableRefObject<EdgeRefs>;\n readonly onAnswer: (dir: DeckDirection) => void;\n readonly suggestionLabel: string;\n readonly disabled?: boolean;\n}\n\n/** One large button on each enabled edge, where its swipe goes. */\nexport function EdgeButtons({ keyMap, suggested, refs, onAnswer, suggestionLabel, disabled }: EdgeButtonsProps) {\n return (\n <>\n {([\"up\", \"left\", \"right\", \"down\"] as const).map((dir) => {\n const answer = keyMap[dir];\n if (!answer) return null;\n const isSuggested = dir === suggested;\n return (\n // ui-exception: the deck's edge targets are its own geometry (the swipe they mirror), not a form control\n <button\n key={dir}\n ref={(el) => {\n refs.current[dir] = el;\n }}\n type=\"button\"\n className=\"matrx-sd-edge\"\n data-dir={dir}\n data-tone={answer.tone}\n data-suggested={isSuggested ? \"\" : undefined}\n aria-label={isSuggested ? `${answer.label} (${suggestionLabel})` : answer.label}\n aria-keyshortcuts={{ right: \"ArrowRight\", left: \"ArrowLeft\", up: \"ArrowUp\", down: \"ArrowDown\" }[dir]}\n title={`${answer.label} ${KEY_GLYPH[dir]}`}\n disabled={disabled}\n onClick={() => onAnswer(dir)}\n >\n <AnswerGlyph answer={answer} dir={dir} />\n </button>\n );\n })}\n </>\n );\n}\n\nexport interface CornerButtonProps {\n readonly corner: \"tl\" | \"tr\" | \"bl\" | \"br\";\n readonly label: string;\n readonly shortcut?: string;\n readonly onClick: () => void;\n readonly disabled?: boolean;\n readonly pressed?: boolean;\n readonly children: React.ReactNode;\n}\n\nexport function CornerButton({ corner, label, shortcut, onClick, disabled, pressed, children }: CornerButtonProps) {\n return (\n // ui-exception: the deck's four corner targets sit in its own frame geometry\n <button\n type=\"button\"\n className=\"matrx-sd-corner\"\n data-corner={corner}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n aria-keyshortcuts={shortcut}\n disabled={disabled}\n aria-pressed={pressed}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\nexport interface WashHandle {\n show(answer: DeckAnswer, dir: DeckDirection | null, amount: number): void;\n hide(): void;\n}\n\n/** The whole screen takes the answer's color and shows its name big, the moment a drag starts. */\nexport const Wash = React.forwardRef<WashHandle>(function Wash(_props, ref) {\n const bg = React.useRef<HTMLDivElement>(null);\n const label = React.useRef<HTMLDivElement>(null);\n const [shown, setShown] = React.useState<{ answer: DeckAnswer; dir: DeckDirection | null } | null>(null);\n React.useImperativeHandle(\n ref,\n () => ({\n show(answer, dir, amount) {\n setShown((cur) => (cur && cur.answer.id === answer.id && cur.dir === dir ? cur : { answer, dir }));\n showWash(bg.current, label.current, amount);\n },\n hide() {\n hideWash(bg.current, label.current);\n },\n }),\n [],\n );\n return (\n <div className=\"matrx-sd-wash\" aria-hidden=\"true\" data-tone={shown?.answer.tone}>\n <div ref={bg} className=\"matrx-sd-wash-bg\" />\n <div ref={label} className=\"matrx-sd-wash-label\">\n {shown ? <AnswerGlyph answer={shown.answer} dir={shown.dir} /> : null}\n <b>{shown?.answer.label}</b>\n </div>\n </div>\n );\n});\n","/**\n * The deck's direct-to-DOM motion: card follow, snap back, fly out, enter, the full-screen wash,\n * and the text fit. Each writes `transform`/`opacity` only (compositor properties) and never\n * React state, so dragging stays on the 60fps path.\n */\nimport type { DeckDirection } from \"./model\";\n\nexport const VECTOR: Record<DeckDirection, readonly [number, number]> = {\n right: [1, 0],\n left: [-1, 0],\n up: [0, -1],\n down: [0, 1],\n};\n\n/** A short buzz, only once the page has had a tap (browsers refuse, and say so, before one). */\nexport function buzz(nav: Navigator | undefined, ms: number): void {\n try {\n const activation = (nav as (Navigator & { userActivation?: { hasBeenActive: boolean } }) | undefined)?.userActivation;\n if (activation && !activation.hasBeenActive) return;\n nav?.vibrate?.(ms);\n } catch {\n /* no haptics */\n }\n}\n\nexport function prefersReducedMotion(): boolean {\n try {\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n } catch {\n return false;\n }\n}\n\nexport function finePointer(): boolean {\n try {\n return typeof matchMedia === \"function\" && matchMedia(\"(hover: hover) and (pointer: fine)\").matches;\n } catch {\n return false;\n }\n}\n\n/**\n * The card follows the drag; `amount` (distance over the threshold) fades it, so the answer's big name\n * reads over a quiet card (full drag: 0.3), never two texts printed over each other.\n */\nexport function follow(el: HTMLElement | null, dx: number, dy: number, amount = 0): void {\n if (!el) return;\n el.style.transition = \"none\";\n el.style.transform = dx || dy ? `translate3d(${dx}px,${dy}px,0) rotate(${(dx / 28).toFixed(2)}deg)` : \"\";\n el.style.opacity = amount > 0 ? String(1 - 0.7 * Math.min(1, amount)) : \"\";\n}\n\nexport function snapBack(el: HTMLElement | null): void {\n if (!el) return;\n el.style.transition = \"transform 260ms cubic-bezier(.2,.8,.2,1), opacity 260ms ease\";\n el.style.transform = \"\";\n el.style.opacity = \"\";\n}\n\n/** Throw the card off the edge it went toward; faster throws leave faster. */\nexport function flyOut(el: HTMLElement | null, dir: DeckDirection, speed = 0): Promise<void> {\n if (!el || prefersReducedMotion()) return new Promise((r) => setTimeout(r, 90));\n const [vx, vy] = VECTOR[dir];\n const ms = Math.round(Math.max(150, Math.min(260, 260 - speed * 60)));\n el.style.transition = `transform ${ms}ms cubic-bezier(.4,0,1,1), opacity ${ms}ms linear`;\n el.style.transform = `translate3d(${vx * 120}vw,${vy * 110}vh,0) rotate(${vx * 14}deg)`;\n el.style.opacity = \"0\";\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** A new card arrives: from the edge it left by (undo), or rising in place. */\nexport function enter(el: HTMLElement | null, from: DeckDirection | null): void {\n if (!el || prefersReducedMotion() || typeof el.animate !== \"function\") return;\n if (from) {\n const [vx, vy] = VECTOR[from];\n el.animate(\n [\n { transform: `translate3d(${vx * 100}vw,${vy * 100}vh,0) rotate(${vx * 10}deg)`, opacity: 0.3 },\n { transform: \"none\", opacity: 1 },\n ],\n { duration: 320, easing: \"cubic-bezier(.2,.8,.2,1)\" },\n );\n } else {\n el.animate([{ transform: \"scale(.95)\", opacity: 0 }, { transform: \"none\", opacity: 1 }], { duration: 260, easing: \"cubic-bezier(.2,.8,.2,1)\" });\n }\n}\n\n/** The card leans toward its suggested answer once, then settles. */\nexport function nudge(el: HTMLElement | null, dir: DeckDirection): Animation | null {\n if (!el || prefersReducedMotion() || typeof el.animate !== \"function\") return null;\n const [vx, vy] = VECTOR[dir];\n return el.animate(\n [\n { transform: \"none\" },\n { transform: `translate3d(${vx * 24}px,${vy * 24}px,0) rotate(${vx * 1.2}deg)`, offset: 0.3 },\n { transform: \"none\", offset: 0.6 },\n { transform: `translate3d(${vx * 10}px,${vy * 10}px,0)`, offset: 0.8 },\n { transform: \"none\" },\n ],\n { duration: 1100, easing: \"ease-in-out\" },\n );\n}\n\n/** Fill the screen with the answer's color; `amount` 0..1+ is how far the drag has gone. */\nexport function showWash(bg: HTMLElement | null, label: HTMLElement | null, amount: number): void {\n if (!bg || !label) return;\n const a = Math.max(0, Math.min(1, amount));\n bg.style.opacity = String(Math.min(0.93, 0.2 + 0.73 * a));\n label.style.opacity = String(Math.min(1, 0.35 + a));\n label.style.transform = `scale(${0.82 + 0.22 * a})`;\n}\n\nexport function hideWash(bg: HTMLElement | null, label: HTMLElement | null): void {\n if (bg) bg.style.opacity = \"0\";\n if (label) label.style.opacity = \"0\";\n}\n\n/**\n * The largest font size (px) at which `text` fits: `inner` no taller than `box`, and no word wider\n * than the line. Binary search, ten measurements.\n */\nexport function fitText(box: HTMLElement, inner: HTMLElement, text: HTMLElement, min: number, max: number): number {\n let lo = min;\n let hi = Math.max(min, max);\n let best = lo;\n for (let k = 0; k < 10; k++) {\n const mid = (lo + hi) / 2;\n text.style.fontSize = `${mid}px`;\n const ok = inner.offsetHeight <= box.clientHeight && text.scrollWidth <= text.clientWidth + 1;\n if (ok) {\n best = mid;\n lo = mid;\n } else hi = mid;\n }\n const size = Math.floor(best);\n text.style.fontSize = `${size}px`;\n // Even the smallest size does not fit (a very long text, a narrow phone): this one screen scrolls, never clips.\n if (inner.offsetHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n return size;\n}\n\n/** The card's text at a fixed size: the one screen scrolls when the card is taller than the stage, never clips. */\nexport function markOverflow(box: HTMLElement, inner: HTMLElement): void {\n if (inner.offsetHeight > box.clientHeight + 1) box.setAttribute(\"data-sd-overflow\", \"\");\n else box.removeAttribute(\"data-sd-overflow\");\n}\n\n/** Run a fit now, again once the web font has loaded (it changes every measure), and on every resize. */\nexport function keepFitted(box: HTMLElement, run: () => void): () => void {\n run();\n let alive = true;\n box.ownerDocument.fonts?.ready.then(() => alive && run()).catch(() => undefined);\n if (typeof ResizeObserver === \"undefined\") return () => void (alive = false);\n const ro = new ResizeObserver(run);\n ro.observe(box);\n return () => {\n alive = false;\n ro.disconnect();\n };\n}\n\n/**\n * The largest the card's text may be. A phone (under 480px) goes by its text column (column / 2.6, so a\n * short line like \"junk\" goes huge and the height fills first); wider screens by the screen's width.\n */\nexport function heroMax(box: HTMLElement): number {\n const vw = box.ownerDocument.defaultView?.innerWidth ?? box.clientWidth;\n if (vw < 480) return Math.min(104, Math.max(36, box.clientWidth / 2.6));\n const wide = vw >= 1024;\n return Math.min(wide ? 132 : 104, Math.max(36, Math.min(vw, box.clientWidth * 1.6) / 3.2));\n}\n","/**\n * THE DECK CONTROLLER — the one place a deck's changes go, in either mode.\n *\n * CONTROLLED (no binding): the state lives here; every change is reported through `onChange`.\n * BOUND (a {@link SwipeDeckBinding}): the binding holds the truth (its store, its realtime); this\n * controller draws each change at once on top of it (optimistic), sends the ops, and when the\n * connection refuses, takes the change back and keeps the refusal's own sentence for the screen.\n * Undo in both modes is the change's inverse, sent the same way.\n */\nimport * as React from \"react\";\n\nimport { applyOps, deckState, type DeckChange, type DeckItem, type DeckOp, type DeckState } from \"./model\";\n\n/**\n * A connection a deck persists through: hand one to `SwipeDeck` and it saves every answer, pick,\n * part edit and category the moment it happens. `state` must follow the connection's truth\n * (including other devices' writes); `apply` resolves when the connection kept the ops and rejects\n * with an Error whose message is the connection's own refusal sentence.\n */\nexport interface SwipeDeckBinding {\n readonly status: \"loading\" | \"ready\" | \"error\";\n /** Why the connection cannot be read, in its own words. */\n readonly error: string | null;\n readonly items: readonly DeckItem[];\n readonly state: DeckState;\n apply(ops: readonly DeckOp[]): Promise<void>;\n /**\n * Optional: the undo history the connection kept (newest last). Given, the deck starts from it, so undo\n * still works after a reload or on another device; `saveHistory` is handed every change to it (at most\n * {@link UNDO_KEPT} steps).\n */\n readonly history?: readonly DeckChange[];\n saveHistory?(history: readonly DeckChange[]): void;\n}\n\n/** How many steps of undo a connection is asked to keep. */\nexport const UNDO_KEPT = 100;\n\ninterface Pending {\n readonly id: number;\n readonly ops: readonly DeckOp[];\n settledAt: number | null;\n /** Never kept by the connection (a requeue): dropped the moment it settles, not held until reflected. */\n readonly transient?: boolean;\n}\n\nexport interface DeckController {\n readonly items: readonly DeckItem[];\n readonly state: DeckState;\n readonly status: \"loading\" | \"ready\" | \"error\";\n readonly readError: string | null;\n /** The last refusal of a write, in the connection's words; cleared by the next write that lands. */\n readonly writeError: string | null;\n readonly canUndo: boolean;\n commit(change: DeckChange): void;\n /** Takes back the last change; returns it (its `from` is the edge the card comes back from). */\n undo(): DeckChange | null;\n}\n\nexport interface DeckControllerOptions {\n readonly items?: readonly DeckItem[] | undefined;\n readonly binding?: SwipeDeckBinding | undefined;\n readonly initialState?: Partial<DeckState> | undefined;\n readonly onChange?: ((state: DeckState, change: DeckChange, undo: boolean) => void) | undefined;\n}\n\nconst SETTLE_GRACE_MS = 6000;\n\n/** True when `state` already holds what `op` writes. */\nexport function reflects(state: DeckState, op: DeckOp): boolean {\n switch (op.kind) {\n case \"answer\":\n return (state.answers[op.itemId] ?? null) === op.answer;\n case \"pick\":\n return (state.picks[op.group] ?? null) === op.itemId;\n case \"parts\":\n return JSON.stringify(state.parts[op.itemId] ?? null) === JSON.stringify(op.parts);\n case \"category\":\n return op.remove ? !state.categories[op.name] : (state.categories[op.name]?.answer ?? null) === op.answer;\n }\n}\n\nexport function useDeckController({ items, binding, initialState, onChange }: DeckControllerOptions): DeckController {\n const [local, setLocal] = React.useState<DeckState>(() => deckState(initialState));\n const [history, setHistory] = React.useState<readonly DeckChange[]>([]);\n const [pending, setPending] = React.useState<readonly Pending[]>([]);\n const [writeError, setWriteError] = React.useState<string | null>(null);\n const seq = React.useRef(0);\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n\n // A connection's state is read through the one sanitizer: an old or broken shape never blanks the deck.\n const bound = binding?.state;\n const base = React.useMemo(() => (bound ? deckState(bound) : local), [bound, local]);\n\n // A connection that keeps the undo history: the deck takes the kept steps while she has done nothing here\n // yet (they may arrive after the deck draws), and hands the history back only after a change of hers, so\n // opening a deck never writes and kept steps are never replaced by none.\n const touched = React.useRef(false);\n const bindingRef = React.useRef(binding);\n bindingRef.current = binding;\n const kept = binding?.history;\n React.useEffect(() => {\n // Follows the kept steps (a later read may bring more, fewer or none) until she acts here.\n if (touched.current || !kept) return;\n setHistory(kept);\n }, [kept]);\n React.useEffect(() => {\n if (touched.current) bindingRef.current?.saveHistory?.(history.slice(-UNDO_KEPT));\n }, [history]);\n // A settled write stays drawn until the connection's state CARRIES it (an unrelated remote write arriving\n // first must not flicker it away), or until a grace passes (another device wrote over it meanwhile).\n React.useEffect(() => {\n setPending((list) => {\n const kept = list.filter((p) => p.settledAt === null || !p.ops.every((op) => reflects(base, op)));\n return kept.length === list.length ? list : kept;\n });\n }, [base]);\n React.useEffect(() => {\n if (!pending.some((p) => p.settledAt !== null)) return;\n const t = setTimeout(() => setPending((list) => list.filter((p) => p.settledAt === null || Date.now() - p.settledAt < SETTLE_GRACE_MS)), SETTLE_GRACE_MS);\n return () => clearTimeout(t);\n }, [pending]);\n\n const state = React.useMemo(() => pending.reduce((s, p) => applyOps(s, p.ops), base), [base, pending]);\n const stateRef = React.useRef(state);\n stateRef.current = state;\n\n const send = React.useCallback(\n (ops: readonly DeckOp[], onRefused: () => void, transient = false) => {\n if (!binding) {\n setLocal((s) => applyOps(s, ops));\n return;\n }\n const id = ++seq.current;\n setPending((list) => [...list, { id, ops, settledAt: null, ...(transient ? { transient } : {}) }]);\n binding.apply(ops).then(\n () => {\n setWriteError(null);\n // A transient change is never in the connection's state: it stops drawing the moment it lands.\n setPending((list) => (transient ? list.filter((p) => p.id !== id) : list.map((p) => (p.id === id ? { ...p, settledAt: Date.now() } : p))));\n },\n (err: unknown) => {\n setPending((list) => list.filter((p) => p.id !== id));\n setWriteError(err instanceof Error && err.message ? err.message : String(err));\n onRefused();\n },\n );\n },\n [binding],\n );\n\n const commit = React.useCallback(\n (change: DeckChange) => {\n touched.current = true;\n setHistory((h) => [...h, change]);\n send(change.ops, () => setHistory((h) => h.filter((c) => c !== change)), change.transient);\n onChangeRef.current?.(applyOps(stateRef.current, change.ops), change, false);\n },\n [send],\n );\n\n const historyRef = React.useRef(history);\n historyRef.current = history;\n const undo = React.useCallback((): DeckChange | null => {\n const last = historyRef.current[historyRef.current.length - 1];\n if (!last) return null;\n touched.current = true;\n setHistory((h) => h.slice(0, -1));\n // A refused undo puts the change back on the stack: the person can try again.\n send(last.inverse, () => setHistory((h) => [...h, last]), last.transient);\n onChangeRef.current?.(applyOps(stateRef.current, last.inverse), last, true);\n return last;\n }, [send]);\n\n return {\n items: binding ? binding.items : (items ?? []),\n state,\n status: binding ? binding.status : \"ready\",\n readError: binding ? binding.error : null,\n writeError,\n canUndo: history.length > 0,\n commit,\n undo,\n };\n}\n","/**\n * THE SWIPE DECK MODEL — everything the deck decides, with no DOM and no React.\n *\n * A deck is a list of items a person answers by swiping one of four ways. The deck never stores\n * anything itself: every change is a list of {@link DeckOp}s applied to a {@link DeckState}, and\n * every change carries its exact inverse, so undo is unlimited and covers every kind of change\n * (answers, picks, part edits, categories). A bound deck sends the same ops to its connection.\n *\n * WHERE THE PERSON IS IS DERIVED, never stored: the current step is the first one not yet done.\n * So a deck open on two devices stays in step by sharing state alone, and a reload resumes where\n * the person left off.\n */\nimport type { ReactNode } from \"react\";\n\nexport type DeckDirection = \"right\" | \"up\" | \"left\" | \"down\";\nexport const DECK_DIRECTIONS: readonly DeckDirection[] = [\"right\", \"up\", \"left\", \"down\"];\n\n/** Semantic color of an answer; each names a design-system token pair (`--success` / `--success-foreground`…). */\nexport type DeckTone = \"success\" | \"info\" | \"destructive\" | \"warning\" | \"primary\" | \"neutral\";\n\nexport interface DeckAnswer {\n /** Stable id: what results, callbacks and connections carry. */\n readonly id: string;\n readonly label: string;\n /**\n * Offered only through the card's own controls (`renderCardActions` / `renderCardBody` call\n * `answer(id)`), never drawn as a button: an answer that needs a choice first (\"Related ▸ Partner\").\n */\n readonly hidden?: boolean;\n /**\n * \"Skip for now\": in a bound deck the connection moves the card to the back of the line and keeps no\n * answer (it comes back once the rest are answered); undo brings it back to the front. In a deck with no\n * connection it is kept like any other answer.\n */\n readonly requeue?: boolean;\n readonly tone: DeckTone;\n /** Higher is better. Decides which answer wins when categories disagree (default by direction). */\n readonly rank?: number;\n /** Replaces the arrow on the edge button and the full-screen wash. */\n readonly icon?: ReactNode;\n /** One key that gives this answer (\"Y\", \"3\"), beside the arrows. Case does not matter. */\n readonly shortcut?: string;\n}\n\n/** The answer on each edge. A missing direction is disabled (two, three or four ways). */\nexport type DeckKey = Partial<Record<DeckDirection, DeckAnswer>>;\n/** An override: an answer replaces that edge, `null` turns the edge off. */\nexport type DeckKeyOverride = Partial<Record<DeckDirection, DeckAnswer | null>>;\n\nexport const DEFAULT_DECK_KEY: DeckKey = {\n right: { id: \"yes\", label: \"Yes!\", tone: \"success\", rank: 3 },\n up: { id: \"sort_of\", label: \"Sort of\", tone: \"info\", rank: 2 },\n left: { id: \"no\", label: \"No\", tone: \"destructive\", rank: 0 },\n down: { id: \"not_sure\", label: \"Not sure\", tone: \"warning\", rank: 1 },\n};\n\n/** The part screen's down edge: close it, changing no answer. */\nexport const KEEP_ANSWER_ID = \"__keep\";\nexport const DEFAULT_KEEP_ANSWER: DeckAnswer = { id: KEEP_ANSWER_ID, label: \"Keep as is\", tone: \"neutral\" };\n\nconst DIRECTION_RANK: Record<DeckDirection, number> = { right: 3, up: 2, down: 1, left: 0 };\n\nexport function mergeKey(base: DeckKey, override?: DeckKeyOverride | null): DeckKey {\n if (!override) return base;\n const out: DeckKey = { ...base };\n for (const dir of DECK_DIRECTIONS) {\n if (!(dir in override)) continue;\n const next = override[dir];\n if (next) out[dir] = next;\n else delete out[dir];\n }\n return out;\n}\n\nexport function directionOf(key: DeckKey, answerId: string | null | undefined): DeckDirection | null {\n if (!answerId) return null;\n for (const dir of DECK_DIRECTIONS) if (key[dir]?.id === answerId) return dir;\n return null;\n}\n\n/** The answer with this id: on an edge of `key`, else among `more` (the answers off the edges). */\nexport function answerOf(key: DeckKey, answerId: string | null | undefined, more?: readonly DeckAnswer[]): DeckAnswer | null {\n const dir = directionOf(key, answerId);\n if (dir) return key[dir] ?? null;\n if (!answerId || !more) return null;\n return more.find((a) => a.id === answerId) ?? null;\n}\n\nfunction rankOf(key: DeckKey, answerId: string): number {\n const dir = directionOf(key, answerId);\n if (!dir) return -1;\n return key[dir]?.rank ?? DIRECTION_RANK[dir];\n}\n\n// ─── items, parts, categories ─────────────────────────────────────────────\n\nexport interface DeckField {\n readonly label: string;\n readonly value: string;\n}\n\n/** A part as an item first offers it: by phrase (first match) or by token span. */\nexport interface DeckPartSeed {\n readonly phrase?: string;\n readonly start?: number;\n readonly end?: number;\n readonly categories?: readonly string[];\n /** The answer this part leans to before anyone answers it. */\n readonly suggested?: string | null;\n readonly answer?: string | null;\n}\n\n/** A span of the item's words [start, end] (token indexes, inclusive) with its own answer. */\nexport interface DeckPart {\n readonly start: number;\n readonly end: number;\n readonly categories: readonly string[];\n readonly suggested: string | null;\n readonly answer: string | null;\n}\n\nexport interface DeckCategory {\n readonly name: string;\n readonly answer: string | null;\n /** The chip row it was added in (see {@link DeckCategoryRow}), when the deck has rows. */\n readonly row?: string;\n}\n\n/** A labelled row of categories on the part screen (\"Who\", \"Cares about\"); a category added with its \"+\" carries the row's id. */\nexport interface DeckCategoryRow {\n readonly id: string;\n readonly label: string;\n readonly categories: readonly string[];\n}\n\n/** A picture on the card: an image by address, or anything the host draws (an avatar with its own fallback). */\nexport type DeckMedia =\n | { readonly src: string; readonly alt?: string; readonly shape?: \"circle\" | \"square\" | \"wide\" }\n | { readonly node: ReactNode; readonly shape?: \"circle\" | \"square\" | \"wide\" };\n\n/** One member of a group card (\"these four logos\"): each can be switched off before the card is answered. */\nexport interface DeckMember {\n readonly id: string;\n readonly label: string;\n readonly media?: DeckMedia;\n /** Starts switched off. */\n readonly off?: boolean;\n}\n\n/**\n * When a card is asked: about one earlier card's answer, or a combination. A leaf names the card (`item`)\n * and, optionally, the answers that count (`is`), the ones that must not (`isNot`), or whether it was\n * answered at all (`answered`, default true). A card only ever depends on cards BEFORE it (no loops);\n * a card that is not asked has no answer as far as later cards are concerned.\n */\nexport type DeckCondition =\n | {\n readonly item: string;\n readonly is?: string | readonly string[];\n readonly isNot?: string | readonly string[];\n readonly answered?: boolean;\n }\n | { readonly all: readonly DeckCondition[] }\n | { readonly any: readonly DeckCondition[] }\n | { readonly not: DeckCondition };\n\n/** What rides with an answer beyond its id: the members switched off, a value typed on the card. */\nexport type DeckDetail = Readonly<Record<string, unknown>>;\n\nexport interface DeckItem {\n readonly id: string;\n /** The main text: fitted to the largest size the screen allows. */\n readonly text: string;\n /** A small label above the text (what kind of item this is). */\n readonly kicker?: string;\n /** A small fact tag beside the kicker. */\n readonly tag?: string;\n /** The suggested answer id: its button is filled and pulses, and the card leans toward it. */\n readonly suggested?: string | null;\n /**\n * The suggestion in finer words than its answer's label, shown as the Suggestion (the card still leans to\n * `suggested`): an answer that merges two (\"Sustain or Accept\") can show the precise one (\"Accept\").\n */\n readonly suggestedLabel?: string;\n /** Shown under the text with the \"Reason\" label. */\n readonly reason?: string;\n /** More label/value lines under the text. */\n readonly fields?: readonly DeckField[];\n /** Draw the text in quotation marks. */\n readonly quoted?: boolean;\n readonly parts?: readonly DeckPartSeed[];\n /** This item's own key: replaces or turns off edges of the deck's key. */\n readonly answers?: DeckKeyOverride;\n /** Pick-one group: when every item of a pick-one group is answered, the person picks one of its Yes items. */\n readonly group?: string;\n /** The suggested pick of its group. */\n readonly pickSuggested?: boolean;\n /**\n * The right answer(s), by answer id, for a deck that is graded (a quiz). Never shown while she answers;\n * the result says which were right and the end shows the score. Absent: the item is not graded.\n */\n readonly correct?: string | readonly string[];\n /** Answers off the edges, as a row of buttons on the card; replaces the deck's own `more` for this item. */\n readonly more?: readonly DeckAnswer[];\n /** A picture above the text. */\n readonly media?: DeckMedia;\n /** A group card: its members, each switched on or off; the off ones ride with the answer as `detail.off`. */\n readonly members?: readonly DeckMember[];\n /**\n * Asked only when this holds (see {@link DeckCondition}). Not asked: skipped, and left out of progress,\n * counts, the score and the results; an answer it already had is KEPT but does not apply, and comes\n * back if the card is asked again.\n */\n readonly showIf?: DeckCondition;\n /**\n * The card this one narrows (a tree: \"Too broad\" on a parent asks for its children). The deck itself only\n * carries it; the optional `@ai-matrx/design-system/swipe-deck-tree` entry grows, orders and draws the tree.\n */\n readonly parent?: string;\n}\n\nexport interface DeckState {\n readonly answers: Readonly<Record<string, string>>;\n readonly picks: Readonly<Record<string, string>>;\n /** Parts as changed or loaded; an item absent here shows its seeds. */\n readonly parts: Readonly<Record<string, readonly DeckPart[]>>;\n readonly categories: Readonly<Record<string, DeckCategory>>;\n /** What rode with each answer (see {@link DeckDetail}); a binding that keeps none may leave it out. */\n readonly details?: Readonly<Record<string, DeckDetail>>;\n}\n\nexport const EMPTY_DECK_STATE: DeckState = { answers: {}, picks: {}, parts: {}, categories: {}, details: {} };\n\nconst plain = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst keep = <T,>(v: unknown, ok: (x: unknown) => x is T): Record<string, T> =>\n plain(v) ? Object.fromEntries(Object.entries(v).filter((e): e is [string, T] => ok(e[1]))) : {};\nconst isText = (x: unknown): x is string => typeof x === \"string\" && x.length > 0;\nconst isPart = (x: unknown): x is DeckPart => plain(x) && Number.isInteger(x.start) && Number.isInteger(x.end) && Array.isArray(x.categories);\nconst isParts = (x: unknown): x is readonly DeckPart[] => Array.isArray(x) && x.every(isPart);\nconst isCategory = (x: unknown): x is DeckCategory => plain(x) && typeof x.name === \"string\";\n\n/**\n * A full deck state from anything saved or handed in: missing parts start empty, and an entry of the\n * wrong shape (an old save, a hand-edited row) is left out, so a deck never draws blank over bad data.\n */\nexport function deckState(partial?: Partial<DeckState> | null): DeckState {\n const p: Record<string, unknown> = plain(partial) ? partial : {};\n return {\n answers: keep(p.answers, isText),\n picks: keep(p.picks, isText),\n parts: keep(p.parts, isParts),\n categories: keep(p.categories, isCategory),\n details: keep(p.details, plain) as Record<string, DeckDetail>,\n };\n}\n\nexport function tokenize(text: string): string[] {\n return text.split(/\\s+/).filter(Boolean);\n}\n\nfunction norm(token: string): string {\n return token.toLowerCase().replace(/[^\\p{L}\\p{N}+-]/gu, \"\");\n}\n\n/** The parts an item opens with: each seed placed on its tokens; seeds that match nothing are dropped. */\nexport function seedParts(item: DeckItem): DeckPart[] {\n const tokens = tokenize(item.text);\n const normed = tokens.map(norm);\n const out: DeckPart[] = [];\n for (const seed of item.parts ?? []) {\n let start = seed.start;\n let end = seed.end;\n if (seed.phrase !== undefined) {\n const want = tokenize(seed.phrase).map(norm);\n start = undefined;\n for (let i = 0; i + want.length <= normed.length && want.length; i++) {\n if (want.every((w, j) => normed[i + j] === w)) {\n start = i;\n end = i + want.length - 1;\n break;\n }\n }\n }\n if (start === undefined || start < 0 || start >= tokens.length) continue;\n const e = Math.min(tokens.length - 1, Math.max(start, end ?? start));\n out.push({ start, end: e, categories: seed.categories ?? [], suggested: seed.suggested ?? null, answer: seed.answer ?? null });\n }\n return withoutOverlaps(out);\n}\n\nfunction withoutOverlaps(parts: DeckPart[]): DeckPart[] {\n const sorted = [...parts].sort((a, b) => a.start - b.start);\n const out: DeckPart[] = [];\n for (const p of sorted) if (!out.some((q) => !(q.end < p.start || q.start > p.end))) out.push(p);\n return out;\n}\n\nexport function partsOf(state: DeckState, item: DeckItem): readonly DeckPart[] {\n return state.parts[item.id] ?? seedParts(item);\n}\n\nexport function partText(item: DeckItem, part: Pick<DeckPart, \"start\" | \"end\">): string {\n return tokenize(item.text)\n .slice(part.start, part.end + 1)\n .join(\" \")\n .replace(/^[“\"‘'(\\[]+|[”\"’'.,;:!?)\\]]+$/g, \"\");\n}\n\n/** Every category the deck knows: the configured rows, then any a part or the state names. */\nexport function knownCategories(configured: readonly string[], items: readonly DeckItem[], state: DeckState): string[] {\n const out: string[] = [];\n const add = (name: string) => {\n if (name && !out.includes(name)) out.push(name);\n };\n configured.forEach(add);\n for (const item of items) for (const part of partsOf(state, item)) part.categories.forEach(add);\n Object.keys(state.categories).forEach(add);\n return out;\n}\n\nexport type CategoryConflict = \"worse\" | \"better\" | ((answerIds: readonly string[]) => string);\n\n/** One answer from several categories' answers: by default the worse one wins. */\nexport function resolveConflict(answerIds: readonly string[], key: DeckKey, conflict: CategoryConflict = \"worse\"): string | null {\n if (!answerIds.length) return null;\n if (typeof conflict === \"function\") return conflict(answerIds);\n const sign = conflict === \"better\" ? -1 : 1;\n return [...answerIds].sort((a, b) => sign * (rankOf(key, a) - rankOf(key, b)))[0] ?? null;\n}\n\n/** What a part leans to: its categories' answers flow down to it; otherwise its own suggestion. */\nexport function partSuggestion(part: DeckPart, state: DeckState, key: DeckKey, conflict?: CategoryConflict): string | null {\n const flowed = part.categories.map((c) => state.categories[c]?.answer).filter((a): a is string => !!a);\n return resolveConflict(flowed, key, conflict) ?? part.suggested;\n}\n\n/** The answer a part shows: its own, else what flows down to it. */\nexport function partAnswer(part: DeckPart, state: DeckState, key: DeckKey, conflict?: CategoryConflict): string | null {\n return part.answer ?? partSuggestion(part, state, key, conflict);\n}\n\n/** Place a part on its span: every part it overlaps is replaced. */\nexport function placePart(parts: readonly DeckPart[], next: DeckPart): DeckPart[] {\n return [...parts.filter((p) => p.end < next.start || p.start > next.end), next].sort((a, b) => a.start - b.start);\n}\n\nexport function forgetSpan(parts: readonly DeckPart[], span: Pick<DeckPart, \"start\" | \"end\">): DeckPart[] {\n return parts.filter((p) => p.end < span.start || p.start > span.end);\n}\n\n// ─── steps ────────────────────────────────────────────────────────────────\n\nexport type DeckStep =\n | { readonly kind: \"card\"; readonly id: string; readonly item: DeckItem }\n | { readonly kind: \"pick\"; readonly id: string; readonly group: string; readonly items: readonly DeckItem[] }\n | { readonly kind: \"end\"; readonly id: \"end\" };\n\nexport interface DeckRules {\n readonly key: DeckKey;\n /** Groups that end in a pick-one screen: `true` = every group. */\n readonly pickOne?: boolean | readonly string[];\n /** The answer that makes an item a contender in its group's pick (default: the right edge's). */\n readonly pickAnswer?: string;\n /** Answers off the edges, offered on every card (an item's own `more` replaces them). */\n readonly more?: readonly DeckAnswer[];\n}\n\nexport function keyFor(rules: DeckRules, item: DeckItem): DeckKey {\n return mergeKey(rules.key, item.answers);\n}\n\n/** The answers off the edges for this item: its own, or the deck's; never one already on an edge. */\nexport function moreFor(rules: DeckRules, item: DeckItem): readonly DeckAnswer[] {\n const key = keyFor(rules, item);\n const list = item.more ?? rules.more ?? [];\n return list.filter((a) => !directionOf(key, a.id));\n}\n\n/** Every answer this item can take: the edges' (clockwise from the top), then the ones off the edges. */\nexport function answersFor(rules: DeckRules, item: DeckItem): readonly DeckAnswer[] {\n const key = keyFor(rules, item);\n const edges = ([\"up\", \"right\", \"down\", \"left\"] as const).map((d) => key[d]).filter((a): a is DeckAnswer => !!a);\n return [...edges, ...moreFor(rules, item)];\n}\n\n/** The answer with this id for this item, on an edge or off it. */\nexport function findAnswer(rules: DeckRules, item: DeckItem, answerId: string | null | undefined): DeckAnswer | null {\n return answerOf(keyFor(rules, item), answerId, moreFor(rules, item));\n}\n\n/**\n * What rides with an item's answer: the detail given, and on a group card always its members switched off\n * (`off`, the starting ones included), so a consumer never has to know the item's defaults.\n */\nexport function answerDetail(item: DeckItem, detail: DeckDetail | null | undefined): DeckDetail | null {\n if (!item.members?.length) return detail ?? null;\n return { ...(detail ?? {}), off: [...membersOff(item, detail)] };\n}\n\n/** The members switched off on a group card: what the person set, else what the item starts with. */\nexport function membersOff(item: DeckItem, detail: DeckDetail | null | undefined): readonly string[] {\n const off = detail?.off;\n if (Array.isArray(off)) return off.filter((x): x is string => typeof x === \"string\");\n return (item.members ?? []).filter((m) => m.off).map((m) => m.id);\n}\n\nfunction pickAnswerOf(rules: DeckRules): string | null {\n return rules.pickAnswer ?? rules.key.right?.id ?? null;\n}\n\nfunction isPickGroup(rules: DeckRules, group: string | undefined): group is string {\n if (!group || !rules.pickOne) return false;\n return rules.pickOne === true || rules.pickOne.includes(group);\n}\n\nconst asList = (v: string | readonly string[] | undefined): readonly string[] | null => (v === undefined ? null : typeof v === \"string\" ? [v] : v);\n\n/** Whether a condition holds, given the cards asked so far (`asked`: id → asked) and the answers. */\nexport function conditionHolds(cond: DeckCondition, state: DeckState, asked: ReadonlyMap<string, boolean>): boolean {\n if (\"all\" in cond) return cond.all.every((c) => conditionHolds(c, state, asked));\n if (\"any\" in cond) return cond.any.some((c) => conditionHolds(c, state, asked));\n if (\"not\" in cond) return !conditionHolds(cond.not, state, asked);\n // A card not (yet) asked — later, missing, or skipped by its own condition — has no answer.\n const answer = asked.get(cond.item) ? (state.answers[cond.item] ?? null) : null;\n const wantAnswered = cond.answered ?? true;\n if (!wantAnswered) return answer === null;\n if (answer === null) return false;\n const is = asList(cond.is);\n const isNot = asList(cond.isNot);\n if (is && !is.includes(answer)) return false;\n if (isNot && isNot.includes(answer)) return false;\n return true;\n}\n\n/** Which cards are asked, in order: a card with no condition always; one with a condition when it holds over the cards before it. */\nexport function askedItems(items: readonly DeckItem[], state: DeckState): ReadonlyMap<string, boolean> {\n const asked = new Map<string, boolean>();\n for (const item of items) asked.set(item.id, item.showIf ? conditionHolds(item.showIf, state, asked) : true);\n return asked;\n}\n\n/** The cards asked, in order. */\nexport function shownItems(items: readonly DeckItem[], state: DeckState): DeckItem[] {\n if (!items.some((i) => i.showIf)) return [...items];\n const asked = askedItems(items, state);\n return items.filter((i) => asked.get(i.id));\n}\n\n/** Every card id a condition names. */\nexport function conditionItems(cond: DeckCondition): string[] {\n if (\"all\" in cond) return cond.all.flatMap(conditionItems);\n if (\"any\" in cond) return cond.any.flatMap(conditionItems);\n if (\"not\" in cond) return conditionItems(cond.not);\n return [cond.item];\n}\n\n/**\n * THE ORDER A DECK WITH CONDITIONS IS ASKED IN, when its order is not authored (a table sorted any way):\n * the given order, except that a card always comes after every card its condition names. Stable — a\n * deck whose conditions already point backwards is returned unchanged. A loop (two cards naming each\n * other) is left in the given order, where `conditionProblems` says so.\n */\nexport function dependencyOrder<T extends DeckItem>(items: readonly T[]): T[] {\n const ids = new Set(items.map((i) => i.id));\n const needs = new Map(items.map((i) => [i.id, new Set(i.showIf ? conditionItems(i.showIf).filter((d) => ids.has(d) && d !== i.id) : [])]));\n const out: T[] = [];\n const placed = new Set<string>();\n const left = [...items];\n while (left.length) {\n const k = left.findIndex((i) => [...needs.get(i.id)!].every((d) => placed.has(d)));\n const [next] = left.splice(k < 0 ? 0 : k, 1);\n out.push(next!);\n placed.add(next!.id);\n }\n return out;\n}\n\n/**\n * What is wrong with the deck's conditions, in words (never silent): a condition naming a card that does\n * not exist, one that comes later (it could never be answered first), or an answer the card does not have.\n */\n/**\n * A condition as a person or an agent wrote it (`{item, is, is_not | isNot, answered}`, `{all}`, `{any}`,\n * `{not}`, or a list meaning all), with its card and answers resolved by the host: `ref` names the card\n * (an id, a position, its words), `answer(itemId, word)` the answer id. Null when nothing can be read.\n * The one reader for every source of conditions (a chat answer, a table column, a definition).\n */\nexport function readDeckCondition(\n raw: unknown,\n resolve: { ref: (v: unknown) => string; answer: (itemId: string, word: unknown) => string | null },\n): DeckCondition | null {\n const rec = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\n const read = (r: unknown): DeckCondition | null => {\n if (Array.isArray(r)) {\n const all = r.map(read).filter((c): c is DeckCondition => !!c);\n return all.length ? { all } : null;\n }\n if (!rec(r)) return null;\n if (Array.isArray(r.all)) return { all: r.all.map(read).filter((c): c is DeckCondition => !!c) };\n if (Array.isArray(r.any)) return { any: r.any.map(read).filter((c): c is DeckCondition => !!c) };\n if (r.not !== undefined) {\n const inner = read(r.not);\n return inner ? { not: inner } : null;\n }\n if (r.item === undefined || r.item === null) return null;\n const item = resolve.ref(r.item);\n const words = (v: unknown): string[] | undefined =>\n v === undefined || v === null ? undefined : (Array.isArray(v) ? v : [v]).map((w) => resolve.answer(item, w) ?? String(w).trim()).filter(Boolean);\n const is = words(r.is);\n const isNot = words(r.is_not ?? r.isNot);\n return {\n item,\n ...(is ? { is } : {}),\n ...(isNot ? { isNot } : {}),\n ...(typeof r.answered === \"boolean\" ? { answered: r.answered } : {}),\n };\n };\n return read(raw);\n}\n\nexport function conditionProblems(items: readonly DeckItem[], rules: DeckRules): string[] {\n const out: string[] = [];\n const index = new Map(items.map((i, k) => [i.id, k]));\n items.forEach((item, k) => {\n if (!item.showIf) return;\n const visit = (c: DeckCondition): void => {\n if (\"all\" in c) return c.all.forEach(visit);\n if (\"any\" in c) return c.any.forEach(visit);\n if (\"not\" in c) return visit(c.not);\n const at = index.get(c.item);\n if (at === undefined) {\n out.push(`\"${item.text}\" depends on a card that is not in the deck (${c.item}).`);\n return;\n }\n if (at >= k) {\n out.push(`\"${item.text}\" depends on \"${items[at]?.text ?? c.item}\", which comes after it, so it can never be asked.`);\n return;\n }\n const target = items[at];\n if (!target) return;\n for (const id of [...(asList(c.is) ?? []), ...(asList(c.isNot) ?? [])]) {\n if (!findAnswer(rules, target, id)) out.push(`\"${item.text}\" waits for an answer \"${id}\" that \"${target.text}\" does not have.`);\n }\n };\n visit(item.showIf);\n });\n return out;\n}\n\nexport function contenders(items: readonly DeckItem[], state: DeckState, rules: DeckRules, group: string): DeckItem[] {\n const yes = pickAnswerOf(rules);\n return shownItems(items, state).filter((i) => i.group === group && yes !== null && state.answers[i.id] === yes);\n}\n\n/** The picked item of a group: the person's pick while it still stands, or the only contender. */\nexport function pickedItem(items: readonly DeckItem[], state: DeckState, rules: DeckRules, group: string): DeckItem | null {\n const all = contenders(items, state, rules, group);\n const chosen = state.picks[group];\n const hit = chosen ? all.find((i) => i.id === chosen) : undefined;\n if (hit) return hit;\n return all.length === 1 ? (all[0] ?? null) : null;\n}\n\nexport function deckSteps(allItems: readonly DeckItem[], state: DeckState, rules: DeckRules): DeckStep[] {\n const out: DeckStep[] = [];\n // Only the cards that are asked are steps; a card whose condition does not hold is skipped.\n const items = shownItems(allItems, state);\n items.forEach((item, index) => {\n out.push({ kind: \"card\", id: `card:${item.id}`, item });\n const group = item.group;\n if (!isPickGroup(rules, group)) return;\n const isLast = !items.slice(index + 1).some((i) => i.group === group);\n if (!isLast) return;\n const members = items.filter((i) => i.group === group);\n const all = contenders(items, state, rules, group);\n if (all.length > 1 && members.every((i) => state.answers[i.id])) out.push({ kind: \"pick\", id: `pick:${group}`, group, items: all });\n });\n out.push({ kind: \"end\", id: \"end\" });\n return out;\n}\n\nexport function stepDone(step: DeckStep, state: DeckState): boolean {\n if (step.kind === \"card\") return !!state.answers[step.item.id];\n if (step.kind === \"pick\") return step.items.some((i) => i.id === state.picks[step.group]);\n return false;\n}\n\n/** Where the person is: the first step not done (the end when all are). */\nexport function currentStepIndex(steps: readonly DeckStep[], state: DeckState): number {\n const i = steps.findIndex((s) => !stepDone(s, state));\n return i < 0 ? steps.length - 1 : i;\n}\n\n// ─── ops, changes, undo ───────────────────────────────────────────────────\n\nexport type DeckOp =\n | { readonly kind: \"answer\"; readonly itemId: string; readonly answer: string | null; readonly detail?: DeckDetail | null }\n | { readonly kind: \"pick\"; readonly group: string; readonly itemId: string | null }\n | { readonly kind: \"parts\"; readonly itemId: string; readonly parts: readonly DeckPart[] }\n | { readonly kind: \"category\"; readonly name: string; readonly answer: string | null; readonly remove?: boolean; readonly row?: string };\n\n/** One thing the person did: its ops, their exact inverse, and the edge it left by. */\nexport interface DeckChange {\n readonly ops: readonly DeckOp[];\n readonly inverse: readonly DeckOp[];\n readonly from: DeckDirection | null;\n /**\n * The connection acts on it but never keeps it as an answer (a `requeue` answer: the card goes to the\n * back of the line): once the connection resolves, the deck stops drawing it, so the card is unanswered.\n */\n readonly transient?: boolean;\n}\n\nfunction omit<T>(record: Readonly<Record<string, T>>, k: string): Record<string, T> {\n const { [k]: _gone, ...rest } = record;\n return rest;\n}\n\nexport function applyOp(state: DeckState, op: DeckOp): DeckState {\n switch (op.kind) {\n case \"answer\": {\n const details = state.details ?? {};\n return {\n ...state,\n answers: op.answer ? { ...state.answers, [op.itemId]: op.answer } : omit(state.answers, op.itemId),\n details: op.answer && op.detail ? { ...details, [op.itemId]: op.detail } : omit(details, op.itemId),\n };\n }\n case \"pick\":\n return { ...state, picks: op.itemId ? { ...state.picks, [op.group]: op.itemId } : omit(state.picks, op.group) };\n case \"parts\":\n return { ...state, parts: { ...state.parts, [op.itemId]: op.parts } };\n case \"category\":\n return {\n ...state,\n categories: op.remove\n ? omit(state.categories, op.name)\n : { ...state.categories, [op.name]: { name: op.name, answer: op.answer, ...(op.row ? { row: op.row } : {}) } },\n };\n default:\n // An op this deck does not know (saved by a newer one): leave the state as it is.\n return state;\n }\n}\n\nexport function applyOps(state: DeckState, ops: readonly DeckOp[]): DeckState {\n return ops.reduce(applyOp, state);\n}\n\n/** The op that puts back what `op` changes, read from the state before it. */\nexport function invertOp(before: DeckState, op: DeckOp, items: readonly DeckItem[]): DeckOp {\n switch (op.kind) {\n case \"answer\":\n return { kind: \"answer\", itemId: op.itemId, answer: before.answers[op.itemId] ?? null, detail: before.details?.[op.itemId] ?? null };\n case \"pick\":\n return { kind: \"pick\", group: op.group, itemId: before.picks[op.group] ?? null };\n case \"parts\": {\n const item = items.find((i) => i.id === op.itemId);\n return { kind: \"parts\", itemId: op.itemId, parts: before.parts[op.itemId] ?? (item ? seedParts(item) : []) };\n }\n case \"category\": {\n const had = before.categories[op.name];\n return had ? { kind: \"category\", name: op.name, answer: had.answer } : { kind: \"category\", name: op.name, answer: null, remove: true };\n }\n }\n}\n\nexport function makeChange(before: DeckState, ops: readonly DeckOp[], items: readonly DeckItem[], from: DeckDirection | null = null): DeckChange {\n const inverse: DeckOp[] = [];\n let s = before;\n for (const op of ops) {\n inverse.unshift(invertOp(s, op, items));\n s = applyOp(s, op);\n }\n return { ops, inverse, from };\n}\n\n/** Answer an item; an answer that drops it out of its group's contenders also drops a pick that named it. */\nexport function answerChange(\n before: DeckState,\n item: DeckItem,\n answerId: string,\n rules: DeckRules,\n items: readonly DeckItem[],\n from: DeckDirection | null,\n detail?: DeckDetail | null,\n): DeckChange {\n const ops: DeckOp[] = [{ kind: \"answer\", itemId: item.id, answer: answerId, ...(detail ? { detail } : {}) }];\n if (item.group && answerId !== pickAnswerOf(rules) && before.picks[item.group] === item.id) ops.push({ kind: \"pick\", group: item.group, itemId: null });\n return makeChange(before, ops, items, from);\n}\n\n// ─── results and copy ─────────────────────────────────────────────────────\n\nexport interface DeckResultPart {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n readonly categories: readonly string[];\n readonly answer: DeckAnswer | null;\n /** True when the person answered the part itself, false when its answer flowed down. */\n readonly own: boolean;\n}\n\nexport interface DeckResultEntry {\n readonly item: DeckItem;\n readonly answer: DeckAnswer | null;\n readonly parts: readonly DeckResultPart[];\n /** Graded items only: whether the answer given is a right one (null: not graded, or not answered). */\n readonly right: boolean | null;\n /** What rode with the answer (members switched off, a value typed on the card); null when nothing did. */\n readonly detail: DeckDetail | null;\n /** False when the card is not asked (its condition does not hold): its answer, if any, does not apply. */\n readonly shown: boolean;\n}\n\nexport interface DeckResult {\n readonly entries: readonly DeckResultEntry[];\n readonly answered: number;\n readonly total: number;\n readonly complete: boolean;\n /** Per answer id: how many items took it. */\n readonly counts: Readonly<Record<string, number>>;\n readonly picks: Readonly<Record<string, DeckItem>>;\n readonly categories: readonly DeckCategory[];\n readonly state: DeckState;\n /** When any item is graded: how many answered items were right, of how many graded items. */\n readonly score: { readonly right: number; readonly graded: number } | null;\n}\n\nexport function deckResult(items: readonly DeckItem[], state: DeckState, rules: DeckRules, conflict?: CategoryConflict): DeckResult {\n const counts: Record<string, number> = {};\n const asked = askedItems(items, state);\n const entries = items.map((item): DeckResultEntry => {\n const key = keyFor(rules, item);\n const more = moreFor(rules, item);\n const shown = asked.get(item.id) !== false;\n // A card not asked keeps its answer in the state, but the answer does not apply anywhere.\n const id = shown ? (state.answers[item.id] ?? null) : null;\n if (id) counts[id] = (counts[id] ?? 0) + 1;\n const parts = partsOf(state, item).map((p): DeckResultPart => {\n const pa = partAnswer(p, state, key, conflict);\n return { text: partText(item, p), start: p.start, end: p.end, categories: p.categories, answer: answerOf(key, pa), own: !!p.answer };\n });\n const correct = item.correct === undefined ? null : typeof item.correct === \"string\" ? [item.correct] : item.correct;\n const right = correct && id ? correct.includes(id) : null;\n return { item, answer: answerOf(key, id, more), parts, right, detail: (id && state.details?.[item.id]) || null, shown };\n });\n const picks: Record<string, DeckItem> = {};\n const groups = new Set(items.map((i) => i.group).filter((g): g is string => isPickGroup(rules, g)));\n for (const g of groups) {\n const p = pickedItem(items, state, rules, g);\n if (p) picks[g] = p;\n }\n const answered = entries.filter((e) => e.answer).length;\n const steps = deckSteps(items, state, rules);\n const complete = steps[currentStepIndex(steps, state)]?.kind === \"end\";\n const graded = entries.filter((e) => e.shown && e.item.correct !== undefined).length;\n const score = graded ? { right: entries.filter((e) => e.right === true).length, graded } : null;\n const total = entries.filter((e) => e.shown).length;\n return { entries, answered, total, complete, counts, picks, categories: Object.values(state.categories), state, score };\n}\n\nexport interface DeckCopyLabels {\n readonly suggestion: string;\n readonly reason: string;\n readonly answer: string;\n readonly unanswered: string;\n}\n\n/** One item as plain text for an AI or a note: what it says, what was suggested, and what the person answered. */\nexport function itemCopyText(\n item: DeckItem,\n state: DeckState,\n key: DeckKey,\n labels: DeckCopyLabels,\n conflict?: CategoryConflict,\n more?: readonly DeckAnswer[],\n): string {\n const lines = [[item.kicker, item.quoted ? `“${item.text}”` : item.text].filter(Boolean).join(\": \")];\n if (item.tag) lines.push(item.tag);\n const off = membersOff(item, state.details?.[item.id]);\n for (const m of item.members ?? []) lines.push(`- ${m.label}${off.includes(m.id) ? \" (off)\" : \"\"}`);\n const sug = answerOf(key, item.suggested, more);\n if (sug) lines.push(`${labels.suggestion}: ${item.suggestedLabel ?? sug.label}`);\n if (item.reason) lines.push(`${labels.reason}: ${item.reason}`);\n for (const f of item.fields ?? []) lines.push(`${f.label}: ${f.value}`);\n const parts = partsOf(state, item);\n for (const p of parts) {\n const a = answerOf(key, partAnswer(p, state, key, conflict));\n lines.push(`- ${partText(item, p)}: ${[a?.label, ...p.categories].filter(Boolean).join(\" · \")}`);\n }\n lines.push(`${labels.answer}: ${answerOf(key, state.answers[item.id], more)?.label ?? labels.unanswered}`);\n return lines.join(\"\\n\");\n}\n\nexport function deckCopyText(result: DeckResult, rules: DeckRules): string {\n const lines: string[] = [];\n for (const [group, item] of Object.entries(result.picks)) lines.push(`${group}: ${item.text}`);\n // Each answer given, in the deck's order (its edges, then the rest as they first appear).\n const order: DeckAnswer[] = DECK_DIRECTIONS.map((d) => rules.key[d]).filter((a): a is DeckAnswer => !!a);\n for (const e of result.entries) if (e.answer && !order.some((a) => a.id === e.answer?.id)) order.push(e.answer);\n for (const a of order) {\n const hits = result.entries.filter((e) => e.answer?.id === a.id);\n if (!hits.length) continue;\n if (lines.length) lines.push(\"\");\n lines.push(`${a.label}:`);\n for (const e of hits) lines.push(`- ${e.item.text}`);\n }\n const placed = result.entries.flatMap((e) => e.parts.filter((p) => p.own && p.answer).map((p) => `- ${p.text}: ${p.answer?.label ?? \"\"}`));\n if (placed.length) lines.push(\"\", ...placed);\n return lines.join(\"\\n\");\n}\n\n// ─── chained decks ────────────────────────────────────────────────────────\n\n/**\n * Feed one deck's answers into the next deck's suggestions: each next item names the earlier item it\n * follows (`link`), and the earlier answer maps to the next suggestion (`map`, identity by default).\n * An item that already carries a suggestion keeps it.\n */\nexport function chainSuggestions(\n next: readonly DeckItem[],\n previous: DeckResult | DeckState,\n link: (item: DeckItem) => string | null | undefined,\n map: (answerId: string, item: DeckItem) => string | null | undefined = (a) => a,\n): DeckItem[] {\n const answers = \"entries\" in previous ? previous.state.answers : previous.answers;\n return next.map((item) => {\n if (item.suggested) return item;\n const from = link(item);\n const prior = from ? answers[from] : undefined;\n const suggested = prior ? map(prior, item) : undefined;\n return suggested ? { ...item, suggested } : item;\n });\n}\n","/**\n * THE SWIPE GESTURE — one pointer, four ways, plus tap and hold.\n *\n * A press that moves more than a few pixels becomes a drag; the drag commits when it passes the\n * distance threshold OR when it is released as a flick (speed over the last ~100ms, so a short fast\n * throw counts the way it does on every phone). A press that never moves is a tap; held still over\n * a `holdSelector` element it becomes a hold. Nothing here renders: the caller moves the card through\n * `move`, which runs per pointer event without touching React state (60fps on a mid-range phone).\n */\nimport type { DeckDirection } from \"./model\";\nimport { buzz } from \"./visual\";\n\nexport interface SwipeHandlers {\n enabled(): boolean;\n directions(): Partial<Record<DeckDirection, unknown>>;\n start?(): void;\n /** `amount` is distance over the threshold: 1 means letting go here commits. */\n move(dx: number, dy: number, dir: DeckDirection | null, amount: number): void;\n release(): void;\n /** `speed` in px/ms, so the card can leave as fast as it was thrown. */\n commit(dir: DeckDirection, speed: number): void;\n tap?(target: Element): void;\n hold?(target: Element): void;\n holdSelector?: string;\n /** Presses starting inside these never swipe (buttons, inputs, chip rows). */\n ignoreSelector?: string;\n}\n\nexport const HOLD_MS = 450;\nconst DRAG_SLOP = 10;\nconst FLICK_MIN_DISTANCE = 40;\nconst FLICK_MIN_SPEED = 0.55;\n\nexport function swipeThreshold(width: number): number {\n return Math.max(70, Math.min(120, width * 0.2));\n}\n\nexport function dominantDirection(dx: number, dy: number): DeckDirection {\n return Math.abs(dx) >= Math.abs(dy) ? (dx > 0 ? \"right\" : \"left\") : dy < 0 ? \"up\" : \"down\";\n}\n\n/** Decide a release: commit a direction, or null to snap back. Pure, so it is tested alone. */\nexport function releaseDecision(\n dx: number,\n dy: number,\n speed: number,\n width: number,\n enabled: Partial<Record<DeckDirection, unknown>>,\n): DeckDirection | null {\n const dir = dominantDirection(dx, dy);\n if (!enabled[dir]) return null;\n const dist = Math.max(Math.abs(dx), Math.abs(dy));\n if (dist >= swipeThreshold(width)) return dir;\n if (dist > FLICK_MIN_DISTANCE && speed > FLICK_MIN_SPEED) return dir;\n return null;\n}\n\nexport function attachSwipe(root: HTMLElement, h: SwipeHandlers): () => void {\n let id: number | null = null;\n let sx = 0;\n let sy = 0;\n let dx = 0;\n let dy = 0;\n let mode: \"press\" | \"drag\" | \"held\" | null = null;\n let holdTimer: ReturnType<typeof setTimeout> | null = null;\n let downTarget: Element | null = null;\n let samples: { t: number; x: number; y: number }[] = [];\n const view = root.ownerDocument.defaultView ?? window;\n\n const clearHold = () => {\n if (holdTimer) clearTimeout(holdTimer);\n holdTimer = null;\n root.querySelectorAll(\"[data-sd-press]\").forEach((el) => el.removeAttribute(\"data-sd-press\"));\n };\n\n const width = () => root.getBoundingClientRect().width || view.innerWidth;\n\n const onDown = (e: PointerEvent) => {\n if (id !== null || e.button > 0 || !h.enabled()) return;\n const target = e.target instanceof Element ? e.target : null;\n if (!target || target.closest(h.ignoreSelector ?? \"button, a, input, textarea, [data-sd-noswipe]\")) return;\n id = e.pointerId;\n sx = e.clientX;\n sy = e.clientY;\n dx = dy = 0;\n mode = \"press\";\n downTarget = target;\n samples = [{ t: e.timeStamp, x: e.clientX, y: e.clientY }];\n h.start?.();\n const holdable = h.hold && h.holdSelector ? target.closest(h.holdSelector) : null;\n if (holdable) {\n holdable.setAttribute(\"data-sd-press\", \"\");\n holdTimer = setTimeout(() => {\n if (mode !== \"press\") return;\n mode = \"held\";\n clearHold();\n buzz(view.navigator, 10);\n h.hold?.(holdable);\n }, HOLD_MS);\n }\n view.addEventListener(\"pointermove\", onMove);\n view.addEventListener(\"pointerup\", onUp);\n view.addEventListener(\"pointercancel\", onCancel);\n };\n\n const onMove = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n dx = e.clientX - sx;\n dy = e.clientY - sy;\n samples.push({ t: e.timeStamp, x: e.clientX, y: e.clientY });\n if (samples.length > 8) samples.shift();\n if (mode === \"press\" && Math.hypot(dx, dy) > DRAG_SLOP) {\n clearHold();\n mode = \"drag\";\n }\n if (mode !== \"drag\") return;\n const dir = dominantDirection(dx, dy);\n const dist = Math.max(Math.abs(dx), Math.abs(dy));\n h.move(dx, dy, h.directions()[dir] ? dir : null, dist / swipeThreshold(width()));\n };\n\n const detach = () => {\n view.removeEventListener(\"pointermove\", onMove);\n view.removeEventListener(\"pointerup\", onUp);\n view.removeEventListener(\"pointercancel\", onCancel);\n };\n\n const speedNow = (t: number) => {\n const recent = samples.filter((s) => t - s.t <= 100);\n const first = recent[0];\n const last = samples[samples.length - 1];\n if (!first || !last || last.t === first.t) return 0;\n return Math.hypot(last.x - first.x, last.y - first.y) / (last.t - first.t);\n };\n\n const onUp = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n detach();\n clearHold();\n const m = mode;\n id = null;\n mode = null;\n if (m === \"drag\") {\n const speed = speedNow(e.timeStamp);\n const dir = releaseDecision(dx, dy, speed, width(), h.directions());\n if (dir) h.commit(dir, speed);\n else h.release();\n } else if (m === \"press\" && downTarget) h.tap?.(downTarget);\n };\n\n const onCancel = (e: PointerEvent) => {\n if (e.pointerId !== id) return;\n detach();\n clearHold();\n const m = mode;\n id = null;\n mode = null;\n if (m === \"drag\") h.release();\n };\n\n const onContext = (e: Event) => {\n if (h.hold) e.preventDefault();\n };\n\n // iOS Safari: a vertical swipe while the page under the deck can scroll is taken by the page (the swipe\n // is cancelled, so \"up\" never answered there) unless the touch's own move is refused. Refused only while\n // this deck holds a press, and a vertical move only when the deck answers up or down (a two-way deck in a\n // chat lets the chat scroll).\n let touchFrom: { x: number; y: number } | null = null;\n const onTouchStart = (e: TouchEvent) => {\n const t = e.touches[0];\n touchFrom = t ? { x: t.clientX, y: t.clientY } : null;\n };\n const onTouchMove = (e: TouchEvent) => {\n if (id === null || !e.cancelable) return;\n const t = e.touches[0];\n const mx = t && touchFrom ? t.clientX - touchFrom.x : dx;\n const my = t && touchFrom ? t.clientY - touchFrom.y : dy;\n const dirs = h.directions();\n if (Math.abs(my) > Math.abs(mx) && !dirs.up && !dirs.down) return;\n e.preventDefault();\n };\n\n root.addEventListener(\"pointerdown\", onDown);\n root.addEventListener(\"contextmenu\", onContext);\n root.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n root.addEventListener(\"touchmove\", onTouchMove, { passive: false });\n return () => {\n detach();\n clearHold();\n root.removeEventListener(\"pointerdown\", onDown);\n root.removeEventListener(\"contextmenu\", onContext);\n root.removeEventListener(\"touchstart\", onTouchStart);\n root.removeEventListener(\"touchmove\", onTouchMove);\n };\n}\n","/** Every word the deck draws: short, because in-app text is layout. A host overrides any of them. */\nexport interface SwipeDeckLabels {\n readonly suggestion: string;\n readonly reason: string;\n readonly exit: string;\n readonly help: string;\n readonly undo: string;\n readonly copy: string;\n readonly copied: string;\n readonly copyFailed: string;\n readonly part: string;\n readonly keep: string;\n readonly forget: string;\n readonly forgotten: string;\n readonly category: string;\n readonly addCategory: string;\n readonly newCategory: string;\n readonly done: string;\n readonly holdHint: string;\n readonly clickHint: string;\n readonly answer: string;\n readonly unanswered: string;\n readonly next: string;\n readonly undone: string;\n readonly pick: string;\n readonly expand: string;\n readonly collapse: string;\n readonly score: string;\n /** The end's headline when nothing else leads it. */\n readonly allDone: string;\n /** \"{answered} of {total} answered\". */\n readonly answeredOf: string;\n /** The end's list of answers. */\n readonly yourAnswers: string;\n /** On an answered item at the end: take this answer back and answer it again. */\n readonly change: string;\n readonly rightAnswer: string;\n readonly right: string;\n readonly wrong: string;\n readonly showAll: string;\n /** The finish's filter chips, by name. */\n readonly filterAnswers: string;\n /** The empty screen (no items). */\n readonly emptyTitle: string;\n /** The corner that opens every answer so far, and that list's title. */\n readonly answered: string;\n /** Leave the answered list for the card in focus. */\n readonly backToCards: string;\n}\n\nexport const DEFAULT_SWIPE_DECK_LABELS: SwipeDeckLabels = {\n suggestion: \"Suggestion\",\n reason: \"Reason\",\n exit: \"Exit\",\n help: \"Show me how\",\n undo: \"Undo\",\n copy: \"Copy\",\n copied: \"Copied\",\n copyFailed: \"Copy failed\",\n part: \"This part\",\n keep: \"Keep as is\",\n forget: \"Forget this\",\n forgotten: \"Forgotten\",\n category: \"Category\",\n addCategory: \"Add a category\",\n newCategory: \"New category\",\n done: \"Done\",\n holdHint: \"Hold any word\",\n clickHint: \"Double-click any word\",\n answer: \"Answer\",\n unanswered: \"Not answered\",\n next: \"Next\",\n undone: \"Undone\",\n pick: \"Pick one\",\n expand: \"Full screen\",\n collapse: \"Exit full screen\",\n score: \"Score\",\n allDone: \"All done\",\n answeredOf: \"{answered} of {total} answered\",\n yourAnswers: \"Your answers\",\n answered: \"Answered\",\n backToCards: \"Back to cards\",\n change: \"Change\",\n rightAnswer: \"Right answer\",\n right: \"Right\",\n wrong: \"Wrong\",\n showAll: \"All\",\n filterAnswers: \"Filter answers\",\n emptyTitle: \"Nothing to answer\",\n};\n","\"use client\";\n\n/**\n * THE PART SCREEN — one part of an item (a span of its words), answered with the same four swipes.\n *\n * Select the span by dragging either handle, sweeping across words, or tapping a word to grow or\n * shrink it; tag it from the category rows (\"+\" adds a missing category and gives that category its\n * own answer with the same swipe); place it; or forget it. Down keeps it as is.\n */\nimport * as React from \"react\";\n\nimport { Input } from \"../input\";\nimport { EraserIcon, PlusIcon, XIcon } from \"../icons\";\nimport { CornerButton, EdgeButtons, setHot, Wash, type EdgeRefs, type WashHandle } from \"./chrome\";\nimport { attachSwipe } from \"./gesture\";\nimport {\n answerOf,\n directionOf,\n KEEP_ANSWER_ID,\n partSuggestion,\n tokenize,\n type CategoryConflict,\n type DeckDirection,\n type DeckItem,\n type DeckKey,\n type DeckCategoryRow,\n type DeckPart,\n type DeckState,\n} from \"./model\";\nimport { fitText, flyOut, follow, keepFitted, snapBack } from \"./visual\";\nimport type { SwipeDeckLabels } from \"./labels\";\n\nexport interface PartScreenProps {\n readonly item: DeckItem;\n readonly parts: readonly DeckPart[];\n readonly initial: { start: number; end: number };\n readonly keyMap: DeckKey;\n /** The deck's key: what a category's answer means (flows down to parts). */\n readonly deckKey: DeckKey;\n readonly state: DeckState;\n readonly categories: readonly string[];\n /** Labelled chip rows (\"Who\", \"Cares about\"); each has its own \"+\". Absent: one row of every category. */\n readonly rows?: readonly DeckCategoryRow[] | undefined;\n readonly allowNewCategories: boolean;\n readonly conflict: CategoryConflict | undefined;\n readonly labels: SwipeDeckLabels;\n readonly onClose: () => void;\n readonly onPlace: (part: DeckPart) => void;\n readonly onForget: (span: { start: number; end: number }) => void;\n readonly onCategoryAnswer: (name: string, answer: string | null, row?: string) => void;\n readonly announce: (text: string) => void;\n}\n\nfunction overlapping(parts: readonly DeckPart[], s: number, e: number): DeckPart[] {\n return parts.filter((p) => !(p.end < s || p.start > e));\n}\n\nexport function PartScreen(props: PartScreenProps) {\n const { item, parts, keyMap, deckKey, state, labels, conflict } = props;\n const tokens = React.useMemo(() => tokenize(item.text), [item.text]);\n const exactAt = (s: number, e: number) => parts.find((p) => p.start === s && p.end === e) ?? null;\n const startPart = parts.find((p) => props.initial.start >= p.start && props.initial.start <= p.end) ?? null;\n const [sel, setSel] = React.useState(() => (startPart ? { s: startPart.start, e: startPart.end } : { s: props.initial.start, e: props.initial.end }));\n const [tagged, setTagged] = React.useState<readonly string[]>(() => startPart?.categories ?? []);\n /** The row whose \"+\" is open (\"\" when the deck has no rows), or null. */\n const [adding, setAdding] = React.useState<string | null>(null);\n const [draft, setDraft] = React.useState(\"\");\n /** Giving a just-added category its own answer: the phrase area shows the category instead. */\n const [categoryMode, setCategoryMode] = React.useState<string | null>(null);\n const [categoryModeRow, setCategoryModeRow] = React.useState<string | undefined>(undefined);\n const [extra, setExtra] = React.useState<readonly { name: string; row: string }[]>([]);\n const guard = React.useRef(true);\n const busy = React.useRef(false);\n\n React.useEffect(() => {\n const t = setTimeout(() => {\n guard.current = false;\n }, 350);\n return () => clearTimeout(t);\n }, []);\n\n const exact = exactAt(sel.s, sel.e);\n const draftPart: DeckPart = { start: sel.s, end: sel.e, categories: tagged, suggested: exact?.suggested ?? null, answer: exact?.answer ?? null };\n const suggestedId = categoryMode ? null : partSuggestion(draftPart, state, deckKey, conflict);\n const suggestedDir = directionOf(keyMap, suggestedId);\n const phrase = categoryMode ?? tokens.slice(sel.s, sel.e + 1).join(\" \").replace(/^[“\"‘'(\\[]+|[”\"’'.,;:!?)\\]]+$/g, \"\");\n const nowAnswer = exact ? answerOf(deckKey, exact.answer ?? partSuggestion(exact, state, deckKey, conflict)) : null;\n const allCategories = React.useMemo(\n () => [...props.categories, ...extra.map((x) => x.name).filter((c) => !props.categories.includes(c))],\n [props.categories, extra],\n );\n // The chip rows: the deck's rows (anything they do not name joins the first), or one row of every category.\n const chipRows = React.useMemo(() => {\n const given = props.rows?.length ? props.rows : null;\n if (!given) return [{ id: \"\", label: null as string | null, categories: allCategories }];\n const named = new Set(given.flatMap((r) => r.categories));\n const loose = allCategories.filter((c) => !named.has(c) && !extra.some((x) => x.name === c));\n return given.map((r, i) => ({\n id: r.id,\n label: r.label as string | null,\n categories: [...r.categories, ...(i === 0 ? loose : []), ...extra.filter((x) => x.row === r.id && !r.categories.includes(x.name)).map((x) => x.name)],\n }));\n }, [props.rows, allCategories, extra]);\n\n // ─── the swipe on the phrase ───────────────────────────────────────────\n const frameRef = React.useRef<HTMLDivElement>(null);\n const phraseRef = React.useRef<HTMLDivElement>(null);\n const edgeRefs = React.useRef<EdgeRefs>({});\n const wash = React.useRef<WashHandle>(null);\n\n const act = async (dir: DeckDirection, speed = 0) => {\n if (busy.current || guard.current) return;\n const answer = keyMap[dir];\n if (!answer) return;\n if (answer.id === KEEP_ANSWER_ID) {\n if (categoryMode) {\n setCategoryMode(null);\n return;\n }\n // Keep as is: the answer stays; a new span or a changed tag is still kept.\n const changed = !exact || exact.categories.join(\"\\u0000\") !== tagged.join(\"\\u0000\");\n if (changed && (exact || tagged.length)) props.onPlace(draftPart);\n props.onClose();\n return;\n }\n busy.current = true;\n wash.current?.show(answer, dir, 1);\n setHot(edgeRefs.current, dir);\n await flyOut(phraseRef.current, dir, speed);\n busy.current = false;\n if (categoryMode) {\n props.onCategoryAnswer(categoryMode, answer.id, categoryModeRow || undefined);\n props.announce(`${categoryMode}: ${answer.label}`);\n setCategoryMode(null);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n if (phraseRef.current) {\n phraseRef.current.style.transition = \"none\";\n phraseRef.current.style.transform = \"\";\n phraseRef.current.style.opacity = \"\";\n }\n return;\n }\n props.onPlace({ ...draftPart, answer: answer.id });\n props.announce(`${phrase}: ${answer.label}`);\n props.onClose();\n };\n const actRef = React.useRef(act);\n actRef.current = act;\n\n React.useEffect(() => {\n const root = frameRef.current;\n if (!root) return;\n return attachSwipe(root, {\n enabled: () => !busy.current && !guard.current,\n directions: () => keyMap,\n move: (dx, dy, dir, amount) => {\n const answer = dir ? keyMap[dir] : undefined;\n follow(phraseRef.current, dx, dy, dir && answer ? amount : 0);\n if (dir && answer) {\n wash.current?.show(answer, dir, amount);\n setHot(edgeRefs.current, amount >= 1 ? dir : null);\n } else {\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n }\n },\n release: () => {\n snapBack(phraseRef.current);\n wash.current?.hide();\n setHot(edgeRefs.current, null);\n },\n commit: (dir, speed) => void actRef.current(dir, speed),\n ignoreSelector: \"button, a, input, textarea, [data-sd-noswipe]\",\n });\n }, [keyMap]);\n\n // ─── selecting the span ────────────────────────────────────────────────\n const sentRef = React.useRef<HTMLDivElement>(null);\n const handleS = React.useRef<HTMLSpanElement>(null);\n const handleE = React.useRef<HTMLSpanElement>(null);\n const sweep = React.useRef<{ id: number; mode: \"s\" | \"e\" | \"sweep\"; anchor: number | null; moved: boolean } | null>(null);\n\n React.useLayoutEffect(() => {\n const box = sentRef.current;\n if (!box) return;\n const a = box.querySelector<HTMLElement>(`[data-sd-w=\"${sel.s}\"]`);\n const b = box.querySelector<HTMLElement>(`[data-sd-w=\"${sel.e}\"]`);\n const hs = handleS.current;\n const he = handleE.current;\n if (!a || !b || !hs || !he) return;\n const r = box.getBoundingClientRect();\n const ra = a.getBoundingClientRect();\n const rb = b.getBoundingClientRect();\n const st = box.scrollTop;\n hs.style.left = `${ra.left - r.left}px`;\n hs.style.top = `${ra.top - r.top + st - 12}px`;\n hs.style.height = `${ra.height + 22}px`;\n he.style.left = `${rb.right - r.left}px`;\n he.style.top = `${rb.top - r.top + st - 10}px`;\n he.style.height = `${rb.height + 22}px`;\n });\n\n const wordAt = (x: number, y: number): number | null => {\n const doc = sentRef.current?.ownerDocument;\n const el = doc?.elementFromPoint(x, y);\n const t = el?.closest(\"[data-sd-w], [data-sd-sp]\");\n if (!t || !sentRef.current?.contains(t)) return null;\n const v = t.getAttribute(\"data-sd-w\") ?? t.getAttribute(\"data-sd-sp\");\n return v === null ? null : Number(v);\n };\n\n const tapWord = (i: number) =>\n setSel(({ s, e }) => {\n if (i < s) return { s: i, e };\n if (i > e) return { s, e: i };\n if (s === e) return { s, e };\n if (i === s) return { s: s + 1, e };\n if (i === e) return { s, e: e - 1 };\n return { s: i, e: i };\n });\n\n const onSentDown = (ev: React.PointerEvent) => {\n if (guard.current || categoryMode) return;\n const target = ev.target instanceof Element ? ev.target : null;\n const handle = target?.closest(\"[data-sd-handle]\");\n const word = target?.closest(\"[data-sd-w]\");\n if (!handle && !word) return;\n ev.preventDefault();\n sweep.current = {\n id: ev.pointerId,\n mode: handle ? (handle.getAttribute(\"data-sd-handle\") === \"s\" ? \"s\" : \"e\") : \"sweep\",\n anchor: word ? Number(word.getAttribute(\"data-sd-w\")) : null,\n moved: false,\n };\n const view = sentRef.current?.ownerDocument.defaultView ?? window;\n const move = (e: PointerEvent) => {\n const sw = sweep.current;\n if (!sw || e.pointerId !== sw.id) return;\n const k = wordAt(e.clientX, e.clientY);\n if (k === null) return;\n if (sw.mode === \"s\") setSel(({ e: end }) => ({ s: Math.min(k, end), e: end }));\n else if (sw.mode === \"e\") setSel(({ s }) => ({ s, e: Math.max(k, s) }));\n else if (sw.anchor !== null && (k !== sw.anchor || sw.moved)) {\n sw.moved = true;\n const anchor = sw.anchor;\n setSel({ s: Math.min(k, anchor), e: Math.max(k, anchor) });\n }\n };\n const up = (e: PointerEvent) => {\n const sw = sweep.current;\n if (!sw || e.pointerId !== sw.id) return;\n view.removeEventListener(\"pointermove\", move);\n view.removeEventListener(\"pointerup\", up);\n view.removeEventListener(\"pointercancel\", up);\n if (sw.mode === \"sweep\" && !sw.moved && sw.anchor !== null) tapWord(sw.anchor);\n sweep.current = null;\n };\n view.addEventListener(\"pointermove\", move);\n view.addEventListener(\"pointerup\", up);\n view.addEventListener(\"pointercancel\", up);\n };\n\n // On open, the chosen words are in view (a late word in a long line sits below the capped box) and hold\n // the focus, so the keyboard can grow or shrink them at once.\n React.useEffect(() => {\n const word = sentRef.current?.querySelector<HTMLElement>(`[data-sd-w=\"${sel.s}\"]`);\n word?.scrollIntoView?.({ block: \"nearest\" });\n word?.focus({ preventScroll: true });\n // Open only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // When the span moves onto an existing part, its tags come with it.\n const lastSpan = React.useRef(`${sel.s}:${sel.e}`);\n React.useEffect(() => {\n const k = `${sel.s}:${sel.e}`;\n if (k === lastSpan.current) return;\n lastSpan.current = k;\n const hit = parts.find((p) => p.start === sel.s && p.end === sel.e);\n if (hit) setTagged(hit.categories);\n }, [sel, parts]);\n\n // ─── fit the phrase ────────────────────────────────────────────────────\n const stageRef = React.useRef<HTMLDivElement>(null);\n const pinRef = React.useRef<HTMLDivElement>(null);\n const textRef = React.useRef<HTMLParagraphElement>(null);\n React.useLayoutEffect(() => {\n const box = stageRef.current;\n if (!box || !pinRef.current || !textRef.current) return;\n return keepFitted(box, () => {\n if (pinRef.current && textRef.current) fitText(box, pinRef.current, textRef.current, 22, (box.ownerDocument.defaultView?.innerWidth ?? 0) >= 1024 ? 120 : 84);\n });\n }, [phrase, nowAnswer?.id, categoryMode]);\n\n const addCategory = () => {\n const name = draft.trim();\n const row = adding ?? \"\";\n setAdding(null);\n setDraft(\"\");\n if (!name) return;\n if (!allCategories.includes(name)) setExtra((x) => [...x, { name, row }]);\n setTagged((t) => (t.includes(name) ? t : [...t, name]));\n if (!state.categories[name]?.answer) {\n setCategoryMode(name);\n setCategoryModeRow(row);\n }\n };\n\n // Escape closes (keeping as is); the arrows answer.\n React.useEffect(() => {\n const view = frameRef.current?.ownerDocument.defaultView ?? window;\n const onKey = (e: KeyboardEvent) => {\n const t = e.target instanceof Element ? e.target : null;\n if (t?.closest(\"input, textarea, [contenteditable='true']\")) return;\n if (e.altKey || e.ctrlKey || e.metaKey) return;\n const dir = ({ ArrowRight: \"right\", ArrowLeft: \"left\", ArrowUp: \"up\", ArrowDown: \"down\" } as const)[e.key as \"ArrowRight\"];\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopImmediatePropagation();\n if (categoryMode) setCategoryMode(null);\n else props.onClose();\n } else if (dir) {\n e.preventDefault();\n e.stopImmediatePropagation();\n // A held arrow places the part once.\n if (!e.repeat) void actRef.current(dir);\n }\n };\n view.addEventListener(\"keydown\", onKey, true);\n return () => view.removeEventListener(\"keydown\", onKey, true);\n }, [categoryMode, props]);\n\n // The first tagged chip is in view when the screen opens or the tags move.\n const chipsRef = React.useRef<HTMLDivElement>(null);\n const firstTag = tagged[0];\n React.useEffect(() => {\n const on = chipsRef.current?.querySelector<HTMLElement>('[aria-pressed=\"true\"]');\n on?.scrollIntoView?.({ block: \"nearest\", inline: \"center\" });\n }, [firstTag]);\n\n const canForget = !categoryMode && overlapping(parts, sel.s, sel.e).length > 0;\n\n return (\n <div ref={frameRef} className=\"matrx-sd-frame matrx-sd-partscreen\" role=\"dialog\" aria-modal=\"true\" aria-label={labels.part}>\n <CornerButton corner=\"tl\" label={labels.keep} shortcut=\"Escape\" onClick={() => (categoryMode ? setCategoryMode(null) : props.onClose())}>\n <XIcon />\n </CornerButton>\n <div className=\"matrx-sd-partbody\">\n <div ref={sentRef} className=\"matrx-sd-sentence\" data-sd-noswipe=\"\" data-dim={categoryMode ? \"\" : undefined} onPointerDown={onSentDown}>\n {tokens.map((t, i) => (\n <React.Fragment key={i}>\n {i > 0 ? (\n <span className=\"matrx-sd-space\" data-sd-sp={i} data-sel={i > sel.s && i <= sel.e ? \"\" : undefined}>\n {\" \"}\n </span>\n ) : null}\n <span\n className=\"matrx-sd-word\"\n tabIndex={0}\n role=\"button\"\n aria-pressed={i >= sel.s && i <= sel.e}\n onKeyDown={(e) => {\n // The keyboard's way to grow or shrink the words: Enter or Space on a word, as a tap does.\n if ((e.key === \"Enter\" || e.key === \" \") && !e.repeat && !categoryMode) {\n e.preventDefault();\n tapWord(i);\n }\n }}\n data-sd-w={i}\n data-sel={i >= sel.s && i <= sel.e ? \"\" : undefined}\n data-first={i === sel.s ? \"\" : undefined}\n data-last={i === sel.e ? \"\" : undefined}\n >\n {t}\n </span>\n </React.Fragment>\n ))}\n <span ref={handleS} className=\"matrx-sd-handle\" data-sd-handle=\"s\" aria-hidden=\"true\" />\n <span ref={handleE} className=\"matrx-sd-handle\" data-sd-handle=\"e\" aria-hidden=\"true\" />\n </div>\n <div ref={stageRef} className=\"matrx-sd-phrase-stage\">\n <div ref={phraseRef} className=\"matrx-sd-phrase\">\n <div ref={pinRef}>\n {categoryMode ? <div className=\"matrx-sd-kicker\">{labels.category}</div> : null}\n <p ref={textRef} className=\"matrx-sd-phrase-text\" data-quoted={categoryMode ? undefined : \"\"}>\n {phrase}\n </p>\n {nowAnswer && !categoryMode ? (\n <div className=\"matrx-sd-now\" data-tone={nowAnswer.tone}>\n <i />\n <span>{[nowAnswer.label, ...(exact?.categories ?? [])].join(\" · \")}</span>\n </div>\n ) : null}\n </div>\n </div>\n </div>\n <div ref={chipsRef} className=\"matrx-sd-chip-rows\" data-sd-noswipe=\"\">\n {chipRows.map((row) => (\n <div key={row.id || \"all\"} className=\"matrx-sd-chips\" role=\"group\" aria-label={row.label ?? labels.category}>\n {row.label ? <span className=\"matrx-sd-chip-row-label\">{row.label}</span> : null}\n {row.categories.map((c) => {\n const on = tagged.includes(c);\n const ca = answerOf(deckKey, state.categories[c]?.answer);\n return (\n // ui-exception: category chips are the part screen's own toggle row\n <button\n key={c}\n type=\"button\"\n className=\"matrx-sd-chip\"\n aria-pressed={on}\n data-tone={ca?.tone}\n disabled={!!categoryMode}\n onClick={() => setTagged((t) => (on ? t.filter((x) => x !== c) : [...t, c]))}\n >\n {ca ? <i aria-hidden=\"true\" /> : null}\n {c}\n </button>\n );\n })}\n {props.allowNewCategories && !categoryMode ? (\n adding === row.id ? (\n <Input\n className=\"matrx-sd-chip-input\"\n autoFocus\n aria-label={labels.newCategory}\n enterKeyHint=\"done\"\n autoComplete=\"off\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={addCategory}\n onKeyDown={(e) => {\n e.stopPropagation();\n if (e.key === \"Enter\") {\n e.preventDefault();\n addCategory();\n } else if (e.key === \"Escape\") {\n setAdding(null);\n setDraft(\"\");\n }\n }}\n />\n ) : (\n // ui-exception: the chip row's own add target\n <button\n type=\"button\"\n className=\"matrx-sd-chip\"\n data-add=\"\"\n aria-label={row.label ? `${labels.addCategory}: ${row.label}` : labels.addCategory}\n title={labels.addCategory}\n onClick={() => setAdding(row.id)}\n >\n <PlusIcon />\n </button>\n )\n ) : null}\n </div>\n ))}\n </div>\n </div>\n <EdgeButtons keyMap={keyMap} suggested={suggestedDir} refs={edgeRefs} onAnswer={(d) => void act(d)} suggestionLabel={labels.suggestion} />\n {canForget ? (\n <CornerButton\n corner=\"br\"\n label={labels.forget}\n onClick={() => {\n if (guard.current) return;\n props.onForget({ start: sel.s, end: sel.e });\n props.onClose();\n }}\n >\n <EraserIcon />\n </CornerButton>\n ) : null}\n <Wash ref={wash} />\n </div>\n );\n}\n","\"use client\";\n\n/**\n * ExpandableSwipeDeck — the deck as a box in the flow (a chat message), fully usable where it is\n * (swipe, keys while focused, buttons, undo), with a corner that opens the SAME deck full screen.\n * Both views share one controller, so answers AND the undo history carry across; leaving full\n * screen (the corner, or Escape) returns to the box exactly where the person is.\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { useDeckController } from \"./controller\";\nimport { SwipeDeck, type SwipeDeckProps } from \"./SwipeDeck\";\n\nexport type ExpandableSwipeDeckProps = Omit<SwipeDeckProps, \"layout\" | \"onExpand\" | \"controller\" | \"onExit\" | \"exitKind\"> & {\n /** Full screen from the start (a host that opened the deck from elsewhere). */\n readonly defaultExpanded?: boolean;\n /** Told when the person opens or leaves full screen (a host may prefer its own canvas: return true to take it over). */\n readonly onExpandChange?: (expanded: boolean) => boolean | void;\n};\n\nexport function ExpandableSwipeDeck({ defaultExpanded = false, onExpandChange, ...props }: ExpandableSwipeDeckProps) {\n const controller = useDeckController({ items: props.items, binding: props.binding, initialState: props.initialState, onChange: props.onChange });\n const [expanded, setExpanded] = React.useState(defaultExpanded);\n const boxRef = React.useRef<HTMLDivElement>(null);\n const open = () => {\n if (onExpandChange?.(true) === true) return;\n setExpanded(true);\n };\n const close = () => {\n onExpandChange?.(false);\n setExpanded(false);\n // Back in the chat, the box holds the keys again.\n requestAnimationFrame(() => boxRef.current?.querySelector<HTMLElement>(\".matrx-sd\")?.focus({ preventScroll: true }));\n };\n const doc = typeof document === \"undefined\" ? null : document;\n return (\n <div ref={boxRef} className=\"matrx-sd-inline-host\">\n {expanded ? (\n // The box keeps its height while the deck is full screen, so the chat never jumps.\n <div className=\"matrx-sd\" data-layout=\"inline\" aria-hidden=\"true\" />\n ) : (\n <SwipeDeck {...props} layout=\"inline\" controller={controller} onExpand={open} />\n )}\n {expanded && doc\n ? createPortal(<SwipeDeck {...props} layout=\"fullscreen\" controller={controller} onExit={close} exitKind=\"collapse\" tourKey={null} />, doc.body)\n : null}\n </div>\n );\n}\n","/**\n * THE ONE READER of a `swipe_deck` kind value (what an agent writes) into the deck's own terms.\n *\n * Only `items[].text` is required; every other field is optional and nothing is invented for what is\n * absent. Directions are the agent's words: `suggested: \"right\"`, `answers: { up: null }`, a mark's\n * `lean: \"left\"`. An item's `choices` (2 to 8) become that item's own answers: the first four placed\n * clockwise from the top (2: right, left; 3: up, right, left; 4: up, right, down, left), any more as\n * buttons on the card; `correct` names a choice by its words (or a direction). Server declaration: aidream `aidream/kinds/swipe_deck.py`.\n */\nimport { DEFAULT_DECK_KEY, DECK_DIRECTIONS, askedItems, conditionProblems, mergeKey, readDeckCondition, type DeckAnswer, type DeckDirection, type DeckItem, type DeckKey, type DeckKeyOverride, type DeckTone } from \"./model\";\n\nexport interface SwipeDeckKindDeck {\n readonly title: string | null;\n readonly items: DeckItem[];\n /** The deck's key over the default; undefined when the value names none. */\n readonly answers: DeckKeyOverride | undefined;\n readonly pickOne: boolean;\n readonly categories: string[];\n /** Every item carries its own choices: the deck is a quiz-like set of questions. */\n readonly everyItemHasChoices: boolean;\n /** What the agent wrote that could not be honored (a right answer naming no choice, extra choices). Never silent: the host reports them. */\n readonly problems: string[];\n}\n\nconst TONES: readonly DeckTone[] = [\"success\", \"info\", \"destructive\", \"warning\", \"primary\", \"neutral\"];\nconst CHOICE_PLACES: Record<number, readonly DeckDirection[]> = {\n 2: [\"right\", \"left\"],\n 3: [\"up\", \"right\", \"left\"],\n 4: [\"up\", \"right\", \"down\", \"left\"],\n};\n/** Choice tones read as distinct options, never as right/wrong (no green, no red). */\nconst CHOICE_TONES: Record<DeckDirection, DeckTone> = { up: \"primary\", right: \"info\", down: \"warning\", left: \"neutral\" };\n\n/** A card holds four answers on its edges and four more as buttons. */\nconst MAX_CHOICES = 8;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> => !!v && typeof v === \"object\" && !Array.isArray(v);\nconst text = (v: unknown): string => (typeof v === \"string\" ? v.trim() : typeof v === \"number\" ? String(v) : \"\");\nconst isDirection = (v: unknown): v is DeckDirection => typeof v === \"string\" && (DECK_DIRECTIONS as readonly string[]).includes(v);\n\nfunction answerOverride(raw: unknown): DeckKeyOverride | undefined {\n if (!isRecord(raw)) return undefined;\n const out: { -readonly [D in DeckDirection]?: DeckAnswer | null } = {};\n let any = false;\n for (const dir of DECK_DIRECTIONS) {\n if (!(dir in raw)) continue;\n const v = raw[dir];\n const base = DEFAULT_DECK_KEY[dir];\n if (v === null || v === false) {\n out[dir] = null;\n any = true;\n continue;\n }\n const label = isRecord(v) ? text(v.label) : text(v);\n if (!label || !base) continue;\n const tone = isRecord(v) && TONES.includes(v.tone as DeckTone) ? (v.tone as DeckTone) : base.tone;\n out[dir] = { ...base, label, tone };\n any = true;\n }\n return any ? out : undefined;\n}\n\nfunction norm(s: string): string {\n return s.trim().toLowerCase().replace(/\\s+/g, \" \");\n}\n\n/** Read a swipe_deck value; null when it holds no readable item (the host shows its stand-in). */\nexport function swipeDeckFromKindValue(value: unknown): SwipeDeckKindDeck | null {\n if (!isRecord(value)) return null;\n const answers = answerOverride(value.answers);\n const deckKey: DeckKey = mergeKey(DEFAULT_DECK_KEY, answers);\n const rawItems = Array.isArray(value.items) ? value.items : [];\n const items: DeckItem[] = [];\n const problems: string[] = [];\n const seenIds = new Set<string>();\n // Each item's own answer reader and its raw `show_if`, resolved once every item is known.\n const readers = new Map<string, (w: unknown) => string | undefined>();\n const rawShow = new Map<string, unknown>();\n const positions: string[] = [];\n let withChoices = 0;\n rawItems.forEach((raw, index) => {\n const r = isRecord(raw) ? raw : typeof raw === \"string\" ? { text: raw } : null;\n if (!r) return;\n const body = text(r.text) || text(r.statement) || text(r.question) || text(r.title);\n if (!body) return;\n const allChoices = (Array.isArray(r.choices) ? r.choices : Array.isArray(r.options) ? r.options : [])\n .map((c) => (isRecord(c) ? text(c.label) || text(c.text) : text(c)))\n .filter(Boolean);\n if (allChoices.length > MAX_CHOICES) problems.push(`Item ${index + 1} has ${allChoices.length} choices; a card holds ${MAX_CHOICES}, so the rest were left off.`);\n if (allChoices.length === 1) problems.push(`Item ${index + 1} has a single choice; the deck's own answers were used.`);\n const choiceWords = allChoices.slice(0, MAX_CHOICES);\n const places = choiceWords.length >= 2 ? CHOICE_PLACES[Math.min(4, choiceWords.length)] : undefined;\n let own: DeckKeyOverride | undefined;\n let more: DeckAnswer[] = [];\n let key = deckKey;\n if (places) {\n withChoices++;\n const o: { -readonly [D in DeckDirection]?: DeckAnswer | null } = { up: null, right: null, down: null, left: null };\n places.forEach((dir, i) => {\n o[dir] = { id: `choice_${i + 1}`, label: choiceWords[i] ?? \"\", tone: CHOICE_TONES[dir] };\n });\n own = o;\n key = mergeKey(deckKey, o);\n more = choiceWords.slice(4).map((label, i) => ({ id: `choice_${i + 5}`, label, tone: \"neutral\" as const }));\n }\n // An answer named by its words first (a choice may itself read \"left\"), then — for an item with\n // choices — by letter (\"B\", \"b)\") or number (1-based, or a 0-based number the agent counted from),\n // then by direction.\n const byWords = (w: unknown): string | undefined => {\n const t = text(w);\n if (!t) return undefined;\n for (const a of [...DECK_DIRECTIONS.map((d) => key[d]), ...more]) {\n if (a && (norm(a.label) === norm(t) || a.id === t)) return a.id;\n }\n if (places) {\n const stripped = norm(t.replace(/^\\(?[a-h1-8][).:]\\s+/i, \"\"));\n const byLabel = choiceWords.findIndex((c) => norm(c) === stripped);\n if (byLabel >= 0) return `choice_${byLabel + 1}`;\n const letter = /^\\(?([a-h])[).:]?$/i.exec(t);\n if (letter?.[1]) {\n const i = letter[1].toLowerCase().charCodeAt(0) - 97;\n if (i < choiceWords.length) return `choice_${i + 1}`;\n }\n const numeral = /^\\(?([1-8])[).:]?$/.exec(t);\n if (numeral?.[1] && Number(numeral[1]) <= choiceWords.length) return `choice_${numeral[1]}`;\n if (typeof w === \"number\" && Number.isInteger(w)) {\n if (w >= 1 && w <= choiceWords.length) return `choice_${w}`;\n if (w === 0) return \"choice_1\";\n }\n }\n if (isDirection(t)) return key[t]?.id;\n return undefined;\n };\n const correct = Array.isArray(r.correct) ? r.correct.map(byWords).filter((x): x is string => !!x) : byWords(r.correct);\n const correctGiven = Array.isArray(r.correct) ? r.correct.length > 0 : r.correct !== undefined && r.correct !== null && text(r.correct) !== \"\";\n if (correctGiven && (correct === undefined || (Array.isArray(correct) && !correct.length)))\n problems.push(`Item ${index + 1}'s right answer \"${Array.isArray(r.correct) ? r.correct.map(text).join(\", \") : text(r.correct)}\" names none of its choices, so it is not graded.`);\n const details = (Array.isArray(r.details) ? r.details : Array.isArray(r.fields) ? r.fields : [])\n .filter(isRecord)\n .map((d) => ({ label: text(d.label), value: text(d.value) }))\n .filter((d) => d.label && d.value);\n const marks = (Array.isArray(r.marks) ? r.marks : [])\n .filter(isRecord)\n .map((m) => ({\n phrase: text(m.phrase),\n categories: Array.isArray(m.categories) ? m.categories.map(text).filter(Boolean) : [],\n suggested: isDirection(m.lean) ? (key[m.lean]?.id ?? null) : null,\n }))\n .filter((m) => m.phrase);\n const suggested = byWords(r.suggested);\n let id = text(r.id) || `item_${index + 1}`;\n if (seenIds.has(id)) {\n problems.push(`Two items share the id \"${id}\"; the second was given its own.`);\n id = `${id}_${index + 1}`;\n }\n seenIds.add(id);\n readers.set(id, byWords);\n positions[index] = id;\n const show = r.show_if ?? r.showIf;\n if (show !== undefined && show !== null) rawShow.set(id, show);\n const item: DeckItem = {\n id,\n text: body,\n ...(text(r.kicker) ? { kicker: text(r.kicker) } : {}),\n ...(text(r.tag) ? { tag: text(r.tag) } : {}),\n ...(suggested ? { suggested } : {}),\n ...(text(r.reason) ? { reason: text(r.reason) } : {}),\n ...(details.length ? { fields: details } : {}),\n ...(own ? { answers: own } : {}),\n ...(more.length ? { more } : {}),\n ...(correct !== undefined && (typeof correct === \"string\" || correct.length) ? { correct } : {}),\n ...(text(r.group) ? { group: text(r.group) } : {}),\n ...(marks.length ? { parts: marks } : {}),\n };\n items.push(item);\n });\n if (!items.length) return null;\n // Conditions name a card by its id, its position (1-based) or its exact words, and its answers by\n // their words (or a letter, a number, a direction), as `correct` does.\n const byText = new Map(items.map((i) => [norm(i.text), i.id]));\n const refOf = (v: unknown): string => {\n const t = text(v);\n if (readers.has(t)) return t;\n if (typeof v === \"number\" && Number.isInteger(v) && positions[v - 1]) return positions[v - 1] ?? t;\n return byText.get(norm(t)) ?? t;\n };\n const shaped = items.map((item) => {\n const raw = rawShow.get(item.id);\n const showIf = raw === undefined ? null : readDeckCondition(raw, { ref: refOf, answer: (id, w) => readers.get(id)?.(w) ?? null });\n if (raw !== undefined && !showIf) problems.push(`\"${item.text}\" has a show_if the deck cannot read, so it is always asked.`);\n return showIf ? { ...item, showIf } : item;\n });\n problems.push(...conditionProblems(shaped, { key: deckKey }));\n return {\n title: text(value.title) || null,\n items: shaped,\n answers,\n pickOne: value.pick_one === true,\n categories: Array.isArray(value.categories) ? value.categories.map(text).filter(Boolean) : [],\n everyItemHasChoices: withChoices === items.length,\n problems,\n };\n}\n\n/** The deck's results as rows (one per item), for \"Save to a table\". Column names are words. */\nexport function swipeDeckResultRows(\n deck: SwipeDeckKindDeck,\n answers: Readonly<Record<string, string>>,\n): Record<string, string>[] {\n const deckKey = mergeKey(DEFAULT_DECK_KEY, deck.answers);\n const graded = deck.items.some((i) => i.correct !== undefined);\n // Only the cards that were asked: a card skipped by its condition has no row (its kept answer does not apply).\n const asked = askedItems(deck.items, { answers, picks: {}, parts: {}, categories: {} });\n return deck.items.filter((item) => asked.get(item.id)).map((item) => {\n const key = mergeKey(deckKey, item.answers);\n const all = [...DECK_DIRECTIONS.map((d) => key[d]), ...(item.more ?? [])];\n const id = answers[item.id];\n const answer = id ? all.find((a) => a?.id === id) : undefined;\n const row: Record<string, string> = {};\n if (deck.items.some((i) => i.kicker)) row.Kind = item.kicker ?? \"\";\n row.Item = item.text;\n row.Answer = answer?.label ?? \"\";\n if (graded) {\n const correct = item.correct === undefined ? [] : typeof item.correct === \"string\" ? [item.correct] : item.correct;\n row[\"Right answer\"] = correct.map((c) => all.find((a) => a?.id === c)?.label ?? \"\").filter(Boolean).join(\", \");\n row.Right = !id || !correct.length ? \"\" : correct.includes(id) ? \"Yes\" : \"No\";\n }\n return row;\n });\n}\n","/**\n * THE DECK'S LOGIC AS A GRAPH — and back. Cards are nodes; each condition is an arrow from the earlier\n * card whose answer it reads to the card it opens, labelled by the answers that open it. Editing the\n * graph (draw an arrow, delete one, pick its answers, choose whether a card needs ANY or ALL of its\n * arrows) rebuilds each card's `showIf`; reading it back gives the same graph. Pure data: any graph\n * editor (the diagram canvas, a test) works through these two functions.\n *\n * A condition the graph cannot draw (a `not`, a nested group) is kept exactly as written and the card is\n * marked `custom`: the graph shows it and leaves it alone until a person replaces it there.\n */\nimport { conditionProblems, findAnswer, keyFor, moreFor, type DeckAnswer, type DeckCondition, type DeckItem, type DeckRules } from \"./model\";\n\nexport interface DeckLogicEdge {\n /** Stable while the graph is edited: `from→to`. */\n readonly id: string;\n /** The earlier card whose answer is read. */\n readonly from: string;\n /** The card it opens. */\n readonly to: string;\n /** Answer ids that open it (empty with `isNot` empty: any answer at all). */\n readonly is: readonly string[];\n /** Answer ids that keep it closed. */\n readonly isNot: readonly string[];\n}\n\nexport interface DeckLogicCard {\n readonly id: string;\n readonly text: string;\n readonly kicker?: string;\n /** Every answer the card can take, edges first. */\n readonly answers: readonly DeckAnswer[];\n /** With two or more arrows in: does the card need any of them, or all? */\n readonly match: \"any\" | \"all\";\n /** Its condition is one the graph cannot draw; kept as written. */\n readonly custom: boolean;\n}\n\nexport interface DeckLogicGraph {\n readonly cards: readonly DeckLogicCard[];\n readonly edges: readonly DeckLogicEdge[];\n}\n\nconst list = (v: string | readonly string[] | undefined): string[] => (v === undefined ? [] : typeof v === \"string\" ? [v] : [...v]);\n\ntype Leaf = Extract<DeckCondition, { item: string }>;\nconst isLeaf = (c: DeckCondition): c is Leaf => \"item\" in c;\n\n/** The leaves of a drawable condition and how they combine, or null when it cannot be drawn. */\nfunction drawable(cond: DeckCondition): { match: \"any\" | \"all\"; leaves: Leaf[] } | null {\n const plain = (l: Leaf) => l.answered !== false;\n if (isLeaf(cond)) return plain(cond) ? { match: \"any\", leaves: [cond] } : null;\n // An empty group (never / always) and two leaves on the same earlier card cannot be drawn as\n // arrows without changing what they mean: kept as written (`custom`).\n const group = (list: readonly DeckCondition[], match: \"any\" | \"all\") => {\n if (!list.length || !list.every((c) => isLeaf(c) && plain(c))) return null;\n const leaves = list as Leaf[];\n return new Set(leaves.map((l) => l.item)).size === leaves.length ? { match, leaves } : null;\n };\n if (\"any\" in cond) return group(cond.any, \"any\");\n if (\"all\" in cond) return group(cond.all, \"all\");\n return null;\n}\n\nfunction answersOf(rules: DeckRules, item: DeckItem): DeckAnswer[] {\n const key = keyFor(rules, item);\n const edges = ([\"right\", \"up\", \"left\", \"down\"] as const).map((d) => key[d]).filter((a): a is DeckAnswer => !!a);\n return [...edges, ...moreFor(rules, item)];\n}\n\n/** The graph of a deck's logic. */\nexport function deckLogicGraph(items: readonly DeckItem[], rules: DeckRules): DeckLogicGraph {\n const edges: DeckLogicEdge[] = [];\n const cards = items.map((item): DeckLogicCard => {\n const drawn = item.showIf ? drawable(item.showIf) : { match: \"any\" as const, leaves: [] };\n if (drawn) {\n for (const leaf of drawn.leaves) {\n const id = `${leaf.item}→${item.id}`;\n const at = edges.findIndex((e) => e.id === id);\n const edge = { id, from: leaf.item, to: item.id, is: list(leaf.is), isNot: list(leaf.isNot) };\n // Two leaves on the same card pair (rare, hand-written) merge into one arrow.\n if (at >= 0) {\n const had = edges[at]!;\n edges[at] = { ...had, is: [...new Set([...had.is, ...edge.is])], isNot: [...new Set([...had.isNot, ...edge.isNot])] };\n } else edges.push(edge);\n }\n }\n return {\n id: item.id,\n text: item.text,\n ...(item.kicker ? { kicker: item.kicker } : {}),\n answers: answersOf(rules, item),\n match: drawn?.match ?? \"any\",\n custom: !drawn,\n };\n });\n return { cards, edges };\n}\n\n/**\n * The deck with each card's `showIf` rebuilt from the graph. A card with no arrows in is always asked;\n * one arrow is that leaf; more combine by the card's `match`. A `custom` card keeps its own condition.\n */\nexport function applyDeckLogic(items: readonly DeckItem[], graph: DeckLogicGraph): DeckItem[] {\n const byCard = new Map(graph.cards.map((c) => [c.id, c]));\n return items.map((item) => {\n const card = byCard.get(item.id);\n if (card?.custom) return item;\n const leaves: Leaf[] = graph.edges\n .filter((e) => e.to === item.id)\n .map((e) => ({ item: e.from, ...(e.is.length ? { is: [...e.is] } : {}), ...(e.isNot.length ? { isNot: [...e.isNot] } : {}) }));\n const { showIf: _old, ...rest } = item;\n if (!leaves.length) return rest;\n const showIf: DeckCondition = leaves.length === 1 ? leaves[0]! : card?.match === \"all\" ? { all: leaves } : { any: leaves };\n return { ...rest, showIf };\n });\n}\n\n/** An arrow's words: the answers that open the card (\"Yes · Sort of\", \"not No\", \"answered\"). */\nexport function logicEdgeLabel(edge: DeckLogicEdge, items: readonly DeckItem[], rules: DeckRules): string {\n const from = items.find((i) => i.id === edge.from);\n const words = (ids: readonly string[]) => ids.map((id) => (from ? (findAnswer(rules, from, id)?.label ?? id) : id));\n const parts = [...words(edge.is), ...words(edge.isNot).map((w) => `not ${w}`)];\n return parts.length ? parts.join(\" · \") : \"answered\";\n}\n\n/** Whether an arrow may be drawn: only from an EARLIER card (no loops), never onto itself or twice. */\nexport function canConnect(items: readonly DeckItem[], graph: DeckLogicGraph, from: string, to: string): string | null {\n const a = items.findIndex((i) => i.id === from);\n const b = items.findIndex((i) => i.id === to);\n if (a < 0 || b < 0) return \"That card is not in the deck.\";\n if (a === b) return \"A card cannot depend on itself.\";\n if (a > b) return \"A card can only depend on a card before it.\";\n if (graph.edges.some((e) => e.from === from && e.to === to)) return \"Those two cards are already joined.\";\n if (graph.cards.find((c) => c.id === to)?.custom) return \"This card has a rule the graph cannot draw. Select it and press Clear rule first.\";\n return null;\n}\n\n/** A new arrow, opened by the earlier card's first answer (its right edge's, usually Yes). */\nexport function newLogicEdge(items: readonly DeckItem[], rules: DeckRules, from: string, to: string): DeckLogicEdge {\n const source = items.find((i) => i.id === from);\n const first = source ? answersOf(rules, source)[0] : undefined;\n return { id: `${from}→${to}`, from, to, is: first ? [first.id] : [], isNot: [] };\n}\n\n/** What is wrong with the logic as drawn, in words (the deck's own checks). */\nexport function logicProblems(items: readonly DeckItem[], rules: DeckRules, graph: DeckLogicGraph): string[] {\n return conditionProblems(applyDeckLogic(items, graph), rules);\n}\n"],"mappings":"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","names":["React","text","Wash","React","text","list","list","kept","React","jsx","jsxs","Fragment","jsx","jsxs","text","a","list","React","jsx","jsxs","norm","plain","list"]}
|