gridsmith-ui 0.28.0 → 0.29.1
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 +47 -1
- package/dist/charts.d.ts +7 -2
- package/dist/charts.js +2 -2
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +5 -5
- package/dist/{chunk-GXMTS3YD.js → chunk-37WOC7F7.js} +29 -12
- package/dist/chunk-37WOC7F7.js.map +1 -0
- package/dist/{chunk-OPFJEL3Z.js → chunk-4TUJXDRU.js} +96 -15
- package/dist/chunk-4TUJXDRU.js.map +1 -0
- package/dist/{chunk-EIWXVICU.js → chunk-6A5RHW2W.js} +3 -3
- package/dist/{chunk-EIWXVICU.js.map → chunk-6A5RHW2W.js.map} +1 -1
- package/dist/{chunk-XVB55M3N.js → chunk-72SDAX54.js} +2 -2
- package/dist/chunk-72SDAX54.js.map +1 -0
- package/dist/{chunk-YUTF2X6B.js → chunk-FUKSLQ77.js} +8 -8
- package/dist/{chunk-YUTF2X6B.js.map → chunk-FUKSLQ77.js.map} +1 -1
- package/dist/{chunk-DQCHCLEJ.js → chunk-I3MTQ3CS.js} +5 -5
- package/dist/{chunk-DQCHCLEJ.js.map → chunk-I3MTQ3CS.js.map} +1 -1
- package/dist/{chunk-66JJCQU3.js → chunk-JTU7OBYJ.js} +5 -3
- package/dist/chunk-JTU7OBYJ.js.map +1 -0
- package/dist/{chunk-2ROVDVLZ.js → chunk-MFAWJSMJ.js} +3 -3
- package/dist/{chunk-2ROVDVLZ.js.map → chunk-MFAWJSMJ.js.map} +1 -1
- package/dist/{chunk-TJEV7YAY.js → chunk-MKFWHWBK.js} +2 -2
- package/dist/{chunk-TJEV7YAY.js.map → chunk-MKFWHWBK.js.map} +1 -1
- package/dist/{chunk-BRAXJEEP.js → chunk-QNHVPE2B.js} +4 -4
- package/dist/{chunk-BRAXJEEP.js.map → chunk-QNHVPE2B.js.map} +1 -1
- package/dist/{chunk-TRDXWHD2.js → chunk-RECCCA7Z.js} +6 -6
- package/dist/chunk-RECCCA7Z.js.map +1 -0
- package/dist/{chunk-R4GXKH4U.js → chunk-RJEUQ7RL.js} +10 -8
- package/dist/chunk-RJEUQ7RL.js.map +1 -0
- package/dist/{chunk-CRQ6KCRD.js → chunk-ZHUVLBCC.js} +7 -4
- package/dist/chunk-ZHUVLBCC.js.map +1 -0
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +9 -9
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +2 -2
- package/dist/editor.js +4 -4
- package/dist/icons.d.ts +9 -0
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +45 -35
- package/dist/index.js +142 -164
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +6 -6
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.js +7 -7
- package/dist/roots.css +2 -0
- package/dist/{table-utils-BkjNEWts.d.ts → table-utils-CxnpFHRF.d.ts} +5 -4
- package/dist/{use-pagination-BxcRlNQG.d.ts → use-pagination-QykGSREv.d.ts} +7 -0
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +1 -1
- package/dist/virtualized.js +6 -6
- package/package.json +2 -2
- package/dist/chunk-66JJCQU3.js.map +0 -1
- package/dist/chunk-CRQ6KCRD.js.map +0 -1
- package/dist/chunk-GXMTS3YD.js.map +0 -1
- package/dist/chunk-OPFJEL3Z.js.map +0 -1
- package/dist/chunk-R4GXKH4U.js.map +0 -1
- package/dist/chunk-TRDXWHD2.js.map +0 -1
- package/dist/chunk-XVB55M3N.js.map +0 -1
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../showcase/src/lib/utils.ts","../../../showcase/src/lib/format-locale.ts","../../../showcase/src/lib/date-grid.ts","../../../showcase/src/lib/locale-cache.ts","../../../showcase/src/lib/recurrence.ts","../../../showcase/src/lib/time-zones.ts","../../../showcase/src/lib/time-days.ts","../../../showcase/src/lib/chart-categories.ts"],"names":["last","at","next","moveKey","carried","whole","formats","list"],"mappings":"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","file":"utils.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n\nexport const GLASS_BACKDROP = \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\";\n\nexport const GLASS_SURFACE = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-card),var(--ds-glass-inset)]`;\n\nexport const GLASS_OVERLAY = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-modal),var(--ds-glass-inset)]`;\n\n/**\n * A modal surface (Dialog, Drawer, Sheet, CommandPalette, GlobalSearch): the theme's surface, never less than 85% opaque.\n * A glass theme's surface is see-through by design, which suits a card on the canvas; over an overlay's scrim the same\n * glass reads as grey mud, and the page shows through (round 27, R27-17, the owner picked 85% from a mock-up). An opaque\n * theme keeps its surface as it is: the alpha only rises, through CSS relative colour, in every mode and scope.\n *\n * The theme's surface comes first, for a browser without relative colour (Chrome before 119, Firefox before 128,\n * Safari before 16.4): a value holding var() is only found invalid once computed, which drops the background to\n * transparent rather than to an earlier declaration, so the raised one applies only where @supports says it can (the\n * round 27 review). A surface with no colour at all (fully transparent) stays so: raising it would paint it black.\n */\nexport const OVERLAY_SURFACE = \"bg-[var(--ds-bg-surface)] supports-[color:oklch(from_red_l_c_h)]:bg-[oklch(from_var(--ds-bg-surface)_l_c_h_/_max(alpha,min(1,alpha*1000)*0.85))]\";\n\nexport const GLASS_DROPDOWN = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]`;\n\n// Keyboard focus (Sprint 30, the owner's D1 and D6): where Tab has landed. A solid outline in the theme's focus colour\n// (--ds-focus, derived to 3:1 on every ground), 2 px, with a 2 px gap between it and the element. The gap shows what the\n// element sits on, so one colour reads beside any fill, and while the outline shows, the element's own shadow steps\n// aside (D7, P12): shadow-none drops its --tw-shadow and keeps any ring. Every part is prefixed: an unprefixed\n// outline-solid draws an outline at rest. And outline-solid is required: in Tailwind 4, outline-none (which many\n// components set at rest) sets --tw-outline-style: none, which outline-2 reads, so without it no outline draws. These\n// draw no border (a button that uses one, the Launcher, gets the outline alone); a field takes FIELD_FOCUS_RING. `cn()`\n// keeps only the last of outline-none and outline-solid in one variant, so a component's own focus-visible:outline-none\n// after a utility would remove the outline: none may follow one.\nexport const FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:shadow-none\";\n\n/**\n * On a wrapper that shows focus for a control inside it: HAS_FOCUS_RING, from the keyboard only (`:has(:focus-visible)`).\n * FOCUS_WITHIN_RING shows it on any focus inside, a click's too, since `:focus-within` has no keyboard-only form: kept\n * for code that uses it, and a new wrapper takes HAS_FOCUS_RING (D6: keyboard focus shows only from the keyboard).\n */\nexport const FOCUS_WITHIN_RING = \"focus-within:outline-2 focus-within:outline-solid focus-within:outline-offset-2 focus-within:outline-[var(--ds-focus)] focus-within:shadow-none\";\n\nexport const HAS_FOCUS_RING = \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-solid has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--ds-focus)] has-[:focus-visible]:shadow-none\";\n\n/**\n * The outline on a drawn child, where the element that takes focus is hidden or wraps it: a checkbox's box beside its\n * input (`peer`), a radio's circle inside its button, a separator's grip, a Gantt milestone's diamond (`group`). The\n * same outline, gap and shadow rule.\n */\nexport const PEER_FOCUS_RING = \"peer-focus-visible:outline-2 peer-focus-visible:outline-solid peer-focus-visible:outline-offset-2 peer-focus-visible:outline-[var(--ds-focus)] peer-focus-visible:shadow-none\";\n\nexport const GROUP_FOCUS_RING = \"group-focus-visible:outline-2 group-focus-visible:outline-solid group-focus-visible:outline-offset-2 group-focus-visible:outline-[var(--ds-focus)] group-focus-visible:shadow-none\";\n\n/**\n * The same outline drawn inside the element's edge, for edge-to-edge rows, cells and scroll regions only (the plan's\n * P3): elements that are never filled solid, since inside the edge there is no gap to keep one colour readable on a fill.\n * It sits `--ds-focus-inset` in: 5 px, deeper where the theme's corners are rounder, so it clears a table's rounded\n * corners (D8, the owner's decision A); what such an element holds keeps 1 px more clear of its edge. Anywhere else the\n * outline stays outside, with room made for it. Moved here from use-keyboard-scroll.ts (Sprint 30) so the server-safe\n * `gridsmith-ui/utils` can export it.\n */\nexport const FOCUS_INSET = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-[var(--ds-focus-inset)] focus-visible:outline-[var(--ds-focus)]\";\n\n/**\n * A field (D6, P4, P13). Reached with Tab: the keyboard's outline, and its border in the focus colour, as GOV.UK turns a\n * focused input's border: it is where you type. Clicked into: the active look instead, the accent border and its soft\n * halo (`ring-2` in --ds-ring-active, laid over the field's own shadow), and no outline. A browser matches :focus-visible\n * on a text field either way, so lib/input-modality.ts notes on <html> whether a pointer moved focus last; with no note\n * yet, the outline. The field keeps its own (inset) shadow in both: no shadow-none here.\n *\n * The wrapper forms (_WITHIN_ and _HAS_, for a box round the part you type in) show it while that part has focus, and\n * not while a control of the field's own does: a button, a select, a link, a checkbox, a radio or a switch inside it (a\n * tag's remove, a picker's chevron, a composer's Send, an editor's toolbar or a task's checkbox), or anything in a popup\n * inside the box (a dialog of its own; a field that is itself in a dialog still shows it). That control shows its own outline, so there is one focus point, never\n * two (P11). _WITHIN_ reads :focus, as a click on a date's segment isn't :focus-visible; _HAS_ reads :focus-visible.\n * Either outranks the field's hover border, so hovering keeps the look.\n */\nexport const FIELD_FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:focus-visible:outline-none [[data-input-modality=pointer]_&]:focus-visible:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:focus-visible:ring-2 [[data-input-modality=pointer]_&]:focus-visible:ring-[var(--ds-ring-active)]\";\n\nexport const FIELD_FOCUS_WITHIN_RING = \"has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-solid has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-offset-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-[var(--ds-focus)] has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-[var(--ds-ring-active)]\";\n\nexport const FIELD_HAS_FOCUS_RING = \"has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-solid has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-offset-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-[var(--ds-focus)] has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-[var(--ds-ring-active)]\";\n\n// A field with an error: the same, its red border kept, and the red halo when clicked into.\nexport const ERROR_FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:focus-visible:outline-none [[data-input-modality=pointer]_&]:focus-visible:ring-2 [[data-input-modality=pointer]_&]:focus-visible:ring-[var(--ds-ring-error)]\";\n\nexport const ERROR_FOCUS_WITHIN_RING = \"has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-solid has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-offset-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-[var(--ds-focus)] has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-[var(--ds-ring-error)]\";\n\nexport const ERROR_HAS_FOCUS_RING = \"has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-solid has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-offset-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-[var(--ds-focus)] has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-[var(--ds-ring-error)]\";\n\n// Active (D6): a field clicked into, or a dropdown or picker that's open, is its accent border (--ds-accent-ink, P8) with\n// the soft halo beyond it; on a field with an error, red with the red halo. Never an outline: that is keyboard focus's.\n// Choices (a selected card, row or swatch, the Stepper's current step) draw their own selected look, not this (D2).\nexport const ACTIVE_RING = \"border-[var(--ds-accent-ink)] ring-2 ring-[var(--ds-ring-active)]\";\n\nexport const ERROR_ACTIVE_RING = \"border-[var(--ds-status-error)] ring-2 ring-[var(--ds-ring-error)]\";\n\n// Body scroll lock is reference-counted so stacked overlays (a Dialog opened\n// from a Drawer, for example) only restore scrolling when the LAST one\n// closes. The original overflow value is captured on the first lock and put\n// back on the last unlock; an unbalanced unlock is clamped at zero.\nlet scrollLockCount = 0;\nlet scrollLockPreviousOverflow = \"\";\n\nexport function lockBodyScroll() {\n if (scrollLockCount === 0) {\n scrollLockPreviousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n }\n scrollLockCount++;\n}\n\nexport function unlockBodyScroll() {\n if (scrollLockCount === 0) return;\n scrollLockCount--;\n if (scrollLockCount === 0) {\n document.body.style.overflow = scrollLockPreviousOverflow;\n scrollLockPreviousOverflow = \"\";\n }\n}\n\n/** Test-only: current number of active locks. */\nexport function getBodyScrollLockCount() {\n return scrollLockCount;\n}\n","/** The last page language and visitor's languages read, and the locale they gave: formatting runs often, they change rarely. */\nlet last: { key: string; locale: string | undefined } | null = null;\n\n/**\n * The form a server-rendered page is written in without LocaleProvider, and what the library writes on a server where no\n * locale is given: an explicit locale, the same on every machine and on both sides of hydration (Sprint 25.20 D2).\n */\nexport const FIXED_FORM = \"en\";\n\n/**\n * The locale the library writes dates, times and numbers in: the app's language, the page's `lang`, in the visitor's own\n * formats where they speak it (Sprint 25.17, the owner's decision of 2 October). An English page shows \"5 minutes ago\"\n * and \"250K\" to a visitor whose browser is Japanese, where it showed \"5 分前\" and \"25万\" in a page of English (WCAG 3.1.2:\n * text in the page's language needs no `lang` of its own), and a British visitor to it keeps \"1 Oct 2026\". The visitor's\n * form counts only in the page's script: a page in traditional Chinese stays traditional for a visitor who reads\n * simplified. A page with no `lang` is written in the browser's language, as before. On a server, where there is no page,\n * English (\"en\"), never the machine's own language (Sprint 25.22's review): server code passes requestLocale's choice.\n */\nexport function formatLocale(): string | undefined {\n if (typeof document === \"undefined\") return FIXED_FORM;\n const page = document.documentElement.lang?.trim();\n if (!page) return undefined;\n return localeFor(page, browserLanguages());\n}\n\n/** The browser's languages, in its order (`navigator.languages`), or none where there is no browser. */\nexport function browserLanguages(): readonly string[] {\n if (typeof navigator === \"undefined\") return [];\n return navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];\n}\n\n/**\n * The locale for a page language and the languages a visitor speaks, in their order: the visitor's form of the page's\n * language where they speak it, else the page's own (Sprint 25.20: the same choice on a server, from the request's\n * languages, and in the browser). Undefined for a page language Intl can't read.\n */\nexport function localeFor(page: string, spoken: readonly string[]): string | undefined {\n const key = `${page}|${spoken.join(\",\")}`;\n if (last?.key !== key) last = { key, locale: choose(page, spoken) };\n return last.locale;\n}\n\n/** What a server-rendered app hands the library at its top: the page's language, and the visitor's from the request. */\nexport interface LocaleChoice {\n /** The page's language, as `<html lang>` says, or \"en\". */\n lang: string;\n /** The request's languages, in a browser's order; empty without the header. */\n spoken: string[];\n /** Whether the request's header was given. */\n hasHeader: boolean;\n /** The locale the server writes in, and the browser while it hydrates. */\n server: string;\n}\n\n/** What LocaleProvider hands down for a page language and a request's Accept-Language header. */\nexport function localeChoice(lang: string | undefined, acceptLanguage: string | null | undefined): LocaleChoice {\n const page = lang?.trim() || FIXED_FORM;\n const spoken = acceptedLanguages(acceptLanguage);\n return { lang: page, spoken, hasHeader: !!acceptLanguage, server: localeFor(page, spoken) ?? FIXED_FORM };\n}\n\n/**\n * The locale LocaleProvider writes in on the server for a page language and a request's Accept-Language header (Sprint\n * 25.22's review), for server code's own dates and numbers: a server page passes it to the helpers from\n * `gridsmith-ui/utils`, so its words read as the components' beside them. `requestLocale(LANG, (await\n * headers()).get('accept-language'))`.\n */\nexport function requestLocale(lang: string | undefined, acceptLanguage?: string | null): string {\n return localeChoice(lang, acceptLanguage).server;\n}\n\n/** The most of a request's languages read: browsers send a handful. */\nconst MAX_LANGUAGES = 20;\n\n/**\n * A request's `Accept-Language` header as the languages a browser lists (Sprint 25.20 L1): highest quality first, ties in\n * the header's order, \"*\" and anything with q=0 left out. \"en-GB,en;q=0.9,fr;q=0.8\" is [\"en-GB\", \"en\", \"fr\"].\n */\nexport function acceptedLanguages(header: string | null | undefined): string[] {\n if (!header) return [];\n const read: Array<{ tag: string; q: number; at: number }> = [];\n // a browser lists a handful; a header made up to be long reads no further than the first twenty (the review)\n header.split(\",\").slice(0, MAX_LANGUAGES).forEach((part, at) => {\n const [tag, ...params] = part.trim().split(\";\");\n const name = tag?.trim();\n if (!name || name === \"*\") return;\n const qParam = params.map((p) => p.trim()).find((p) => /^q=/i.test(p));\n const q = qParam ? Number(qParam.slice(2)) : 1;\n if (!(q > 0)) return;\n read.push({ tag: name, q, at });\n });\n return read.sort((a, b) => b.q - a.q || a.at - b.at).map((r) => r.tag);\n}\n\n/** The language and script a tag is written in: \"en\" and \"en-GB\" are both \"en-Latn\"; \"zh-TW\" is \"zh-Hant\", \"zh-CN\" \"zh-Hans\". */\nfunction writtenIn(tag: string): string | null {\n try {\n const locale = new Intl.Locale(tag).maximize();\n return `${locale.language}-${locale.script ?? \"\"}`;\n } catch {\n return null;\n }\n}\n\n/**\n * A visitor's tag as its language, script and region (Sprint 25.20's review): a request's header can carry private-use,\n * extension and variant parts (\"en-x-…\", \"en-GB-u-nu-thai\") that would change the digits a server writes and make every\n * cache keyed by locale grow with each new header. Read by syntax alone, so a server and a browser reduce a tag alike.\n */\nfunction plainTag(tag: string): string | undefined {\n try {\n const locale = new Intl.Locale(tag);\n return [locale.language, locale.script, locale.region].filter(Boolean).join(\"-\");\n } catch {\n return undefined;\n }\n}\n\nfunction choose(page: string, spoken: readonly string[]): string | undefined {\n const language = writtenIn(page);\n // a tag Intl can't read: the browser's language\n if (language === null) return undefined;\n // the visitor's own form of the page's language (\"en-GB\" for an \"en\" page), wherever it is in their list; else the page's\n const own = spoken.find((tag) => typeof tag === \"string\" && writtenIn(tag) === language);\n try {\n return Intl.getCanonicalLocales((own && plainTag(own)) || page)[0];\n } catch {\n return undefined;\n }\n}\n","/**\n * Keyboard moves for a calendar's day grid (Sprint 25.7, D14(b)): the APG date\n * picker's keys. Left and Right move a day, Up and Down a week, Home and End go\n * to the ends of the week, PageUp and PageDown move a month (Shift: a year) and\n * keep the day, clamped to the month's last day. All arithmetic is on calendar\n * days in local time, so a clock change never lands on the wrong day.\n */\n\nimport type { Weekday } from \"./week-start\";\nexport function addDays(d: Date, n: number): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);\n}\n\n/** The same day `n` months later, or the month's last day when it has fewer days (31 January + 1 month = 28 February). */\nexport function addMonthsClamped(d: Date, n: number): Date {\n const first = new Date(d.getFullYear(), d.getMonth() + n, 1);\n const last = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();\n return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(), last));\n}\n\nexport function sameDay(a: Date, b: Date): boolean {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n}\n\n/** A stable key for a day: YYYY-MM-DD in local time (the grid's data-grid-key). */\nexport function dayKey(d: Date): string {\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, \"0\")}-${String(d.getDate()).padStart(2, \"0\")}`;\n}\n\n/** Where a key moves the grid's focus from `from`, or null for a key the grid does not handle. */\nexport function moveDay(from: Date, key: string, shift: boolean, weekStartsOn: Weekday = 0): Date | null {\n const intoWeek = (from.getDay() - weekStartsOn + 7) % 7;\n switch (key) {\n case \"ArrowLeft\": return addDays(from, -1);\n case \"ArrowRight\": return addDays(from, 1);\n case \"ArrowUp\": return addDays(from, -7);\n case \"ArrowDown\": return addDays(from, 7);\n case \"Home\": return addDays(from, -intoWeek);\n case \"End\": return addDays(from, 6 - intoWeek);\n case \"PageUp\": return addMonthsClamped(from, shift ? -12 : -1);\n case \"PageDown\": return addMonthsClamped(from, shift ? 12 : 1);\n default: return null;\n }\n}\n","/**\n * Caches keyed by locale, each holding at most `limit` entries, the least recently used dropped first (Sprint 25.20's\n * fresh-eyes review). In a browser a page writes in one or two locales; on a server the locale comes from each request's\n * Accept-Language header, so a cache that never forgets grows with every visitor's language, and with headers made up to\n * grow it. Size a cache for its keys: a formatter keyed by locale and options holds about a dozen per locale.\n */\nconst caches = new Set<Map<string, unknown>>();\n\nexport function localeCache<V>(limit: number): (key: string, make: () => V) => V {\n const map = new Map<string, V>();\n caches.add(map as Map<string, unknown>);\n return (key, make) => {\n const hit = map.get(key);\n if (hit !== undefined) {\n // most recently used last\n map.delete(key);\n map.set(key, hit);\n return hit;\n }\n const made = make();\n map.set(key, made);\n if (map.size > limit) map.delete(map.keys().next().value as string);\n return made;\n };\n}\n\n/**\n * Empties every locale cache. For a test that renders a server's HTML and hydrates it in one process: a formatter made\n * without a time zone keeps the zone it was made in, so the browser's side starts with none of the server's.\n */\nexport function clearLocaleCaches(): void {\n for (const map of caches) map.clear();\n}\n\n/** The number of entries in each locale cache (tests). */\nexport function localeCacheSizes(): number[] {\n return Array.from(caches, (map) => map.size);\n}\n","import { formatLocale } from \"./format-locale\";\nimport { dayKey } from \"./date-grid\";\nimport { localeCache } from \"./locale-cache\";\nimport type { Weekday } from \"./week-start\";\n\n/**\n * How something repeats (Sprint 25.19 R1): the iCalendar standard's rule (RFC 5545 `RRULE`), in the subset Outlook's and\n * Google's menus write (P5), read in the event's local time. The quick choices are stored in the standard's implied form\n * (P6): a weekly rule with no `weekdays`, a monthly rule with no `day` or `nth` and a bare yearly rule repeat on the\n * start's own weekday, date or anniversary, so moving the event moves them. The event's own start is always its first\n * occurrence.\n */\nexport type RecurrenceFrequency = \"daily\" | \"weekly\" | \"monthly\" | \"yearly\";\n\n/** An nth weekday of a month: the first to the fourth, or the last (−1). A fifth weekday is the last. */\nexport type WeekOfMonth = 1 | 2 | 3 | 4 | -1;\n\nexport interface Recurrence {\n freq: RecurrenceFrequency;\n /** Every n days, weeks, months or years. Default 1. */\n interval?: number;\n /** Weekly: the days it repeats on, Sunday 0 to Saturday 6. Left out, the start's own weekday. */\n weekdays?: Weekday[];\n /** Monthly, or yearly with `month`: a day of the month, 1 to 31, or −1 for the last day. A month without the day is skipped. */\n day?: number;\n /** Monthly, or yearly with `month`: an nth weekday, `{ week: 1, weekday: 2 }` the first Tuesday. */\n nth?: { week: WeekOfMonth; weekday: Weekday };\n /** Yearly: the month, 1 to 12, with `day` or `nth`. A bare yearly rule repeats on the start's anniversary. */\n month?: number;\n /** The week's first day (WKST), which places a weekly rule's weeks. Default Monday, as RFC 5545 says. */\n weekStart?: Weekday;\n /**\n * The last moment it occurs. A date at midnight includes its whole day (\"until 30 November\"); an all-day event's is a\n * date. RecurrencePicker stores the end of the chosen day, which other apps read exactly. Left out with `count`, it\n * never ends. A rule read back from JSON may carry it as a string: the library reads it as the date it was.\n */\n until?: Date;\n /** How many times it occurs, the first included, and the excluded dates among them (RFC 5545). */\n count?: number;\n}\n\n/** The fields a repeating event carries; a Calendar event has them as `repeat` and `exceptions` (P12: never `recurrence`). */\nexport interface RepeatingEvent {\n id: string;\n start: Date;\n end?: Date;\n allDay?: boolean;\n /** The rule, or a rule string `parseRRule` reads (\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"). */\n repeat?: Recurrence | string;\n /** The dates left out, as day keys in local time (\"2026-10-20\"): the original date of each occurrence removed or moved. */\n exceptions?: string[];\n /**\n * On an occurrence, its series' id and its original date (a day key), as RFC 5545's RECURRENCE-ID links an edited\n * instance to its series. Each occurrence `occurrences` gives carries it, and so does an occurrence changed on its own\n * (\"This event\"), which the page stores under an id of its own: the series leaves the date out, and the edit helpers\n * find it by its link.\n */\n series?: { id: string; date: string };\n}\n\n/** Which occurrences a change or a deletion applies to: this one, it and the ones after it, or the whole series. */\nexport type RecurrenceScope = \"this\" | \"following\" | \"all\";\n\n/**\n * What a choice in RecurrenceScopeDialog does to the page's events: `events`, the list as it now is, for a page that\n * keeps its events in state; or `save`, the events to write (new or changed, each by its id), and `remove`, the ids to\n * delete, for a page that stores them elsewhere.\n */\nexport interface RepeatChange<T> {\n events: T[];\n save: T[];\n remove: string[];\n}\n\n/** One occurrence of a series: the event without its repeat fields, its own id, start and end, and where it came from. */\nexport type Occurrence<T extends RepeatingEvent> = Omit<T, \"repeat\" | \"exceptions\"> & {\n id: string;\n start: Date;\n end?: Date;\n /** The series' id and this occurrence's original date (a day key), which the edit helpers take. */\n series: { id: string; date: string };\n};\n\nconst DAY_CODES = [\"SU\", \"MO\", \"TU\", \"WE\", \"TH\", \"FR\", \"SA\"] as const;\nconst FREQS: Record<string, RecurrenceFrequency> = { DAILY: \"daily\", WEEKLY: \"weekly\", MONTHLY: \"monthly\", YEARLY: \"yearly\" };\nconst KNOWN_PARTS = new Set([\"FREQ\", \"INTERVAL\", \"WKST\", \"BYDAY\", \"BYSETPOS\", \"BYMONTHDAY\", \"BYMONTH\", \"UNTIL\", \"COUNT\"]);\n\nconst whole = (text: string | undefined): number | null => (text !== undefined && /^[+-]?\\d+$/.test(text) ? Number(text) : null);\n\n/** Plain days (\"TU,TH\"), in weekday order, or null for anything else (a number before a day, a repeat). */\nfunction plainDays(text: string): Weekday[] | null {\n const days = text.split(\",\").map((code) => DAY_CODES.indexOf(code as (typeof DAY_CODES)[number]));\n if (days.some((d) => d < 0) || new Set(days).size !== days.length) return null;\n return (days as Weekday[]).sort((a, b) => a - b);\n}\n\n/** An nth weekday: \"1TU\", \"-1FR\", or a plain day with BYSETPOS (Outlook's form); null for anything else. */\nfunction nthDay(byday: string, setpos: string | undefined): { week: WeekOfMonth; weekday: Weekday } | null {\n const m = /^([+-]?\\d)?(SU|MO|TU|WE|TH|FR|SA)$/.exec(byday);\n if (!m) return null;\n const week = m[1] !== undefined ? (setpos === undefined ? Number(m[1]) : NaN) : whole(setpos);\n if (week === null || ![1, 2, 3, 4, -1].includes(week)) return null;\n return { week: week as WeekOfMonth, weekday: DAY_CODES.indexOf(m[2] as (typeof DAY_CODES)[number]) as Weekday };\n}\n\n/** UNTIL as a date (its whole day), a floating date-time (local) or a UTC date-time. */\nfunction parseUntil(text: string): Date | null {\n const m = /^(\\d{4})(\\d{2})(\\d{2})(?:T(\\d{2})(\\d{2})(\\d{2})(Z)?)?$/.exec(text);\n if (!m) return null;\n const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];\n const date = m[4] === undefined ? new Date(y, mo, d) : m[7] ? new Date(Date.UTC(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]))) : new Date(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]));\n // a day the month doesn't have (20260231) rolls over into the next: not a date\n return Number.isNaN(date.getTime()) || (m[7] ? date.getUTCMonth() : date.getMonth()) !== mo ? null : date;\n}\n\n/**\n * The rule a string holds, or null when it is outside P5's subset (the event is then drawn once, its rule kept as written):\n * FREQ, INTERVAL and WKST; weekly BYDAY days; a monthly or yearly BYMONTHDAY, or one nth BYDAY (\"1TU\", or \"TU\" with\n * BYSETPOS=1); a yearly BYMONTH with either; UNTIL (a date, a floating or a UTC date-time) or COUNT. The \"RRULE:\" prefix\n * is optional. A daily rule with days (every weekday, as some apps write it) reads as weekly on them.\n */\nexport function parseRRule(text: string): Recurrence | null {\n if (typeof text !== \"string\") return null;\n const body = text.trim().replace(/^RRULE:/i, \"\");\n if (!body) return null;\n const parts = new Map<string, string>();\n for (const part of body.split(\";\")) {\n if (!part) continue;\n const at = part.indexOf(\"=\");\n const key = part.slice(0, at).toUpperCase();\n if (at <= 0 || parts.has(key) || !KNOWN_PARTS.has(key)) return null;\n parts.set(key, part.slice(at + 1).toUpperCase());\n }\n const freq = FREQS[parts.get(\"FREQ\") ?? \"\"];\n if (!freq) return null;\n const rule: Recurrence = { freq };\n if (parts.has(\"INTERVAL\")) {\n const n = whole(parts.get(\"INTERVAL\"));\n if (n === null || n < 1) return null;\n if (n > 1) rule.interval = n;\n }\n if (parts.has(\"WKST\")) {\n const d = DAY_CODES.indexOf(parts.get(\"WKST\") as (typeof DAY_CODES)[number]);\n if (d < 0) return null;\n if (d !== 1) rule.weekStart = d as Weekday;\n }\n if (parts.has(\"UNTIL\") && parts.has(\"COUNT\")) return null;\n if (parts.has(\"COUNT\")) {\n const n = whole(parts.get(\"COUNT\"));\n if (n === null || n < 1) return null;\n rule.count = n;\n }\n if (parts.has(\"UNTIL\")) {\n const until = parseUntil(parts.get(\"UNTIL\")!);\n if (!until) return null;\n rule.until = until;\n }\n const byday = parts.get(\"BYDAY\"), setpos = parts.get(\"BYSETPOS\"), monthday = parts.get(\"BYMONTHDAY\"), month = parts.get(\"BYMONTH\");\n if (freq === \"daily\" || freq === \"weekly\") {\n if (setpos !== undefined || monthday !== undefined || month !== undefined) return null;\n if (byday === undefined) return rule;\n if (freq === \"daily\" && rule.interval) return null;\n const days = plainDays(byday);\n if (!days) return null;\n return { ...rule, freq: \"weekly\", weekdays: days };\n }\n if (month !== undefined) {\n const m = whole(month);\n if (freq !== \"yearly\" || m === null || m < 1 || m > 12) return null;\n rule.month = m;\n }\n if (setpos !== undefined && byday === undefined) return null;\n if (byday !== undefined) {\n const nth = nthDay(byday, setpos);\n if (!nth || monthday !== undefined) return null;\n rule.nth = nth;\n } else if (monthday !== undefined) {\n const d = whole(monthday);\n if (d === null || !(d === -1 || (d >= 1 && d <= 31))) return null;\n rule.day = d;\n }\n // a yearly rule's day or weekday names its month, and a month names its day (the subset: no BYMONTH alone)\n if (freq === \"yearly\" && (rule.month === undefined) !== (rule.day === undefined && rule.nth === undefined)) return null;\n return rule;\n}\n\nconst pad = (n: number, width = 2) => String(n).padStart(width, \"0\");\n\n/**\n * The rule as an RRULE string, \"RRULE:FREQ=…\", for an iCalendar file or another app. UNTIL is written as a date for an\n * all-day event and in UTC for a timed one, as RFC 5545 asks.\n */\nexport function toRRule(rule: Recurrence, { allDay = false }: { allDay?: boolean } = {}): string {\n const out = [`FREQ=${rule.freq.toUpperCase()}`];\n if (rule.interval && rule.interval > 1) out.push(`INTERVAL=${rule.interval}`);\n if (rule.month !== undefined) out.push(`BYMONTH=${rule.month}`);\n if (rule.day !== undefined) out.push(`BYMONTHDAY=${rule.day}`);\n const weekStart = rule.weekStart ?? 1;\n if (rule.weekdays?.length) out.push(`BYDAY=${inWeekOrder(rule.weekdays, weekStart).map((d) => DAY_CODES[d]).join(\",\")}`);\n if (rule.nth) out.push(`BYDAY=${rule.nth.week}${DAY_CODES[rule.nth.weekday]}`);\n if (weekStart !== 1) out.push(`WKST=${DAY_CODES[weekStart]}`);\n if (rule.until) {\n const u = rule.until;\n out.push(allDay\n ? `UNTIL=${u.getFullYear()}${pad(u.getMonth() + 1)}${pad(u.getDate())}`\n : `UNTIL=${u.getUTCFullYear()}${pad(u.getUTCMonth() + 1)}${pad(u.getUTCDate())}T${pad(u.getUTCHours())}${pad(u.getUTCMinutes())}${pad(u.getUTCSeconds())}Z`);\n }\n if (rule.count !== undefined) out.push(`COUNT=${rule.count}`);\n return `RRULE:${out.join(\";\")}`;\n}\n\n/** The days from the week's first day: Monday-first [1, 2, …, 0]. */\nconst inWeekOrder = (days: readonly Weekday[], weekStart: Weekday) => [...days].sort((a, b) => ((a - weekStart + 7) % 7) - ((b - weekStart + 7) % 7));\n\n/**\n * A rule from a value: the object itself, the rule a string holds, or null for an unreadable string or none. A rule read\n * back from JSON (storage, an API) has its end as a string, which is read as the date it was; an end that isn't a date\n * makes the rule unreadable, so the event is drawn once rather than guessed at.\n */\nexport function readRecurrence(value: Recurrence | string | undefined | null): Recurrence | null {\n if (!value) return null;\n if (typeof value === \"string\") return parseRRule(value);\n if (value.until === undefined || value.until instanceof Date) return value;\n const until = new Date(value.until as unknown as string | number);\n return Number.isNaN(until.getTime()) ? null : { ...value, until };\n}\n\n// ── Dates by calendar arithmetic (P13: wall-clock times and whole days, never milliseconds) ──\n\nconst daysIn = (year: number, month: number) => new Date(year, month + 1, 0).getDate();\nconst atDay = (year: number, month: number, day: number, time: Date) => new Date(year, month, day, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());\nconst dayIndex = (d: Date) => Math.round(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / 864e5);\nconst isMidnight = (d: Date) => d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;\n\n/** The day of a month an nth weekday falls on, or null when there is none. */\nfunction nthWeekdayOf(year: number, month: number, week: WeekOfMonth, weekday: Weekday): number | null {\n const last = daysIn(year, month);\n if (week === -1) return last - ((new Date(year, month, last).getDay() - weekday + 7) % 7);\n const day = 1 + ((weekday - new Date(year, month, 1).getDay() + 7) % 7) + (week - 1) * 7;\n return day <= last ? day : null;\n}\n\n/** The nth weekday a date is: the last when it is in its month's last seven days (a fifth Tuesday is the last). */\nexport function nthOf(date: Date): { week: WeekOfMonth; weekday: Weekday } {\n const d = date.getDate();\n return { week: d + 7 > daysIn(date.getFullYear(), date.getMonth()) ? -1 : (Math.ceil(d / 7) as WeekOfMonth), weekday: date.getDay() as Weekday };\n}\n\n/**\n * Every nth weekday a date is, for the choices: its week of the month, first to fourth, and the last when it is in its\n * month's last seven days. A fourth Wednesday on the 28th is both, as Outlook and Google offer; a fifth is only the last.\n */\nexport function nthChoices(date: Date): Array<{ week: WeekOfMonth; weekday: Weekday }> {\n const d = date.getDate(), weekday = date.getDay() as Weekday;\n const out: Array<{ week: WeekOfMonth; weekday: Weekday }> = [];\n if (d <= 28) out.push({ week: Math.ceil(d / 7) as WeekOfMonth, weekday });\n if (d + 7 > daysIn(date.getFullYear(), date.getMonth())) out.push({ week: -1, weekday });\n return out;\n}\n\n/** The week of the month a rule's nth weekday keeps on a moved date: the last stays the last while the date is in its month's last seven days. */\nfunction weekOnMoved(week: WeekOfMonth, to: Date): WeekOfMonth {\n const d = to.getDate();\n if (week === -1 && d + 7 > daysIn(to.getFullYear(), to.getMonth())) return -1;\n return d <= 28 ? (Math.ceil(d / 7) as WeekOfMonth) : -1;\n}\n\n/** Whether an occurrence starting at `at` is within the rule's end: a date at midnight includes its whole day. */\nfunction withinUntil(at: Date, until: Date): boolean {\n return at <= until || (isMidnight(until) && dayIndex(at) === dayIndex(until));\n}\n\n/**\n * Each occurrence's start, in order, from the event's own start, until `stop` returns true for a start or the rule ends\n * (UNTIL, or COUNT, which counts the excluded dates too). Exceptions are not removed here.\n */\nfunction* starts(rule: Recurrence, first: Date): Generator<Date> {\n const interval = Math.max(1, Math.floor(rule.interval ?? 1));\n const firstDay = dayIndex(first);\n let produced = 0;\n const accept = (d: Date) => {\n if (rule.until && !withinUntil(d, rule.until)) return false;\n return rule.count === undefined || produced < rule.count;\n };\n // the start is always the first occurrence (RFC 5545), even when the rule's end comes before it\n if (rule.count !== undefined && rule.count < 1) return;\n produced++;\n yield first;\n const y0 = first.getFullYear(), m0 = first.getMonth();\n // a bound on the periods looked at: 400 years of days, so a rule that never matches ends\n for (let k = 0, empty = 0; k < 146_100 && empty < 400 * 12; k++) {\n const dates: Date[] = [];\n if (rule.freq === \"daily\") dates.push(atDay(y0, m0, first.getDate() + k * interval, first));\n else if (rule.freq === \"weekly\") {\n const weekStart = rule.weekStart ?? 1;\n const base = first.getDate() - ((first.getDay() - weekStart + 7) % 7) + k * interval * 7;\n for (const wd of inWeekOrder(rule.weekdays?.length ? rule.weekdays : [first.getDay() as Weekday], weekStart)) dates.push(atDay(y0, m0, base + ((wd - weekStart + 7) % 7), first));\n } else {\n const monthsFrom = rule.freq === \"monthly\" ? k * interval : k * interval * 12;\n const at = new Date(y0, m0 + monthsFrom, 1);\n const year = at.getFullYear(), month = rule.freq === \"yearly\" && rule.month !== undefined ? rule.month - 1 : at.getMonth();\n let day: number | null;\n if (rule.nth) day = nthWeekdayOf(year, month, rule.nth.week, rule.nth.weekday);\n else if (rule.day === -1) day = daysIn(year, month);\n else day = rule.day ?? first.getDate();\n if (day !== null && day <= daysIn(year, month)) dates.push(atDay(year, month, day, first));\n }\n let any = false;\n for (const d of dates) {\n if (dayIndex(d) <= firstDay) continue;\n if (!accept(d)) return;\n produced++;\n any = true;\n yield d;\n }\n empty = any ? 0 : empty + 1;\n }\n}\n\n/** The number of whole days an event runs over, and its end's time of day, so each occurrence keeps both (P13). */\nfunction lengthOf(event: RepeatingEvent): { days: number; end: Date } | null {\n return event.end ? { days: dayIndex(event.end) - dayIndex(event.start), end: event.end } : null;\n}\n\n/** An occurrence starting on `start`'s day: the event's times on that day, its id and where it came from. */\nfunction occurrenceAt<T extends RepeatingEvent>(event: T, start: Date): Occurrence<T> {\n const { repeat: _repeat, exceptions: _exceptions, ...rest } = event;\n const length = lengthOf(event);\n const date = dayKey(start);\n const end = length ? atDay(start.getFullYear(), start.getMonth(), start.getDate() + length.days, length.end) : undefined;\n return { ...rest, id: `${event.id}::${date}`, start, ...(end ? { end } : {}), series: { id: event.id, date } } as Occurrence<T>;\n}\n\n/** Where an occurrence stops, for overlap: an all-day event's last day included, a timed one's end, or an hour. */\nfunction stopOf(event: { start: Date; end?: Date; allDay?: boolean }): Date {\n if (event.allDay) {\n const last = event.end ?? event.start;\n return new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1);\n }\n return event.end ?? new Date(event.start.getTime() + 36e5);\n}\n\n/**\n * Every occurrence of a repeating event that overlaps [from, to), in order: the event without its repeat fields, each\n * with the id \"<id>::<date>\", its own start and end (the same wall-clock times and number of days) and `series`, its\n * original date. Its excluded dates are left out. An event that doesn't repeat, or whose rule can't be read, is itself,\n * when it overlaps.\n */\nexport function occurrences<T extends RepeatingEvent>(event: T, from: Date, to: Date): Array<T | Occurrence<T>> {\n const rule = readRecurrence(event.repeat);\n if (!rule) return event.start < to && stopOf(event) > from ? [event] : [];\n const skip = new Set(event.exceptions ?? []);\n // starting one event-length earlier, so an occurrence that began before the range and runs into it is found\n const reach = stopOf(event).getTime() - event.start.getTime();\n const out: Occurrence<T>[] = [];\n for (const start of starts(rule, event.start)) {\n if (start >= to) break;\n // a day of slack: across a clock change an occurrence is an hour longer or shorter than the event\n if (start.getTime() + reach + 864e5 <= from.getTime()) continue;\n if (skip.has(dayKey(start))) continue;\n const occurrence = occurrenceAt(event, start);\n if (stopOf(occurrence) > from) out.push(occurrence);\n }\n return out;\n}\n\n/** The original dates a series produces, excluded ones included, before a day (a day key): for COUNT when it splits. */\nfunction startsBefore(rule: Recurrence, first: Date, date: string): number {\n let n = 0;\n for (const start of starts(rule, first)) {\n if (dayKey(start) >= date) break;\n n++;\n }\n return n;\n}\n\n/** A series' rule written back in the form it came in: a string stays a string. */\nconst asWritten = (event: RepeatingEvent, rule: Recurrence): Recurrence | string => (typeof event.repeat === \"string\" ? toRRule(rule, { allDay: event.allDay }) : rule);\n\n/** Shifts a day key by whole days. */\nconst shiftKey = (key: string, days: number) => {\n const [y, m, d] = key.split(\"-\").map(Number);\n return dayKey(new Date(y, m - 1, d + days));\n};\n\n/** The occurrence a series would have on a day key, whether or not the rule gives that day. */\nconst occurrenceOnDay = <T extends RepeatingEvent>(series: T, date: string): Occurrence<T> => {\n const [y, m, d] = date.split(\"-\").map(Number);\n return occurrenceAt(series, atDay(y, m - 1, d, series.start));\n};\n\n/** The page's events changed on their own from a series (\"This event\"): the ones its id links to it. */\nconst editedOf = <T extends RepeatingEvent>(events: readonly T[], seriesId: string): T[] => events.filter((e) => e.series?.id === seriesId && e.id !== seriesId);\n\n/**\n * The occurrence of a series on a day (a day key), or undefined when it has none that day (the rule skips it, or it is\n * excluded): for a page whose Edit has an address of its own, which carries the series' id and the date. Given the\n * page's events, an occurrence changed on its own on that date (\"This event\") is found too.\n */\nexport function occurrenceOn<T extends RepeatingEvent>(series: T, date: string, events?: readonly T[]): Occurrence<T> | undefined {\n const edited = events && editedOf(events, series.id).find((e) => e.series!.date === date);\n if (edited) return edited as unknown as Occurrence<T>;\n const [y, m, d] = date.split(\"-\").map(Number);\n return occurrences(series, new Date(y, m - 1, d), new Date(y, m - 1, d + 1)).find((o): o is Occurrence<T> => \"series\" in o && (o as Occurrence<T>).series?.date === date);\n}\n\n/** The fields an edit carries onto an event: never its id, its series or, for a one-off, its repeat fields. */\nconst editOf = <T extends RepeatingEvent>(changes: Partial<T> | undefined): Partial<T> => {\n if (!changes) return {};\n const { id: _id, repeat: _repeat, exceptions: _exceptions, ...rest } = changes as Partial<T> & { series?: unknown };\n delete (rest as { series?: unknown }).series;\n return rest as Partial<T>;\n};\n\n/** Whether an edit changes the series' rule: its repeat given, and not the same rule (an unreadable string the same string). */\nconst repeatChanged = <T extends RepeatingEvent>(series: T, changes: Partial<T> | undefined): boolean => {\n if (!changes || !(\"repeat\" in changes)) return false;\n const given = changes.repeat;\n if (given === series.repeat) return false;\n const a = readRecurrence(given), b = readRecurrence(series.repeat);\n return !(a && b && sameRecurrence(a, b));\n};\n\n/** Whether two field values are the same: dates by their moment, lists and objects by what they hold. */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();\n if (a && b && typeof a === \"object\" && typeof b === \"object\") return JSON.stringify(a) === JSON.stringify(b);\n return a === b;\n}\n\n/**\n * What the user changed: the fields of `changes` that differ from the event they opened (an occurrence, or one changed on\n * its own before), and the repeat when it isn't the series' rule. A form that hands back every field then changes only\n * what the user changed, and an occurrence changed on its own never passes its own changes to its series.\n */\nfunction editFrom<T extends RepeatingEvent>(opened: Occurrence<T> | T, series: T, changes: Partial<T>): Partial<T> {\n const was = opened as unknown as Record<string, unknown>;\n const edit: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(editOf(changes))) if (!sameValue(value, was[key])) edit[key] = value;\n if (repeatChanged(series, changes)) edit.repeat = changes.repeat;\n return edit as Partial<T>;\n}\n\n/**\n * A rule re-anchored on a moved date, as the implied forms move with the start: a weekly rule's days turn by the move,\n * a month's day or nth weekday and a year's month become the moved date's.\n */\nfunction moveRule(rule: Recurrence, days: number, to: Date): Recurrence {\n const next: Recurrence = { ...rule };\n if (rule.weekdays?.length) next.weekdays = rule.weekdays.map((d) => ((((d + days) % 7) + 7) % 7) as Weekday).sort((a, b) => a - b);\n if (rule.freq === \"monthly\" || rule.freq === \"yearly\") {\n if (rule.nth) next.nth = { week: weekOnMoved(rule.nth.week, to), weekday: to.getDay() as Weekday };\n else if (rule.day === -1) { if (to.getDate() !== daysIn(to.getFullYear(), to.getMonth())) next.day = to.getDate(); }\n else if (rule.day !== undefined) next.day = to.getDate();\n if (rule.freq === \"yearly\" && rule.month !== undefined) next.month = to.getMonth() + 1;\n }\n return next;\n}\n\n/**\n * Where a date of a series (a day key) goes when the series moves by `days` and its rule with it: the moved rule's own\n * date nearest the date `days` later, within a week. That is the shifted date itself, except for an nth weekday, whose\n * moved date can be up to a week away (a first Tuesday on the 7th, a day later, is the first Wednesday, the 1st). A date\n * the moved rule has none near (a day 31 in a month without one) is simply shifted.\n */\nfunction onMovedRule(rule: Recurrence, start: Date, days: number): (key: string) => string {\n const endless: Recurrence = { ...rule, until: undefined, count: undefined };\n return (key) => {\n const shifted = shiftKey(key, days);\n const [y, m, d] = shifted.split(\"-\").map(Number);\n const target = dayIndex(new Date(y, m - 1, d));\n let found: Date | null = null;\n for (const at of starts(endless, start)) {\n const i = dayIndex(at);\n if (i > target + 7) break;\n if (i >= target - 7 && (!found || Math.abs(i - target) < Math.abs(dayIndex(found) - target))) found = at;\n }\n return found ? dayKey(found) : shifted;\n };\n}\n\n/** A time of day, the same to the millisecond. */\nconst sameClock = (a: Date, b: Date) => a.getHours() === b.getHours() && a.getMinutes() === b.getMinutes() && a.getSeconds() === b.getSeconds() && a.getMilliseconds() === b.getMilliseconds();\n/** The whole days an event's end is after its start's day, or null without an end. */\nconst spanOf = (event: { start: Date; end?: Date }) => (event.end ? dayIndex(event.end) - dayIndex(event.start) : null);\n\n/** A series after an edit to one of its occurrences (updateSeries), and where each of its dates (a day key) went. */\nfunction changeSeries<T extends RepeatingEvent>(series: T, occurrence: Occurrence<T> | T | string, changes: Partial<T>): { next: T; moveKey: (key: string) => string } {\n const at = typeof occurrence === \"string\" ? occurrenceOnDay(series, occurrence) : occurrence;\n const { start: newStart, end: newEnd, ...rest } = editOf(changes) as Partial<T>;\n const next: T = { ...series, ...rest };\n // a moved day moves the series as many days, and a changed time is its new time: each measured from the event the user\n // opened, so the times an occurrence changed on its own had never reach the series when only its day moves\n const moveBy = (from: Date, to: Date, base: Date) => atDay(base.getFullYear(), base.getMonth(), base.getDate() + dayIndex(to) - dayIndex(from), sameClock(to, from) ? base : to);\n let days = 0;\n if (newStart) {\n days = dayIndex(newStart) - dayIndex(at.start);\n next.start = moveBy(at.start, newStart, series.start);\n }\n if (newEnd) {\n const from = at.end ?? at.start;\n next.end = moveBy(from, newEnd, series.end ?? series.start);\n }\n const rule = readRecurrence(series.repeat);\n let moveKey = (key: string) => shiftKey(key, days);\n const moveExceptions = () => { if (days !== 0 && series.exceptions?.length) next.exceptions = series.exceptions.map(moveKey); };\n if (repeatChanged(series, changes)) {\n if (changes.repeat) { next.repeat = changes.repeat; moveExceptions(); }\n else { delete next.repeat; delete next.exceptions; }\n } else if (days !== 0 && rule && newStart) {\n const moved = moveRule(rule, days, newStart);\n next.repeat = asWritten(series, moved);\n // an nth weekday a day later isn't always that weekday's same nth (a month starting on the new weekday makes the\n // first Tuesday's next day the second Wednesday): the series starts on the moved rule's first date from its moved\n // start, so its start is one of its dates and no stray date is left\n if (moved.nth) {\n const from = next.start;\n const anchor = (k: number) => {\n const at = new Date(from.getFullYear() + (moved.freq === \"yearly\" ? k : 0), (moved.freq === \"yearly\" && moved.month !== undefined ? moved.month - 1 : from.getMonth()) + (moved.freq === \"monthly\" ? k : 0), 1);\n const d = nthWeekdayOf(at.getFullYear(), at.getMonth(), moved.nth!.week, moved.nth!.weekday) ?? nthWeekdayOf(at.getFullYear(), at.getMonth(), -1, moved.nth!.weekday)!;\n return atDay(at.getFullYear(), at.getMonth(), d, from);\n };\n let first = anchor(0);\n if (dayIndex(first) < dayIndex(from)) first = anchor(1);\n const extra = dayIndex(first) - dayIndex(from);\n if (extra) {\n next.start = first;\n if (next.end) next.end = atDay(next.end.getFullYear(), next.end.getMonth(), next.end.getDate() + extra, next.end);\n }\n }\n // each excluded date goes to the moved rule's own date, so the occurrence it left out stays left out\n moveKey = onMovedRule(moved, next.start, days);\n moveExceptions();\n }\n return { next, moveKey };\n}\n\n/**\n * \"This and following\", and where each of the new half's dates went: `at` is the event the user opened (an occurrence,\n * or one changed on its own), or its date, which a move of the time or the day is measured from.\n */\nfunction splitWith<T extends RepeatingEvent>(series: T, date: string, id: string, at: Occurrence<T> | T | string, changes?: Partial<T>): { before?: T; after: T; moveKey: (key: string) => string } {\n const rule = readRecurrence(series.repeat);\n const firstDate = dayKey(series.start);\n if (!rule || date <= firstDate) {\n if (!changes) return { after: series, moveKey: (key) => key };\n const { next, moveKey } = changeSeries(series, typeof at === \"string\" ? (at <= firstDate ? firstDate : at) : at, changes);\n return { after: next, moveKey };\n }\n const [y, m, d] = date.split(\"-\").map(Number);\n const first = occurrenceOnDay(series, date);\n const exceptions = series.exceptions ?? [];\n const counted = rule.count !== undefined ? startsBefore(rule, series.start, date) : 0;\n const beforeRule: Recurrence = { ...rule };\n if (rule.count !== undefined) beforeRule.count = counted;\n else {\n delete beforeRule.until;\n // the day before, all of it: a date for an all-day event, its last second for a timed one (other apps read it exactly)\n beforeRule.until = series.allDay ? new Date(y, m - 1, d - 1) : new Date(y, m - 1, d - 1, 23, 59, 59);\n }\n const afterRule: Recurrence = { ...rule };\n if (rule.count !== undefined) afterRule.count = rule.count - counted;\n const before = { ...series, repeat: asWritten(series, beforeRule), exceptions: exceptions.filter((x) => x < date) };\n const after = { ...series, id, start: first.start, ...(first.end ? { end: first.end } : {}), repeat: asWritten(series, afterRule), exceptions: exceptions.filter((x) => x >= date) };\n if (!changes) return { before, after, moveKey: (key) => key };\n // the edit's repeat is the whole series' rule unless the user changed it: then the new half keeps its share of COUNT\n const edit = repeatChanged(series, changes) ? changes : editOf(changes);\n const { next, moveKey } = changeSeries(after, typeof at === \"string\" ? date : at, edit);\n return { before, after: next, moveKey };\n}\n\n/**\n * \"This event\": the series with the occurrence's date excluded, and the occurrence as an event of its own, with no repeat,\n * linked to the series by `series` (the series' id and the date), for the page to save beside the series under `id`\n * (give it one of your own; the default, \"<series id>-<date>\", is never an occurrence's), with the user's changes. There\n * is never a second series. Pages use saveOccurrence, which also finds the events changed on their own before.\n */\nexport function detachOccurrence<T extends RepeatingEvent>(series: T, date: string, id = `${series.id}-${date}`, changes?: Partial<T>): { series: T; event: Omit<T, \"repeat\" | \"exceptions\"> } {\n return {\n series: { ...series, exceptions: [...new Set([...(series.exceptions ?? []), date])].sort() },\n event: { ...(occurrenceOnDay(series, date) as unknown as Omit<T, \"repeat\" | \"exceptions\">), ...(editOf(changes) as object), id },\n };\n}\n\n/**\n * \"This and following events\": the series ends the day before `date` and a new one starts at it, under `id`, taking the\n * excluded dates from it on. With COUNT, each half counts its own share of the occurrences. Split at its first\n * occurrence, the series is replaced: there is no `before`, and `after` keeps the series' id. Together the two produce\n * the same dates as the series did. `changes`, the user's edit to the occurrence on `date`, apply to the new series as\n * updateSeries applies them: a move of the time or the day moves it, and its rule with it; its share of a COUNT stays\n * unless the edit changes the rule, which is then saved as given. Pages use saveOccurrence, which also moves the events\n * changed on their own with the new series.\n */\nexport function splitSeries<T extends RepeatingEvent>(series: T, date: string, id: string, changes?: Partial<T>): { before?: T; after: T } {\n const { before, after } = splitWith(series, date, id, date, changes);\n return before ? { before, after } : { after };\n}\n\n/**\n * \"All events\": the series with the changes made to one occurrence (the occurrence, or its date as a day key). A change\n * of time or day moves the series' start by the same amount, so every earlier date stays (a series saved as the edited\n * occurrence would lose them), and the rule moves with it: a weekly rule's days, a month's day or nth weekday and a\n * year's month become the moved date's, and each excluded date moves to the moved rule's own date. A changed repeat is\n * saved as given (the field writes it for the moved date already); a repeat taken away leaves one event, at the series'\n * start. Other changes (a title, a room) apply as they are. Pages use saveOccurrence, which also carries the events\n * changed on their own.\n */\nexport function updateSeries<T extends RepeatingEvent>(series: T, occurrence: Occurrence<T> | T | string, changes: Partial<T>): T {\n return changeSeries(series, occurrence, changes).next;\n}\n\n// ── Events changed on their own, linked to their series (the owner's answer of 3 October 2026: build it now) ──\n\n/** The fields `follow` leaves to the series' own bookkeeping. */\nconst NOT_FOLLOWED = new Set([\"id\", \"series\", \"start\", \"end\", \"repeat\", \"exceptions\"]);\n\n/**\n * An event changed on its own, after its series changed: what it changed itself stays (a field, another day, other\n * times), and what it still had from the series follows it, from `was` (the series' occurrence on its date before the\n * change) to `now` (after it), as Outlook's edited occurrences keep their own changes.\n */\nfunction follow<T extends RepeatingEvent>(edited: T, was: Occurrence<T>, now: Occurrence<T>): T {\n const out = { ...edited } as Record<string, unknown>;\n const before = was as unknown as Record<string, unknown>, after = now as unknown as Record<string, unknown>;\n for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {\n if (NOT_FOLLOWED.has(key) || !sameValue(out[key], before[key])) continue;\n if (after[key] === undefined) delete out[key];\n else out[key] = after[key];\n }\n // when it happens: its day, and its times (the start's, the end's and the days between), each its own if it changed it\n const ownDay = dayIndex(edited.start) !== dayIndex(was.start);\n const ownTimes = !sameClock(edited.start, was.start) || spanOf(edited) !== spanOf(was) || (!!edited.end && !!was.end && !sameClock(edited.end, was.end));\n const day = ownDay ? edited.start : now.start;\n const times = ownTimes ? edited : now;\n const start = atDay(day.getFullYear(), day.getMonth(), day.getDate(), times.start);\n out.start = start;\n const span = spanOf(times);\n if (times.end && span !== null) out.end = atDay(start.getFullYear(), start.getMonth(), start.getDate() + span, times.end);\n else delete out.end;\n return out as T;\n}\n\n/**\n * A series' events changed on their own, after the series changed from `old` to `next`, its dates moved by `moveKey`:\n * each stays linked, its date moved with the series' dates, and follows the change; the one the user opened takes their\n * edit too. When the repeat changed they go, as Outlook's do, and their dates go back to the new rule.\n */\nfunction carry<T extends RepeatingEvent>(old: T, next: T, linked: T[], moveKey: (key: string) => string, changed: boolean, opened: T | undefined, edit: Partial<T>): { next: T; save: T[]; remove: string[] } {\n if (!linked.length) return { next, save: [], remove: [] };\n if (changed) {\n const freed = new Set(linked.map((e) => moveKey(e.series!.date)));\n return { next: next.exceptions ? { ...next, exceptions: next.exceptions.filter((x) => !freed.has(x)) } : next, save: [], remove: linked.map((e) => e.id) };\n }\n const save = linked.map((e) => {\n const date = moveKey(e.series!.date);\n const followed = follow(e, occurrenceOnDay(old, e.series!.date), occurrenceOnDay(next, date));\n return { ...followed, ...(e.id === opened?.id ? editOf(edit) : {}), series: { id: next.id, date } } as T;\n });\n return { next, save, remove: [] };\n}\n\n/** An occurrence's series among the page's events (one whose rule the library reads), the stored event when it is one changed on its own, and its date. */\nfunction findSeries<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T): { series?: T; stored?: T; date?: string } {\n const stored = events.find((e) => e.id === occurrence.id);\n const link = (stored ?? occurrence).series;\n const series = link ? events.find((e) => e.id === link.id && readRecurrence(e.repeat) !== null) : undefined;\n return { series, stored, date: link?.date };\n}\n\n/** The page's events with `save` written (each by its id, a new one at the end) and `remove` taken out. */\nfunction commit<T extends RepeatingEvent>(events: readonly T[], save: T[], remove: string[]): RepeatChange<T> {\n const gone = new Set(remove);\n const saved = new Map(save.map((e) => [e.id, e]));\n const had = new Set(events.map((e) => e.id));\n return { events: [...events.filter((e) => !gone.has(e.id)).map((e) => saved.get(e.id) ?? e), ...save.filter((e) => !had.has(e.id))], save, remove };\n}\n\n/**\n * Saves the user's edit to an occurrence, for the scope they chose in RecurrenceScopeDialog: the page stores what it\n * returns. `occurrence` is the event they opened, one the Calendar handed over or one changed on its own before (the\n * page's own); `changes` the form's fields, every one or only those changed (only what differs from the opened event\n * applies); `newId` an id of the page's, for the event or the series a choice makes.\n * - \"This event\": the occurrence becomes an event of its own, linked to its series by `series`, its date left out of the\n * series; one changed on its own before just takes the edit.\n * - \"This and following events\": the series ends the day before and a new one starts on the date, under `newId`, with\n * the edit; the events changed on their own from the date on go with it.\n * - \"All events\": the series takes the edit, and a moved time or day moves it and its rule, so every earlier date stays.\n * The events changed on their own keep what they changed themselves (a field, another day, other times) and follow the\n * rest. A changed repeat removes them, as Outlook does, and their dates go back to the new rule (RecurrenceScopeDialog's\n * `edited` says so first); a deleted date stays deleted.\n */\nexport function saveOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope, changes: Partial<T>, newId: string): RepeatChange<T> {\n const { series, stored, date } = findSeries(events, occurrence);\n // no series the library can read: the event itself, if it is the page's\n if (!series || date === undefined) return commit(events, stored ? [{ ...stored, ...editOf(changes) }] : [], []);\n const opened = stored ?? occurrenceOnDay(series, date);\n const edit = editFrom(opened, series, changes);\n if (scope === \"this\") {\n if (stored) return commit(events, [{ ...stored, ...editOf(edit) }], []);\n const { series: kept, event } = detachOccurrence(series, date, newId, edit);\n return commit(events, [kept, event as unknown as T], []);\n }\n const linked = editedOf(events, series.id);\n const changed = repeatChanged(series, edit);\n // from the series' first date, \"This and following\" is all of it\n if (scope === \"following\" && date > dayKey(series.start)) {\n const { before, after, moveKey } = splitWith(series, date, newId, opened, edit);\n const carried = carry(series, after, linked.filter((e) => e.series!.date >= date), moveKey, changed, stored, edit);\n return commit(events, [...(before ? [before] : []), carried.next, ...carried.save], carried.remove);\n }\n const { next, moveKey } = changeSeries(series, opened, edit);\n const carried = carry(series, next, linked, moveKey, changed, stored, edit);\n return commit(events, [carried.next, ...carried.save], carried.remove);\n}\n\n/**\n * Deletes an occurrence, for the scope the user chose in RecurrenceScopeDialog: the page stores what it returns. \"This\n * event\" leaves its date out of the series (an event changed on its own is removed, and its date stays empty); \"This\n * and following events\" ends the series the day before and removes the events changed on their own from the date on;\n * \"All events\" removes the series and every event changed on its own.\n */\nexport function deleteOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope): RepeatChange<T> {\n const { series, stored, date } = findSeries(events, occurrence);\n if (!series || date === undefined) return commit(events, [], stored ? [stored.id] : []);\n if (scope === \"this\") return stored ? commit(events, [], [stored.id]) : commit(events, [detachOccurrence(series, date).series], []);\n const linked = editedOf(events, series.id);\n if (scope === \"following\" && date > dayKey(series.start)) {\n const { before } = splitWith(series, date, series.id, date);\n return commit(events, before ? [before] : [], linked.filter((e) => e.series!.date >= date).map((e) => e.id));\n }\n return commit(events, [], [series.id, ...linked.map((e) => e.id)]);\n}\n\n/**\n * How many of a series' events changed on their own each scope covers, for RecurrenceScopeDialog's `edited`: \"This and\n * following events\" those from the occurrence's date on, \"All events\" every one.\n */\nexport function countEdited<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T): { following: number; all: number } {\n const { series, date } = findSeries(events, occurrence);\n if (!series || date === undefined) return { following: 0, all: 0 };\n const linked = editedOf(events, series.id);\n return { following: date > dayKey(series.start) ? linked.filter((e) => e.series!.date >= date).length : linked.length, all: linked.length };\n}\n\n// ── In words: names and dates in the page's language, the words the library's English (as 25.18's F2) ──\n\nconst formats = localeCache<Intl.DateTimeFormat>(128);\nfunction format(options: Intl.DateTimeFormatOptions, date: Date, locale: string | undefined): string {\n return formats(`${locale ?? \"\"}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options)).format(date);\n}\nconst weekdayName = (d: Weekday, locale: string | undefined) => format({ weekday: \"long\" }, new Date(2026, 0, 4 + d), locale);\nconst monthName = (m: number, locale: string | undefined) => format({ month: \"long\" }, new Date(2026, m - 1, 1), locale);\nconst ORDINAL: Record<WeekOfMonth, string> = { 1: \"first\", 2: \"second\", 3: \"third\", 4: \"fourth\", [-1]: \"last\" } as Record<WeekOfMonth, string>;\nconst list = (items: string[]) => (items.length < 2 ? items.join(\"\") : `${items.slice(0, -1).join(\", \")} and ${items[items.length - 1]}`);\nconst every = (n: number, one: string, many: string) => (n > 1 ? `Every ${n} ${many}` : `Every ${one}`);\n\n/**\n * The rule in words, for its date: \"Every week on Tuesday and Thursday, until 30 November 2026\", \"Every month on the\n * first Tuesday\", \"Every year on 6 October\". The days and dates are written in the locale given (a component's\n * useFormatLocale(), Sprint 25.20), else the browser's reading of the page's language.\n */\nexport function describeRecurrence(rule: Recurrence, start: Date, locale: string | undefined = formatLocale()): string {\n const n = Math.max(1, Math.floor(rule.interval ?? 1));\n const weekStart = rule.weekStart ?? 1;\n let text: string;\n if (rule.freq === \"daily\") text = every(n, \"day\", \"days\");\n else if (rule.freq === \"weekly\") {\n const days = inWeekOrder(rule.weekdays?.length ? rule.weekdays : [start.getDay() as Weekday], weekStart);\n if (days.length === 7) text = every(n, \"day\", \"weeks on every day\");\n else if (n === 1 && days.join() === \"1,2,3,4,5\") text = \"Every weekday (Monday to Friday)\";\n else text = `${every(n, \"week\", \"weeks\")} on ${list(days.map((d) => weekdayName(d, locale)))}`;\n } else {\n const nth = rule.nth ? `the ${ORDINAL[rule.nth.week]} ${weekdayName(rule.nth.weekday, locale)}` : undefined;\n if (rule.freq === \"monthly\") {\n const on = nth ?? (rule.day === -1 ? \"the last day\" : `day ${rule.day ?? start.getDate()}`);\n text = `${every(n, \"month\", \"months\")} on ${on}`;\n } else {\n const month = rule.month ?? start.getMonth() + 1;\n const on = nth ? `${nth} of ${monthName(month, locale)}` : rule.day === -1 ? `the last day of ${monthName(month, locale)}` : // a leap year, so 29 February reads as itself\n format({ day: \"numeric\", month: \"long\" }, new Date(2028, month - 1, rule.day ?? start.getDate()), locale);\n text = `${every(n, \"year\", \"years\")} on ${on}`;\n }\n }\n if (rule.until) text += `, until ${format({ day: \"numeric\", month: \"long\", year: \"numeric\" }, rule.until, locale)}`;\n else if (rule.count !== undefined) text += rule.count === 1 ? \", once\" : `, ${rule.count} times`;\n return text;\n}\n\nexport interface RecurrencePreset {\n /** The choice in words, as describeRecurrence writes it for the date. */\n label: string;\n rule: Recurrence;\n}\n\n/**\n * The quick choices for a date, each one including it (P6): every day; every weekday, for a weekday; every week on its\n * weekday; every month on its nth weekday (the fourth and \"the last\" both for a fourth one in a month's last seven days,\n * only \"the last\" for a fifth); every month on its date, and on the last day when it is one; every year on its\n * anniversary. The weekly, monthly-by-date and yearly choices are the\n * implied form, so they follow the date when the event moves.\n */\nexport function recurrencePresets(start: Date, locale: string | undefined = formatLocale()): RecurrencePreset[] {\n const rules: Recurrence[] = [{ freq: \"daily\" }];\n const weekday = start.getDay();\n if (weekday >= 1 && weekday <= 5) rules.push({ freq: \"weekly\", weekdays: [1, 2, 3, 4, 5] });\n rules.push({ freq: \"weekly\" }, ...nthChoices(start).map((nth): Recurrence => ({ freq: \"monthly\", nth })), { freq: \"monthly\" });\n if (start.getDate() === daysIn(start.getFullYear(), start.getMonth())) rules.push({ freq: \"monthly\", day: -1 });\n rules.push({ freq: \"yearly\" });\n return rules.map((rule) => ({ rule, label: describeRecurrence(rule, start, locale) }));\n}\n\n/** Whether two rules repeat the same way (an `until` compared by its moment). */\nexport function sameRecurrence(a: Recurrence | null | undefined, b: Recurrence | null | undefined): boolean {\n if (!a || !b) return a === b;\n const norm = (r: Recurrence) => toRRule({ ...r, weekdays: r.weekdays?.length ? [...r.weekdays].sort() : undefined });\n return norm(a) === norm(b);\n}\n","import { formatLocale } from \"./format-locale\";\n\n/**\n * Time zones by the browser's own names, and their offsets (Sprint 25.17 A28), apart from the TimezoneSelect component since\n * Sprint 25.22 so a server can call them: nothing here needs React. `gridsmith-ui/utils` exports canonicalTimeZone and\n * timeZoneOffset for server code; browserTimeZone reads the zone of whatever runs it, a server's own there.\n */\n\n/**\n * The browser's own name for a zone (Sprint 25.17 A28, R28-51): one browser always names a zone one way, so a stored\n * \"Asia/Calcutta\" and a listed \"Asia/Kolkata\" are one zone, with no alias table shipped. An id the browser doesn't know\n * stays as given.\n */\nexport function canonicalTimeZone(zone: string): string {\n try {\n return new Intl.DateTimeFormat(\"en-US\", { timeZone: zone }).resolvedOptions().timeZone;\n } catch {\n return zone;\n }\n}\n\n/** The browser's time zone, by its own name; \"UTC\" where the browser names none. On a server, the server's zone. */\nexport function browserTimeZone(): string {\n try {\n return canonicalTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\");\n } catch {\n return \"UTC\";\n }\n}\n\n/**\n * A zone's offset from UTC at an instant, as the locale given names it (\"GMT+1\", \"GMT-5\", \"GMT+5:30\"; a component's\n * useFormatLocale(), else the browser's reading): read at that instant, so it follows daylight saving.\n */\nexport function timeZoneOffset(zone: string, at: Date = new Date(), locale: string | undefined = formatLocale()): string {\n try {\n return new Intl.DateTimeFormat(locale, { timeZone: zone, timeZoneName: \"shortOffset\" }).formatToParts(at).find((p) => p.type === \"timeZoneName\")?.value ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/** Every zone the browser knows, each once by its own name, UTC always among them; UTC first, then by name. */\nexport function timeZones(): string[] {\n const listed = typeof Intl.supportedValuesOf === \"function\" ? Intl.supportedValuesOf(\"timeZone\") : [];\n const zones = [...new Set(listed.map(canonicalTimeZone))].filter((z) => z !== \"UTC\").sort((a, b) => a.localeCompare(b));\n return [\"UTC\", ...zones];\n}\n","import { formatLocale } from \"./format-locale\";\nimport { localeCache } from \"./locale-cache\";\n\n/**\n * Calendar days, and ranges of them in words (Sprint 25.7, Part D). A calendar day is a whole-number day index: days since\n * 1970-01-01, counted on UTC day boundaries, so every day is the same width and a clock change never stretches or shrinks\n * one. A \"YYYY-MM-DD\" string is a calendar day in the user's zone and is never parsed as UTC (new Date(\"2026-03-03\") is\n * 2 March, 19:00 in New York). Apart from the time scale (lib/time-scale.ts) since Sprint 25.22, so a server can call\n * them: nothing here needs React or a browser, and `gridsmith-ui/utils` exports them for server code. On a server a Date\n * or a date-time string is read in the server's time zone; a calendar day or a day index is the same everywhere.\n */\n\n/** A Date, or a string: \"YYYY-MM-DD\" is a calendar day; any other string is a date-time. */\nexport type DateInput = Date | string;\nexport type TimeZoom = \"day\" | \"week\" | \"month\" | \"quarter\";\n/** Narrow to wide. */\nexport const TIME_ZOOMS: readonly TimeZoom[] = [\"day\", \"week\", \"month\", \"quarter\"];\n\nexport const DAY_MS = 86_400_000;\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport const utcDay = (y: number, m: number, d: number) => Math.round(Date.UTC(y, m, d) / DAY_MS);\n\nfunction dayOfDate(d: Date): number {\n const t = d.getTime();\n if (Number.isNaN(t)) return NaN;\n const day = utcDay(d.getFullYear(), d.getMonth(), d.getDate());\n // The first instant of the local day is the whole day, also where a clock change skips midnight (Chile, Cuba, Egypt\n // and Lebanon in spring): there a date picker's \"midnight\" is 01:00.\n const first = new Date(t);\n first.setHours(0, 0, 0, 0);\n if (first.getTime() === t) return day;\n const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1000 + d.getMilliseconds();\n return day + ms / DAY_MS;\n}\n\n/**\n * The day index of a date: \"2026-03-03\" → that calendar day's index; a Date or a date-time string → its local calendar\n * day plus the fraction of the day its local clock shows (a day's first instant is the whole day); a number is a day\n * index already, as the scale's own functions take it. NaN for anything else: null from JSON, a string that is no date.\n */\nexport function dayOf(value: DateInput | number): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : NaN;\n if (value instanceof Date) return dayOfDate(value);\n if (typeof value !== \"string\") return NaN;\n const m = DATE_ONLY.exec(value.trim());\n if (!m) return dayOfDate(new Date(value));\n const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];\n const day = utcDay(y, mo, d);\n const back = new Date(day * DAY_MS);\n return back.getUTCFullYear() === y && back.getUTCMonth() === mo && back.getUTCDate() === d ? day : NaN;\n}\n\n/** Local midnight of that calendar day; a fraction adds that much of the day on the local clock. */\nexport function dateOfDay(day: number): Date {\n const whole = Math.floor(day);\n const u = new Date(whole * DAY_MS);\n return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));\n}\n\n/**\n * Whether a value is read in the visitor's time zone (Sprint 25.20 D3): a Date, or a date string with a time of day, whose\n * local day a server doesn't know. A calendar day (\"2026-03-03\") and a day index are the same everywhere.\n */\nexport function isZoned(value: DateInput | number | null | undefined): boolean {\n if (value instanceof Date) return !Number.isNaN(value.getTime());\n if (typeof value !== \"string\") return false;\n const text = value.trim();\n return !DATE_ONLY.test(text) && !Number.isNaN(new Date(text).getTime());\n}\n\n/** A whole day: a \"YYYY-MM-DD\" string, a Date at the start of its local day or a whole day index. */\nfunction isWholeDay(value: DateInput | number): boolean {\n return typeof value === \"string\" ? DATE_ONLY.test(value.trim()) : Number.isInteger(dayOf(value));\n}\n\n/**\n * Where a range that ends at `value` stops. A whole-day end is inclusive: \"2026-03-14\" (or a Date at local midnight,\n * as the date pickers give) → the start of 15 March. A date-time end is half-open: it stops at that moment, as a day\n * index does. A range's start can make a midnight Date half-open too (scale.span, formatDateRange, timeExtent).\n */\nexport function endDayOf(value: DateInput | number): number {\n const day = dayOf(value);\n return typeof value !== \"number\" && isWholeDay(value) ? day + 1 : day;\n}\n\n/**\n * Where a range from `start` stops at `end`. A Date at local midnight is an inclusive whole day after a whole-day start\n * (a date picker's range), and the moment the range stops after a time of day (an evening shift that ends at midnight).\n */\nexport function rangeEnd(start: DateInput | number, end: DateInput | number): number {\n return end instanceof Date && !isWholeDay(start) ? dayOf(end) : endDayOf(end);\n}\n\n// ─── Formats ────────────────────────────────────────────────────────────────\n\nconst formats = localeCache<Intl.DateTimeFormat>(128);\n\n/**\n * A formatter for calendar days in the locale, else the page's language (formatLocale). Day indices are UTC days, so they\n * are formatted in UTC.\n */\nexport function dayFormatter(given: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const locale = given ?? formatLocale();\n return formats(`${locale ?? \"\"}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, { ...options, timeZone: \"UTC\" }));\n}\n\n// ─── Ranges ─────────────────────────────────────────────────────────────────\n\n/**\n * The earliest start and the latest end of some ranges, as day indices for useTimeScale: the end is where the last\n * range stops (inclusive for a whole day, as endDayOf), and a range with no end ends where it starts (a milestone).\n * NaN for no dated range, which the scale shows as today. A range, a start or an end that is null is skipped.\n */\nexport function timeExtent(ranges: Iterable<{ start: DateInput; end?: DateInput }>): { start: number; end: number } {\n let start = Infinity;\n let end = -Infinity;\n for (const r of ranges) {\n if (r == null) continue;\n const s = dayOf(r.start);\n const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);\n if (Number.isFinite(s)) start = Math.min(start, s);\n if (Number.isFinite(e)) end = Math.max(end, e);\n }\n return Number.isFinite(start) && Number.isFinite(end) ? { start, end: Math.max(start, end) } : { start: NaN, end: NaN };\n}\n\nexport interface DateRangeWords {\n locale?: string;\n /** Joins the two ends in place of Intl's separator. Default \" to \" in English, and Intl's own separator elsewhere. */\n to?: string;\n /** Intl options for the days. Default { day: \"numeric\", month: \"long\" }; the year is added when the ends' years differ. */\n day?: Intl.DateTimeFormatOptions;\n /** Intl options for the times of a date-time range. Default { hour: \"2-digit\", minute: \"2-digit\" }. */\n time?: Intl.DateTimeFormatOptions;\n}\n\nconst DAY_WORDS: Intl.DateTimeFormatOptions = { day: \"numeric\", month: \"long\" };\nconst TIME_WORDS: Intl.DateTimeFormatOptions = { hour: \"2-digit\", minute: \"2-digit\" };\n\n/** A range's own separator: a dash or a tilde, and the spaces either side of it. */\nconst SEPARATOR = /\\s*[\\u2010-\\u2015\\u2212~\\uff5e\\u301c-]\\s*/;\n\nconst english = (f: Intl.DateTimeFormat) => new Intl.Locale(f.resolvedOptions().locale).language === \"en\";\n\n/**\n * `f` over two instants. With `to`, only the separator between the ends is replaced: the literal there can carry the\n * start's own closing mark too (ja-JP's \")~\", de-DE's \".–\"), which stays.\n */\nfunction range(f: Intl.DateTimeFormat, a: Date, b: Date, to: string | undefined): string {\n if (typeof f.formatRangeToParts !== \"function\") return to === undefined ? f.formatRange(a, b) : `${f.format(a)}${to}${f.format(b)}`;\n const parts = f.formatRangeToParts(a, b);\n const lastOfStart = parts.map((p) => p.source).lastIndexOf(\"startRange\");\n const firstOfEnd = parts.findIndex((p) => p.source === \"endRange\");\n // Intl names one day once when the two are the same instant in its terms\n if (lastOfStart < 0 || firstOfEnd < 0) return f.format(a);\n if (to === undefined) return parts.map((p) => p.value).join(\"\");\n let joined = false;\n const out = parts.map((p, i) => {\n if (joined || i <= lastOfStart || i >= firstOfEnd || !SEPARATOR.test(p.value)) return p.value;\n joined = true;\n return p.value.replace(SEPARATOR, to);\n });\n // no separator between the ends to replace: `to` goes after the start\n if (!joined) out.splice(lastOfStart + 1, 0, to);\n return out.join(\"\");\n}\n\n/**\n * A range in words, in the locale, for accessible names: \"3 to 14 March\", \"28 September to 3 October\", \"16 September\"\n * for one day. The end is inclusive for a whole day, as scale.span (a day index is where the range stops). A date-time\n * range is named by its times, and the end's day only when it differs: \"Friday 23 October, 06:00 to 14:00\". Intl\n * joins each day and time in the locale's own way, and outside English the two ends too (\"10/31(土曜日)~11/01(日曜日)\");\n * the year shows when the two ends are in different years. A null end is the start's own day; a start that is no date\n * gives \"\".\n */\nexport function formatDateRange(start: DateInput | number, end?: DateInput | number, words?: DateRangeWords): string {\n const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};\n const until = end ?? start;\n const from = dayOf(start);\n const stop = rangeEnd(start, until);\n if (!Number.isFinite(from) || !Number.isFinite(stop)) return \"\";\n const timed = !isWholeDay(start) || !isWholeDay(until);\n const first = timed ? from : Math.floor(from);\n const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);\n const a = new Date(first * DAY_MS);\n const b = new Date(last * DAY_MS);\n const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === undefined;\n const f = dayFormatter(locale, { ...day, ...(years ? { year: \"numeric\" } : {}), ...(timed ? time : {}) });\n return first === last ? f.format(a) : range(f, a, b, to ?? (english(f) ? \" to \" : undefined));\n}\n","/**\n * Sprint 25.9, A3 — what a chart's category axis holds, and how its labels fit. No Recharts here: the charts entry and\n * the tests import it, and it never measures on its own (the measurer is handed in).\n *\n * - `categoryKind(labels)`: \"scale\" when every non-empty label is a date, a time, a period or a number, else \"names\".\n * Anchored patterns only — never `Date.parse`, which V8 lets read \"Tier 1\", \"Sprint 1\" and \"Northern Region 2\" as dates.\n * - `createAxisMeasurer(el)`: canvas text widths in the axis's resolved font, read from a probe that carries\n * `font-size: var(--ds-font-size-xs)`, so a `calc()` token (`calc(16px * .75)`, a 14 px base) measures right.\n * - `fitLabel(name, width, measure)`: one line; else two lines split at a space; else \"…\" on the second. Never drops it.\n */\n\nexport type CategoryKind = \"names\" | \"scale\";\n\n/** A text's width in px in the axis font. */\nexport type Measure = (text: string) => number;\n\nconst ENGLISH_MONTHS = [\n \"january\", \"february\", \"march\", \"april\", \"may\", \"june\", \"july\", \"august\", \"september\", \"october\", \"november\", \"december\",\n \"jan\", \"feb\", \"mar\", \"apr\", \"jun\", \"jul\", \"aug\", \"sep\", \"sept\", \"oct\", \"nov\", \"dec\",\n];\nconst ENGLISH_WEEKDAYS = [\n \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\", \"sunday\",\n \"mon\", \"tue\", \"tues\", \"wed\", \"thu\", \"thur\", \"thurs\", \"fri\", \"sat\", \"sun\",\n];\n\nconst escape = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\nconst clean = (s: string) => s.trim().toLowerCase().replace(/\\.$/, \"\");\n\nfunction intlNames(locale: string, kind: \"month\" | \"weekday\"): string[] {\n const out: string[] = [];\n try {\n for (const width of [\"short\", \"long\"] as const) {\n const fmt = new Intl.DateTimeFormat(locale, kind === \"month\" ? { month: width, timeZone: \"UTC\" } : { weekday: width, timeZone: \"UTC\" });\n // 2026-01-05 is a Monday: seven days give the weekdays, the 15th of each month the months\n const count = kind === \"month\" ? 12 : 7;\n for (let i = 0; i < count; i++) {\n const date = kind === \"month\" ? new Date(Date.UTC(2026, i, 15)) : new Date(Date.UTC(2026, 0, 5 + i));\n out.push(clean(fmt.format(date)));\n }\n }\n } catch {\n // an unknown locale tag: English covers it\n }\n return out;\n}\n\n/**\n * The languages whose month and weekday names count: English, and the locale given (a chart's locale while a\n * server-rendered page hydrates, the same on both sides: Sprint 25.20); with none given, the runtime's, the browser's and\n * the page's, as an app's own call and a chart in the browser read them (labels in the visitor's own language count).\n */\nfunction locales(given?: string): string[] {\n const out = new Set<string>([\"en\"]);\n if (given !== undefined) {\n out.add(given);\n return [...out];\n }\n try { out.add(new Intl.DateTimeFormat().resolvedOptions().locale); } catch { /* no Intl locale */ }\n if (typeof navigator !== \"undefined\" && navigator.language) out.add(navigator.language);\n if (typeof document !== \"undefined\" && document.documentElement?.lang) out.add(document.documentElement.lang);\n return [...out];\n}\n\ninterface Patterns { key: string; list: RegExp[] }\nlet cached: Patterns | null = null;\n\nfunction patterns(given?: string): Patterns {\n const tags = locales(given);\n const key = tags.join(\"|\");\n if (cached?.key === key) return cached;\n const months = new Set(ENGLISH_MONTHS);\n const weekdays = new Set(ENGLISH_WEEKDAYS);\n for (const tag of tags) {\n for (const m of intlNames(tag, \"month\")) if (m) months.add(m);\n for (const d of intlNames(tag, \"weekday\")) if (d) weekdays.add(d);\n }\n // the longest first, so \"sept\" wins over \"sep\" and \"june\" over \"jun\"\n const alt = (set: Set<string>) => [...set].sort((a, b) => b.length - a.length).map(escape).join(\"|\");\n const M = `(?:${alt(months)})\\\\.?`;\n const D = `(?:${alt(weekdays)})\\\\.?`;\n const day = String.raw`\\d{1,2}(?:st|nd|rd|th|\\.)?`;\n const year = String.raw`'?\\d{2,4}`;\n const list = [\n // dates in digits: 2026-09-21, 21/09, 09/21/2026, 21.09.2026, an ISO date-time\n /^\\d{4}[-/.]\\d{1,2}(?:[-/.]\\d{1,2})?$/,\n /^\\d{1,2}[-/.]\\d{1,2}(?:[-/.]\\d{2,4})?$/,\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{1,2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/,\n // a day and a month in either order, and a month alone or with its year: 16 Sep, 21. Sept., Sept 21, March 2026\n new RegExp(`^${day}\\\\s*${M}(?:,?\\\\s+${year})?$`, \"iu\"),\n new RegExp(`^${M}\\\\s*${day}(?:,?\\\\s+${year})?$`, \"iu\"),\n new RegExp(`^${M}(?:\\\\s*${year})?$`, \"iu\"),\n // CJK dates: 9月21日, 2026年9月, 9월 21일\n /^(?:\\d{4}年)?\\d{1,2}月(?:\\d{1,2}日)?$/u,\n /^\\d{4}年(?:\\d{1,2}月)?$/u,\n /^(?:\\d{4}년\\s?)?\\d{1,2}월(?:\\s?\\d{1,2}일)?$/u,\n // a quarter or a half: Q3, Q3 2026, Q3 FY26, 2026 Q3, 3Q26, H1 2026\n /^Q[1-4](?:\\s*[-/']?\\s*(?:FY\\s?)?'?\\d{2,4})?$/i,\n /^[1-4]Q\\s*'?\\d{0,4}$/i,\n /^(?:FY\\s?)?'?\\d{2,4}\\s*[-/]?\\s*Q[1-4]$/i,\n /^H[12](?:\\s*'?\\d{2,4})?$/i,\n // a year or a fiscal year: 2026, FY26, FY 2025/26, 2025/26, 2025-2026\n /^(?:19|20)\\d{2}$/,\n /^FY\\s?'?\\d{2,4}(?:\\s?[-/]\\s?'?\\d{2,4})?$/i,\n /^(?:19|20)\\d{2}\\s?[-/–]\\s?(?:(?:19|20)?\\d{2})$/,\n // a week: W12, Wk 3, Week 12, Week 12 2026, 2026-W12\n /^(?:W|Wk|Week)\\.?\\s?\\d{1,2}(?:\\s*[,/-]?\\s*\\d{4})?$/i,\n /^\\d{4}-?W\\d{1,2}(?:-?\\d)?$/i,\n // a weekday: Mon, Tuesday, and the runtime and page locales' own\n new RegExp(`^${D}$`, \"iu\"),\n // a time: 09:00, 9:30 pm, 9am, 14h\n /^\\d{1,2}:\\d{2}(?::\\d{2})?\\s?(?:[ap]\\.?m\\.?)?$/i,\n /^\\d{1,2}\\s?[ap]\\.?m\\.?$/i,\n /^\\d{1,2}h(?:\\d{2})?$/i,\n // a number, a percentage or an amount: 12, -3.5, 1,200, 12%, $5k, €1.2m, 5 €, a bin (10–20, <10, 50+)\n /^[<>≤≥~]?\\s?[+\\-−]?\\s?[$€£¥₹]?\\s?\\d[\\d,. \\u00a0\\u202f]*(?:\\s?(?:k|m|mn|bn|b|t))?\\s?(?:%|[$€£¥₹])?\\+?$/iu,\n /^[$€£¥₹]?\\d[\\d,.]*\\s?[-–]\\s?[$€£¥₹]?\\d[\\d,.]*\\s?(?:k|m|bn|%)?$/iu,\n ];\n cached = { key, list };\n return cached;\n}\n\n/**\n * Whether a category axis holds names or a scale (dates, times, periods, numbers). Every non-empty label must match an\n * anchored pattern to be \"scale\"; an all-empty set is \"scale\". LineChart and AreaChart are always \"scale\"; BarChart and\n * CompositeChart guess with this, and their `categoryKind` prop overrides the guess.\n */\nexport function categoryKind(labels: ReadonlyArray<unknown>, locale?: string): CategoryKind {\n const { list } = patterns(locale);\n for (const raw of labels) {\n if (raw == null) continue;\n if (typeof raw === \"number\") { if (Number.isFinite(raw)) continue; return \"names\"; }\n if (raw instanceof Date) continue;\n const text = String(raw).trim();\n if (!text) continue;\n if (!list.some((re) => re.test(text))) return \"names\";\n }\n return \"scale\";\n}\n\n/* ── Measuring ──────────────────────────────────────────────────────────── */\n\n/** The axis font as the page resolves it: size and family from a probe carrying the chart's tick tokens. */\nexport function resolvedAxisFont(el: Element): { font: string; px: number } {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n let probe = el.querySelector<HTMLElement>(\"[data-chart-probe]\");\n let temporary = false;\n if (!probe) {\n probe = doc.createElement(\"span\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n probe.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none;white-space:nowrap;font-size:var(--ds-font-size-xs);font-family:var(--ds-font-sans)\";\n el.appendChild(probe);\n temporary = true;\n }\n const cs = view?.getComputedStyle(probe);\n const px = parseFloat(cs?.fontSize ?? \"\") || 12;\n const family = (cs?.fontFamily ?? \"\").trim() || \"sans-serif\";\n const style = cs?.fontStyle && cs.fontStyle !== \"normal\" ? `${cs.fontStyle} ` : \"\";\n const weight = cs?.fontWeight && cs.fontWeight !== \"400\" && cs.fontWeight !== \"normal\" ? `${cs.fontWeight} ` : \"\";\n if (temporary) probe.remove();\n return { font: `${style}${weight}${px}px ${family}`, px };\n}\n\n/** One 2D context for every chart, kept per getContext implementation (a test may swap it for a stub). */\nlet shared: { getContext: unknown; ctx: CanvasRenderingContext2D | null } | null = null;\n\nfunction canvasContext(): CanvasRenderingContext2D | null {\n if (typeof document === \"undefined\") return null;\n const getContext = (globalThis as { HTMLCanvasElement?: { prototype: { getContext?: unknown } } }).HTMLCanvasElement?.prototype.getContext;\n if (shared && shared.getContext === getContext) return shared.ctx;\n let ctx: CanvasRenderingContext2D | null = null;\n try { ctx = document.createElement(\"canvas\").getContext?.(\"2d\") ?? null; } catch { ctx = null; }\n shared = { getContext, ctx };\n return ctx;\n}\n\n/**\n * A text measurer in the chart's own axis font, or null where there is no canvas (jsdom): the charts then show every\n * label in full on one line and leave the thinning to nobody.\n */\nexport function createAxisMeasurer(el: Element): { measure: Measure; px: number; font: string } | null {\n const ctx = canvasContext();\n if (!ctx) return null;\n const { font, px } = resolvedAxisFont(el);\n ctx.font = font;\n const widths = new Map<string, number>();\n const measure: Measure = (text) => {\n let w = widths.get(text);\n if (w === undefined) {\n // the context is shared: another chart may have set its own font since\n ctx.font = font;\n w = ctx.measureText(text).width;\n widths.set(text, w);\n }\n return w;\n };\n return { measure, px, font };\n}\n\n/* ── Fitting a name ─────────────────────────────────────────────────────── */\n\nexport const ELLIPSIS = \"…\";\n\nexport interface FittedLabel {\n /** One or two lines; the second ends with \"…\" when the name was cut. */\n lines: string[];\n cut: boolean;\n /** Characters of the name that show, spaces and the ellipsis left out. */\n shown: number;\n}\n\nconst letters = (s: string) => s.replace(/\\s+/g, \"\").replace(/…/g, \"\").length;\n\n/** The longest prefix of `text` that fits `width` (at least one character). */\nfunction prefixThatFits(text: string, width: number, measure: Measure, suffix = \"\"): number {\n let lo = 1;\n let hi = text.length;\n let best = 0;\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n if (measure(text.slice(0, mid).trimEnd() + suffix) <= width) { best = mid; lo = mid + 1; } else hi = mid - 1;\n }\n return best;\n}\n\n/**\n * A name fitted to `width`: one line when it fits; else two lines split at a space; else the second line ends with \"…\".\n * A first word wider than the line breaks where the line ends, with a hyphen, so it reads as one word going on. The\n * name is never dropped, and without a measurer it shows in full on one line.\n */\nexport function fitLabel(name: string, width: number, measure: Measure | null): FittedLabel {\n const text = name.replace(/\\s+/g, \" \").trim();\n if (!measure || !text || width <= 0 || measure(text) <= width) return { lines: [text], cut: false, shown: letters(text) };\n const words = text.split(\" \");\n let first = \"\";\n let firstShown = \"\";\n let rest = \"\";\n for (let i = words.length - 1; i >= 1; i--) {\n const candidate = words.slice(0, i).join(\" \");\n if (measure(candidate) <= width) { first = firstShown = candidate; rest = words.slice(i).join(\" \"); break; }\n }\n if (!first) {\n // the first word alone is too wide: the first line holds what fits of it and a hyphen\n const k = Math.max(1, prefixThatFits(text, width, measure, \"-\"));\n firstShown = text.slice(0, k).trimEnd();\n rest = text.slice(k).trimStart();\n first = rest && !text.slice(k - 1, k + 1).includes(\" \") ? `${firstShown}-` : firstShown;\n }\n if (!rest) return { lines: [first], cut: false, shown: letters(firstShown) };\n if (measure(rest) <= width) return { lines: [first, rest], cut: false, shown: letters(firstShown) + letters(rest) };\n const k = prefixThatFits(rest, width, measure, ELLIPSIS);\n const kept = k > 0 ? rest.slice(0, k).trimEnd() : \"\";\n return { lines: [first, kept + ELLIPSIS], cut: true, shown: letters(firstShown) + letters(kept) };\n}\n\n/** D8: fewer visible characters than this on a cut name turns an upright chart of names sideways. */\nexport const MIN_NAME_CHARS = 6;\n\n/** Whether any name, fitted to `width`, would be cut to fewer than MIN_NAME_CHARS characters. */\nexport function namesCutShort(names: ReadonlyArray<string>, width: number, measure: Measure): boolean {\n return names.some((n) => {\n const fit = fitLabel(n, width, measure);\n return fit.cut && fit.shown < MIN_NAME_CHARS;\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../showcase/src/lib/utils.ts","../../../showcase/src/lib/format-locale.ts","../../../showcase/src/lib/date-grid.ts","../../../showcase/src/lib/locale-cache.ts","../../../showcase/src/lib/recurrence.ts","../../../showcase/src/lib/time-zones.ts","../../../showcase/src/lib/time-days.ts","../../../showcase/src/lib/chart-categories.ts"],"names":["last","at","next","moveKey","carried","whole","formats","list"],"mappings":";;;;AAGO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;AAEO,IAAM,cAAA,GAAiB;AAEvB,IAAM,aAAA,GAAgB,GAAG,cAAc,CAAA,qDAAA;AAEvC,IAAM,aAAA,GAAgB,GAAG,cAAc,CAAA,sDAAA;AAevC,IAAM,cAAA,GAAiB,GAAG,cAAc,CAAA,yDAAA;AAWxC,IAAM,UAAA,GAAa;AAOnB,IAAM,iBAAA,GAAoB;AAE1B,IAAM,cAAA,GAAiB;AAOvB,IAAM,eAAA,GAAkB;AAExB,IAAM,gBAAA,GAAmB;AAUzB,IAAM,WAAA,GAAc;AA0BpB,IAAM,gBAAA,GAAmB;AAEzB,IAAM,uBAAA,GAA0B;AAEhC,IAAM,oBAAA,GAAuB;AAG7B,IAAM,gBAAA,GAAmB;AAEzB,IAAM,uBAAA,GAA0B;AAEhC,IAAM,oBAAA,GAAuB;AAK7B,IAAM,WAAA,GAAc;AAEpB,IAAM,iBAAA,GAAoB;;;AC5GjC,IAAI,IAAA,GAA2D,IAAA;AAMxD,IAAM,UAAA,GAAa,IAAA;AAWnB,SAAS,YAAA,GAAmC;AACjD,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,UAAA;AAC5C,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,eAAA,CAAgB,IAAA,EAAM,IAAA,EAAK;AACjD,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,OAAO,SAAA,CAAU,IAAA,EAAM,gBAAA,EAAkB,CAAA;AAC3C;AAGO,SAAS,gBAAA,GAAsC;AACpD,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,EAAa,OAAO,EAAC;AAC9C,EAAA,OAAO,SAAA,CAAU,SAAA,EAAW,MAAA,GAAS,SAAA,CAAU,SAAA,GAAY,SAAA,CAAU,QAAA,GAAW,CAAC,SAAA,CAAU,QAAQ,CAAA,GAAI,EAAC;AAC1G;AAOO,SAAS,SAAA,CAAU,MAAc,MAAA,EAA+C;AACrF,EAAA,MAAM,MAAM,CAAA,EAAG,IAAI,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACvC,EAAA,IAAI,IAAA,EAAM,GAAA,KAAQ,GAAA,EAAK,IAAA,GAAO,EAAE,KAAK,MAAA,EAAQ,MAAA,CAAO,IAAA,EAAM,MAAM,CAAA,EAAE;AAClE,EAAA,OAAO,IAAA,CAAK,MAAA;AACd;AAeO,SAAS,YAAA,CAAa,MAA0B,cAAA,EAAyD;AAC9G,EAAA,MAAM,IAAA,GAAO,IAAA,EAAM,IAAA,EAAK,IAAK,UAAA;AAC7B,EAAA,MAAM,MAAA,GAAS,kBAAkB,cAAc,CAAA;AAC/C,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,CAAC,CAAC,cAAA,EAAgB,MAAA,EAAQ,SAAA,CAAU,IAAA,EAAM,MAAM,KAAK,UAAA,EAAW;AAC1G;AAQO,SAAS,aAAA,CAAc,MAA0B,cAAA,EAAwC;AAC9F,EAAA,OAAO,YAAA,CAAa,IAAA,EAAM,cAAc,CAAA,CAAE,MAAA;AAC5C;AAGA,IAAM,aAAA,GAAgB,EAAA;AAMf,SAAS,kBAAkB,MAAA,EAA6C;AAC7E,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AACrB,EAAA,MAAM,OAAsD,EAAC;AAE7D,EAAA,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,aAAa,CAAA,CAAE,OAAA,CAAQ,CAAC,IAAA,EAAM,EAAA,KAAO;AAC9D,IAAA,MAAM,CAAC,KAAK,GAAG,MAAM,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,GAAG,CAAA;AAC9C,IAAA,MAAM,IAAA,GAAO,KAAK,IAAA,EAAK;AACvB,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,KAAS,GAAA,EAAK;AAC3B,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,KAAK,CAAC,CAAA,KAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAC,CAAA;AACrE,IAAA,MAAM,IAAI,MAAA,GAAS,MAAA,CAAO,OAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,CAAA;AAC7C,IAAA,IAAI,EAAE,IAAI,CAAA,CAAA,EAAI;AACd,IAAA,IAAA,CAAK,KAAK,EAAE,GAAA,EAAK,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA;AAAA,EAChC,CAAC,CAAA;AACD,EAAA,OAAO,KAAK,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA,IAAK,CAAA,CAAE,EAAA,GAAK,EAAE,EAAE,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,EAAE,GAAG,CAAA;AACvE;AAGA,SAAS,UAAU,GAAA,EAA4B;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,IAAI,IAAA,CAAK,MAAA,CAAO,GAAG,EAAE,QAAA,EAAS;AAC7C,IAAA,OAAO,GAAG,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,EAAE,CAAA,CAAA;AAAA,EAClD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOA,SAAS,SAAS,GAAA,EAAiC;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA;AAClC,IAAA,OAAO,CAAC,MAAA,CAAO,QAAA,EAAU,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,EACjF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,MAAA,CAAO,MAAc,MAAA,EAA+C;AAC3E,EAAA,MAAM,QAAA,GAAW,UAAU,IAAI,CAAA;AAE/B,EAAA,IAAI,QAAA,KAAa,MAAM,OAAO,MAAA;AAE9B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,CAAC,GAAA,KAAQ,OAAO,GAAA,KAAQ,QAAA,IAAY,SAAA,CAAU,GAAG,CAAA,KAAM,QAAQ,CAAA;AACvF,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,oBAAqB,GAAA,IAAO,QAAA,CAAS,GAAG,CAAA,IAAM,IAAI,EAAE,CAAC,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;ACxGO,SAAS,OAAO,CAAA,EAAiB;AACtC,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,WAAA,EAAa,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,QAAA,EAAS,GAAI,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAChH;;;ACrBA,IAAM,MAAA,uBAAa,GAAA,EAA0B;AAEtC,SAAS,YAAe,KAAA,EAAkD;AAC/E,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAe;AAC/B,EAAA,MAAA,CAAO,IAAI,GAA2B,CAAA;AACtC,EAAA,OAAO,CAAC,KAAK,IAAA,KAAS;AACpB,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACvB,IAAA,IAAI,QAAQ,MAAA,EAAW;AAErB,MAAA,GAAA,CAAI,OAAO,GAAG,CAAA;AACd,MAAA,GAAA,CAAI,GAAA,CAAI,KAAK,GAAG,CAAA;AAChB,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,MAAM,OAAO,IAAA,EAAK;AAClB,IAAA,GAAA,CAAI,GAAA,CAAI,KAAK,IAAI,CAAA;AACjB,IAAA,IAAI,GAAA,CAAI,IAAA,GAAO,KAAA,EAAO,GAAA,CAAI,MAAA,CAAO,IAAI,IAAA,EAAK,CAAE,IAAA,EAAK,CAAE,KAAe,CAAA;AAClE,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF;;;AC2DA,IAAM,SAAA,GAAY,CAAC,IAAA,EAAM,IAAA,EAAM,MAAM,IAAA,EAAM,IAAA,EAAM,MAAM,IAAI,CAAA;AAC3D,IAAM,KAAA,GAA6C,EAAE,KAAA,EAAO,OAAA,EAAS,QAAQ,QAAA,EAAU,OAAA,EAAS,SAAA,EAAW,MAAA,EAAQ,QAAA,EAAS;AAC5H,IAAM,WAAA,mBAAc,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,OAAA,EAAS,UAAA,EAAY,YAAA,EAAc,SAAA,EAAW,OAAA,EAAS,OAAO,CAAC,CAAA;AAExH,IAAM,KAAA,GAAQ,CAAC,IAAA,KAA6C,IAAA,KAAS,MAAA,IAAa,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,GAAI,MAAA,CAAO,IAAI,CAAA,GAAI,IAAA;AAG3H,SAAS,UAAU,IAAA,EAAgC;AACjD,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,SAAA,CAAU,OAAA,CAAQ,IAAkC,CAAC,CAAA;AAChG,EAAA,IAAI,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,KAAM,IAAI,CAAC,CAAA,IAAK,IAAI,GAAA,CAAI,IAAI,CAAA,CAAE,IAAA,KAAS,IAAA,CAAK,QAAQ,OAAO,IAAA;AAC1E,EAAA,OAAQ,KAAmB,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AACjD;AAGA,SAAS,MAAA,CAAO,OAAe,MAAA,EAA4E;AACzG,EAAA,MAAM,CAAA,GAAI,oCAAA,CAAqC,IAAA,CAAK,KAAK,CAAA;AACzD,EAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,CAAC,CAAA,KAAM,SAAa,MAAA,KAAW,MAAA,GAAY,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAA,GAAO,MAAM,MAAM,CAAA;AAC5F,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,CAAC,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA,CAAE,QAAA,CAAS,IAAI,GAAG,OAAO,IAAA;AAC9D,EAAA,OAAO,EAAE,MAA2B,OAAA,EAAS,SAAA,CAAU,QAAQ,CAAA,CAAE,CAAC,CAA+B,CAAA,EAAa;AAChH;AAGA,SAAS,WAAW,IAAA,EAA2B;AAC7C,EAAA,MAAM,CAAA,GAAI,wDAAA,CAAyD,IAAA,CAAK,IAAI,CAAA;AAC5E,EAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,EAAA,MAAM,CAAC,GAAG,EAAA,EAAI,CAAC,IAAI,CAAC,MAAA,CAAO,EAAE,CAAC,CAAC,GAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAChE,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,CAAC,CAAA,KAAM,MAAA,GAAY,IAAI,IAAA,CAAK,CAAA,EAAG,EAAA,EAAI,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,IAAI,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAC,CAAC,CAAA,GAAI,IAAI,IAAA,CAAK,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAElM,EAAA,OAAO,OAAO,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,MAAM,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,aAAY,GAAI,IAAA,CAAK,QAAA,EAAS,MAAO,KAAK,IAAA,GAAO,IAAA;AACvG;AAQO,SAAS,WAAW,IAAA,EAAiC;AAC1D,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,EAAK,CAAE,OAAA,CAAQ,YAAY,EAAE,CAAA;AAC/C,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAoB;AACtC,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,EAAG;AAClC,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC3B,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,WAAA,EAAY;AAC1C,IAAA,IAAI,EAAA,IAAM,CAAA,IAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,IAAK,CAAC,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,IAAA;AAC/D,IAAA,KAAA,CAAM,GAAA,CAAI,KAAK,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA,CAAE,aAAa,CAAA;AAAA,EACjD;AACA,EAAA,MAAM,OAAO,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,MAAM,KAAK,EAAE,CAAA;AAC1C,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,IAAA,GAAmB,EAAE,IAAA,EAAK;AAChC,EAAA,IAAI,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA,EAAG;AACzB,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,UAAU,CAAC,CAAA;AACrC,IAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,GAAI,CAAA,EAAG,OAAO,IAAA;AAChC,IAAA,IAAI,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,QAAA,GAAW,CAAA;AAAA,EAC7B;AACA,EAAA,IAAI,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,SAAA,CAAU,OAAA,CAAQ,KAAA,CAAM,GAAA,CAAI,MAAM,CAA+B,CAAA;AAC3E,IAAA,IAAI,CAAA,GAAI,GAAG,OAAO,IAAA;AAClB,IAAA,IAAI,CAAA,KAAM,CAAA,EAAG,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,EAChC;AACA,EAAA,IAAI,KAAA,CAAM,IAAI,OAAO,CAAA,IAAK,MAAM,GAAA,CAAI,OAAO,GAAG,OAAO,IAAA;AACrD,EAAA,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AACtB,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,OAAO,CAAC,CAAA;AAClC,IAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,GAAI,CAAA,EAAG,OAAO,IAAA;AAChC,IAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AAAA,EACf;AACA,EAAA,IAAI,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG;AACtB,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAA,CAAI,OAAO,CAAE,CAAA;AAC5C,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AACA,EAAA,MAAM,QAAQ,KAAA,CAAM,GAAA,CAAI,OAAO,CAAA,EAAG,MAAA,GAAS,MAAM,GAAA,CAAI,UAAU,CAAA,EAAG,QAAA,GAAW,MAAM,GAAA,CAAI,YAAY,GAAG,KAAA,GAAQ,KAAA,CAAM,IAAI,SAAS,CAAA;AACjI,EAAA,IAAI,IAAA,KAAS,OAAA,IAAW,IAAA,KAAS,QAAA,EAAU;AACzC,IAAA,IAAI,WAAW,MAAA,IAAa,QAAA,KAAa,MAAA,IAAa,KAAA,KAAU,QAAW,OAAO,IAAA;AAClF,IAAA,IAAI,KAAA,KAAU,QAAW,OAAO,IAAA;AAChC,IAAA,IAAI,IAAA,KAAS,OAAA,IAAW,IAAA,CAAK,QAAA,EAAU,OAAO,IAAA;AAC9C,IAAA,MAAM,IAAA,GAAO,UAAU,KAAK,CAAA;AAC5B,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,UAAU,IAAA,EAAK;AAAA,EACnD;AACA,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,CAAA,GAAI,MAAM,KAAK,CAAA;AACrB,IAAA,IAAI,IAAA,KAAS,YAAY,CAAA,KAAM,IAAA,IAAQ,IAAI,CAAA,IAAK,CAAA,GAAI,IAAI,OAAO,IAAA;AAC/D,IAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AAAA,EACf;AACA,EAAA,IAAI,MAAA,KAAW,MAAA,IAAa,KAAA,KAAU,MAAA,EAAW,OAAO,IAAA;AACxD,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAChC,IAAA,IAAI,CAAC,GAAA,IAAO,QAAA,KAAa,MAAA,EAAW,OAAO,IAAA;AAC3C,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AAAA,EACb,CAAA,MAAA,IAAW,aAAa,MAAA,EAAW;AACjC,IAAA,MAAM,CAAA,GAAI,MAAM,QAAQ,CAAA;AACxB,IAAA,IAAI,CAAA,KAAM,QAAQ,EAAE,CAAA,KAAM,MAAO,CAAA,IAAK,CAAA,IAAK,CAAA,IAAK,EAAA,CAAA,EAAM,OAAO,IAAA;AAC7D,IAAA,IAAA,CAAK,GAAA,GAAM,CAAA;AAAA,EACb;AAEA,EAAA,IAAI,IAAA,KAAS,QAAA,IAAa,IAAA,CAAK,KAAA,KAAU,MAAA,MAAgB,IAAA,CAAK,GAAA,KAAQ,MAAA,IAAa,IAAA,CAAK,GAAA,KAAQ,MAAA,CAAA,EAAY,OAAO,IAAA;AACnH,EAAA,OAAO,IAAA;AACT;AAEA,IAAM,GAAA,GAAM,CAAC,CAAA,EAAW,KAAA,GAAQ,CAAA,KAAM,OAAO,CAAC,CAAA,CAAE,QAAA,CAAS,KAAA,EAAO,GAAG,CAAA;AAM5D,SAAS,QAAQ,IAAA,EAAkB,EAAE,SAAS,KAAA,EAAM,GAA0B,EAAC,EAAW;AAC/F,EAAA,MAAM,MAAM,CAAC,CAAA,KAAA,EAAQ,KAAK,IAAA,CAAK,WAAA,EAAa,CAAA,CAAE,CAAA;AAC9C,EAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,QAAA,GAAW,CAAA,MAAO,IAAA,CAAK,CAAA,SAAA,EAAY,IAAA,CAAK,QAAQ,CAAA,CAAE,CAAA;AAC5E,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW,GAAA,CAAI,KAAK,CAAA,QAAA,EAAW,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAC9D,EAAA,IAAI,IAAA,CAAK,QAAQ,MAAA,EAAW,GAAA,CAAI,KAAK,CAAA,WAAA,EAAc,IAAA,CAAK,GAAG,CAAA,CAAE,CAAA;AAC7D,EAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,CAAA;AACpC,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ,GAAA,CAAI,KAAK,CAAA,MAAA,EAAS,WAAA,CAAY,KAAK,QAAA,EAAU,SAAS,EAAE,GAAA,CAAI,CAAC,MAAM,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAE,CAAA;AACvH,EAAA,IAAI,IAAA,CAAK,GAAA,EAAK,GAAA,CAAI,IAAA,CAAK,SAAS,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,GAAA,CAAI,OAAO,CAAC,CAAA,CAAE,CAAA;AAC7E,EAAA,IAAI,SAAA,KAAc,GAAG,GAAA,CAAI,IAAA,CAAK,QAAQ,SAAA,CAAU,SAAS,CAAC,CAAA,CAAE,CAAA;AAC5D,EAAA,IAAI,KAAK,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,IAAA,CAAK,KAAA;AACf,IAAA,GAAA,CAAI,IAAA,CAAK,MAAA,GACL,CAAA,MAAA,EAAS,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,QAAA,EAAS,GAAI,CAAC,CAAC,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,OAAA,EAAS,CAAC,CAAA,CAAA,GACnE,CAAA,MAAA,EAAS,CAAA,CAAE,cAAA,EAAgB,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,aAAY,GAAI,CAAC,CAAC,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,UAAA,EAAY,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,aAAA,EAAe,CAAC,CAAA,EAAG,GAAA,CAAI,CAAA,CAAE,aAAA,EAAe,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/J;AACA,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAW,GAAA,CAAI,KAAK,CAAA,MAAA,EAAS,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAC5D,EAAA,OAAO,CAAA,MAAA,EAAS,GAAA,CAAI,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAC/B;AAGA,IAAM,cAAc,CAAC,IAAA,EAA0B,cAAuB,CAAC,GAAG,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAA,CAAQ,IAAI,SAAA,GAAY,CAAA,IAAK,KAAO,CAAA,GAAI,SAAA,GAAY,KAAK,CAAE,CAAA;AAO7I,SAAS,eAAe,KAAA,EAAkE;AAC/F,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,WAAW,KAAK,CAAA;AACtD,EAAA,IAAI,MAAM,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,KAAA,YAAiB,MAAM,OAAO,KAAA;AACrE,EAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,KAAmC,CAAA;AAChE,EAAA,OAAO,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS,IAAI,IAAA,GAAO,EAAE,GAAG,KAAA,EAAO,KAAA,EAAM;AAClE;AAIA,IAAM,MAAA,GAAS,CAAC,IAAA,EAAc,KAAA,KAAkB,IAAI,IAAA,CAAK,IAAA,EAAM,KAAA,GAAQ,CAAA,EAAG,CAAC,CAAA,CAAE,OAAA,EAAQ;AACrF,IAAM,KAAA,GAAQ,CAAC,IAAA,EAAc,KAAA,EAAe,KAAa,IAAA,KAAe,IAAI,IAAA,CAAK,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,KAAK,QAAA,EAAS,EAAG,KAAK,UAAA,EAAW,EAAG,KAAK,UAAA,EAAW,EAAG,IAAA,CAAK,eAAA,EAAiB,CAAA;AAChL,IAAM,WAAW,CAAC,CAAA,KAAY,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,CAAI,CAAA,CAAE,WAAA,EAAY,EAAG,EAAE,QAAA,EAAS,EAAG,EAAE,OAAA,EAAS,IAAI,KAAK,CAAA;AACrG,IAAM,aAAa,CAAC,CAAA,KAAY,CAAA,CAAE,QAAA,OAAe,CAAA,IAAK,CAAA,CAAE,UAAA,EAAW,KAAM,KAAK,CAAA,CAAE,UAAA,OAAiB,CAAA,IAAK,CAAA,CAAE,iBAAgB,KAAM,CAAA;AAG9H,SAAS,YAAA,CAAa,IAAA,EAAc,KAAA,EAAe,IAAA,EAAmB,OAAA,EAAiC;AACrG,EAAA,MAAMA,KAAAA,GAAO,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA;AAC/B,EAAA,IAAI,IAAA,KAAS,EAAA,EAAI,OAAOA,KAAAA,GAAAA,CAAS,IAAI,IAAA,CAAK,IAAA,EAAM,KAAA,EAAOA,KAAI,CAAA,CAAE,MAAA,EAAO,GAAI,UAAU,CAAA,IAAK,CAAA;AACvF,EAAA,MAAM,GAAA,GAAM,CAAA,GAAA,CAAM,OAAA,GAAU,IAAI,KAAK,IAAA,EAAM,KAAA,EAAO,CAAC,CAAA,CAAE,MAAA,EAAO,GAAI,CAAA,IAAK,CAAA,GAAA,CAAM,OAAO,CAAA,IAAK,CAAA;AACvF,EAAA,OAAO,GAAA,IAAOA,QAAO,GAAA,GAAM,IAAA;AAC7B;AAGO,SAAS,MAAM,IAAA,EAAqD;AACzE,EAAA,MAAM,CAAA,GAAI,KAAK,OAAA,EAAQ;AACvB,EAAA,OAAO,EAAE,MAAM,CAAA,GAAI,CAAA,GAAI,OAAO,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,QAAA,EAAU,CAAA,GAAI,EAAA,GAAM,KAAK,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,EAAmB,OAAA,EAAS,IAAA,CAAK,MAAA,EAAO,EAAa;AACjJ;AAMO,SAAS,WAAW,IAAA,EAA4D;AACrF,EAAA,MAAM,IAAI,IAAA,CAAK,OAAA,EAAQ,EAAG,OAAA,GAAU,KAAK,MAAA,EAAO;AAChD,EAAA,MAAM,MAAsD,EAAC;AAC7D,EAAA,IAAI,CAAA,IAAK,EAAA,EAAI,GAAA,CAAI,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,EAAkB,OAAA,EAAS,CAAA;AACxE,EAAA,IAAI,IAAI,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,QAAA,EAAU,CAAA,MAAO,IAAA,CAAK,EAAE,IAAA,EAAM,EAAA,EAAI,SAAS,CAAA;AACvF,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,WAAA,CAAY,MAAmB,EAAA,EAAuB;AAC7D,EAAA,MAAM,CAAA,GAAI,GAAG,OAAA,EAAQ;AACrB,EAAA,IAAI,IAAA,KAAS,EAAA,IAAM,CAAA,GAAI,CAAA,GAAI,MAAA,CAAO,EAAA,CAAG,WAAA,EAAY,EAAG,EAAA,CAAG,QAAA,EAAU,CAAA,EAAG,OAAO,EAAA;AAC3E,EAAA,OAAO,KAAK,EAAA,GAAM,IAAA,CAAK,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAoB,EAAA;AACvD;AAGA,SAAS,WAAA,CAAY,IAAU,KAAA,EAAsB;AACnD,EAAA,OAAO,EAAA,IAAM,SAAU,UAAA,CAAW,KAAK,KAAK,QAAA,CAAS,EAAE,CAAA,KAAM,QAAA,CAAS,KAAK,CAAA;AAC7E;AAMA,UAAU,MAAA,CAAO,MAAkB,KAAA,EAA8B;AAC/D,EAAA,MAAM,QAAA,GAAW,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,IAAY,CAAC,CAAC,CAAA;AAC3D,EAAA,MAAM,QAAA,GAAW,SAAS,KAAK,CAAA;AAC/B,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAY;AAC1B,IAAA,IAAI,IAAA,CAAK,SAAS,CAAC,WAAA,CAAY,GAAG,IAAA,CAAK,KAAK,GAAG,OAAO,KAAA;AACtD,IAAA,OAAO,IAAA,CAAK,KAAA,KAAU,MAAA,IAAa,QAAA,GAAW,IAAA,CAAK,KAAA;AAAA,EACrD,CAAA;AAEA,EAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,IAAa,IAAA,CAAK,QAAQ,CAAA,EAAG;AAChD,EAAA,QAAA,EAAA;AACA,EAAA,MAAM,KAAA;AACN,EAAA,MAAM,KAAK,KAAA,CAAM,WAAA,EAAY,EAAG,EAAA,GAAK,MAAM,QAAA,EAAS;AAEpD,EAAA,KAAA,IAAS,CAAA,GAAI,GAAG,KAAA,GAAQ,CAAA,EAAG,IAAI,MAAA,IAAW,KAAA,GAAQ,GAAA,GAAM,EAAA,EAAI,CAAA,EAAA,EAAK;AAC/D,IAAA,MAAM,QAAgB,EAAC;AACvB,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,OAAA,EAAS,KAAA,CAAM,KAAK,KAAA,CAAM,EAAA,EAAI,EAAA,EAAI,KAAA,CAAM,OAAA,EAAQ,GAAI,CAAA,GAAI,QAAA,EAAU,KAAK,CAAC,CAAA;AAAA,SAAA,IACjF,IAAA,CAAK,SAAS,QAAA,EAAU;AAC/B,MAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,CAAA;AACpC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,EAAQ,GAAA,CAAM,KAAA,CAAM,MAAA,EAAO,GAAI,SAAA,GAAY,CAAA,IAAK,CAAA,GAAK,CAAA,GAAI,QAAA,GAAW,CAAA;AACvF,MAAA,KAAA,MAAW,EAAA,IAAM,WAAA,CAAY,IAAA,CAAK,QAAA,EAAU,MAAA,GAAS,KAAK,QAAA,GAAW,CAAC,KAAA,CAAM,MAAA,EAAmB,CAAA,EAAG,SAAS,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,EAAA,EAAI,EAAA,EAAI,IAAA,GAAA,CAAS,EAAA,GAAK,SAAA,GAAY,CAAA,IAAK,CAAA,EAAI,KAAK,CAAC,CAAA;AAAA,IAClL,CAAA,MAAO;AACL,MAAA,MAAM,aAAa,IAAA,CAAK,IAAA,KAAS,YAAY,CAAA,GAAI,QAAA,GAAW,IAAI,QAAA,GAAW,EAAA;AAC3E,MAAA,MAAM,KAAK,IAAI,IAAA,CAAK,EAAA,EAAI,EAAA,GAAK,YAAY,CAAC,CAAA;AAC1C,MAAA,MAAM,IAAA,GAAO,EAAA,CAAG,WAAA,EAAY,EAAG,QAAQ,IAAA,CAAK,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,UAAU,MAAA,GAAY,IAAA,CAAK,KAAA,GAAQ,CAAA,GAAI,GAAG,QAAA,EAAS;AACzH,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI,IAAA,CAAK,GAAA,EAAK,GAAA,GAAM,YAAA,CAAa,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAAA,WAAA,IACpE,KAAK,GAAA,KAAQ,EAAA,EAAI,GAAA,GAAM,MAAA,CAAO,MAAM,KAAK,CAAA;AAAA,WAC7C,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,KAAA,CAAM,OAAA,EAAQ;AACrC,MAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,GAAA,IAAO,MAAA,CAAO,MAAM,KAAK,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,KAAK,CAAC,CAAA;AAAA,IAC3F;AACA,IAAA,IAAI,GAAA,GAAM,KAAA;AACV,IAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,MAAA,IAAI,QAAA,CAAS,CAAC,CAAA,IAAK,QAAA,EAAU;AAC7B,MAAA,IAAI,CAAC,MAAA,CAAO,CAAC,CAAA,EAAG;AAChB,MAAA,QAAA,EAAA;AACA,MAAA,GAAA,GAAM,IAAA;AACN,MAAA,MAAM,CAAA;AAAA,IACR;AACA,IAAA,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,GAAQ,CAAA;AAAA,EAC5B;AACF;AAGA,SAAS,SAAS,KAAA,EAA2D;AAC3E,EAAA,OAAO,KAAA,CAAM,GAAA,GAAM,EAAE,IAAA,EAAM,SAAS,KAAA,CAAM,GAAG,CAAA,GAAI,QAAA,CAAS,MAAM,KAAK,CAAA,EAAG,GAAA,EAAK,KAAA,CAAM,KAAI,GAAI,IAAA;AAC7F;AAGA,SAAS,YAAA,CAAuC,OAAU,KAAA,EAA4B;AACpF,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,YAAY,WAAA,EAAa,GAAG,MAAK,GAAI,KAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,SAAS,KAAK,CAAA;AAC7B,EAAA,MAAM,IAAA,GAAO,OAAO,KAAK,CAAA;AACzB,EAAA,MAAM,MAAM,MAAA,GAAS,KAAA,CAAM,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,QAAA,EAAS,EAAG,KAAA,CAAM,SAAQ,GAAI,MAAA,CAAO,IAAA,EAAM,MAAA,CAAO,GAAG,CAAA,GAAI,MAAA;AAC/G,EAAA,OAAO,EAAE,GAAG,IAAA,EAAM,EAAA,EAAI,CAAA,EAAG,MAAM,EAAE,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,KAAA,EAAO,GAAI,MAAM,EAAE,GAAA,EAAI,GAAI,EAAC,EAAI,MAAA,EAAQ,EAAE,EAAA,EAAI,KAAA,CAAM,EAAA,EAAI,IAAA,EAAK,EAAE;AAC/G;AAGA,SAAS,OAAO,KAAA,EAA4D;AAC1E,EAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,IAAA,MAAMA,KAAAA,GAAO,KAAA,CAAM,GAAA,IAAO,KAAA,CAAM,KAAA;AAChC,IAAA,OAAO,IAAI,IAAA,CAAKA,KAAAA,CAAK,WAAA,EAAY,EAAGA,KAAAA,CAAK,QAAA,EAAS,EAAGA,KAAAA,CAAK,OAAA,EAAQ,GAAI,CAAC,CAAA;AAAA,EACzE;AACA,EAAA,OAAO,KAAA,CAAM,OAAO,IAAI,IAAA,CAAK,MAAM,KAAA,CAAM,OAAA,KAAY,IAAI,CAAA;AAC3D;AAQO,SAAS,WAAA,CAAsC,KAAA,EAAU,IAAA,EAAY,EAAA,EAAoC;AAC9G,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,CAAM,MAAM,CAAA;AACxC,EAAA,IAAI,CAAC,IAAA,EAAM,OAAO,KAAA,CAAM,KAAA,GAAQ,EAAA,IAAM,MAAA,CAAO,KAAK,CAAA,GAAI,IAAA,GAAO,CAAC,KAAK,IAAI,EAAC;AACxE,EAAA,MAAM,OAAO,IAAI,GAAA,CAAI,KAAA,CAAM,UAAA,IAAc,EAAE,CAAA;AAE3C,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA,CAAE,SAAQ,GAAI,KAAA,CAAM,MAAM,OAAA,EAAQ;AAC5D,EAAA,MAAM,MAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,EAAM,KAAA,CAAM,KAAK,CAAA,EAAG;AAC7C,IAAA,IAAI,SAAS,EAAA,EAAI;AAEjB,IAAA,IAAI,MAAM,OAAA,EAAQ,GAAI,QAAQ,KAAA,IAAS,IAAA,CAAK,SAAQ,EAAG;AACvD,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,KAAK,CAAC,CAAA,EAAG;AAC7B,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,KAAA,EAAO,KAAK,CAAA;AAC5C,IAAA,IAAI,OAAO,UAAU,CAAA,GAAI,IAAA,EAAM,GAAA,CAAI,KAAK,UAAU,CAAA;AAAA,EACpD;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,YAAA,CAAa,IAAA,EAAkB,KAAA,EAAa,IAAA,EAAsB;AACzE,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA,EAAG;AACvC,IAAA,IAAI,MAAA,CAAO,KAAK,CAAA,IAAK,IAAA,EAAM;AAC3B,IAAA,CAAA,EAAA;AAAA,EACF;AACA,EAAA,OAAO,CAAA;AACT;AAGA,IAAM,SAAA,GAAY,CAAC,KAAA,EAAuB,IAAA,KAA2C,OAAO,KAAA,CAAM,MAAA,KAAW,QAAA,GAAW,OAAA,CAAQ,MAAM,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAQ,CAAA,GAAI,IAAA;AAGlK,IAAM,QAAA,GAAW,CAAC,GAAA,EAAa,IAAA,KAAiB;AAC9C,EAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,IAAI,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC3C,EAAA,OAAO,MAAA,CAAO,IAAI,IAAA,CAAK,CAAA,EAAG,IAAI,CAAA,EAAG,CAAA,GAAI,IAAI,CAAC,CAAA;AAC5C,CAAA;AAGA,IAAM,eAAA,GAAkB,CAA2B,MAAA,EAAW,IAAA,KAAgC;AAC5F,EAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,KAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC5C,EAAA,OAAO,YAAA,CAAa,QAAQ,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,EAAG,CAAA,EAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAC9D,CAAA;AAGA,IAAM,QAAA,GAAW,CAA2B,MAAA,EAAsB,QAAA,KAA0B,OAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,EAAQ,EAAA,KAAO,QAAA,IAAY,CAAA,CAAE,OAAO,QAAQ,CAAA;AAOxJ,SAAS,YAAA,CAAuC,MAAA,EAAW,IAAA,EAAc,MAAA,EAAkD;AAChI,EAAA,MAAM,MAAA,GAAS,MAAA,IAAU,QAAA,CAAS,MAAA,EAAQ,MAAA,CAAO,EAAE,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,CAAQ,SAAS,IAAI,CAAA;AACxF,EAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,EAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,KAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC5C,EAAA,OAAO,WAAA,CAAY,MAAA,EAAQ,IAAI,IAAA,CAAK,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAC,CAAA,EAAG,IAAI,IAAA,CAAK,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,GAAI,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAA0B,QAAA,IAAY,CAAA,IAAM,CAAA,CAAoB,MAAA,EAAQ,IAAA,KAAS,IAAI,CAAA;AAC1K;AAGA,IAAM,MAAA,GAAS,CAA2B,OAAA,KAAgD;AACxF,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAC;AACtB,EAAA,MAAM,EAAE,IAAI,GAAA,EAAK,MAAA,EAAQ,SAAS,UAAA,EAAY,WAAA,EAAa,GAAG,IAAA,EAAK,GAAI,OAAA;AACvE,EAAA,OAAQ,IAAA,CAA8B,MAAA;AACtC,EAAA,OAAO,IAAA;AACT,CAAA;AAGA,IAAM,aAAA,GAAgB,CAA2B,MAAA,EAAW,OAAA,KAA6C;AACvG,EAAA,IAAI,CAAC,OAAA,IAAW,EAAE,QAAA,IAAY,UAAU,OAAO,KAAA;AAC/C,EAAA,MAAM,QAAQ,OAAA,CAAQ,MAAA;AACtB,EAAA,IAAI,KAAA,KAAU,MAAA,CAAO,MAAA,EAAQ,OAAO,KAAA;AACpC,EAAA,MAAM,IAAI,cAAA,CAAe,KAAK,GAAG,CAAA,GAAI,cAAA,CAAe,OAAO,MAAM,CAAA;AACjE,EAAA,OAAO,EAAE,CAAA,IAAK,CAAA,IAAK,cAAA,CAAe,GAAG,CAAC,CAAA,CAAA;AACxC,CAAA;AAGA,SAAS,SAAA,CAAU,GAAY,CAAA,EAAqB;AAClD,EAAA,IAAI,CAAA,YAAa,IAAA,IAAQ,CAAA,YAAa,IAAA,EAAM,OAAO,CAAA,YAAa,IAAA,IAAQ,CAAA,YAAa,IAAA,IAAQ,CAAA,CAAE,OAAA,EAAQ,KAAM,EAAE,OAAA,EAAQ;AACvH,EAAA,IAAI,CAAA,IAAK,CAAA,IAAK,OAAO,CAAA,KAAM,YAAY,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,KAAK,SAAA,CAAU,CAAC,CAAA,KAAM,IAAA,CAAK,UAAU,CAAC,CAAA;AAC3G,EAAA,OAAO,CAAA,KAAM,CAAA;AACf;AAOA,SAAS,QAAA,CAAmC,MAAA,EAA2B,MAAA,EAAW,OAAA,EAAiC;AACjH,EAAA,MAAM,GAAA,GAAM,MAAA;AACZ,EAAA,MAAM,OAAgC,EAAC;AACvC,EAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAC,CAAA,MAAO,CAAC,SAAA,CAAU,OAAO,GAAA,CAAI,GAAG,CAAC,CAAA,EAAG,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AACzG,EAAA,IAAI,cAAc,MAAA,EAAQ,OAAO,CAAA,EAAG,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AAC1D,EAAA,OAAO,IAAA;AACT;AAMA,SAAS,QAAA,CAAS,IAAA,EAAkB,IAAA,EAAc,EAAA,EAAsB;AACtE,EAAA,MAAM,IAAA,GAAmB,EAAE,GAAG,IAAA,EAAK;AACnC,EAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,CAAK,WAAW,IAAA,CAAK,QAAA,CAAS,IAAI,CAAC,CAAA,KAAA,CAAA,CAAU,IAAI,IAAA,IAAQ,CAAA,GAAK,KAAK,CAAa,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA;AACjI,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,SAAA,IAAa,IAAA,CAAK,SAAS,QAAA,EAAU;AACrD,IAAA,IAAI,IAAA,CAAK,GAAA,EAAK,IAAA,CAAK,GAAA,GAAM,EAAE,IAAA,EAAM,WAAA,CAAY,IAAA,CAAK,GAAA,CAAI,MAAM,EAAE,CAAA,EAAG,OAAA,EAAS,EAAA,CAAG,QAAO,EAAa;AAAA,SAAA,IACxF,IAAA,CAAK,QAAQ,EAAA,EAAI;AAAE,MAAA,IAAI,EAAA,CAAG,OAAA,EAAQ,KAAM,MAAA,CAAO,GAAG,WAAA,EAAY,EAAG,EAAA,CAAG,QAAA,EAAU,CAAA,EAAG,IAAA,CAAK,GAAA,GAAM,GAAG,OAAA,EAAQ;AAAA,IAAG,WAC1G,IAAA,CAAK,GAAA,KAAQ,QAAW,IAAA,CAAK,GAAA,GAAM,GAAG,OAAA,EAAQ;AACvD,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,KAAA,KAAU,QAAW,IAAA,CAAK,KAAA,GAAQ,EAAA,CAAG,QAAA,EAAS,GAAI,CAAA;AAAA,EACvF;AACA,EAAA,OAAO,IAAA;AACT;AAQA,SAAS,WAAA,CAAY,IAAA,EAAkB,KAAA,EAAa,IAAA,EAAuC;AACzF,EAAA,MAAM,UAAsB,EAAE,GAAG,MAAM,KAAA,EAAO,MAAA,EAAW,OAAO,MAAA,EAAU;AAC1E,EAAA,OAAO,CAAC,GAAA,KAAQ;AACd,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,GAAA,EAAK,IAAI,CAAA;AAClC,IAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,QAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC/C,IAAA,MAAM,MAAA,GAAS,SAAS,IAAI,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA,EAAG,CAAC,CAAC,CAAA;AAC7C,IAAA,IAAI,KAAA,GAAqB,IAAA;AACzB,IAAA,KAAA,MAAW,EAAA,IAAM,MAAA,CAAO,OAAA,EAAS,KAAK,CAAA,EAAG;AACvC,MAAA,MAAM,CAAA,GAAI,SAAS,EAAE,CAAA;AACrB,MAAA,IAAI,CAAA,GAAI,SAAS,CAAA,EAAG;AACpB,MAAA,IAAI,KAAK,MAAA,GAAS,CAAA,KAAM,CAAC,KAAA,IAAS,KAAK,GAAA,CAAI,CAAA,GAAI,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,GAAI,MAAM,IAAI,KAAA,GAAQ,EAAA;AAAA,IACxG;AACA,IAAA,OAAO,KAAA,GAAQ,MAAA,CAAO,KAAK,CAAA,GAAI,OAAA;AAAA,EACjC,CAAA;AACF;AAGA,IAAM,SAAA,GAAY,CAAC,CAAA,EAAS,CAAA,KAAY,CAAA,CAAE,QAAA,EAAS,KAAM,CAAA,CAAE,QAAA,EAAS,IAAK,CAAA,CAAE,UAAA,EAAW,KAAM,EAAE,UAAA,EAAW,IAAK,CAAA,CAAE,UAAA,EAAW,KAAM,CAAA,CAAE,UAAA,EAAW,IAAK,CAAA,CAAE,eAAA,EAAgB,KAAM,CAAA,CAAE,eAAA,EAAgB;AAE7L,IAAM,MAAA,GAAS,CAAC,KAAA,KAAwC,KAAA,CAAM,GAAA,GAAM,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA,GAAI,IAAA;AAGlH,SAAS,YAAA,CAAuC,MAAA,EAAW,UAAA,EAAwC,OAAA,EAAoE;AACrK,EAAA,MAAM,KAAK,OAAO,UAAA,KAAe,WAAW,eAAA,CAAgB,MAAA,EAAQ,UAAU,CAAA,GAAI,UAAA;AAClF,EAAA,MAAM,EAAE,OAAO,QAAA,EAAU,GAAA,EAAK,QAAQ,GAAG,IAAA,EAAK,GAAI,MAAA,CAAO,OAAO,CAAA;AAChE,EAAA,MAAM,IAAA,GAAU,EAAE,GAAG,MAAA,EAAQ,GAAG,IAAA,EAAK;AAGrC,EAAA,MAAM,MAAA,GAAS,CAAC,IAAA,EAAY,EAAA,EAAU,IAAA,KAAe,KAAA,CAAM,IAAA,CAAK,WAAA,EAAY,EAAG,IAAA,CAAK,QAAA,EAAS,EAAG,IAAA,CAAK,SAAQ,GAAI,QAAA,CAAS,EAAE,CAAA,GAAI,QAAA,CAAS,IAAI,CAAA,EAAG,SAAA,CAAU,EAAA,EAAI,IAAI,CAAA,GAAI,IAAA,GAAO,EAAE,CAAA;AAC/K,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,IAAA,GAAO,QAAA,CAAS,QAAQ,CAAA,GAAI,QAAA,CAAS,GAAG,KAAK,CAAA;AAC7C,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,EAAA,CAAG,KAAA,EAAO,QAAA,EAAU,OAAO,KAAK,CAAA;AAAA,EACtD;AACA,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,GAAA,IAAO,EAAA,CAAG,KAAA;AAC1B,IAAA,IAAA,CAAK,MAAM,MAAA,CAAO,IAAA,EAAM,QAAQ,MAAA,CAAO,GAAA,IAAO,OAAO,KAAK,CAAA;AAAA,EAC5D;AACA,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,MAAA,CAAO,MAAM,CAAA;AACzC,EAAA,IAAI,OAAA,GAAU,CAAC,GAAA,KAAgB,QAAA,CAAS,KAAK,IAAI,CAAA;AACjD,EAAA,MAAM,iBAAiB,MAAM;AAAE,IAAA,IAAI,IAAA,KAAS,CAAA,IAAK,MAAA,CAAO,UAAA,EAAY,MAAA,OAAa,UAAA,GAAa,MAAA,CAAO,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAAA,EAAG,CAAA;AAC9H,EAAA,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA,EAAG;AAClC,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAAE,MAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AAAQ,MAAA,cAAA,EAAe;AAAA,IAAG,CAAA,MACjE;AAAE,MAAA,OAAO,IAAA,CAAK,MAAA;AAAQ,MAAA,OAAO,IAAA,CAAK,UAAA;AAAA,IAAY;AAAA,EACrD,CAAA,MAAA,IAAW,IAAA,KAAS,CAAA,IAAK,IAAA,IAAQ,QAAA,EAAU;AACzC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,QAAQ,CAAA;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAA;AAIrC,IAAA,IAAI,MAAM,GAAA,EAAK;AACb,MAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAc;AAC5B,QAAA,MAAMC,GAAAA,GAAK,IAAI,IAAA,CAAK,IAAA,CAAK,WAAA,EAAY,IAAK,KAAA,CAAM,IAAA,KAAS,QAAA,GAAW,CAAA,GAAI,CAAA,CAAA,EAAA,CAAK,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,KAAA,KAAU,MAAA,GAAY,KAAA,CAAM,KAAA,GAAQ,CAAA,GAAI,IAAA,CAAK,QAAA,EAAS,KAAM,KAAA,CAAM,IAAA,KAAS,SAAA,GAAY,CAAA,GAAI,CAAA,CAAA,EAAI,CAAC,CAAA;AAC9M,QAAA,MAAM,CAAA,GAAI,YAAA,CAAaA,GAAAA,CAAG,WAAA,EAAY,EAAGA,IAAG,QAAA,EAAS,EAAG,KAAA,CAAM,GAAA,CAAK,IAAA,EAAM,KAAA,CAAM,IAAK,OAAO,CAAA,IAAK,YAAA,CAAaA,GAAAA,CAAG,WAAA,EAAY,EAAGA,GAAAA,CAAG,QAAA,EAAS,EAAG,EAAA,EAAI,KAAA,CAAM,GAAA,CAAK,OAAO,CAAA;AACpK,QAAA,OAAO,KAAA,CAAMA,IAAG,WAAA,EAAY,EAAGA,IAAG,QAAA,EAAS,EAAG,GAAG,IAAI,CAAA;AAAA,MACvD,CAAA;AACA,MAAA,IAAI,KAAA,GAAQ,OAAO,CAAC,CAAA;AACpB,MAAA,IAAI,QAAA,CAAS,KAAK,CAAA,GAAI,QAAA,CAAS,IAAI,CAAA,EAAG,KAAA,GAAQ,OAAO,CAAC,CAAA;AACtD,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAK,CAAA,GAAI,SAAS,IAAI,CAAA;AAC7C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,QAAA,IAAI,KAAK,GAAA,EAAK,IAAA,CAAK,MAAM,KAAA,CAAM,IAAA,CAAK,IAAI,WAAA,EAAY,EAAG,KAAK,GAAA,CAAI,QAAA,IAAY,IAAA,CAAK,GAAA,CAAI,SAAQ,GAAI,KAAA,EAAO,KAAK,GAAG,CAAA;AAAA,MAClH;AAAA,IACF;AAEA,IAAA,OAAA,GAAU,WAAA,CAAY,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAC7C,IAAA,cAAA,EAAe;AAAA,EACjB;AACA,EAAA,OAAO,EAAE,MAAM,OAAA,EAAQ;AACzB;AAMA,SAAS,SAAA,CAAoC,MAAA,EAAW,IAAA,EAAc,EAAA,EAAY,IAAgC,OAAA,EAAkF;AAClM,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,MAAA,CAAO,MAAM,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AACrC,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,IAAQ,SAAA,EAAW;AAC9B,IAAA,IAAI,CAAC,SAAS,OAAO,EAAE,OAAO,MAAA,EAAQ,OAAA,EAAS,CAAC,GAAA,KAAQ,GAAA,EAAI;AAC5D,IAAA,MAAM,EAAE,IAAA,EAAAC,KAAAA,EAAM,OAAA,EAAAC,QAAAA,KAAY,YAAA,CAAa,MAAA,EAAQ,OAAO,EAAA,KAAO,WAAY,EAAA,IAAM,SAAA,GAAY,SAAA,GAAY,EAAA,GAAM,IAAI,OAAO,CAAA;AACxH,IAAA,OAAO,EAAE,KAAA,EAAOD,KAAAA,EAAM,OAAA,EAAAC,QAAAA,EAAQ;AAAA,EAChC;AACA,EAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,KAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,MAAA,EAAQ,IAAI,CAAA;AAC1C,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,IAAc,EAAC;AACzC,EAAA,MAAM,OAAA,GAAU,KAAK,KAAA,KAAU,MAAA,GAAY,aAAa,IAAA,EAAM,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA,GAAI,CAAA;AACpF,EAAA,MAAM,UAAA,GAAyB,EAAE,GAAG,IAAA,EAAK;AACzC,EAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,EAAW,UAAA,CAAW,KAAA,GAAQ,OAAA;AAAA,OAC5C;AACH,IAAA,OAAO,UAAA,CAAW,KAAA;AAElB,IAAA,UAAA,CAAW,KAAA,GAAQ,OAAO,MAAA,GAAS,IAAI,KAAK,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,GAAI,CAAC,IAAI,IAAI,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,EAAI,IAAI,EAAE,CAAA;AAAA,EACrG;AACA,EAAA,MAAM,SAAA,GAAwB,EAAE,GAAG,IAAA,EAAK;AACxC,EAAA,IAAI,KAAK,KAAA,KAAU,MAAA,EAAW,SAAA,CAAU,KAAA,GAAQ,KAAK,KAAA,GAAQ,OAAA;AAC7D,EAAA,MAAM,SAAS,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,UAAU,MAAA,EAAQ,UAAU,CAAA,EAAG,UAAA,EAAY,WAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,GAAI,IAAI,CAAA,EAAE;AAClH,EAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,MAAA,EAAQ,EAAA,EAAI,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,GAAI,KAAA,CAAM,GAAA,GAAM,EAAE,KAAK,KAAA,CAAM,GAAA,EAAI,GAAI,EAAC,EAAI,MAAA,EAAQ,SAAA,CAAU,MAAA,EAAQ,SAAS,CAAA,EAAG,UAAA,EAAY,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,IAAK,IAAI,CAAA,EAAE;AACnL,EAAA,IAAI,CAAC,SAAS,OAAO,EAAE,QAAQ,KAAA,EAAO,OAAA,EAAS,CAAC,GAAA,KAAQ,GAAA,EAAI;AAE5D,EAAA,MAAM,OAAO,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA,GAAI,OAAA,GAAU,OAAO,OAAO,CAAA;AACtE,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,YAAA,CAAa,KAAA,EAAO,OAAO,EAAA,KAAO,QAAA,GAAW,IAAA,GAAO,EAAA,EAAI,IAAI,CAAA;AACtF,EAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,OAAA,EAAQ;AACxC;AAQO,SAAS,gBAAA,CAA2C,MAAA,EAAW,IAAA,EAAc,EAAA,GAAK,CAAA,EAAG,OAAO,EAAE,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,OAAA,EAA8E;AAC7L,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,EAAE,GAAG,MAAA,EAAQ,YAAY,CAAC,uBAAO,GAAA,CAAI,CAAC,GAAI,MAAA,CAAO,UAAA,IAAc,EAAC,EAAI,IAAI,CAAC,CAAC,CAAA,CAAE,MAAK,EAAE;AAAA,IAC3F,KAAA,EAAO,EAAE,GAAI,eAAA,CAAgB,MAAA,EAAQ,IAAI,CAAA,EAAmD,GAAI,MAAA,CAAO,OAAO,CAAA,EAAc,EAAA;AAAG,GACjI;AACF;AAgCA,IAAM,YAAA,mBAAe,IAAI,GAAA,CAAI,CAAC,IAAA,EAAM,UAAU,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,YAAY,CAAC,CAAA;AAOrF,SAAS,MAAA,CAAiC,MAAA,EAAW,GAAA,EAAoB,GAAA,EAAuB;AAC9F,EAAA,MAAM,GAAA,GAAM,EAAE,GAAG,MAAA,EAAO;AACxB,EAAA,MAAM,MAAA,GAAS,KAA2C,KAAA,GAAQ,GAAA;AAClE,EAAA,KAAA,MAAW,GAAA,oBAAO,IAAI,GAAA,CAAI,CAAC,GAAG,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG,GAAG,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAC,CAAA,EAAG;AAC1E,IAAA,IAAI,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,IAAK,CAAC,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA,EAAG,MAAA,CAAO,GAAG,CAAC,CAAA,EAAG;AAChE,IAAA,IAAI,MAAM,GAAG,CAAA,KAAM,MAAA,EAAW,OAAO,IAAI,GAAG,CAAA;AAAA,SACvC,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA,CAAM,GAAG,CAAA;AAAA,EAC3B;AAEA,EAAA,MAAM,SAAS,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA,KAAM,QAAA,CAAS,IAAI,KAAK,CAAA;AAC5D,EAAA,MAAM,QAAA,GAAW,CAAC,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,GAAA,CAAI,KAAK,CAAA,IAAK,MAAA,CAAO,MAAM,CAAA,KAAM,MAAA,CAAO,GAAG,CAAA,IAAM,CAAC,CAAC,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,GAAA,CAAI,GAAA,IAAO,CAAC,SAAA,CAAU,MAAA,CAAO,GAAA,EAAK,GAAA,CAAI,GAAG,CAAA;AACtJ,EAAA,MAAM,GAAA,GAAM,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,GAAA,CAAI,KAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,WAAW,MAAA,GAAS,GAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,WAAA,EAAY,EAAG,GAAA,CAAI,QAAA,EAAS,EAAG,GAAA,CAAI,OAAA,EAAQ,EAAG,KAAA,CAAM,KAAK,CAAA;AACjF,EAAA,GAAA,CAAI,KAAA,GAAQ,KAAA;AACZ,EAAA,MAAM,IAAA,GAAO,OAAO,KAAK,CAAA;AACzB,EAAA,IAAI,MAAM,GAAA,IAAO,IAAA,KAAS,MAAM,GAAA,CAAI,GAAA,GAAM,MAAM,KAAA,CAAM,WAAA,EAAY,EAAG,KAAA,CAAM,UAAS,EAAG,KAAA,CAAM,SAAQ,GAAI,IAAA,EAAM,MAAM,GAAG,CAAA;AAAA,cAC5G,GAAA,CAAI,GAAA;AAChB,EAAA,OAAO,GAAA;AACT;AAOA,SAAS,MAAgC,GAAA,EAAQ,IAAA,EAAS,QAAa,OAAA,EAAkC,OAAA,EAAkB,QAAuB,IAAA,EAA4D;AAC5M,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AACxD,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,CAAE,MAAA,CAAQ,IAAI,CAAC,CAAC,CAAA;AAChE,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,UAAA,GAAa,EAAE,GAAG,IAAA,EAAM,UAAA,EAAY,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,CAAC,MAAM,CAAC,KAAA,CAAM,GAAA,CAAI,CAAC,CAAC,CAAA,EAAE,GAAI,IAAA,EAAM,MAAM,EAAC,EAAG,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA,EAAE;AAAA,EAC3J;AACA,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM;AAC7B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,CAAA,CAAE,MAAA,CAAQ,IAAI,CAAA;AACnC,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,CAAA,EAAG,eAAA,CAAgB,GAAA,EAAK,CAAA,CAAE,MAAA,CAAQ,IAAI,CAAA,EAAG,eAAA,CAAgB,IAAA,EAAM,IAAI,CAAC,CAAA;AAC5F,IAAA,OAAO,EAAE,GAAG,QAAA,EAAU,GAAI,CAAA,CAAE,EAAA,KAAO,QAAQ,EAAA,GAAK,MAAA,CAAO,IAAI,CAAA,GAAI,IAAK,MAAA,EAAQ,EAAE,IAAI,IAAA,CAAK,EAAA,EAAI,MAAK,EAAE;AAAA,EACpG,CAAC,CAAA;AACD,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAE;AAClC;AAGA,SAAS,UAAA,CAAqC,QAAsB,UAAA,EAA0E;AAC5I,EAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,WAAW,EAAE,CAAA;AACxD,EAAA,MAAM,IAAA,GAAA,CAAQ,UAAU,UAAA,EAAY,MAAA;AACpC,EAAA,MAAM,MAAA,GAAS,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,IAAA,CAAK,MAAM,cAAA,CAAe,CAAA,CAAE,MAAM,CAAA,KAAM,IAAI,CAAA,GAAI,MAAA;AAClG,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,MAAM,IAAA,EAAK;AAC5C;AAGA,SAAS,MAAA,CAAiC,MAAA,EAAsB,IAAA,EAAW,MAAA,EAAmC;AAC5G,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,MAAM,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AAChD,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC3C,EAAA,OAAO,EAAE,MAAA,EAAQ,CAAC,GAAG,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,CAAC,IAAA,CAAK,IAAI,CAAA,CAAE,EAAE,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,IAAK,CAAC,GAAG,GAAG,IAAA,CAAK,OAAO,CAAC,CAAA,KAAM,CAAC,GAAA,CAAI,IAAI,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA,EAAG,MAAM,MAAA,EAAO;AACpJ;AAgBO,SAAS,cAAA,CAAyC,MAAA,EAAsB,UAAA,EAA+B,KAAA,EAAwB,SAAqB,KAAA,EAAgC;AACzL,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,MAAK,GAAI,UAAA,CAAW,QAAQ,UAAU,CAAA;AAE9D,EAAA,IAAI,CAAC,UAAU,IAAA,KAAS,MAAA,SAAkB,MAAA,CAAO,MAAA,EAAQ,SAAS,CAAC,EAAE,GAAG,MAAA,EAAQ,GAAG,OAAO,OAAO,CAAA,EAAG,CAAA,GAAI,EAAC,EAAG,EAAE,CAAA;AAC9G,EAAA,MAAM,MAAA,GAAS,MAAA,IAAU,eAAA,CAAgB,MAAA,EAAQ,IAAI,CAAA;AACrD,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,CAAA;AAC7C,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,IAAI,MAAA,EAAQ,OAAO,MAAA,CAAO,MAAA,EAAQ,CAAC,EAAE,GAAG,MAAA,EAAQ,GAAG,OAAO,IAAI,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA;AACtE,IAAA,MAAM,EAAE,QAAQ,IAAA,EAAM,KAAA,KAAU,gBAAA,CAAiB,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,IAAI,CAAA;AAC1E,IAAA,OAAO,OAAO,MAAA,EAAQ,CAAC,MAAM,KAAqB,CAAA,EAAG,EAAE,CAAA;AAAA,EACzD;AACA,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,EAAQ,MAAA,CAAO,EAAE,CAAA;AACzC,EAAA,MAAM,OAAA,GAAU,aAAA,CAAc,MAAA,EAAQ,IAAI,CAAA;AAE1C,EAAA,IAAI,UAAU,WAAA,IAAe,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAA,EAAAA,QAAAA,EAAQ,GAAI,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAA;AAC9E,IAAA,MAAMC,WAAU,KAAA,CAAM,MAAA,EAAQ,KAAA,EAAO,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,CAAQ,QAAQ,IAAI,CAAA,EAAGD,QAAAA,EAAS,OAAA,EAAS,QAAQ,IAAI,CAAA;AACjH,IAAA,OAAO,OAAO,MAAA,EAAQ,CAAC,GAAI,MAAA,GAAS,CAAC,MAAM,CAAA,GAAI,EAAC,EAAIC,SAAQ,IAAA,EAAM,GAAGA,SAAQ,IAAI,CAAA,EAAGA,SAAQ,MAAM,CAAA;AAAA,EACpG;AACA,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,KAAY,YAAA,CAAa,MAAA,EAAQ,QAAQ,IAAI,CAAA;AAC3D,EAAA,MAAM,OAAA,GAAU,MAAM,MAAA,EAAQ,IAAA,EAAM,QAAQ,OAAA,EAAS,OAAA,EAAS,QAAQ,IAAI,CAAA;AAC1E,EAAA,OAAO,MAAA,CAAO,MAAA,EAAQ,CAAC,OAAA,CAAQ,IAAA,EAAM,GAAG,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA;AACvE;AAQO,SAAS,gBAAA,CAA2C,MAAA,EAAsB,UAAA,EAA+B,KAAA,EAAyC;AACvJ,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,MAAK,GAAI,UAAA,CAAW,QAAQ,UAAU,CAAA;AAC9D,EAAA,IAAI,CAAC,MAAA,IAAU,IAAA,KAAS,MAAA,SAAkB,MAAA,CAAO,MAAA,EAAQ,EAAC,EAAG,SAAS,CAAC,MAAA,CAAO,EAAE,CAAA,GAAI,EAAE,CAAA;AACtF,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,MAAA,GAAS,OAAO,MAAA,EAAQ,EAAC,EAAG,CAAC,MAAA,CAAO,EAAE,CAAC,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,CAAC,gBAAA,CAAiB,MAAA,EAAQ,IAAI,CAAA,CAAE,MAAM,CAAA,EAAG,EAAE,CAAA;AAClI,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,EAAQ,MAAA,CAAO,EAAE,CAAA;AACzC,EAAA,IAAI,UAAU,WAAA,IAAe,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,EAAE,QAAO,GAAI,SAAA,CAAU,QAAQ,IAAA,EAAM,MAAA,CAAO,IAAI,IAAI,CAAA;AAC1D,IAAA,OAAO,MAAA,CAAO,QAAQ,MAAA,GAAS,CAAC,MAAM,CAAA,GAAI,EAAC,EAAG,MAAA,CAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,CAAQ,QAAQ,IAAI,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,EAC7G;AACA,EAAA,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAC,EAAG,CAAC,MAAA,CAAO,EAAA,EAAI,GAAG,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAC,CAAA;AACnE;AAMO,SAAS,WAAA,CAAsC,QAAsB,UAAA,EAAmE;AAC7I,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,UAAA,CAAW,QAAQ,UAAU,CAAA;AACtD,EAAA,IAAI,CAAC,UAAU,IAAA,KAAS,MAAA,SAAkB,EAAE,SAAA,EAAW,CAAA,EAAG,GAAA,EAAK,CAAA,EAAE;AACjE,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,EAAQ,MAAA,CAAO,EAAE,CAAA;AACzC,EAAA,OAAO,EAAE,WAAW,IAAA,GAAO,MAAA,CAAO,OAAO,KAAK,CAAA,GAAI,OAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,CAAQ,QAAQ,IAAI,CAAA,CAAE,SAAS,MAAA,CAAO,MAAA,EAAQ,GAAA,EAAK,MAAA,CAAO,MAAA,EAAO;AAC5I;AAIA,IAAM,OAAA,GAAU,YAAiC,GAAG,CAAA;AACpD,SAAS,MAAA,CAAO,OAAA,EAAqC,IAAA,EAAY,MAAA,EAAoC;AACnG,EAAA,OAAO,QAAQ,CAAA,EAAG,MAAA,IAAU,EAAE,CAAA,CAAA,EAAI,IAAA,CAAK,UAAU,OAAO,CAAC,IAAI,MAAM,IAAI,KAAK,cAAA,CAAe,MAAA,EAAQ,OAAO,CAAC,CAAA,CAAE,OAAO,IAAI,CAAA;AAC1H;AACA,IAAM,cAAc,CAAC,CAAA,EAAY,MAAA,KAA+B,MAAA,CAAO,EAAE,OAAA,EAAS,MAAA,EAAO,EAAG,IAAI,KAAK,IAAA,EAAM,CAAA,EAAG,CAAA,GAAI,CAAC,GAAG,MAAM,CAAA;AAC5H,IAAM,YAAY,CAAC,CAAA,EAAW,MAAA,KAA+B,MAAA,CAAO,EAAE,KAAA,EAAO,MAAA,EAAO,EAAG,IAAI,KAAK,IAAA,EAAM,CAAA,GAAI,CAAA,EAAG,CAAC,GAAG,MAAM,CAAA;AACvH,IAAM,OAAA,GAAuC,EAAE,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,CAAC,EAAE,GAAG,MAAA,EAAO;AAC9G,IAAM,IAAA,GAAO,CAAC,KAAA,KAAqB,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAG,EAAE,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,QAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAC,CAAA,CAAA;AACtI,IAAM,KAAA,GAAQ,CAAC,CAAA,EAAW,GAAA,EAAa,IAAA,KAAkB,CAAA,GAAI,CAAA,GAAI,CAAA,MAAA,EAAS,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GAAK,SAAS,GAAG,CAAA,CAAA;AAO7F,SAAS,kBAAA,CAAmB,IAAA,EAAkB,KAAA,EAAa,MAAA,GAA6B,cAAa,EAAW;AACrH,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,IAAY,CAAC,CAAC,CAAA;AACpD,EAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,CAAA;AACpC,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,KAAK,IAAA,KAAS,OAAA,SAAgB,KAAA,CAAM,CAAA,EAAG,OAAO,MAAM,CAAA;AAAA,OAAA,IAC/C,IAAA,CAAK,SAAS,QAAA,EAAU;AAC/B,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,IAAA,CAAK,QAAA,EAAU,MAAA,GAAS,IAAA,CAAK,QAAA,GAAW,CAAC,KAAA,CAAM,MAAA,EAAmB,CAAA,EAAG,SAAS,CAAA;AACvG,IAAA,IAAI,KAAK,MAAA,KAAW,CAAA,SAAU,KAAA,CAAM,CAAA,EAAG,OAAO,oBAAoB,CAAA;AAAA,SAAA,IACzD,MAAM,CAAA,IAAK,IAAA,CAAK,IAAA,EAAK,KAAM,aAAa,IAAA,GAAO,kCAAA;AAAA,gBAC5C,CAAA,EAAG,KAAA,CAAM,GAAG,MAAA,EAAQ,OAAO,CAAC,CAAA,IAAA,EAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA,CAAA;AAAA,EAC9F,CAAA,MAAO;AACL,IAAA,MAAM,MAAM,IAAA,CAAK,GAAA,GAAM,CAAA,IAAA,EAAO,OAAA,CAAQ,KAAK,GAAA,CAAI,IAAI,CAAC,CAAA,CAAA,EAAI,YAAY,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,MAAM,CAAC,CAAA,CAAA,GAAK,MAAA;AAClG,IAAA,IAAI,IAAA,CAAK,SAAS,SAAA,EAAW;AAC3B,MAAA,MAAM,EAAA,GAAK,GAAA,KAAQ,IAAA,CAAK,GAAA,KAAQ,EAAA,GAAK,cAAA,GAAiB,CAAA,IAAA,EAAO,IAAA,CAAK,GAAA,IAAO,KAAA,CAAM,OAAA,EAAS,CAAA,CAAA,CAAA;AACxF,MAAA,IAAA,GAAO,GAAG,KAAA,CAAM,CAAA,EAAG,SAAS,QAAQ,CAAC,OAAO,EAAE,CAAA,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,KAAA,CAAM,UAAS,GAAI,CAAA;AAC/C,MAAA,MAAM,KAAK,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,IAAA,EAAO,UAAU,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA,GAAK,KAAK,GAAA,KAAQ,EAAA,GAAK,mBAAmB,SAAA,CAAU,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA;AAAA;AAAA,QACtH,OAAO,EAAE,GAAA,EAAK,WAAW,KAAA,EAAO,MAAA,IAAU,IAAI,IAAA,CAAK,IAAA,EAAM,KAAA,GAAQ,GAAG,IAAA,CAAK,GAAA,IAAO,MAAM,OAAA,EAAS,GAAG,MAAM;AAAA,OAAA;AAC1G,MAAA,IAAA,GAAO,GAAG,KAAA,CAAM,CAAA,EAAG,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAA,CAAA;AAAA,IAC9C;AAAA,EACF;AACA,EAAA,IAAI,KAAK,KAAA,EAAO,IAAA,IAAQ,CAAA,QAAA,EAAW,MAAA,CAAO,EAAE,GAAA,EAAK,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,MAAM,SAAA,EAAU,EAAG,IAAA,CAAK,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA;AAAA,OAAA,IACxG,IAAA,CAAK,KAAA,KAAU,MAAA,EAAW,IAAA,IAAQ,IAAA,CAAK,UAAU,CAAA,GAAI,QAAA,GAAW,CAAA,EAAA,EAAK,IAAA,CAAK,KAAK,CAAA,MAAA,CAAA;AACxF,EAAA,OAAO,IAAA;AACT;AAeO,SAAS,iBAAA,CAAkB,KAAA,EAAa,MAAA,GAA6B,YAAA,EAAa,EAAuB;AAC9G,EAAA,MAAM,KAAA,GAAsB,CAAC,EAAE,IAAA,EAAM,SAAS,CAAA;AAC9C,EAAA,MAAM,OAAA,GAAU,MAAM,MAAA,EAAO;AAC7B,EAAA,IAAI,WAAW,CAAA,IAAK,OAAA,IAAW,CAAA,EAAG,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,CAAC,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAC,GAAG,CAAA;AAC1F,EAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,IAAY,GAAG,UAAA,CAAW,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,MAAqB,EAAE,MAAM,SAAA,EAAW,GAAA,GAAM,CAAA,EAAG,EAAE,IAAA,EAAM,SAAA,EAAW,CAAA;AAC7H,EAAA,IAAI,MAAM,OAAA,EAAQ,KAAM,OAAO,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,QAAA,EAAU,CAAA,QAAS,IAAA,CAAK,EAAE,MAAM,SAAA,EAAW,GAAA,EAAK,IAAI,CAAA;AAC9G,EAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,EAAU,CAAA;AAC7B,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,IAAA,EAAM,KAAA,EAAO,kBAAA,CAAmB,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA,EAAE,CAAE,CAAA;AACvF;AAGO,SAAS,cAAA,CAAe,GAAkC,CAAA,EAA2C;AAC1G,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,SAAU,CAAA,KAAM,CAAA;AAC3B,EAAA,MAAM,OAAO,CAAC,CAAA,KAAkB,QAAQ,EAAE,GAAG,GAAG,QAAA,EAAU,CAAA,CAAE,UAAU,MAAA,GAAS,CAAC,GAAG,CAAA,CAAE,QAAQ,EAAE,IAAA,EAAK,GAAI,QAAW,CAAA;AACnH,EAAA,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,IAAA,CAAK,CAAC,CAAA;AAC3B;;;ACnyBO,SAAS,kBAAkB,IAAA,EAAsB;AACtD,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,IAAA,CAAK,cAAA,CAAe,OAAA,EAAS,EAAE,UAAU,IAAA,EAAM,CAAA,CAAE,eAAA,EAAgB,CAAE,QAAA;AAAA,EAChF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAeO,SAAS,cAAA,CAAe,MAAc,EAAA,mBAAW,IAAI,MAAK,EAAG,MAAA,GAA6B,cAAa,EAAW;AACvH,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,KAAK,cAAA,CAAe,MAAA,EAAQ,EAAE,QAAA,EAAU,IAAA,EAAM,cAAc,aAAA,EAAe,EAAE,aAAA,CAAc,EAAE,EAAE,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,cAAc,CAAA,EAAG,KAAA,IAAS,EAAA;AAAA,EAC7J,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF;;;ACxBO,IAAM,UAAA,GAAkC,CAAC,KAAA,EAAO,MAAA,EAAQ,SAAS,SAAS;AAE1E,IAAM,MAAA,GAAS,KAAA;AACtB,IAAM,SAAA,GAAY,2BAAA;AAEX,IAAM,MAAA,GAAS,CAAC,CAAA,EAAW,CAAA,EAAW,CAAA,KAAc,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,EAAG,CAAC,IAAI,MAAM,CAAA;AAEhG,SAAS,UAAU,CAAA,EAAiB;AAClC,EAAA,MAAM,CAAA,GAAI,EAAE,OAAA,EAAQ;AACpB,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,EAAG,OAAO,GAAA;AAC5B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,WAAA,EAAY,EAAG,EAAE,QAAA,EAAS,EAAG,CAAA,CAAE,OAAA,EAAS,CAAA;AAG7D,EAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,CAAC,CAAA;AACxB,EAAA,KAAA,CAAM,QAAA,CAAS,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AACzB,EAAA,IAAI,KAAA,CAAM,OAAA,EAAQ,KAAM,CAAA,EAAG,OAAO,GAAA;AAClC,EAAA,MAAM,EAAA,GAAA,CAAA,CAAO,CAAA,CAAE,QAAA,EAAS,GAAI,KAAK,CAAA,CAAE,UAAA,EAAW,IAAK,EAAA,GAAK,CAAA,CAAE,UAAA,EAAW,IAAK,GAAA,GAAO,EAAE,eAAA,EAAgB;AACnG,EAAA,OAAO,MAAM,EAAA,GAAK,MAAA;AACpB;AAOO,SAAS,MAAM,KAAA,EAAmC;AACvD,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU,OAAO,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,GAAQ,GAAA;AACvE,EAAA,IAAI,KAAA,YAAiB,IAAA,EAAM,OAAO,SAAA,CAAU,KAAK,CAAA;AACjD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,GAAA;AACtC,EAAA,MAAM,CAAA,GAAI,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACrC,EAAA,IAAI,CAAC,CAAA,EAAG,OAAO,UAAU,IAAI,IAAA,CAAK,KAAK,CAAC,CAAA;AACxC,EAAA,MAAM,CAAC,GAAG,EAAA,EAAI,CAAC,IAAI,CAAC,MAAA,CAAO,EAAE,CAAC,CAAC,GAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,GAAG,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAChE,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,EAAG,EAAA,EAAI,CAAC,CAAA;AAC3B,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,GAAA,GAAM,MAAM,CAAA;AAClC,EAAA,OAAO,IAAA,CAAK,cAAA,EAAe,KAAM,CAAA,IAAK,IAAA,CAAK,WAAA,EAAY,KAAM,EAAA,IAAM,IAAA,CAAK,UAAA,EAAW,KAAM,CAAA,GAAI,GAAA,GAAM,GAAA;AACrG;AAGO,SAAS,UAAU,GAAA,EAAmB;AAC3C,EAAA,MAAMC,MAAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAKA,MAAAA,GAAQ,MAAM,CAAA;AACjC,EAAA,OAAO,IAAI,IAAA,CAAK,CAAA,CAAE,gBAAe,EAAG,CAAA,CAAE,aAAY,EAAG,CAAA,CAAE,YAAW,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,IAAA,CAAK,OAAO,GAAA,GAAMA,MAAAA,IAAS,MAAM,CAAC,CAAA;AAClH;AAcA,SAAS,WAAW,KAAA,EAAoC;AACtD,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,CAAA,GAAI,MAAA,CAAO,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,CAAA;AACjG;AAOO,SAAS,SAAS,KAAA,EAAmC;AAC1D,EAAA,MAAM,GAAA,GAAM,MAAM,KAAK,CAAA;AACvB,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,WAAW,KAAK,CAAA,GAAI,MAAM,CAAA,GAAI,GAAA;AACpE;AAMO,SAAS,QAAA,CAAS,OAA2B,GAAA,EAAiC;AACnF,EAAA,OAAO,GAAA,YAAe,IAAA,IAAQ,CAAC,UAAA,CAAW,KAAK,IAAI,KAAA,CAAM,GAAG,CAAA,GAAI,QAAA,CAAS,GAAG,CAAA;AAC9E;AAIA,IAAMC,QAAAA,GAAU,YAAiC,GAAG,CAAA;AAM7C,SAAS,YAAA,CAAa,OAA2B,OAAA,EAA0D;AAChH,EAAA,MAAM,MAAA,GAAS,SAAS,YAAA,EAAa;AACrC,EAAA,OAAOA,QAAAA,CAAQ,GAAG,MAAA,IAAU,EAAE,IAAI,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA,CAAA,EAAI,MAAM,IAAI,IAAA,CAAK,eAAe,MAAA,EAAQ,EAAE,GAAG,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,CAAC,CAAA;AACrI;AASO,SAAS,WAAW,MAAA,EAAyF;AAClH,EAAA,IAAI,KAAA,GAAQ,QAAA;AACZ,EAAA,IAAI,GAAA,GAAM,CAAA,QAAA;AACV,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,IAAI,KAAK,IAAA,EAAM;AACf,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA;AACvB,IAAA,MAAM,CAAA,GAAI,CAAA,CAAE,GAAA,IAAO,IAAA,GAAO,QAAA,CAAS,CAAA,CAAE,KAAK,CAAA,GAAI,QAAA,CAAS,CAAA,CAAE,KAAA,EAAO,CAAA,CAAE,GAAG,CAAA;AACrE,IAAA,IAAI,MAAA,CAAO,SAAS,CAAC,CAAA,UAAW,IAAA,CAAK,GAAA,CAAI,OAAO,CAAC,CAAA;AACjD,IAAA,IAAI,MAAA,CAAO,SAAS,CAAC,CAAA,QAAS,IAAA,CAAK,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,MAAA,CAAO,SAAS,KAAK,CAAA,IAAK,OAAO,QAAA,CAAS,GAAG,IAAI,EAAE,KAAA,EAAO,KAAK,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA,KAAM,EAAE,KAAA,EAAO,GAAA,EAAK,GAAA,EAAK,GAAA,EAAI;AACxH;AAYA,IAAM,SAAA,GAAwC,EAAE,GAAA,EAAK,SAAA,EAAW,OAAO,MAAA,EAAO;AAC9E,IAAM,UAAA,GAAyC,EAAE,IAAA,EAAM,SAAA,EAAW,QAAQ,SAAA,EAAU;AAGpF,IAAM,SAAA,GAAY,2CAAA;AAElB,IAAM,OAAA,GAAU,CAAC,CAAA,KAA2B,IAAI,IAAA,CAAK,MAAA,CAAO,CAAA,CAAE,eAAA,EAAgB,CAAE,MAAM,CAAA,CAAE,QAAA,KAAa,IAAA;AAMrG,SAAS,KAAA,CAAM,CAAA,EAAwB,CAAA,EAAS,CAAA,EAAS,EAAA,EAAgC;AACvF,EAAA,IAAI,OAAO,EAAE,kBAAA,KAAuB,UAAA,SAAmB,EAAA,KAAO,MAAA,GAAY,CAAA,CAAE,WAAA,CAAY,CAAA,EAAG,CAAC,IAAI,CAAA,EAAG,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA,EAAG,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA;AACjI,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,kBAAA,CAAmB,CAAA,EAAG,CAAC,CAAA;AACvC,EAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,MAAM,CAAA,CAAE,WAAA,CAAY,YAAY,CAAA;AACvE,EAAA,MAAM,aAAa,KAAA,CAAM,SAAA,CAAU,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,UAAU,CAAA;AAEjE,EAAA,IAAI,cAAc,CAAA,IAAK,UAAA,GAAa,GAAG,OAAO,CAAA,CAAE,OAAO,CAAC,CAAA;AACxD,EAAA,IAAI,EAAA,KAAO,MAAA,EAAW,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC9D,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AAC9B,IAAA,IAAI,MAAA,IAAU,CAAA,IAAK,WAAA,IAAe,CAAA,IAAK,UAAA,IAAc,CAAC,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA,EAAG,OAAO,CAAA,CAAE,KAAA;AACxF,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,OAAO,CAAA,CAAE,KAAA,CAAM,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAAA,EACtC,CAAC,CAAA;AAED,EAAA,IAAI,CAAC,MAAA,EAAQ,GAAA,CAAI,OAAO,WAAA,GAAc,CAAA,EAAG,GAAG,EAAE,CAAA;AAC9C,EAAA,OAAO,GAAA,CAAI,KAAK,EAAE,CAAA;AACpB;AAUO,SAAS,eAAA,CAAgB,KAAA,EAA2B,GAAA,EAA0B,KAAA,EAAgC;AACnH,EAAA,MAAM,EAAE,QAAQ,EAAA,EAAI,GAAA,GAAM,WAAW,IAAA,GAAO,UAAA,EAAW,GAAI,KAAA,IAAS,EAAC;AACrE,EAAA,MAAM,QAAQ,GAAA,IAAO,KAAA;AACrB,EAAA,MAAM,IAAA,GAAO,MAAM,KAAK,CAAA;AACxB,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,EAAO,KAAK,CAAA;AAClC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,EAAA;AAC7D,EAAA,MAAM,QAAQ,CAAC,UAAA,CAAW,KAAK,CAAA,IAAK,CAAC,WAAW,KAAK,CAAA;AACrD,EAAA,MAAM,KAAA,GAAQ,KAAA,GAAQ,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAC5C,EAAA,MAAMN,KAAAA,GAAO,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,MAAM,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,IAAA,CAAK,IAAA,CAAK,IAAI,IAAI,CAAC,CAAA;AAC/E,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,KAAA,GAAQ,MAAM,CAAA;AACjC,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAKA,KAAAA,GAAO,MAAM,CAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,EAAE,cAAA,EAAe,KAAM,EAAE,cAAA,EAAe,IAAK,IAAI,IAAA,KAAS,MAAA;AACxE,EAAA,MAAM,IAAI,YAAA,CAAa,MAAA,EAAQ,EAAE,GAAG,GAAA,EAAK,GAAI,KAAA,GAAQ,EAAE,MAAM,SAAA,EAAU,GAAI,EAAC,EAAI,GAAI,QAAQ,IAAA,GAAO,IAAK,CAAA;AACxG,EAAA,OAAO,KAAA,KAAUA,KAAAA,GAAO,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,GAAI,KAAA,CAAM,CAAA,EAAG,CAAA,EAAG,GAAG,EAAA,KAAO,OAAA,CAAQ,CAAC,CAAA,GAAI,SAAS,MAAA,CAAU,CAAA;AAC9F;;;AC9KA,IAAM,cAAA,GAAiB;AAAA,EACrB,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,WAAA;AAAA,EAAa,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,UAAA;AAAA,EAC9G,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO;AAChF,CAAA;AACA,IAAM,gBAAA,GAAmB;AAAA,EACvB,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,WAAA;AAAA,EAAa,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,UAAA;AAAA,EAAY,QAAA;AAAA,EACpE,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO;AACrE,CAAA;AAEA,IAAM,SAAS,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,uBAAuB,MAAM,CAAA;AACrE,IAAM,KAAA,GAAQ,CAAC,CAAA,KAAc,CAAA,CAAE,IAAA,GAAO,WAAA,EAAY,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAErE,SAAS,SAAA,CAAU,QAAgB,IAAA,EAAqC;AACtE,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,IAAI;AACF,IAAA,KAAA,MAAW,KAAA,IAAS,CAAC,OAAA,EAAS,MAAM,CAAA,EAAY;AAC9C,MAAA,MAAM,MAAM,IAAI,IAAA,CAAK,eAAe,MAAA,EAAQ,IAAA,KAAS,UAAU,EAAE,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,OAAM,GAAI,EAAE,SAAS,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AAEtI,MAAA,MAAM,KAAA,GAAQ,IAAA,KAAS,OAAA,GAAU,EAAA,GAAK,CAAA;AACtC,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,QAAA,MAAM,IAAA,GAAO,SAAS,OAAA,GAAU,IAAI,KAAK,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,EAAG,EAAE,CAAC,CAAA,GAAI,IAAI,KAAK,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,EAAG,CAAA,GAAI,CAAC,CAAC,CAAA;AACnG,QAAA,GAAA,CAAI,KAAK,KAAA,CAAM,GAAA,CAAI,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,GAAA;AACT;AAOA,SAAS,QAAQ,KAAA,EAA0B;AACzC,EAAA,MAAM,GAAA,mBAAM,IAAI,GAAA,CAAY,CAAC,IAAI,CAAC,CAAA;AAClC,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,GAAA,CAAI,IAAI,KAAK,CAAA;AACb,IAAA,OAAO,CAAC,GAAG,GAAG,CAAA;AAAA,EAChB;AACA,EAAA,IAAI;AAAE,IAAA,GAAA,CAAI,IAAI,IAAI,IAAA,CAAK,gBAAe,CAAE,eAAA,GAAkB,MAAM,CAAA;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAA,EAAuB;AAClG,EAAA,IAAI,OAAO,cAAc,WAAA,IAAe,SAAA,CAAU,UAAU,GAAA,CAAI,GAAA,CAAI,UAAU,QAAQ,CAAA;AACtF,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,QAAA,CAAS,eAAA,EAAiB,MAAM,GAAA,CAAI,GAAA,CAAI,QAAA,CAAS,eAAA,CAAgB,IAAI,CAAA;AAC5G,EAAA,OAAO,CAAC,GAAG,GAAG,CAAA;AAChB;AAGA,IAAI,MAAA,GAA0B,IAAA;AAE9B,SAAS,SAAS,KAAA,EAA0B;AAC1C,EAAA,MAAM,IAAA,GAAO,QAAQ,KAAK,CAAA;AAC1B,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AACzB,EAAA,IAAI,MAAA,EAAQ,GAAA,KAAQ,GAAA,EAAK,OAAO,MAAA;AAChC,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,cAAc,CAAA;AACrC,EAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,gBAAgB,CAAA;AACzC,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,KAAA,MAAW,CAAA,IAAK,UAAU,GAAA,EAAK,OAAO,GAAG,IAAI,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA;AAC5D,IAAA,KAAA,MAAW,CAAA,IAAK,UAAU,GAAA,EAAK,SAAS,GAAG,IAAI,CAAA,EAAG,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA;AAAA,EAClE;AAEA,EAAA,MAAM,GAAA,GAAM,CAAC,GAAA,KAAqB,CAAC,GAAG,GAAG,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,GAAS,EAAE,MAAM,CAAA,CAAE,IAAI,MAAM,CAAA,CAAE,KAAK,GAAG,CAAA;AACnG,EAAA,MAAM,CAAA,GAAI,CAAA,GAAA,EAAM,GAAA,CAAI,MAAM,CAAC,CAAA,KAAA,CAAA;AAC3B,EAAA,MAAM,CAAA,GAAI,CAAA,GAAA,EAAM,GAAA,CAAI,QAAQ,CAAC,CAAA,KAAA,CAAA;AAC7B,EAAA,MAAM,MAAM,MAAA,CAAO,GAAA,CAAA,0BAAA,CAAA;AACnB,EAAA,MAAM,OAAO,MAAA,CAAO,GAAA,CAAA,SAAA,CAAA;AACpB,EAAA,MAAMO,KAAAA,GAAO;AAAA;AAAA,IAEX,sCAAA;AAAA,IACA,wCAAA;AAAA,IACA,kFAAA;AAAA;AAAA,IAEA,IAAI,OAAO,CAAA,CAAA,EAAI,GAAG,OAAO,CAAC,CAAA,SAAA,EAAY,IAAI,CAAA,GAAA,CAAA,EAAO,IAAI,CAAA;AAAA,IACrD,IAAI,OAAO,CAAA,CAAA,EAAI,CAAC,OAAO,GAAG,CAAA,SAAA,EAAY,IAAI,CAAA,GAAA,CAAA,EAAO,IAAI,CAAA;AAAA,IACrD,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,CAAC,CAAA,OAAA,EAAU,IAAI,OAAO,IAAI,CAAA;AAAA;AAAA,IAEzC,qCAAA;AAAA,IACA,wBAAA;AAAA,IACA,2CAAA;AAAA;AAAA,IAEA,+CAAA;AAAA,IACA,uBAAA;AAAA,IACA,yCAAA;AAAA,IACA,2BAAA;AAAA;AAAA,IAEA,kBAAA;AAAA,IACA,2CAAA;AAAA,IACA,gDAAA;AAAA;AAAA,IAEA,qDAAA;AAAA,IACA,6BAAA;AAAA;AAAA,IAEA,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,CAAC,KAAK,IAAI,CAAA;AAAA;AAAA,IAEzB,gDAAA;AAAA,IACA,0BAAA;AAAA,IACA,uBAAA;AAAA;AAAA,IAEA,yGAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAA,GAAS,EAAE,GAAA,EAAK,IAAA,EAAAA,KAAAA,EAAK;AACrB,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,YAAA,CAAa,QAAgC,MAAA,EAA+B;AAC1F,EAAA,MAAM,EAAE,IAAA,EAAAA,KAAAA,EAAK,GAAI,SAAS,MAAM,CAAA;AAChC,EAAA,KAAA,MAAW,OAAO,MAAA,EAAQ;AACxB,IAAA,IAAI,OAAO,IAAA,EAAM;AACjB,IAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAAE,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AAAU,MAAA,OAAO,OAAA;AAAA,IAAS;AACnF,IAAA,IAAI,eAAe,IAAA,EAAM;AACzB,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,EAAK;AAC9B,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAI,CAACA,KAAAA,CAAK,IAAA,CAAK,CAAC,EAAA,KAAO,GAAG,IAAA,CAAK,IAAI,CAAC,CAAA,EAAG,OAAO,OAAA;AAAA,EAChD;AACA,EAAA,OAAO,OAAA;AACT","file":"utils.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n\nexport const GLASS_BACKDROP = \"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]\";\n\nexport const GLASS_SURFACE = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-card),var(--ds-glass-inset)]`;\n\nexport const GLASS_OVERLAY = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-modal),var(--ds-glass-inset)]`;\n\n/**\n * A modal surface (Dialog, Drawer, Sheet, CommandPalette, GlobalSearch): the theme's surface, never less than 85% opaque.\n * A glass theme's surface is see-through by design, which suits a card on the canvas; over an overlay's scrim the same\n * glass reads as grey mud, and the page shows through (round 27, R27-17, the owner picked 85% from a mock-up). An opaque\n * theme keeps its surface as it is: the alpha only rises, through CSS relative colour, in every mode and scope.\n *\n * The theme's surface comes first, for a browser without relative colour (Chrome before 119, Firefox before 128,\n * Safari before 16.4): a value holding var() is only found invalid once computed, which drops the background to\n * transparent rather than to an earlier declaration, so the raised one applies only where @supports says it can (the\n * round 27 review). A surface with no colour at all (fully transparent) stays so: raising it would paint it black.\n */\nexport const OVERLAY_SURFACE = \"bg-[var(--ds-bg-surface)] supports-[color:oklch(from_red_l_c_h)]:bg-[oklch(from_var(--ds-bg-surface)_l_c_h_/_max(alpha,min(1,alpha*1000)*0.85))]\";\n\nexport const GLASS_DROPDOWN = `${GLASS_BACKDROP} shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]`;\n\n// Keyboard focus (Sprint 30, the owner's D1 and D6): where Tab has landed. A solid outline in the theme's focus colour\n// (--ds-focus, derived to 3:1 on every ground), 2 px, with a 2 px gap between it and the element. The gap shows what the\n// element sits on, so one colour reads beside any fill, and while the outline shows, the element's own shadow steps\n// aside (D7, P12): shadow-none drops its --tw-shadow and keeps any ring. Every part is prefixed: an unprefixed\n// outline-solid draws an outline at rest. And outline-solid is required: in Tailwind 4, outline-none (which many\n// components set at rest) sets --tw-outline-style: none, which outline-2 reads, so without it no outline draws. These\n// draw no border (a button that uses one, the Launcher, gets the outline alone); a field takes FIELD_FOCUS_RING. `cn()`\n// keeps only the last of outline-none and outline-solid in one variant, so a component's own focus-visible:outline-none\n// after a utility would remove the outline: none may follow one.\nexport const FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:shadow-none\";\n\n/**\n * On a wrapper that shows focus for a control inside it: HAS_FOCUS_RING, from the keyboard only (`:has(:focus-visible)`).\n * FOCUS_WITHIN_RING shows it on any focus inside, a click's too, since `:focus-within` has no keyboard-only form: kept\n * for code that uses it, and a new wrapper takes HAS_FOCUS_RING (D6: keyboard focus shows only from the keyboard).\n */\nexport const FOCUS_WITHIN_RING = \"focus-within:outline-2 focus-within:outline-solid focus-within:outline-offset-2 focus-within:outline-[var(--ds-focus)] focus-within:shadow-none\";\n\nexport const HAS_FOCUS_RING = \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-solid has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-[var(--ds-focus)] has-[:focus-visible]:shadow-none\";\n\n/**\n * The outline on a drawn child, where the element that takes focus is hidden or wraps it: a checkbox's box beside its\n * input (`peer`), a radio's circle inside its button, a separator's grip, a Gantt milestone's diamond (`group`). The\n * same outline, gap and shadow rule.\n */\nexport const PEER_FOCUS_RING = \"peer-focus-visible:outline-2 peer-focus-visible:outline-solid peer-focus-visible:outline-offset-2 peer-focus-visible:outline-[var(--ds-focus)] peer-focus-visible:shadow-none\";\n\nexport const GROUP_FOCUS_RING = \"group-focus-visible:outline-2 group-focus-visible:outline-solid group-focus-visible:outline-offset-2 group-focus-visible:outline-[var(--ds-focus)] group-focus-visible:shadow-none\";\n\n/**\n * The same outline drawn inside the element's edge, for edge-to-edge rows, cells and scroll regions only (the plan's\n * P3): elements that are never filled solid, since inside the edge there is no gap to keep one colour readable on a fill.\n * It sits `--ds-focus-inset` in: 5 px, deeper where the theme's corners are rounder, so it clears a table's rounded\n * corners (D8, the owner's decision A); what such an element holds keeps 1 px more clear of its edge. Anywhere else the\n * outline stays outside, with room made for it. Moved here from use-keyboard-scroll.ts (Sprint 30) so the server-safe\n * `gridsmith-ui/utils` can export it.\n */\nexport const FOCUS_INSET = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-[var(--ds-focus-inset)] focus-visible:outline-[var(--ds-focus)]\";\n\n/**\n * The room FOCUS_RING's outline takes outside its element, in px: its 2 px gap and 2 px line (Sprint 30, P3). Where a\n * container clips, what sits beside its edge keeps this much clear of it: a fixed size, never a theme space. Internal,\n * as is the one below (exports/utils.ts exports by name).\n */\nexport const FOCUS_ROOM = 4;\n\n/** A theme's length that sets how far something sits from a clipping edge, never under FOCUS_ROOM (Sprint 25.27). */\nexport const atLeastFocusRoom = (length: string) => `max(${length}, ${FOCUS_ROOM}px)`;\n\n/**\n * A field (D6, P4, P13). Reached with Tab: the keyboard's outline, and its border in the focus colour, as GOV.UK turns a\n * focused input's border: it is where you type. Clicked into: the active look instead, the accent border and its soft\n * halo (`ring-2` in --ds-ring-active, laid over the field's own shadow), and no outline. A browser matches :focus-visible\n * on a text field either way, so lib/input-modality.ts notes on <html> whether a pointer moved focus last; with no note\n * yet, the outline. The field keeps its own (inset) shadow in both: no shadow-none here.\n *\n * The wrapper forms (_WITHIN_ and _HAS_, for a box round the part you type in) show it while that part has focus, and\n * not while a control of the field's own does: a button, a select, a link, a checkbox, a radio or a switch inside it (a\n * tag's remove, a picker's chevron, a composer's Send, an editor's toolbar or a task's checkbox), or anything in a popup\n * inside the box (a dialog of its own; a field that is itself in a dialog still shows it). That control shows its own outline, so there is one focus point, never\n * two (P11). _WITHIN_ reads :focus, as a click on a date's segment isn't :focus-visible; _HAS_ reads :focus-visible.\n * Either outranks the field's hover border, so hovering keeps the look.\n */\nexport const FIELD_FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:focus-visible:outline-none [[data-input-modality=pointer]_&]:focus-visible:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:focus-visible:ring-2 [[data-input-modality=pointer]_&]:focus-visible:ring-[var(--ds-ring-active)]\";\n\nexport const FIELD_FOCUS_WITHIN_RING = \"has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-solid has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-offset-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-[var(--ds-focus)] has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-[var(--ds-ring-active)]\";\n\nexport const FIELD_HAS_FOCUS_RING = \"has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-solid has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-offset-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-[var(--ds-focus)] has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-focus)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-accent-ink)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-[var(--ds-ring-active)]\";\n\n// A field with an error: the same, its red border kept, and the red halo when clicked into.\nexport const ERROR_FOCUS_RING = \"focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-[var(--ds-focus)] focus-visible:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:focus-visible:outline-none [[data-input-modality=pointer]_&]:focus-visible:ring-2 [[data-input-modality=pointer]_&]:focus-visible:ring-[var(--ds-ring-error)]\";\n\nexport const ERROR_FOCUS_WITHIN_RING = \"has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-solid has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-offset-2 has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-[var(--ds-focus)] has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus))]:ring-[var(--ds-ring-error)]\";\n\nexport const ERROR_HAS_FOCUS_RING = \"has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-solid has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-offset-2 has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-[var(--ds-focus)] has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:border-[var(--ds-status-error)] [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:outline-none [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-2 [[data-input-modality=pointer]_&]:has-[:focus-visible:not(button,select,a,[role=button],input[type=checkbox],input[type=radio],[role=checkbox],[role=radio],[role=switch])]:[&:not(:has([role=dialog]_:focus-visible))]:ring-[var(--ds-ring-error)]\";\n\n// Active (D6): a field clicked into, or a dropdown or picker that's open, is its accent border (--ds-accent-ink, P8) with\n// the soft halo beyond it; on a field with an error, red with the red halo. Never an outline: that is keyboard focus's.\n// Choices (a selected card, row or swatch, the Stepper's current step) draw their own selected look, not this (D2).\nexport const ACTIVE_RING = \"border-[var(--ds-accent-ink)] ring-2 ring-[var(--ds-ring-active)]\";\n\nexport const ERROR_ACTIVE_RING = \"border-[var(--ds-status-error)] ring-2 ring-[var(--ds-ring-error)]\";\n\n// Body scroll lock is reference-counted so stacked overlays (a Dialog opened\n// from a Drawer, for example) only restore scrolling when the LAST one\n// closes. The original overflow value is captured on the first lock and put\n// back on the last unlock; an unbalanced unlock is clamped at zero.\nlet scrollLockCount = 0;\nlet scrollLockPreviousOverflow = \"\";\n\nexport function lockBodyScroll() {\n if (scrollLockCount === 0) {\n scrollLockPreviousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n }\n scrollLockCount++;\n}\n\nexport function unlockBodyScroll() {\n if (scrollLockCount === 0) return;\n scrollLockCount--;\n if (scrollLockCount === 0) {\n document.body.style.overflow = scrollLockPreviousOverflow;\n scrollLockPreviousOverflow = \"\";\n }\n}\n\n/** Test-only: current number of active locks. */\nexport function getBodyScrollLockCount() {\n return scrollLockCount;\n}\n","/** The last page language and visitor's languages read, and the locale they gave: formatting runs often, they change rarely. */\nlet last: { key: string; locale: string | undefined } | null = null;\n\n/**\n * The form a server-rendered page is written in without LocaleProvider, and what the library writes on a server where no\n * locale is given: an explicit locale, the same on every machine and on both sides of hydration (Sprint 25.20 D2).\n */\nexport const FIXED_FORM = \"en\";\n\n/**\n * The locale the library writes dates, times and numbers in: the app's language, the page's `lang`, in the visitor's own\n * formats where they speak it (Sprint 25.17, the owner's decision of 2 October). An English page shows \"5 minutes ago\"\n * and \"250K\" to a visitor whose browser is Japanese, where it showed \"5 分前\" and \"25万\" in a page of English (WCAG 3.1.2:\n * text in the page's language needs no `lang` of its own), and a British visitor to it keeps \"1 Oct 2026\". The visitor's\n * form counts only in the page's script: a page in traditional Chinese stays traditional for a visitor who reads\n * simplified. A page with no `lang` is written in the browser's language, as before. On a server, where there is no page,\n * English (\"en\"), never the machine's own language (Sprint 25.22's review): server code passes requestLocale's choice.\n */\nexport function formatLocale(): string | undefined {\n if (typeof document === \"undefined\") return FIXED_FORM;\n const page = document.documentElement.lang?.trim();\n if (!page) return undefined;\n return localeFor(page, browserLanguages());\n}\n\n/** The browser's languages, in its order (`navigator.languages`), or none where there is no browser. */\nexport function browserLanguages(): readonly string[] {\n if (typeof navigator === \"undefined\") return [];\n return navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];\n}\n\n/**\n * The locale for a page language and the languages a visitor speaks, in their order: the visitor's form of the page's\n * language where they speak it, else the page's own (Sprint 25.20: the same choice on a server, from the request's\n * languages, and in the browser). Undefined for a page language Intl can't read.\n */\nexport function localeFor(page: string, spoken: readonly string[]): string | undefined {\n const key = `${page}|${spoken.join(\",\")}`;\n if (last?.key !== key) last = { key, locale: choose(page, spoken) };\n return last.locale;\n}\n\n/** What a server-rendered app hands the library at its top: the page's language, and the visitor's from the request. */\nexport interface LocaleChoice {\n /** The page's language, as `<html lang>` says, or \"en\". */\n lang: string;\n /** The request's languages, in a browser's order; empty without the header. */\n spoken: string[];\n /** Whether the request's header was given. */\n hasHeader: boolean;\n /** The locale the server writes in, and the browser while it hydrates. */\n server: string;\n}\n\n/** What LocaleProvider hands down for a page language and a request's Accept-Language header. */\nexport function localeChoice(lang: string | undefined, acceptLanguage: string | null | undefined): LocaleChoice {\n const page = lang?.trim() || FIXED_FORM;\n const spoken = acceptedLanguages(acceptLanguage);\n return { lang: page, spoken, hasHeader: !!acceptLanguage, server: localeFor(page, spoken) ?? FIXED_FORM };\n}\n\n/**\n * The locale LocaleProvider writes in on the server for a page language and a request's Accept-Language header (Sprint\n * 25.22's review), for server code's own dates and numbers: a server page passes it to the helpers from\n * `gridsmith-ui/utils`, so its words read as the components' beside them. `requestLocale(LANG, (await\n * headers()).get('accept-language'))`.\n */\nexport function requestLocale(lang: string | undefined, acceptLanguage?: string | null): string {\n return localeChoice(lang, acceptLanguage).server;\n}\n\n/** The most of a request's languages read: browsers send a handful. */\nconst MAX_LANGUAGES = 20;\n\n/**\n * A request's `Accept-Language` header as the languages a browser lists (Sprint 25.20 L1): highest quality first, ties in\n * the header's order, \"*\" and anything with q=0 left out. \"en-GB,en;q=0.9,fr;q=0.8\" is [\"en-GB\", \"en\", \"fr\"].\n */\nexport function acceptedLanguages(header: string | null | undefined): string[] {\n if (!header) return [];\n const read: Array<{ tag: string; q: number; at: number }> = [];\n // a browser lists a handful; a header made up to be long reads no further than the first twenty (the review)\n header.split(\",\").slice(0, MAX_LANGUAGES).forEach((part, at) => {\n const [tag, ...params] = part.trim().split(\";\");\n const name = tag?.trim();\n if (!name || name === \"*\") return;\n const qParam = params.map((p) => p.trim()).find((p) => /^q=/i.test(p));\n const q = qParam ? Number(qParam.slice(2)) : 1;\n if (!(q > 0)) return;\n read.push({ tag: name, q, at });\n });\n return read.sort((a, b) => b.q - a.q || a.at - b.at).map((r) => r.tag);\n}\n\n/** The language and script a tag is written in: \"en\" and \"en-GB\" are both \"en-Latn\"; \"zh-TW\" is \"zh-Hant\", \"zh-CN\" \"zh-Hans\". */\nfunction writtenIn(tag: string): string | null {\n try {\n const locale = new Intl.Locale(tag).maximize();\n return `${locale.language}-${locale.script ?? \"\"}`;\n } catch {\n return null;\n }\n}\n\n/**\n * A visitor's tag as its language, script and region (Sprint 25.20's review): a request's header can carry private-use,\n * extension and variant parts (\"en-x-…\", \"en-GB-u-nu-thai\") that would change the digits a server writes and make every\n * cache keyed by locale grow with each new header. Read by syntax alone, so a server and a browser reduce a tag alike.\n */\nfunction plainTag(tag: string): string | undefined {\n try {\n const locale = new Intl.Locale(tag);\n return [locale.language, locale.script, locale.region].filter(Boolean).join(\"-\");\n } catch {\n return undefined;\n }\n}\n\nfunction choose(page: string, spoken: readonly string[]): string | undefined {\n const language = writtenIn(page);\n // a tag Intl can't read: the browser's language\n if (language === null) return undefined;\n // the visitor's own form of the page's language (\"en-GB\" for an \"en\" page), wherever it is in their list; else the page's\n const own = spoken.find((tag) => typeof tag === \"string\" && writtenIn(tag) === language);\n try {\n return Intl.getCanonicalLocales((own && plainTag(own)) || page)[0];\n } catch {\n return undefined;\n }\n}\n","/**\n * Keyboard moves for a calendar's day grid (Sprint 25.7, D14(b)): the APG date\n * picker's keys. Left and Right move a day, Up and Down a week, Home and End go\n * to the ends of the week, PageUp and PageDown move a month (Shift: a year) and\n * keep the day, clamped to the month's last day. All arithmetic is on calendar\n * days in local time, so a clock change never lands on the wrong day.\n */\n\nimport type { Weekday } from \"./week-start\";\nexport function addDays(d: Date, n: number): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);\n}\n\n/** The same day `n` months later, or the month's last day when it has fewer days (31 January + 1 month = 28 February). */\nexport function addMonthsClamped(d: Date, n: number): Date {\n const first = new Date(d.getFullYear(), d.getMonth() + n, 1);\n const last = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();\n return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(), last));\n}\n\nexport function sameDay(a: Date, b: Date): boolean {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n}\n\n/** A stable key for a day: YYYY-MM-DD in local time (the grid's data-grid-key). */\nexport function dayKey(d: Date): string {\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, \"0\")}-${String(d.getDate()).padStart(2, \"0\")}`;\n}\n\n/** Where a key moves the grid's focus from `from`, or null for a key the grid does not handle. */\nexport function moveDay(from: Date, key: string, shift: boolean, weekStartsOn: Weekday = 0): Date | null {\n const intoWeek = (from.getDay() - weekStartsOn + 7) % 7;\n switch (key) {\n case \"ArrowLeft\": return addDays(from, -1);\n case \"ArrowRight\": return addDays(from, 1);\n case \"ArrowUp\": return addDays(from, -7);\n case \"ArrowDown\": return addDays(from, 7);\n case \"Home\": return addDays(from, -intoWeek);\n case \"End\": return addDays(from, 6 - intoWeek);\n case \"PageUp\": return addMonthsClamped(from, shift ? -12 : -1);\n case \"PageDown\": return addMonthsClamped(from, shift ? 12 : 1);\n default: return null;\n }\n}\n","/**\n * Caches keyed by locale, each holding at most `limit` entries, the least recently used dropped first (Sprint 25.20's\n * fresh-eyes review). In a browser a page writes in one or two locales; on a server the locale comes from each request's\n * Accept-Language header, so a cache that never forgets grows with every visitor's language, and with headers made up to\n * grow it. Size a cache for its keys: a formatter keyed by locale and options holds about a dozen per locale.\n */\nconst caches = new Set<Map<string, unknown>>();\n\nexport function localeCache<V>(limit: number): (key: string, make: () => V) => V {\n const map = new Map<string, V>();\n caches.add(map as Map<string, unknown>);\n return (key, make) => {\n const hit = map.get(key);\n if (hit !== undefined) {\n // most recently used last\n map.delete(key);\n map.set(key, hit);\n return hit;\n }\n const made = make();\n map.set(key, made);\n if (map.size > limit) map.delete(map.keys().next().value as string);\n return made;\n };\n}\n\n/**\n * Empties every locale cache. For a test that renders a server's HTML and hydrates it in one process: a formatter made\n * without a time zone keeps the zone it was made in, so the browser's side starts with none of the server's.\n */\nexport function clearLocaleCaches(): void {\n for (const map of caches) map.clear();\n}\n\n/** The number of entries in each locale cache (tests). */\nexport function localeCacheSizes(): number[] {\n return Array.from(caches, (map) => map.size);\n}\n","import { formatLocale } from \"./format-locale\";\nimport { dayKey } from \"./date-grid\";\nimport { localeCache } from \"./locale-cache\";\nimport type { Weekday } from \"./week-start\";\n\n/**\n * How something repeats (Sprint 25.19 R1): the iCalendar standard's rule (RFC 5545 `RRULE`), in the subset Outlook's and\n * Google's menus write (P5), read in the event's local time. The quick choices are stored in the standard's implied form\n * (P6): a weekly rule with no `weekdays`, a monthly rule with no `day` or `nth` and a bare yearly rule repeat on the\n * start's own weekday, date or anniversary, so moving the event moves them. The event's own start is always its first\n * occurrence.\n */\nexport type RecurrenceFrequency = \"daily\" | \"weekly\" | \"monthly\" | \"yearly\";\n\n/** An nth weekday of a month: the first to the fourth, or the last (−1). A fifth weekday is the last. */\nexport type WeekOfMonth = 1 | 2 | 3 | 4 | -1;\n\nexport interface Recurrence {\n freq: RecurrenceFrequency;\n /** Every n days, weeks, months or years. Default 1. */\n interval?: number;\n /** Weekly: the days it repeats on, Sunday 0 to Saturday 6. Left out, the start's own weekday. */\n weekdays?: Weekday[];\n /** Monthly, or yearly with `month`: a day of the month, 1 to 31, or −1 for the last day. A month without the day is skipped. */\n day?: number;\n /** Monthly, or yearly with `month`: an nth weekday, `{ week: 1, weekday: 2 }` the first Tuesday. */\n nth?: { week: WeekOfMonth; weekday: Weekday };\n /** Yearly: the month, 1 to 12, with `day` or `nth`. A bare yearly rule repeats on the start's anniversary. */\n month?: number;\n /** The week's first day (WKST), which places a weekly rule's weeks. Default Monday, as RFC 5545 says. */\n weekStart?: Weekday;\n /**\n * The last moment it occurs. A date at midnight includes its whole day (\"until 30 November\"); an all-day event's is a\n * date. RecurrencePicker stores the end of the chosen day, which other apps read exactly. Left out with `count`, it\n * never ends. A rule read back from JSON may carry it as a string: the library reads it as the date it was.\n */\n until?: Date;\n /** How many times it occurs, the first included, and the excluded dates among them (RFC 5545). */\n count?: number;\n}\n\n/** The fields a repeating event carries; a Calendar event has them as `repeat` and `exceptions` (P12: never `recurrence`). */\nexport interface RepeatingEvent {\n id: string;\n start: Date;\n end?: Date;\n allDay?: boolean;\n /** The rule, or a rule string `parseRRule` reads (\"RRULE:FREQ=WEEKLY;BYDAY=TU,TH\"). */\n repeat?: Recurrence | string;\n /** The dates left out, as day keys in local time (\"2026-10-20\"): the original date of each occurrence removed or moved. */\n exceptions?: string[];\n /**\n * On an occurrence, its series' id and its original date (a day key), as RFC 5545's RECURRENCE-ID links an edited\n * instance to its series. Each occurrence `occurrences` gives carries it, and so does an occurrence changed on its own\n * (\"This event\"), which the page stores under an id of its own: the series leaves the date out, and the edit helpers\n * find it by its link.\n */\n series?: { id: string; date: string };\n}\n\n/** Which occurrences a change or a deletion applies to: this one, it and the ones after it, or the whole series. */\nexport type RecurrenceScope = \"this\" | \"following\" | \"all\";\n\n/**\n * What a choice in RecurrenceScopeDialog does to the page's events: `events`, the list as it now is, for a page that\n * keeps its events in state; or `save`, the events to write (new or changed, each by its id), and `remove`, the ids to\n * delete, for a page that stores them elsewhere.\n */\nexport interface RepeatChange<T> {\n events: T[];\n save: T[];\n remove: string[];\n}\n\n/** One occurrence of a series: the event without its repeat fields, its own id, start and end, and where it came from. */\nexport type Occurrence<T extends RepeatingEvent> = Omit<T, \"repeat\" | \"exceptions\"> & {\n id: string;\n start: Date;\n end?: Date;\n /** The series' id and this occurrence's original date (a day key), which the edit helpers take. */\n series: { id: string; date: string };\n};\n\nconst DAY_CODES = [\"SU\", \"MO\", \"TU\", \"WE\", \"TH\", \"FR\", \"SA\"] as const;\nconst FREQS: Record<string, RecurrenceFrequency> = { DAILY: \"daily\", WEEKLY: \"weekly\", MONTHLY: \"monthly\", YEARLY: \"yearly\" };\nconst KNOWN_PARTS = new Set([\"FREQ\", \"INTERVAL\", \"WKST\", \"BYDAY\", \"BYSETPOS\", \"BYMONTHDAY\", \"BYMONTH\", \"UNTIL\", \"COUNT\"]);\n\nconst whole = (text: string | undefined): number | null => (text !== undefined && /^[+-]?\\d+$/.test(text) ? Number(text) : null);\n\n/** Plain days (\"TU,TH\"), in weekday order, or null for anything else (a number before a day, a repeat). */\nfunction plainDays(text: string): Weekday[] | null {\n const days = text.split(\",\").map((code) => DAY_CODES.indexOf(code as (typeof DAY_CODES)[number]));\n if (days.some((d) => d < 0) || new Set(days).size !== days.length) return null;\n return (days as Weekday[]).sort((a, b) => a - b);\n}\n\n/** An nth weekday: \"1TU\", \"-1FR\", or a plain day with BYSETPOS (Outlook's form); null for anything else. */\nfunction nthDay(byday: string, setpos: string | undefined): { week: WeekOfMonth; weekday: Weekday } | null {\n const m = /^([+-]?\\d)?(SU|MO|TU|WE|TH|FR|SA)$/.exec(byday);\n if (!m) return null;\n const week = m[1] !== undefined ? (setpos === undefined ? Number(m[1]) : NaN) : whole(setpos);\n if (week === null || ![1, 2, 3, 4, -1].includes(week)) return null;\n return { week: week as WeekOfMonth, weekday: DAY_CODES.indexOf(m[2] as (typeof DAY_CODES)[number]) as Weekday };\n}\n\n/** UNTIL as a date (its whole day), a floating date-time (local) or a UTC date-time. */\nfunction parseUntil(text: string): Date | null {\n const m = /^(\\d{4})(\\d{2})(\\d{2})(?:T(\\d{2})(\\d{2})(\\d{2})(Z)?)?$/.exec(text);\n if (!m) return null;\n const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];\n const date = m[4] === undefined ? new Date(y, mo, d) : m[7] ? new Date(Date.UTC(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]))) : new Date(y, mo, d, Number(m[4]), Number(m[5]), Number(m[6]));\n // a day the month doesn't have (20260231) rolls over into the next: not a date\n return Number.isNaN(date.getTime()) || (m[7] ? date.getUTCMonth() : date.getMonth()) !== mo ? null : date;\n}\n\n/**\n * The rule a string holds, or null when it is outside P5's subset (the event is then drawn once, its rule kept as written):\n * FREQ, INTERVAL and WKST; weekly BYDAY days; a monthly or yearly BYMONTHDAY, or one nth BYDAY (\"1TU\", or \"TU\" with\n * BYSETPOS=1); a yearly BYMONTH with either; UNTIL (a date, a floating or a UTC date-time) or COUNT. The \"RRULE:\" prefix\n * is optional. A daily rule with days (every weekday, as some apps write it) reads as weekly on them.\n */\nexport function parseRRule(text: string): Recurrence | null {\n if (typeof text !== \"string\") return null;\n const body = text.trim().replace(/^RRULE:/i, \"\");\n if (!body) return null;\n const parts = new Map<string, string>();\n for (const part of body.split(\";\")) {\n if (!part) continue;\n const at = part.indexOf(\"=\");\n const key = part.slice(0, at).toUpperCase();\n if (at <= 0 || parts.has(key) || !KNOWN_PARTS.has(key)) return null;\n parts.set(key, part.slice(at + 1).toUpperCase());\n }\n const freq = FREQS[parts.get(\"FREQ\") ?? \"\"];\n if (!freq) return null;\n const rule: Recurrence = { freq };\n if (parts.has(\"INTERVAL\")) {\n const n = whole(parts.get(\"INTERVAL\"));\n if (n === null || n < 1) return null;\n if (n > 1) rule.interval = n;\n }\n if (parts.has(\"WKST\")) {\n const d = DAY_CODES.indexOf(parts.get(\"WKST\") as (typeof DAY_CODES)[number]);\n if (d < 0) return null;\n if (d !== 1) rule.weekStart = d as Weekday;\n }\n if (parts.has(\"UNTIL\") && parts.has(\"COUNT\")) return null;\n if (parts.has(\"COUNT\")) {\n const n = whole(parts.get(\"COUNT\"));\n if (n === null || n < 1) return null;\n rule.count = n;\n }\n if (parts.has(\"UNTIL\")) {\n const until = parseUntil(parts.get(\"UNTIL\")!);\n if (!until) return null;\n rule.until = until;\n }\n const byday = parts.get(\"BYDAY\"), setpos = parts.get(\"BYSETPOS\"), monthday = parts.get(\"BYMONTHDAY\"), month = parts.get(\"BYMONTH\");\n if (freq === \"daily\" || freq === \"weekly\") {\n if (setpos !== undefined || monthday !== undefined || month !== undefined) return null;\n if (byday === undefined) return rule;\n if (freq === \"daily\" && rule.interval) return null;\n const days = plainDays(byday);\n if (!days) return null;\n return { ...rule, freq: \"weekly\", weekdays: days };\n }\n if (month !== undefined) {\n const m = whole(month);\n if (freq !== \"yearly\" || m === null || m < 1 || m > 12) return null;\n rule.month = m;\n }\n if (setpos !== undefined && byday === undefined) return null;\n if (byday !== undefined) {\n const nth = nthDay(byday, setpos);\n if (!nth || monthday !== undefined) return null;\n rule.nth = nth;\n } else if (monthday !== undefined) {\n const d = whole(monthday);\n if (d === null || !(d === -1 || (d >= 1 && d <= 31))) return null;\n rule.day = d;\n }\n // a yearly rule's day or weekday names its month, and a month names its day (the subset: no BYMONTH alone)\n if (freq === \"yearly\" && (rule.month === undefined) !== (rule.day === undefined && rule.nth === undefined)) return null;\n return rule;\n}\n\nconst pad = (n: number, width = 2) => String(n).padStart(width, \"0\");\n\n/**\n * The rule as an RRULE string, \"RRULE:FREQ=…\", for an iCalendar file or another app. UNTIL is written as a date for an\n * all-day event and in UTC for a timed one, as RFC 5545 asks.\n */\nexport function toRRule(rule: Recurrence, { allDay = false }: { allDay?: boolean } = {}): string {\n const out = [`FREQ=${rule.freq.toUpperCase()}`];\n if (rule.interval && rule.interval > 1) out.push(`INTERVAL=${rule.interval}`);\n if (rule.month !== undefined) out.push(`BYMONTH=${rule.month}`);\n if (rule.day !== undefined) out.push(`BYMONTHDAY=${rule.day}`);\n const weekStart = rule.weekStart ?? 1;\n if (rule.weekdays?.length) out.push(`BYDAY=${inWeekOrder(rule.weekdays, weekStart).map((d) => DAY_CODES[d]).join(\",\")}`);\n if (rule.nth) out.push(`BYDAY=${rule.nth.week}${DAY_CODES[rule.nth.weekday]}`);\n if (weekStart !== 1) out.push(`WKST=${DAY_CODES[weekStart]}`);\n if (rule.until) {\n const u = rule.until;\n out.push(allDay\n ? `UNTIL=${u.getFullYear()}${pad(u.getMonth() + 1)}${pad(u.getDate())}`\n : `UNTIL=${u.getUTCFullYear()}${pad(u.getUTCMonth() + 1)}${pad(u.getUTCDate())}T${pad(u.getUTCHours())}${pad(u.getUTCMinutes())}${pad(u.getUTCSeconds())}Z`);\n }\n if (rule.count !== undefined) out.push(`COUNT=${rule.count}`);\n return `RRULE:${out.join(\";\")}`;\n}\n\n/** The days from the week's first day: Monday-first [1, 2, …, 0]. */\nconst inWeekOrder = (days: readonly Weekday[], weekStart: Weekday) => [...days].sort((a, b) => ((a - weekStart + 7) % 7) - ((b - weekStart + 7) % 7));\n\n/**\n * A rule from a value: the object itself, the rule a string holds, or null for an unreadable string or none. A rule read\n * back from JSON (storage, an API) has its end as a string, which is read as the date it was; an end that isn't a date\n * makes the rule unreadable, so the event is drawn once rather than guessed at.\n */\nexport function readRecurrence(value: Recurrence | string | undefined | null): Recurrence | null {\n if (!value) return null;\n if (typeof value === \"string\") return parseRRule(value);\n if (value.until === undefined || value.until instanceof Date) return value;\n const until = new Date(value.until as unknown as string | number);\n return Number.isNaN(until.getTime()) ? null : { ...value, until };\n}\n\n// ── Dates by calendar arithmetic (P13: wall-clock times and whole days, never milliseconds) ──\n\nconst daysIn = (year: number, month: number) => new Date(year, month + 1, 0).getDate();\nconst atDay = (year: number, month: number, day: number, time: Date) => new Date(year, month, day, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());\nconst dayIndex = (d: Date) => Math.round(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / 864e5);\nconst isMidnight = (d: Date) => d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0;\n\n/** The day of a month an nth weekday falls on, or null when there is none. */\nfunction nthWeekdayOf(year: number, month: number, week: WeekOfMonth, weekday: Weekday): number | null {\n const last = daysIn(year, month);\n if (week === -1) return last - ((new Date(year, month, last).getDay() - weekday + 7) % 7);\n const day = 1 + ((weekday - new Date(year, month, 1).getDay() + 7) % 7) + (week - 1) * 7;\n return day <= last ? day : null;\n}\n\n/** The nth weekday a date is: the last when it is in its month's last seven days (a fifth Tuesday is the last). */\nexport function nthOf(date: Date): { week: WeekOfMonth; weekday: Weekday } {\n const d = date.getDate();\n return { week: d + 7 > daysIn(date.getFullYear(), date.getMonth()) ? -1 : (Math.ceil(d / 7) as WeekOfMonth), weekday: date.getDay() as Weekday };\n}\n\n/**\n * Every nth weekday a date is, for the choices: its week of the month, first to fourth, and the last when it is in its\n * month's last seven days. A fourth Wednesday on the 28th is both, as Outlook and Google offer; a fifth is only the last.\n */\nexport function nthChoices(date: Date): Array<{ week: WeekOfMonth; weekday: Weekday }> {\n const d = date.getDate(), weekday = date.getDay() as Weekday;\n const out: Array<{ week: WeekOfMonth; weekday: Weekday }> = [];\n if (d <= 28) out.push({ week: Math.ceil(d / 7) as WeekOfMonth, weekday });\n if (d + 7 > daysIn(date.getFullYear(), date.getMonth())) out.push({ week: -1, weekday });\n return out;\n}\n\n/** The week of the month a rule's nth weekday keeps on a moved date: the last stays the last while the date is in its month's last seven days. */\nfunction weekOnMoved(week: WeekOfMonth, to: Date): WeekOfMonth {\n const d = to.getDate();\n if (week === -1 && d + 7 > daysIn(to.getFullYear(), to.getMonth())) return -1;\n return d <= 28 ? (Math.ceil(d / 7) as WeekOfMonth) : -1;\n}\n\n/** Whether an occurrence starting at `at` is within the rule's end: a date at midnight includes its whole day. */\nfunction withinUntil(at: Date, until: Date): boolean {\n return at <= until || (isMidnight(until) && dayIndex(at) === dayIndex(until));\n}\n\n/**\n * Each occurrence's start, in order, from the event's own start, until `stop` returns true for a start or the rule ends\n * (UNTIL, or COUNT, which counts the excluded dates too). Exceptions are not removed here.\n */\nfunction* starts(rule: Recurrence, first: Date): Generator<Date> {\n const interval = Math.max(1, Math.floor(rule.interval ?? 1));\n const firstDay = dayIndex(first);\n let produced = 0;\n const accept = (d: Date) => {\n if (rule.until && !withinUntil(d, rule.until)) return false;\n return rule.count === undefined || produced < rule.count;\n };\n // the start is always the first occurrence (RFC 5545), even when the rule's end comes before it\n if (rule.count !== undefined && rule.count < 1) return;\n produced++;\n yield first;\n const y0 = first.getFullYear(), m0 = first.getMonth();\n // a bound on the periods looked at: 400 years of days, so a rule that never matches ends\n for (let k = 0, empty = 0; k < 146_100 && empty < 400 * 12; k++) {\n const dates: Date[] = [];\n if (rule.freq === \"daily\") dates.push(atDay(y0, m0, first.getDate() + k * interval, first));\n else if (rule.freq === \"weekly\") {\n const weekStart = rule.weekStart ?? 1;\n const base = first.getDate() - ((first.getDay() - weekStart + 7) % 7) + k * interval * 7;\n for (const wd of inWeekOrder(rule.weekdays?.length ? rule.weekdays : [first.getDay() as Weekday], weekStart)) dates.push(atDay(y0, m0, base + ((wd - weekStart + 7) % 7), first));\n } else {\n const monthsFrom = rule.freq === \"monthly\" ? k * interval : k * interval * 12;\n const at = new Date(y0, m0 + monthsFrom, 1);\n const year = at.getFullYear(), month = rule.freq === \"yearly\" && rule.month !== undefined ? rule.month - 1 : at.getMonth();\n let day: number | null;\n if (rule.nth) day = nthWeekdayOf(year, month, rule.nth.week, rule.nth.weekday);\n else if (rule.day === -1) day = daysIn(year, month);\n else day = rule.day ?? first.getDate();\n if (day !== null && day <= daysIn(year, month)) dates.push(atDay(year, month, day, first));\n }\n let any = false;\n for (const d of dates) {\n if (dayIndex(d) <= firstDay) continue;\n if (!accept(d)) return;\n produced++;\n any = true;\n yield d;\n }\n empty = any ? 0 : empty + 1;\n }\n}\n\n/** The number of whole days an event runs over, and its end's time of day, so each occurrence keeps both (P13). */\nfunction lengthOf(event: RepeatingEvent): { days: number; end: Date } | null {\n return event.end ? { days: dayIndex(event.end) - dayIndex(event.start), end: event.end } : null;\n}\n\n/** An occurrence starting on `start`'s day: the event's times on that day, its id and where it came from. */\nfunction occurrenceAt<T extends RepeatingEvent>(event: T, start: Date): Occurrence<T> {\n const { repeat: _repeat, exceptions: _exceptions, ...rest } = event;\n const length = lengthOf(event);\n const date = dayKey(start);\n const end = length ? atDay(start.getFullYear(), start.getMonth(), start.getDate() + length.days, length.end) : undefined;\n return { ...rest, id: `${event.id}::${date}`, start, ...(end ? { end } : {}), series: { id: event.id, date } } as Occurrence<T>;\n}\n\n/** Where an occurrence stops, for overlap: an all-day event's last day included, a timed one's end, or an hour. */\nfunction stopOf(event: { start: Date; end?: Date; allDay?: boolean }): Date {\n if (event.allDay) {\n const last = event.end ?? event.start;\n return new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1);\n }\n return event.end ?? new Date(event.start.getTime() + 36e5);\n}\n\n/**\n * Every occurrence of a repeating event that overlaps [from, to), in order: the event without its repeat fields, each\n * with the id \"<id>::<date>\", its own start and end (the same wall-clock times and number of days) and `series`, its\n * original date. Its excluded dates are left out. An event that doesn't repeat, or whose rule can't be read, is itself,\n * when it overlaps.\n */\nexport function occurrences<T extends RepeatingEvent>(event: T, from: Date, to: Date): Array<T | Occurrence<T>> {\n const rule = readRecurrence(event.repeat);\n if (!rule) return event.start < to && stopOf(event) > from ? [event] : [];\n const skip = new Set(event.exceptions ?? []);\n // starting one event-length earlier, so an occurrence that began before the range and runs into it is found\n const reach = stopOf(event).getTime() - event.start.getTime();\n const out: Occurrence<T>[] = [];\n for (const start of starts(rule, event.start)) {\n if (start >= to) break;\n // a day of slack: across a clock change an occurrence is an hour longer or shorter than the event\n if (start.getTime() + reach + 864e5 <= from.getTime()) continue;\n if (skip.has(dayKey(start))) continue;\n const occurrence = occurrenceAt(event, start);\n if (stopOf(occurrence) > from) out.push(occurrence);\n }\n return out;\n}\n\n/** The original dates a series produces, excluded ones included, before a day (a day key): for COUNT when it splits. */\nfunction startsBefore(rule: Recurrence, first: Date, date: string): number {\n let n = 0;\n for (const start of starts(rule, first)) {\n if (dayKey(start) >= date) break;\n n++;\n }\n return n;\n}\n\n/** A series' rule written back in the form it came in: a string stays a string. */\nconst asWritten = (event: RepeatingEvent, rule: Recurrence): Recurrence | string => (typeof event.repeat === \"string\" ? toRRule(rule, { allDay: event.allDay }) : rule);\n\n/** Shifts a day key by whole days. */\nconst shiftKey = (key: string, days: number) => {\n const [y, m, d] = key.split(\"-\").map(Number);\n return dayKey(new Date(y, m - 1, d + days));\n};\n\n/** The occurrence a series would have on a day key, whether or not the rule gives that day. */\nconst occurrenceOnDay = <T extends RepeatingEvent>(series: T, date: string): Occurrence<T> => {\n const [y, m, d] = date.split(\"-\").map(Number);\n return occurrenceAt(series, atDay(y, m - 1, d, series.start));\n};\n\n/** The page's events changed on their own from a series (\"This event\"): the ones its id links to it. */\nconst editedOf = <T extends RepeatingEvent>(events: readonly T[], seriesId: string): T[] => events.filter((e) => e.series?.id === seriesId && e.id !== seriesId);\n\n/**\n * The occurrence of a series on a day (a day key), or undefined when it has none that day (the rule skips it, or it is\n * excluded): for a page whose Edit has an address of its own, which carries the series' id and the date. Given the\n * page's events, an occurrence changed on its own on that date (\"This event\") is found too.\n */\nexport function occurrenceOn<T extends RepeatingEvent>(series: T, date: string, events?: readonly T[]): Occurrence<T> | undefined {\n const edited = events && editedOf(events, series.id).find((e) => e.series!.date === date);\n if (edited) return edited as unknown as Occurrence<T>;\n const [y, m, d] = date.split(\"-\").map(Number);\n return occurrences(series, new Date(y, m - 1, d), new Date(y, m - 1, d + 1)).find((o): o is Occurrence<T> => \"series\" in o && (o as Occurrence<T>).series?.date === date);\n}\n\n/** The fields an edit carries onto an event: never its id, its series or, for a one-off, its repeat fields. */\nconst editOf = <T extends RepeatingEvent>(changes: Partial<T> | undefined): Partial<T> => {\n if (!changes) return {};\n const { id: _id, repeat: _repeat, exceptions: _exceptions, ...rest } = changes as Partial<T> & { series?: unknown };\n delete (rest as { series?: unknown }).series;\n return rest as Partial<T>;\n};\n\n/** Whether an edit changes the series' rule: its repeat given, and not the same rule (an unreadable string the same string). */\nconst repeatChanged = <T extends RepeatingEvent>(series: T, changes: Partial<T> | undefined): boolean => {\n if (!changes || !(\"repeat\" in changes)) return false;\n const given = changes.repeat;\n if (given === series.repeat) return false;\n const a = readRecurrence(given), b = readRecurrence(series.repeat);\n return !(a && b && sameRecurrence(a, b));\n};\n\n/** Whether two field values are the same: dates by their moment, lists and objects by what they hold. */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();\n if (a && b && typeof a === \"object\" && typeof b === \"object\") return JSON.stringify(a) === JSON.stringify(b);\n return a === b;\n}\n\n/**\n * What the user changed: the fields of `changes` that differ from the event they opened (an occurrence, or one changed on\n * its own before), and the repeat when it isn't the series' rule. A form that hands back every field then changes only\n * what the user changed, and an occurrence changed on its own never passes its own changes to its series.\n */\nfunction editFrom<T extends RepeatingEvent>(opened: Occurrence<T> | T, series: T, changes: Partial<T>): Partial<T> {\n const was = opened as unknown as Record<string, unknown>;\n const edit: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(editOf(changes))) if (!sameValue(value, was[key])) edit[key] = value;\n if (repeatChanged(series, changes)) edit.repeat = changes.repeat;\n return edit as Partial<T>;\n}\n\n/**\n * A rule re-anchored on a moved date, as the implied forms move with the start: a weekly rule's days turn by the move,\n * a month's day or nth weekday and a year's month become the moved date's.\n */\nfunction moveRule(rule: Recurrence, days: number, to: Date): Recurrence {\n const next: Recurrence = { ...rule };\n if (rule.weekdays?.length) next.weekdays = rule.weekdays.map((d) => ((((d + days) % 7) + 7) % 7) as Weekday).sort((a, b) => a - b);\n if (rule.freq === \"monthly\" || rule.freq === \"yearly\") {\n if (rule.nth) next.nth = { week: weekOnMoved(rule.nth.week, to), weekday: to.getDay() as Weekday };\n else if (rule.day === -1) { if (to.getDate() !== daysIn(to.getFullYear(), to.getMonth())) next.day = to.getDate(); }\n else if (rule.day !== undefined) next.day = to.getDate();\n if (rule.freq === \"yearly\" && rule.month !== undefined) next.month = to.getMonth() + 1;\n }\n return next;\n}\n\n/**\n * Where a date of a series (a day key) goes when the series moves by `days` and its rule with it: the moved rule's own\n * date nearest the date `days` later, within a week. That is the shifted date itself, except for an nth weekday, whose\n * moved date can be up to a week away (a first Tuesday on the 7th, a day later, is the first Wednesday, the 1st). A date\n * the moved rule has none near (a day 31 in a month without one) is simply shifted.\n */\nfunction onMovedRule(rule: Recurrence, start: Date, days: number): (key: string) => string {\n const endless: Recurrence = { ...rule, until: undefined, count: undefined };\n return (key) => {\n const shifted = shiftKey(key, days);\n const [y, m, d] = shifted.split(\"-\").map(Number);\n const target = dayIndex(new Date(y, m - 1, d));\n let found: Date | null = null;\n for (const at of starts(endless, start)) {\n const i = dayIndex(at);\n if (i > target + 7) break;\n if (i >= target - 7 && (!found || Math.abs(i - target) < Math.abs(dayIndex(found) - target))) found = at;\n }\n return found ? dayKey(found) : shifted;\n };\n}\n\n/** A time of day, the same to the millisecond. */\nconst sameClock = (a: Date, b: Date) => a.getHours() === b.getHours() && a.getMinutes() === b.getMinutes() && a.getSeconds() === b.getSeconds() && a.getMilliseconds() === b.getMilliseconds();\n/** The whole days an event's end is after its start's day, or null without an end. */\nconst spanOf = (event: { start: Date; end?: Date }) => (event.end ? dayIndex(event.end) - dayIndex(event.start) : null);\n\n/** A series after an edit to one of its occurrences (updateSeries), and where each of its dates (a day key) went. */\nfunction changeSeries<T extends RepeatingEvent>(series: T, occurrence: Occurrence<T> | T | string, changes: Partial<T>): { next: T; moveKey: (key: string) => string } {\n const at = typeof occurrence === \"string\" ? occurrenceOnDay(series, occurrence) : occurrence;\n const { start: newStart, end: newEnd, ...rest } = editOf(changes) as Partial<T>;\n const next: T = { ...series, ...rest };\n // a moved day moves the series as many days, and a changed time is its new time: each measured from the event the user\n // opened, so the times an occurrence changed on its own had never reach the series when only its day moves\n const moveBy = (from: Date, to: Date, base: Date) => atDay(base.getFullYear(), base.getMonth(), base.getDate() + dayIndex(to) - dayIndex(from), sameClock(to, from) ? base : to);\n let days = 0;\n if (newStart) {\n days = dayIndex(newStart) - dayIndex(at.start);\n next.start = moveBy(at.start, newStart, series.start);\n }\n if (newEnd) {\n const from = at.end ?? at.start;\n next.end = moveBy(from, newEnd, series.end ?? series.start);\n }\n const rule = readRecurrence(series.repeat);\n let moveKey = (key: string) => shiftKey(key, days);\n const moveExceptions = () => { if (days !== 0 && series.exceptions?.length) next.exceptions = series.exceptions.map(moveKey); };\n if (repeatChanged(series, changes)) {\n if (changes.repeat) { next.repeat = changes.repeat; moveExceptions(); }\n else { delete next.repeat; delete next.exceptions; }\n } else if (days !== 0 && rule && newStart) {\n const moved = moveRule(rule, days, newStart);\n next.repeat = asWritten(series, moved);\n // an nth weekday a day later isn't always that weekday's same nth (a month starting on the new weekday makes the\n // first Tuesday's next day the second Wednesday): the series starts on the moved rule's first date from its moved\n // start, so its start is one of its dates and no stray date is left\n if (moved.nth) {\n const from = next.start;\n const anchor = (k: number) => {\n const at = new Date(from.getFullYear() + (moved.freq === \"yearly\" ? k : 0), (moved.freq === \"yearly\" && moved.month !== undefined ? moved.month - 1 : from.getMonth()) + (moved.freq === \"monthly\" ? k : 0), 1);\n const d = nthWeekdayOf(at.getFullYear(), at.getMonth(), moved.nth!.week, moved.nth!.weekday) ?? nthWeekdayOf(at.getFullYear(), at.getMonth(), -1, moved.nth!.weekday)!;\n return atDay(at.getFullYear(), at.getMonth(), d, from);\n };\n let first = anchor(0);\n if (dayIndex(first) < dayIndex(from)) first = anchor(1);\n const extra = dayIndex(first) - dayIndex(from);\n if (extra) {\n next.start = first;\n if (next.end) next.end = atDay(next.end.getFullYear(), next.end.getMonth(), next.end.getDate() + extra, next.end);\n }\n }\n // each excluded date goes to the moved rule's own date, so the occurrence it left out stays left out\n moveKey = onMovedRule(moved, next.start, days);\n moveExceptions();\n }\n return { next, moveKey };\n}\n\n/**\n * \"This and following\", and where each of the new half's dates went: `at` is the event the user opened (an occurrence,\n * or one changed on its own), or its date, which a move of the time or the day is measured from.\n */\nfunction splitWith<T extends RepeatingEvent>(series: T, date: string, id: string, at: Occurrence<T> | T | string, changes?: Partial<T>): { before?: T; after: T; moveKey: (key: string) => string } {\n const rule = readRecurrence(series.repeat);\n const firstDate = dayKey(series.start);\n if (!rule || date <= firstDate) {\n if (!changes) return { after: series, moveKey: (key) => key };\n const { next, moveKey } = changeSeries(series, typeof at === \"string\" ? (at <= firstDate ? firstDate : at) : at, changes);\n return { after: next, moveKey };\n }\n const [y, m, d] = date.split(\"-\").map(Number);\n const first = occurrenceOnDay(series, date);\n const exceptions = series.exceptions ?? [];\n const counted = rule.count !== undefined ? startsBefore(rule, series.start, date) : 0;\n const beforeRule: Recurrence = { ...rule };\n if (rule.count !== undefined) beforeRule.count = counted;\n else {\n delete beforeRule.until;\n // the day before, all of it: a date for an all-day event, its last second for a timed one (other apps read it exactly)\n beforeRule.until = series.allDay ? new Date(y, m - 1, d - 1) : new Date(y, m - 1, d - 1, 23, 59, 59);\n }\n const afterRule: Recurrence = { ...rule };\n if (rule.count !== undefined) afterRule.count = rule.count - counted;\n const before = { ...series, repeat: asWritten(series, beforeRule), exceptions: exceptions.filter((x) => x < date) };\n const after = { ...series, id, start: first.start, ...(first.end ? { end: first.end } : {}), repeat: asWritten(series, afterRule), exceptions: exceptions.filter((x) => x >= date) };\n if (!changes) return { before, after, moveKey: (key) => key };\n // the edit's repeat is the whole series' rule unless the user changed it: then the new half keeps its share of COUNT\n const edit = repeatChanged(series, changes) ? changes : editOf(changes);\n const { next, moveKey } = changeSeries(after, typeof at === \"string\" ? date : at, edit);\n return { before, after: next, moveKey };\n}\n\n/**\n * \"This event\": the series with the occurrence's date excluded, and the occurrence as an event of its own, with no repeat,\n * linked to the series by `series` (the series' id and the date), for the page to save beside the series under `id`\n * (give it one of your own; the default, \"<series id>-<date>\", is never an occurrence's), with the user's changes. There\n * is never a second series. Pages use saveOccurrence, which also finds the events changed on their own before.\n */\nexport function detachOccurrence<T extends RepeatingEvent>(series: T, date: string, id = `${series.id}-${date}`, changes?: Partial<T>): { series: T; event: Omit<T, \"repeat\" | \"exceptions\"> } {\n return {\n series: { ...series, exceptions: [...new Set([...(series.exceptions ?? []), date])].sort() },\n event: { ...(occurrenceOnDay(series, date) as unknown as Omit<T, \"repeat\" | \"exceptions\">), ...(editOf(changes) as object), id },\n };\n}\n\n/**\n * \"This and following events\": the series ends the day before `date` and a new one starts at it, under `id`, taking the\n * excluded dates from it on. With COUNT, each half counts its own share of the occurrences. Split at its first\n * occurrence, the series is replaced: there is no `before`, and `after` keeps the series' id. Together the two produce\n * the same dates as the series did. `changes`, the user's edit to the occurrence on `date`, apply to the new series as\n * updateSeries applies them: a move of the time or the day moves it, and its rule with it; its share of a COUNT stays\n * unless the edit changes the rule, which is then saved as given. Pages use saveOccurrence, which also moves the events\n * changed on their own with the new series.\n */\nexport function splitSeries<T extends RepeatingEvent>(series: T, date: string, id: string, changes?: Partial<T>): { before?: T; after: T } {\n const { before, after } = splitWith(series, date, id, date, changes);\n return before ? { before, after } : { after };\n}\n\n/**\n * \"All events\": the series with the changes made to one occurrence (the occurrence, or its date as a day key). A change\n * of time or day moves the series' start by the same amount, so every earlier date stays (a series saved as the edited\n * occurrence would lose them), and the rule moves with it: a weekly rule's days, a month's day or nth weekday and a\n * year's month become the moved date's, and each excluded date moves to the moved rule's own date. A changed repeat is\n * saved as given (the field writes it for the moved date already); a repeat taken away leaves one event, at the series'\n * start. Other changes (a title, a room) apply as they are. Pages use saveOccurrence, which also carries the events\n * changed on their own.\n */\nexport function updateSeries<T extends RepeatingEvent>(series: T, occurrence: Occurrence<T> | T | string, changes: Partial<T>): T {\n return changeSeries(series, occurrence, changes).next;\n}\n\n// ── Events changed on their own, linked to their series (the owner's answer of 3 October 2026: build it now) ──\n\n/** The fields `follow` leaves to the series' own bookkeeping. */\nconst NOT_FOLLOWED = new Set([\"id\", \"series\", \"start\", \"end\", \"repeat\", \"exceptions\"]);\n\n/**\n * An event changed on its own, after its series changed: what it changed itself stays (a field, another day, other\n * times), and what it still had from the series follows it, from `was` (the series' occurrence on its date before the\n * change) to `now` (after it), as Outlook's edited occurrences keep their own changes.\n */\nfunction follow<T extends RepeatingEvent>(edited: T, was: Occurrence<T>, now: Occurrence<T>): T {\n const out = { ...edited } as Record<string, unknown>;\n const before = was as unknown as Record<string, unknown>, after = now as unknown as Record<string, unknown>;\n for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {\n if (NOT_FOLLOWED.has(key) || !sameValue(out[key], before[key])) continue;\n if (after[key] === undefined) delete out[key];\n else out[key] = after[key];\n }\n // when it happens: its day, and its times (the start's, the end's and the days between), each its own if it changed it\n const ownDay = dayIndex(edited.start) !== dayIndex(was.start);\n const ownTimes = !sameClock(edited.start, was.start) || spanOf(edited) !== spanOf(was) || (!!edited.end && !!was.end && !sameClock(edited.end, was.end));\n const day = ownDay ? edited.start : now.start;\n const times = ownTimes ? edited : now;\n const start = atDay(day.getFullYear(), day.getMonth(), day.getDate(), times.start);\n out.start = start;\n const span = spanOf(times);\n if (times.end && span !== null) out.end = atDay(start.getFullYear(), start.getMonth(), start.getDate() + span, times.end);\n else delete out.end;\n return out as T;\n}\n\n/**\n * A series' events changed on their own, after the series changed from `old` to `next`, its dates moved by `moveKey`:\n * each stays linked, its date moved with the series' dates, and follows the change; the one the user opened takes their\n * edit too. When the repeat changed they go, as Outlook's do, and their dates go back to the new rule.\n */\nfunction carry<T extends RepeatingEvent>(old: T, next: T, linked: T[], moveKey: (key: string) => string, changed: boolean, opened: T | undefined, edit: Partial<T>): { next: T; save: T[]; remove: string[] } {\n if (!linked.length) return { next, save: [], remove: [] };\n if (changed) {\n const freed = new Set(linked.map((e) => moveKey(e.series!.date)));\n return { next: next.exceptions ? { ...next, exceptions: next.exceptions.filter((x) => !freed.has(x)) } : next, save: [], remove: linked.map((e) => e.id) };\n }\n const save = linked.map((e) => {\n const date = moveKey(e.series!.date);\n const followed = follow(e, occurrenceOnDay(old, e.series!.date), occurrenceOnDay(next, date));\n return { ...followed, ...(e.id === opened?.id ? editOf(edit) : {}), series: { id: next.id, date } } as T;\n });\n return { next, save, remove: [] };\n}\n\n/** An occurrence's series among the page's events (one whose rule the library reads), the stored event when it is one changed on its own, and its date. */\nfunction findSeries<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T): { series?: T; stored?: T; date?: string } {\n const stored = events.find((e) => e.id === occurrence.id);\n const link = (stored ?? occurrence).series;\n const series = link ? events.find((e) => e.id === link.id && readRecurrence(e.repeat) !== null) : undefined;\n return { series, stored, date: link?.date };\n}\n\n/** The page's events with `save` written (each by its id, a new one at the end) and `remove` taken out. */\nfunction commit<T extends RepeatingEvent>(events: readonly T[], save: T[], remove: string[]): RepeatChange<T> {\n const gone = new Set(remove);\n const saved = new Map(save.map((e) => [e.id, e]));\n const had = new Set(events.map((e) => e.id));\n return { events: [...events.filter((e) => !gone.has(e.id)).map((e) => saved.get(e.id) ?? e), ...save.filter((e) => !had.has(e.id))], save, remove };\n}\n\n/**\n * Saves the user's edit to an occurrence, for the scope they chose in RecurrenceScopeDialog: the page stores what it\n * returns. `occurrence` is the event they opened, one the Calendar handed over or one changed on its own before (the\n * page's own); `changes` the form's fields, every one or only those changed (only what differs from the opened event\n * applies); `newId` an id of the page's, for the event or the series a choice makes.\n * - \"This event\": the occurrence becomes an event of its own, linked to its series by `series`, its date left out of the\n * series; one changed on its own before just takes the edit.\n * - \"This and following events\": the series ends the day before and a new one starts on the date, under `newId`, with\n * the edit; the events changed on their own from the date on go with it.\n * - \"All events\": the series takes the edit, and a moved time or day moves it and its rule, so every earlier date stays.\n * The events changed on their own keep what they changed themselves (a field, another day, other times) and follow the\n * rest. A changed repeat removes them, as Outlook does, and their dates go back to the new rule (RecurrenceScopeDialog's\n * `edited` says so first); a deleted date stays deleted.\n */\nexport function saveOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope, changes: Partial<T>, newId: string): RepeatChange<T> {\n const { series, stored, date } = findSeries(events, occurrence);\n // no series the library can read: the event itself, if it is the page's\n if (!series || date === undefined) return commit(events, stored ? [{ ...stored, ...editOf(changes) }] : [], []);\n const opened = stored ?? occurrenceOnDay(series, date);\n const edit = editFrom(opened, series, changes);\n if (scope === \"this\") {\n if (stored) return commit(events, [{ ...stored, ...editOf(edit) }], []);\n const { series: kept, event } = detachOccurrence(series, date, newId, edit);\n return commit(events, [kept, event as unknown as T], []);\n }\n const linked = editedOf(events, series.id);\n const changed = repeatChanged(series, edit);\n // from the series' first date, \"This and following\" is all of it\n if (scope === \"following\" && date > dayKey(series.start)) {\n const { before, after, moveKey } = splitWith(series, date, newId, opened, edit);\n const carried = carry(series, after, linked.filter((e) => e.series!.date >= date), moveKey, changed, stored, edit);\n return commit(events, [...(before ? [before] : []), carried.next, ...carried.save], carried.remove);\n }\n const { next, moveKey } = changeSeries(series, opened, edit);\n const carried = carry(series, next, linked, moveKey, changed, stored, edit);\n return commit(events, [carried.next, ...carried.save], carried.remove);\n}\n\n/**\n * Deletes an occurrence, for the scope the user chose in RecurrenceScopeDialog: the page stores what it returns. \"This\n * event\" leaves its date out of the series (an event changed on its own is removed, and its date stays empty); \"This\n * and following events\" ends the series the day before and removes the events changed on their own from the date on;\n * \"All events\" removes the series and every event changed on its own.\n */\nexport function deleteOccurrence<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T, scope: RecurrenceScope): RepeatChange<T> {\n const { series, stored, date } = findSeries(events, occurrence);\n if (!series || date === undefined) return commit(events, [], stored ? [stored.id] : []);\n if (scope === \"this\") return stored ? commit(events, [], [stored.id]) : commit(events, [detachOccurrence(series, date).series], []);\n const linked = editedOf(events, series.id);\n if (scope === \"following\" && date > dayKey(series.start)) {\n const { before } = splitWith(series, date, series.id, date);\n return commit(events, before ? [before] : [], linked.filter((e) => e.series!.date >= date).map((e) => e.id));\n }\n return commit(events, [], [series.id, ...linked.map((e) => e.id)]);\n}\n\n/**\n * How many of a series' events changed on their own each scope covers, for RecurrenceScopeDialog's `edited`: \"This and\n * following events\" those from the occurrence's date on, \"All events\" every one.\n */\nexport function countEdited<T extends RepeatingEvent>(events: readonly T[], occurrence: Occurrence<T> | T): { following: number; all: number } {\n const { series, date } = findSeries(events, occurrence);\n if (!series || date === undefined) return { following: 0, all: 0 };\n const linked = editedOf(events, series.id);\n return { following: date > dayKey(series.start) ? linked.filter((e) => e.series!.date >= date).length : linked.length, all: linked.length };\n}\n\n// ── In words: names and dates in the page's language, the words the library's English (as 25.18's F2) ──\n\nconst formats = localeCache<Intl.DateTimeFormat>(128);\nfunction format(options: Intl.DateTimeFormatOptions, date: Date, locale: string | undefined): string {\n return formats(`${locale ?? \"\"}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options)).format(date);\n}\nconst weekdayName = (d: Weekday, locale: string | undefined) => format({ weekday: \"long\" }, new Date(2026, 0, 4 + d), locale);\nconst monthName = (m: number, locale: string | undefined) => format({ month: \"long\" }, new Date(2026, m - 1, 1), locale);\nconst ORDINAL: Record<WeekOfMonth, string> = { 1: \"first\", 2: \"second\", 3: \"third\", 4: \"fourth\", [-1]: \"last\" } as Record<WeekOfMonth, string>;\nconst list = (items: string[]) => (items.length < 2 ? items.join(\"\") : `${items.slice(0, -1).join(\", \")} and ${items[items.length - 1]}`);\nconst every = (n: number, one: string, many: string) => (n > 1 ? `Every ${n} ${many}` : `Every ${one}`);\n\n/**\n * The rule in words, for its date: \"Every week on Tuesday and Thursday, until 30 November 2026\", \"Every month on the\n * first Tuesday\", \"Every year on 6 October\". The days and dates are written in the locale given (a component's\n * useFormatLocale(), Sprint 25.20), else the browser's reading of the page's language.\n */\nexport function describeRecurrence(rule: Recurrence, start: Date, locale: string | undefined = formatLocale()): string {\n const n = Math.max(1, Math.floor(rule.interval ?? 1));\n const weekStart = rule.weekStart ?? 1;\n let text: string;\n if (rule.freq === \"daily\") text = every(n, \"day\", \"days\");\n else if (rule.freq === \"weekly\") {\n const days = inWeekOrder(rule.weekdays?.length ? rule.weekdays : [start.getDay() as Weekday], weekStart);\n if (days.length === 7) text = every(n, \"day\", \"weeks on every day\");\n else if (n === 1 && days.join() === \"1,2,3,4,5\") text = \"Every weekday (Monday to Friday)\";\n else text = `${every(n, \"week\", \"weeks\")} on ${list(days.map((d) => weekdayName(d, locale)))}`;\n } else {\n const nth = rule.nth ? `the ${ORDINAL[rule.nth.week]} ${weekdayName(rule.nth.weekday, locale)}` : undefined;\n if (rule.freq === \"monthly\") {\n const on = nth ?? (rule.day === -1 ? \"the last day\" : `day ${rule.day ?? start.getDate()}`);\n text = `${every(n, \"month\", \"months\")} on ${on}`;\n } else {\n const month = rule.month ?? start.getMonth() + 1;\n const on = nth ? `${nth} of ${monthName(month, locale)}` : rule.day === -1 ? `the last day of ${monthName(month, locale)}` : // a leap year, so 29 February reads as itself\n format({ day: \"numeric\", month: \"long\" }, new Date(2028, month - 1, rule.day ?? start.getDate()), locale);\n text = `${every(n, \"year\", \"years\")} on ${on}`;\n }\n }\n if (rule.until) text += `, until ${format({ day: \"numeric\", month: \"long\", year: \"numeric\" }, rule.until, locale)}`;\n else if (rule.count !== undefined) text += rule.count === 1 ? \", once\" : `, ${rule.count} times`;\n return text;\n}\n\nexport interface RecurrencePreset {\n /** The choice in words, as describeRecurrence writes it for the date. */\n label: string;\n rule: Recurrence;\n}\n\n/**\n * The quick choices for a date, each one including it (P6): every day; every weekday, for a weekday; every week on its\n * weekday; every month on its nth weekday (the fourth and \"the last\" both for a fourth one in a month's last seven days,\n * only \"the last\" for a fifth); every month on its date, and on the last day when it is one; every year on its\n * anniversary. The weekly, monthly-by-date and yearly choices are the\n * implied form, so they follow the date when the event moves.\n */\nexport function recurrencePresets(start: Date, locale: string | undefined = formatLocale()): RecurrencePreset[] {\n const rules: Recurrence[] = [{ freq: \"daily\" }];\n const weekday = start.getDay();\n if (weekday >= 1 && weekday <= 5) rules.push({ freq: \"weekly\", weekdays: [1, 2, 3, 4, 5] });\n rules.push({ freq: \"weekly\" }, ...nthChoices(start).map((nth): Recurrence => ({ freq: \"monthly\", nth })), { freq: \"monthly\" });\n if (start.getDate() === daysIn(start.getFullYear(), start.getMonth())) rules.push({ freq: \"monthly\", day: -1 });\n rules.push({ freq: \"yearly\" });\n return rules.map((rule) => ({ rule, label: describeRecurrence(rule, start, locale) }));\n}\n\n/** Whether two rules repeat the same way (an `until` compared by its moment). */\nexport function sameRecurrence(a: Recurrence | null | undefined, b: Recurrence | null | undefined): boolean {\n if (!a || !b) return a === b;\n const norm = (r: Recurrence) => toRRule({ ...r, weekdays: r.weekdays?.length ? [...r.weekdays].sort() : undefined });\n return norm(a) === norm(b);\n}\n","import { formatLocale } from \"./format-locale\";\n\n/**\n * Time zones by the browser's own names, and their offsets (Sprint 25.17 A28), apart from the TimezoneSelect component since\n * Sprint 25.22 so a server can call them: nothing here needs React. `gridsmith-ui/utils` exports canonicalTimeZone and\n * timeZoneOffset for server code; browserTimeZone reads the zone of whatever runs it, a server's own there.\n */\n\n/**\n * The browser's own name for a zone (Sprint 25.17 A28, R28-51): one browser always names a zone one way, so a stored\n * \"Asia/Calcutta\" and a listed \"Asia/Kolkata\" are one zone, with no alias table shipped. An id the browser doesn't know\n * stays as given.\n */\nexport function canonicalTimeZone(zone: string): string {\n try {\n return new Intl.DateTimeFormat(\"en-US\", { timeZone: zone }).resolvedOptions().timeZone;\n } catch {\n return zone;\n }\n}\n\n/** The browser's time zone, by its own name; \"UTC\" where the browser names none. On a server, the server's zone. */\nexport function browserTimeZone(): string {\n try {\n return canonicalTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone || \"UTC\");\n } catch {\n return \"UTC\";\n }\n}\n\n/**\n * A zone's offset from UTC at an instant, as the locale given names it (\"GMT+1\", \"GMT-5\", \"GMT+5:30\"; a component's\n * useFormatLocale(), else the browser's reading): read at that instant, so it follows daylight saving.\n */\nexport function timeZoneOffset(zone: string, at: Date = new Date(), locale: string | undefined = formatLocale()): string {\n try {\n return new Intl.DateTimeFormat(locale, { timeZone: zone, timeZoneName: \"shortOffset\" }).formatToParts(at).find((p) => p.type === \"timeZoneName\")?.value ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/** Every zone the browser knows, each once by its own name, UTC always among them; UTC first, then by name. */\nexport function timeZones(): string[] {\n const listed = typeof Intl.supportedValuesOf === \"function\" ? Intl.supportedValuesOf(\"timeZone\") : [];\n const zones = [...new Set(listed.map(canonicalTimeZone))].filter((z) => z !== \"UTC\").sort((a, b) => a.localeCompare(b));\n return [\"UTC\", ...zones];\n}\n","import { formatLocale } from \"./format-locale\";\nimport { localeCache } from \"./locale-cache\";\n\n/**\n * Calendar days, and ranges of them in words (Sprint 25.7, Part D). A calendar day is a whole-number day index: days since\n * 1970-01-01, counted on UTC day boundaries, so every day is the same width and a clock change never stretches or shrinks\n * one. A \"YYYY-MM-DD\" string is a calendar day in the user's zone and is never parsed as UTC (new Date(\"2026-03-03\") is\n * 2 March, 19:00 in New York). Apart from the time scale (lib/time-scale.ts) since Sprint 25.22, so a server can call\n * them: nothing here needs React or a browser, and `gridsmith-ui/utils` exports them for server code. On a server a Date\n * or a date-time string is read in the server's time zone; a calendar day or a day index is the same everywhere.\n */\n\n/** A Date, or a string: \"YYYY-MM-DD\" is a calendar day; any other string is a date-time. */\nexport type DateInput = Date | string;\nexport type TimeZoom = \"day\" | \"week\" | \"month\" | \"quarter\";\n/** Narrow to wide. */\nexport const TIME_ZOOMS: readonly TimeZoom[] = [\"day\", \"week\", \"month\", \"quarter\"];\n\nexport const DAY_MS = 86_400_000;\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport const utcDay = (y: number, m: number, d: number) => Math.round(Date.UTC(y, m, d) / DAY_MS);\n\nfunction dayOfDate(d: Date): number {\n const t = d.getTime();\n if (Number.isNaN(t)) return NaN;\n const day = utcDay(d.getFullYear(), d.getMonth(), d.getDate());\n // The first instant of the local day is the whole day, also where a clock change skips midnight (Chile, Cuba, Egypt\n // and Lebanon in spring): there a date picker's \"midnight\" is 01:00.\n const first = new Date(t);\n first.setHours(0, 0, 0, 0);\n if (first.getTime() === t) return day;\n const ms = ((d.getHours() * 60 + d.getMinutes()) * 60 + d.getSeconds()) * 1000 + d.getMilliseconds();\n return day + ms / DAY_MS;\n}\n\n/**\n * The day index of a date: \"2026-03-03\" → that calendar day's index; a Date or a date-time string → its local calendar\n * day plus the fraction of the day its local clock shows (a day's first instant is the whole day); a number is a day\n * index already, as the scale's own functions take it. NaN for anything else: null from JSON, a string that is no date.\n */\nexport function dayOf(value: DateInput | number): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : NaN;\n if (value instanceof Date) return dayOfDate(value);\n if (typeof value !== \"string\") return NaN;\n const m = DATE_ONLY.exec(value.trim());\n if (!m) return dayOfDate(new Date(value));\n const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];\n const day = utcDay(y, mo, d);\n const back = new Date(day * DAY_MS);\n return back.getUTCFullYear() === y && back.getUTCMonth() === mo && back.getUTCDate() === d ? day : NaN;\n}\n\n/** Local midnight of that calendar day; a fraction adds that much of the day on the local clock. */\nexport function dateOfDay(day: number): Date {\n const whole = Math.floor(day);\n const u = new Date(whole * DAY_MS);\n return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));\n}\n\n/**\n * Whether a value is read in the visitor's time zone (Sprint 25.20 D3): a Date, or a date string with a time of day, whose\n * local day a server doesn't know. A calendar day (\"2026-03-03\") and a day index are the same everywhere.\n */\nexport function isZoned(value: DateInput | number | null | undefined): boolean {\n if (value instanceof Date) return !Number.isNaN(value.getTime());\n if (typeof value !== \"string\") return false;\n const text = value.trim();\n return !DATE_ONLY.test(text) && !Number.isNaN(new Date(text).getTime());\n}\n\n/** A whole day: a \"YYYY-MM-DD\" string, a Date at the start of its local day or a whole day index. */\nfunction isWholeDay(value: DateInput | number): boolean {\n return typeof value === \"string\" ? DATE_ONLY.test(value.trim()) : Number.isInteger(dayOf(value));\n}\n\n/**\n * Where a range that ends at `value` stops. A whole-day end is inclusive: \"2026-03-14\" (or a Date at local midnight,\n * as the date pickers give) → the start of 15 March. A date-time end is half-open: it stops at that moment, as a day\n * index does. A range's start can make a midnight Date half-open too (scale.span, formatDateRange, timeExtent).\n */\nexport function endDayOf(value: DateInput | number): number {\n const day = dayOf(value);\n return typeof value !== \"number\" && isWholeDay(value) ? day + 1 : day;\n}\n\n/**\n * Where a range from `start` stops at `end`. A Date at local midnight is an inclusive whole day after a whole-day start\n * (a date picker's range), and the moment the range stops after a time of day (an evening shift that ends at midnight).\n */\nexport function rangeEnd(start: DateInput | number, end: DateInput | number): number {\n return end instanceof Date && !isWholeDay(start) ? dayOf(end) : endDayOf(end);\n}\n\n// ─── Formats ────────────────────────────────────────────────────────────────\n\nconst formats = localeCache<Intl.DateTimeFormat>(128);\n\n/**\n * A formatter for calendar days in the locale, else the page's language (formatLocale). Day indices are UTC days, so they\n * are formatted in UTC.\n */\nexport function dayFormatter(given: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const locale = given ?? formatLocale();\n return formats(`${locale ?? \"\"}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, { ...options, timeZone: \"UTC\" }));\n}\n\n// ─── Ranges ─────────────────────────────────────────────────────────────────\n\n/**\n * The earliest start and the latest end of some ranges, as day indices for useTimeScale: the end is where the last\n * range stops (inclusive for a whole day, as endDayOf), and a range with no end ends where it starts (a milestone).\n * NaN for no dated range, which the scale shows as today. A range, a start or an end that is null is skipped.\n */\nexport function timeExtent(ranges: Iterable<{ start: DateInput; end?: DateInput }>): { start: number; end: number } {\n let start = Infinity;\n let end = -Infinity;\n for (const r of ranges) {\n if (r == null) continue;\n const s = dayOf(r.start);\n const e = r.end == null ? endDayOf(r.start) : rangeEnd(r.start, r.end);\n if (Number.isFinite(s)) start = Math.min(start, s);\n if (Number.isFinite(e)) end = Math.max(end, e);\n }\n return Number.isFinite(start) && Number.isFinite(end) ? { start, end: Math.max(start, end) } : { start: NaN, end: NaN };\n}\n\nexport interface DateRangeWords {\n locale?: string;\n /** Joins the two ends in place of Intl's separator. Default \" to \" in English, and Intl's own separator elsewhere. */\n to?: string;\n /** Intl options for the days. Default { day: \"numeric\", month: \"long\" }; the year is added when the ends' years differ. */\n day?: Intl.DateTimeFormatOptions;\n /** Intl options for the times of a date-time range. Default { hour: \"2-digit\", minute: \"2-digit\" }. */\n time?: Intl.DateTimeFormatOptions;\n}\n\nconst DAY_WORDS: Intl.DateTimeFormatOptions = { day: \"numeric\", month: \"long\" };\nconst TIME_WORDS: Intl.DateTimeFormatOptions = { hour: \"2-digit\", minute: \"2-digit\" };\n\n/** A range's own separator: a dash or a tilde, and the spaces either side of it. */\nconst SEPARATOR = /\\s*[\\u2010-\\u2015\\u2212~\\uff5e\\u301c-]\\s*/;\n\nconst english = (f: Intl.DateTimeFormat) => new Intl.Locale(f.resolvedOptions().locale).language === \"en\";\n\n/**\n * `f` over two instants. With `to`, only the separator between the ends is replaced: the literal there can carry the\n * start's own closing mark too (ja-JP's \")~\", de-DE's \".–\"), which stays.\n */\nfunction range(f: Intl.DateTimeFormat, a: Date, b: Date, to: string | undefined): string {\n if (typeof f.formatRangeToParts !== \"function\") return to === undefined ? f.formatRange(a, b) : `${f.format(a)}${to}${f.format(b)}`;\n const parts = f.formatRangeToParts(a, b);\n const lastOfStart = parts.map((p) => p.source).lastIndexOf(\"startRange\");\n const firstOfEnd = parts.findIndex((p) => p.source === \"endRange\");\n // Intl names one day once when the two are the same instant in its terms\n if (lastOfStart < 0 || firstOfEnd < 0) return f.format(a);\n if (to === undefined) return parts.map((p) => p.value).join(\"\");\n let joined = false;\n const out = parts.map((p, i) => {\n if (joined || i <= lastOfStart || i >= firstOfEnd || !SEPARATOR.test(p.value)) return p.value;\n joined = true;\n return p.value.replace(SEPARATOR, to);\n });\n // no separator between the ends to replace: `to` goes after the start\n if (!joined) out.splice(lastOfStart + 1, 0, to);\n return out.join(\"\");\n}\n\n/**\n * A range in words, in the locale, for accessible names: \"3 to 14 March\", \"28 September to 3 October\", \"16 September\"\n * for one day. The end is inclusive for a whole day, as scale.span (a day index is where the range stops). A date-time\n * range is named by its times, and the end's day only when it differs: \"Friday 23 October, 06:00 to 14:00\". Intl\n * joins each day and time in the locale's own way, and outside English the two ends too (\"10/31(土曜日)~11/01(日曜日)\");\n * the year shows when the two ends are in different years. A null end is the start's own day; a start that is no date\n * gives \"\".\n */\nexport function formatDateRange(start: DateInput | number, end?: DateInput | number, words?: DateRangeWords): string {\n const { locale, to, day = DAY_WORDS, time = TIME_WORDS } = words ?? {};\n const until = end ?? start;\n const from = dayOf(start);\n const stop = rangeEnd(start, until);\n if (!Number.isFinite(from) || !Number.isFinite(stop)) return \"\";\n const timed = !isWholeDay(start) || !isWholeDay(until);\n const first = timed ? from : Math.floor(from);\n const last = timed ? Math.max(from, stop) : Math.max(first, Math.ceil(stop) - 1);\n const a = new Date(first * DAY_MS);\n const b = new Date(last * DAY_MS);\n const years = a.getUTCFullYear() !== b.getUTCFullYear() && day.year === undefined;\n const f = dayFormatter(locale, { ...day, ...(years ? { year: \"numeric\" } : {}), ...(timed ? time : {}) });\n return first === last ? f.format(a) : range(f, a, b, to ?? (english(f) ? \" to \" : undefined));\n}\n","/**\n * Sprint 25.9, A3 — what a chart's category axis holds, and how its labels fit. No Recharts here: the charts entry and\n * the tests import it, and it never measures on its own (the measurer is handed in).\n *\n * - `categoryKind(labels)`: \"scale\" when every non-empty label is a date, a time, a period or a number, else \"names\".\n * Anchored patterns only — never `Date.parse`, which V8 lets read \"Tier 1\", \"Sprint 1\" and \"Northern Region 2\" as dates.\n * - `createAxisMeasurer(el)`: canvas text widths in the axis's resolved font, read from a probe that carries\n * `font-size: var(--ds-font-size-xs)`, so a `calc()` token (`calc(16px * .75)`, a 14 px base) measures right.\n * - `fitLabel(name, width, measure)`: one line; else two lines split at a space; else \"…\" on the second. Never drops it.\n */\n\nexport type CategoryKind = \"names\" | \"scale\";\n\n/** A text's width in px in the axis font. */\nexport type Measure = (text: string) => number;\n\nconst ENGLISH_MONTHS = [\n \"january\", \"february\", \"march\", \"april\", \"may\", \"june\", \"july\", \"august\", \"september\", \"october\", \"november\", \"december\",\n \"jan\", \"feb\", \"mar\", \"apr\", \"jun\", \"jul\", \"aug\", \"sep\", \"sept\", \"oct\", \"nov\", \"dec\",\n];\nconst ENGLISH_WEEKDAYS = [\n \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\", \"sunday\",\n \"mon\", \"tue\", \"tues\", \"wed\", \"thu\", \"thur\", \"thurs\", \"fri\", \"sat\", \"sun\",\n];\n\nconst escape = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\nconst clean = (s: string) => s.trim().toLowerCase().replace(/\\.$/, \"\");\n\nfunction intlNames(locale: string, kind: \"month\" | \"weekday\"): string[] {\n const out: string[] = [];\n try {\n for (const width of [\"short\", \"long\"] as const) {\n const fmt = new Intl.DateTimeFormat(locale, kind === \"month\" ? { month: width, timeZone: \"UTC\" } : { weekday: width, timeZone: \"UTC\" });\n // 2026-01-05 is a Monday: seven days give the weekdays, the 15th of each month the months\n const count = kind === \"month\" ? 12 : 7;\n for (let i = 0; i < count; i++) {\n const date = kind === \"month\" ? new Date(Date.UTC(2026, i, 15)) : new Date(Date.UTC(2026, 0, 5 + i));\n out.push(clean(fmt.format(date)));\n }\n }\n } catch {\n // an unknown locale tag: English covers it\n }\n return out;\n}\n\n/**\n * The languages whose month and weekday names count: English, and the locale given (a chart's locale while a\n * server-rendered page hydrates, the same on both sides: Sprint 25.20); with none given, the runtime's, the browser's and\n * the page's, as an app's own call and a chart in the browser read them (labels in the visitor's own language count).\n */\nfunction locales(given?: string): string[] {\n const out = new Set<string>([\"en\"]);\n if (given !== undefined) {\n out.add(given);\n return [...out];\n }\n try { out.add(new Intl.DateTimeFormat().resolvedOptions().locale); } catch { /* no Intl locale */ }\n if (typeof navigator !== \"undefined\" && navigator.language) out.add(navigator.language);\n if (typeof document !== \"undefined\" && document.documentElement?.lang) out.add(document.documentElement.lang);\n return [...out];\n}\n\ninterface Patterns { key: string; list: RegExp[] }\nlet cached: Patterns | null = null;\n\nfunction patterns(given?: string): Patterns {\n const tags = locales(given);\n const key = tags.join(\"|\");\n if (cached?.key === key) return cached;\n const months = new Set(ENGLISH_MONTHS);\n const weekdays = new Set(ENGLISH_WEEKDAYS);\n for (const tag of tags) {\n for (const m of intlNames(tag, \"month\")) if (m) months.add(m);\n for (const d of intlNames(tag, \"weekday\")) if (d) weekdays.add(d);\n }\n // the longest first, so \"sept\" wins over \"sep\" and \"june\" over \"jun\"\n const alt = (set: Set<string>) => [...set].sort((a, b) => b.length - a.length).map(escape).join(\"|\");\n const M = `(?:${alt(months)})\\\\.?`;\n const D = `(?:${alt(weekdays)})\\\\.?`;\n const day = String.raw`\\d{1,2}(?:st|nd|rd|th|\\.)?`;\n const year = String.raw`'?\\d{2,4}`;\n const list = [\n // dates in digits: 2026-09-21, 21/09, 09/21/2026, 21.09.2026, an ISO date-time\n /^\\d{4}[-/.]\\d{1,2}(?:[-/.]\\d{1,2})?$/,\n /^\\d{1,2}[-/.]\\d{1,2}(?:[-/.]\\d{2,4})?$/,\n /^\\d{4}-\\d{2}-\\d{2}[T ]\\d{1,2}:\\d{2}(?::\\d{2}(?:\\.\\d+)?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/,\n // a day and a month in either order, and a month alone or with its year: 16 Sep, 21. Sept., Sept 21, March 2026\n new RegExp(`^${day}\\\\s*${M}(?:,?\\\\s+${year})?$`, \"iu\"),\n new RegExp(`^${M}\\\\s*${day}(?:,?\\\\s+${year})?$`, \"iu\"),\n new RegExp(`^${M}(?:\\\\s*${year})?$`, \"iu\"),\n // CJK dates: 9月21日, 2026年9月, 9월 21일\n /^(?:\\d{4}年)?\\d{1,2}月(?:\\d{1,2}日)?$/u,\n /^\\d{4}年(?:\\d{1,2}月)?$/u,\n /^(?:\\d{4}년\\s?)?\\d{1,2}월(?:\\s?\\d{1,2}일)?$/u,\n // a quarter or a half: Q3, Q3 2026, Q3 FY26, 2026 Q3, 3Q26, H1 2026\n /^Q[1-4](?:\\s*[-/']?\\s*(?:FY\\s?)?'?\\d{2,4})?$/i,\n /^[1-4]Q\\s*'?\\d{0,4}$/i,\n /^(?:FY\\s?)?'?\\d{2,4}\\s*[-/]?\\s*Q[1-4]$/i,\n /^H[12](?:\\s*'?\\d{2,4})?$/i,\n // a year or a fiscal year: 2026, FY26, FY 2025/26, 2025/26, 2025-2026\n /^(?:19|20)\\d{2}$/,\n /^FY\\s?'?\\d{2,4}(?:\\s?[-/]\\s?'?\\d{2,4})?$/i,\n /^(?:19|20)\\d{2}\\s?[-/–]\\s?(?:(?:19|20)?\\d{2})$/,\n // a week: W12, Wk 3, Week 12, Week 12 2026, 2026-W12\n /^(?:W|Wk|Week)\\.?\\s?\\d{1,2}(?:\\s*[,/-]?\\s*\\d{4})?$/i,\n /^\\d{4}-?W\\d{1,2}(?:-?\\d)?$/i,\n // a weekday: Mon, Tuesday, and the runtime and page locales' own\n new RegExp(`^${D}$`, \"iu\"),\n // a time: 09:00, 9:30 pm, 9am, 14h\n /^\\d{1,2}:\\d{2}(?::\\d{2})?\\s?(?:[ap]\\.?m\\.?)?$/i,\n /^\\d{1,2}\\s?[ap]\\.?m\\.?$/i,\n /^\\d{1,2}h(?:\\d{2})?$/i,\n // a number, a percentage or an amount: 12, -3.5, 1,200, 12%, $5k, €1.2m, 5 €, a bin (10–20, <10, 50+)\n /^[<>≤≥~]?\\s?[+\\-−]?\\s?[$€£¥₹]?\\s?\\d[\\d,. \\u00a0\\u202f]*(?:\\s?(?:k|m|mn|bn|b|t))?\\s?(?:%|[$€£¥₹])?\\+?$/iu,\n /^[$€£¥₹]?\\d[\\d,.]*\\s?[-–]\\s?[$€£¥₹]?\\d[\\d,.]*\\s?(?:k|m|bn|%)?$/iu,\n ];\n cached = { key, list };\n return cached;\n}\n\n/**\n * Whether a category axis holds names or a scale (dates, times, periods, numbers). Every non-empty label must match an\n * anchored pattern to be \"scale\"; an all-empty set is \"scale\". LineChart and AreaChart are always \"scale\"; BarChart and\n * CompositeChart guess with this, and their `categoryKind` prop overrides the guess.\n */\nexport function categoryKind(labels: ReadonlyArray<unknown>, locale?: string): CategoryKind {\n const { list } = patterns(locale);\n for (const raw of labels) {\n if (raw == null) continue;\n if (typeof raw === \"number\") { if (Number.isFinite(raw)) continue; return \"names\"; }\n if (raw instanceof Date) continue;\n const text = String(raw).trim();\n if (!text) continue;\n if (!list.some((re) => re.test(text))) return \"names\";\n }\n return \"scale\";\n}\n\n/* ── Measuring ──────────────────────────────────────────────────────────── */\n\n/** The axis font as the page resolves it: size and family from a probe carrying the chart's tick tokens. */\nexport function resolvedAxisFont(el: Element): { font: string; px: number } {\n const doc = el.ownerDocument;\n const view = doc.defaultView;\n let probe = el.querySelector<HTMLElement>(\"[data-chart-probe]\");\n let temporary = false;\n if (!probe) {\n probe = doc.createElement(\"span\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n probe.style.cssText = \"position:absolute;visibility:hidden;pointer-events:none;white-space:nowrap;font-size:var(--ds-font-size-xs);font-family:var(--ds-font-sans)\";\n el.appendChild(probe);\n temporary = true;\n }\n const cs = view?.getComputedStyle(probe);\n const px = parseFloat(cs?.fontSize ?? \"\") || 12;\n const family = (cs?.fontFamily ?? \"\").trim() || \"sans-serif\";\n const style = cs?.fontStyle && cs.fontStyle !== \"normal\" ? `${cs.fontStyle} ` : \"\";\n const weight = cs?.fontWeight && cs.fontWeight !== \"400\" && cs.fontWeight !== \"normal\" ? `${cs.fontWeight} ` : \"\";\n if (temporary) probe.remove();\n return { font: `${style}${weight}${px}px ${family}`, px };\n}\n\n/** One 2D context for every chart, kept per getContext implementation (a test may swap it for a stub). */\nlet shared: { getContext: unknown; ctx: CanvasRenderingContext2D | null } | null = null;\n\nfunction canvasContext(): CanvasRenderingContext2D | null {\n if (typeof document === \"undefined\") return null;\n const getContext = (globalThis as { HTMLCanvasElement?: { prototype: { getContext?: unknown } } }).HTMLCanvasElement?.prototype.getContext;\n if (shared && shared.getContext === getContext) return shared.ctx;\n let ctx: CanvasRenderingContext2D | null = null;\n try { ctx = document.createElement(\"canvas\").getContext?.(\"2d\") ?? null; } catch { ctx = null; }\n shared = { getContext, ctx };\n return ctx;\n}\n\n/**\n * A text measurer in the chart's own axis font, or null where there is no canvas (jsdom): the charts then show every\n * label in full on one line and leave the thinning to nobody.\n */\nexport function createAxisMeasurer(el: Element): { measure: Measure; px: number; font: string } | null {\n const ctx = canvasContext();\n if (!ctx) return null;\n const { font, px } = resolvedAxisFont(el);\n ctx.font = font;\n const widths = new Map<string, number>();\n const measure: Measure = (text) => {\n let w = widths.get(text);\n if (w === undefined) {\n // the context is shared: another chart may have set its own font since\n ctx.font = font;\n w = ctx.measureText(text).width;\n widths.set(text, w);\n }\n return w;\n };\n return { measure, px, font };\n}\n\n/* ── Fitting a name ─────────────────────────────────────────────────────── */\n\nexport const ELLIPSIS = \"…\";\n\nexport interface FittedLabel {\n /** One or two lines; the second ends with \"…\" when the name was cut. */\n lines: string[];\n cut: boolean;\n /** Characters of the name that show, spaces and the ellipsis left out. */\n shown: number;\n}\n\nconst letters = (s: string) => s.replace(/\\s+/g, \"\").replace(/…/g, \"\").length;\n\n/** The longest prefix of `text` that fits `width` (at least one character). */\nfunction prefixThatFits(text: string, width: number, measure: Measure, suffix = \"\"): number {\n let lo = 1;\n let hi = text.length;\n let best = 0;\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n if (measure(text.slice(0, mid).trimEnd() + suffix) <= width) { best = mid; lo = mid + 1; } else hi = mid - 1;\n }\n return best;\n}\n\n/**\n * A name fitted to `width`: one line when it fits; else two lines split at a space; else the second line ends with \"…\".\n * A first word wider than the line breaks where the line ends, with a hyphen, so it reads as one word going on. The\n * name is never dropped, and without a measurer it shows in full on one line.\n */\nexport function fitLabel(name: string, width: number, measure: Measure | null): FittedLabel {\n const text = name.replace(/\\s+/g, \" \").trim();\n if (!measure || !text || width <= 0 || measure(text) <= width) return { lines: [text], cut: false, shown: letters(text) };\n const words = text.split(\" \");\n let first = \"\";\n let firstShown = \"\";\n let rest = \"\";\n for (let i = words.length - 1; i >= 1; i--) {\n const candidate = words.slice(0, i).join(\" \");\n if (measure(candidate) <= width) { first = firstShown = candidate; rest = words.slice(i).join(\" \"); break; }\n }\n if (!first) {\n // the first word alone is too wide: the first line holds what fits of it and a hyphen\n const k = Math.max(1, prefixThatFits(text, width, measure, \"-\"));\n firstShown = text.slice(0, k).trimEnd();\n rest = text.slice(k).trimStart();\n first = rest && !text.slice(k - 1, k + 1).includes(\" \") ? `${firstShown}-` : firstShown;\n }\n if (!rest) return { lines: [first], cut: false, shown: letters(firstShown) };\n if (measure(rest) <= width) return { lines: [first, rest], cut: false, shown: letters(firstShown) + letters(rest) };\n const k = prefixThatFits(rest, width, measure, ELLIPSIS);\n const kept = k > 0 ? rest.slice(0, k).trimEnd() : \"\";\n return { lines: [first, kept + ELLIPSIS], cut: true, shown: letters(firstShown) + letters(kept) };\n}\n\n/** D8: fewer visible characters than this on a cut name turns an upright chart of names sideways. */\nexport const MIN_NAME_CHARS = 6;\n\n/** Whether any name, fitted to `width`, would be cut to fewer than MIN_NAME_CHARS characters. */\nexport function namesCutShort(names: ReadonlyArray<string>, width: number, measure: Measure): boolean {\n return names.some((n) => {\n const fit = fitLabel(n, width, measure);\n return fit.cut && fit.shown < MIN_NAME_CHARS;\n });\n}\n"]}
|