@bettercms-ai/types 1.23.0 → 1.24.0

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/dist/index.d.ts CHANGED
@@ -107,6 +107,15 @@ interface BlockStyle {
107
107
  border?: boolean;
108
108
  /** 🔴 The one free-form string. MUST go through `safeCssUrl()` before reaching CSS. */
109
109
  bgImage?: string;
110
+ /** A button's look while the pointer is over it. Only the paint changes; unset keys keep the rest. */
111
+ hover?: BlockHoverStyle;
112
+ }
113
+ /** The paint a button swaps to on hover: fill, text colour, and the all-round border. */
114
+ interface BlockHoverStyle {
115
+ bg?: BgToken;
116
+ bgCustom?: string;
117
+ textColor?: ColorToken;
118
+ border?: boolean;
110
119
  }
111
120
  interface HeadingProps {
112
121
  text: string;
@@ -1900,6 +1909,15 @@ interface LocatorGrammar {
1900
1909
  * Gated (`landmarks`), because it moves keys AND regions: a project whose pages were derived
1901
1910
  * with that tab list as `nav#0` holds values under `nav-…` keys, and re-reading them as section
1902
1911
  * copy would strand every one of them.
1912
+ *
1913
+ * EXCEPT A `<main>` THAT IS THE PAGE SHELL. Plenty of layouts wrap the whole page in it —
1914
+ * `<main><Navbar/>{children}<Footer/></main>`, or `role="main"` on the app root — and there the
1915
+ * fence would take the site's real masthead and footer away: no region, no `nav-`/`footer-` keys,
1916
+ * nothing for the Layout to claim, and a copy of the nav minted into every route. A `<main>` that
1917
+ * OPENS with a header/nav and CLOSES with a footer is framing the site, not holding page copy, so
1918
+ * its own direct-child landmarks stay chrome. A landmark deeper inside it (a section's tab list)
1919
+ * is still page copy, and a `<main>` that only opens with a header (a changelog's title) still
1920
+ * fences it.
1903
1921
  */
1904
1922
  declare function isChromeLandmark(el: {
1905
1923
  tagName: string;
@@ -2034,4 +2052,4 @@ declare function regionOf<E extends {
2034
2052
  el: E;
2035
2053
  }[], el: unknown): string | null;
2036
2054
 
2037
- export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockStyle, type BlockType, type ButtonBlock, type ButtonProps, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type CollectionBlock, type CollectionProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentFormPropRef, type ComponentPropDef, type ComponentPropType, type ComponentProps, type ComponentSubField, type ComponentVariantGroup, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentModelFieldUi, type ContentPageResult, type ContentResponse, type ContentWidthToken, type CornerToken, DIALOG_SELECTOR, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type ElementLike, type ExpandedBinding, FOOTER_SECTION_ID, type FieldConfig, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, LANDMARK_SELECTOR, LAYOUT_SECTION_ICONS, LAYOUT_SECTION_ICON_SET, type LandmarkChainElement, type LandmarkElement, type LayoutComponentItem, type LayoutDataDocument, type LayoutFieldDefinition, type LayoutFieldItem, type LayoutFieldType, type LayoutScalarFieldType, type LayoutSection, type LayoutSectionIcon, type LayoutSectionItem, type LayoutStructureDocument, type LayoutZone, type LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type RadiusToken, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type SectionBlock, type SectionProps, type SectionSpaceToken, type ShadowToken, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, componentInstanceAddresses, componentPropTargetKey, expandBlockBindings, formatPropsAttribute, getBlockType, isBlock, isChromeLandmark, landmarkRegions, locatorFor, parsePropsAttribute, readPath, regionOf, spaceTokenCss };
2055
+ export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonProps, COMPONENT_PROP_TYPES, type CanonicalInputDefinition, type CollectionBlock, type CollectionProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentFormPropRef, type ComponentPropDef, type ComponentPropType, type ComponentProps, type ComponentSubField, type ComponentVariantGroup, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentModelFieldUi, type ContentPageResult, type ContentResponse, type ContentWidthToken, type CornerToken, DIALOG_SELECTOR, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type ElementLike, type ExpandedBinding, FOOTER_SECTION_ID, type FieldConfig, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, LANDMARK_SELECTOR, LAYOUT_SECTION_ICONS, LAYOUT_SECTION_ICON_SET, type LandmarkChainElement, type LandmarkElement, type LayoutComponentItem, type LayoutDataDocument, type LayoutFieldDefinition, type LayoutFieldItem, type LayoutFieldType, type LayoutScalarFieldType, type LayoutSection, type LayoutSectionIcon, type LayoutSectionItem, type LayoutStructureDocument, type LayoutZone, type LocatorGrammar, MAIN_SELECTOR, type ManagementLayoutCommand, type MediaAsset, type MediaCaptionTrack, type MediaFieldValue, NAVIGATION_SECTION_ID, type NavLink, type NavbarBlock, type NavbarProps, PAGE_CONTENT_ANCHOR_ID, type Page, type PageLayoutOverrideDataDocument, type PageLayoutOverrideDocument, type PageLayoutOverrideState, type PageLayoutOverrideStructureDocument, type PageLayoutSectionOverride, type PageLayoutSectionStructureOverride, type PageMetaJson, type PageOnlyLayoutSection, type PageSectionPlacement, type PaginatedResult, type Perspective, type PortableTextDocument, type PortableTextNode, type RadiusToken, type Redirect, type ReservedLayoutSection, type ResolvedLayoutNode, type RichTextBlock, type RichTextProps, SECTION_DOCTRINE, SECTION_SPACE_TOKENS, SPACE_BOTTOM_TOKENS, SPACE_STEP_TOKENS, type SectionBlock, type SectionProps, type SectionSpaceToken, type ShadowToken, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SpaceStepToken, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type ThemeToken, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, componentInstanceAddresses, componentPropTargetKey, expandBlockBindings, formatPropsAttribute, getBlockType, isBlock, isChromeLandmark, landmarkRegions, locatorFor, parsePropsAttribute, readPath, regionOf, spaceTokenCss };
package/dist/index.js CHANGED
@@ -150,13 +150,18 @@ function blockStyleToCss(style) {
150
150
  const top = spaceTokenCss(s.spaceTop);
151
151
  const bottom = SPACE_BOTTOM_TOKENS.includes(s.spaceBottom ?? "") ? spaceTokenCss(s.spaceBottom) : "";
152
152
  const sides = spaceTokenCss(s.spaceSides);
153
- if (top) css.paddingTop = top;
153
+ const navOverlap = s.spaceTop === "section-space-nav-overlap";
154
+ if (top && !navOverlap) css.paddingTop = top;
154
155
  if (bottom) css.paddingBottom = bottom;
155
156
  if (sides) {
156
157
  css.paddingLeft = sides;
157
158
  css.paddingRight = sides;
158
159
  }
159
160
  if (s.marginTop && SPACE_PX[s.marginTop] != null) css.marginTop = SPACE_PX[s.marginTop];
161
+ if (top && navOverlap) {
162
+ css.marginTop = top;
163
+ css.paddingTop = `calc(-1 * ${top})`;
164
+ }
160
165
  if (s.marginBottom && SPACE_PX[s.marginBottom] != null) css.marginBottom = SPACE_PX[s.marginBottom];
161
166
  if (s.background && COLOR_HEX[s.background]) css.background = COLOR_HEX[s.background];
162
167
  if (s.textColor && COLOR_HEX[s.textColor]) css.color = COLOR_HEX[s.textColor];
@@ -2157,7 +2162,16 @@ var LANDMARK_TAGS = /* @__PURE__ */ new Set(["HEADER", "NAV", "FOOTER"]);
2157
2162
  var DIALOG_SELECTOR = 'dialog,[role="dialog"]';
2158
2163
  var MAIN_SELECTOR = 'main,[role="main"]';
2159
2164
  function isChromeLandmark(el, landmarks) {
2160
- return LANDMARK_TAGS.has(el.tagName) && (!landmarks || !el.parentElement?.closest(MAIN_SELECTOR));
2165
+ if (!LANDMARK_TAGS.has(el.tagName)) return false;
2166
+ if (!landmarks) return true;
2167
+ const fence = el.parentElement?.closest(MAIN_SELECTOR);
2168
+ return !fence || fence === el.parentElement && isPageShell(fence);
2169
+ }
2170
+ var INERT_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "TEMPLATE", "NOSCRIPT", "LINK"]);
2171
+ function isPageShell(main) {
2172
+ const kids = Array.from(main.children).filter((k) => !INERT_TAGS.has(k.tagName));
2173
+ const first = kids[0]?.tagName;
2174
+ return (first === "HEADER" || first === "NAV") && kids.length > 1 && kids[kids.length - 1].tagName === "FOOTER";
2161
2175
  }
2162
2176
  function locatorFor(el, region, landmarks = false) {
2163
2177
  const ancestors = [];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/block.ts","../src/block-bindings.ts","../src/sectionSpace.ts","../src/blockStyle.ts","../src/component.ts","../src/layout-lucide-icons.ts","../src/layout.ts","../src/locator.ts"],"sourcesContent":["/**\n * ContentBlock — a discriminated union of all CMS block types.\n * Each block has a `type` discriminator and a `props` object\n * whose shape matches the block type.\n */\n\nimport type { SectionSpaceToken, SpaceStepToken } from \"./sectionSpace.js\";\n\n// ── Block style (FLO-264) ──────────────────────────────────────────────────────\n// A uniform, BOUNDED set of design tokens any block may carry (sibling to `props`).\n// Tokens map to fixed CSS values in the renderer (`styleTokensToCss`) so styling\n// reaches the live site WITHOUT arbitrary CSS. Additive + fully optional.\n\nexport type SpaceToken = \"none\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type ColorToken = \"none\" | \"white\" | \"black\" | \"muted\" | \"mutedBg\" | \"primary\" | \"accent\";\nexport type AlignToken = \"left\" | \"center\" | \"right\";\nexport type FontSizeToken = \"sm\" | \"base\" | \"lg\" | \"xl\" | \"2xl\";\nexport type WeightToken = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\nexport type RadiusToken = \"none\" | \"sm\" | \"md\" | \"lg\" | \"full\";\n\n// Section design (task 4) — the per-instance design a section carries on the page.\nexport type ThemeToken = \"inherit\" | \"light\" | \"dark\";\nexport type BgToken = \"none\" | \"surface\" | \"muted\" | \"accent\" | \"dark\" | \"custom\";\nexport type ContentWidthToken = \"narrow\" | \"default\" | \"wide\" | \"full\";\nexport type CornerToken = \"0\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\";\nexport type ShadowToken = \"0\" | \"s\" | \"m\" | \"l\" | \"xl\";\n\nexport interface BlockStyle {\n // Legacy token set (FLO-264). Where these overlap the section fields below\n // (background, radius, padding), the section field WINS in the renderer.\n paddingY?: SpaceToken;\n paddingX?: SpaceToken;\n marginTop?: SpaceToken;\n marginBottom?: SpaceToken;\n background?: ColorToken;\n textColor?: ColorToken;\n align?: AlignToken;\n fontSize?: FontSizeToken;\n weight?: WeightToken;\n radius?: RadiusToken;\n\n // Section design (task 4).\n theme?: ThemeToken;\n bg?: BgToken;\n /** Only read when `bg === \"custom\"`. Hex only. */\n bgCustom?: string;\n /** Padding sliders, in px (0–240). Legacy: a `space*` token below wins where both are set. */\n paddingTop?: number;\n paddingBottom?: number;\n paddingSides?: number;\n /** Section spacing as token steps (see sectionSpace.ts). Only the top may pull under the nav. */\n spaceTop?: SectionSpaceToken;\n spaceBottom?: Exclude<SectionSpaceToken, \"section-space-nav-overlap\">;\n spaceSides?: SpaceStepToken;\n contentWidth?: ContentWidthToken;\n /**\n * Where the constrained content column sits, when `contentWidth` constrains it.\n *\n * Split out of `align`, which still means text alignment and is still the fallback when this\n * is unset — so everything written before the split renders byte-identically. The two were one\n * token until anything MEASURED a section's text alignment: copying a source site's\n * `text-align: left` would otherwise also shove its column to the page edge.\n */\n contentAlign?: AlignToken;\n fullHeight?: boolean;\n /** 0–100. */\n opacity?: number;\n corner?: CornerToken;\n shadow?: ShadowToken;\n borderTop?: boolean;\n borderBottom?: boolean;\n /** All four sides, `1px solid currentColor` — an outline button's border follows its text colour. */\n border?: boolean;\n /** 🔴 The one free-form string. MUST go through `safeCssUrl()` before reaching CSS. */\n bgImage?: string;\n}\n\n// ── Heading ──────────────────────────────────────────────────────────────────\n\nexport interface HeadingProps {\n text: string;\n level?: 1 | 2 | 3;\n}\n\nexport interface HeadingBlock {\n type: \"heading\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: HeadingProps;\n}\n\n// ── Text ─────────────────────────────────────────────────────────────────────\n\nexport interface TextProps {\n html: string;\n /** @see RichTextProps.level — the same payload takes the same level. */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface TextBlock {\n type: \"text\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: TextProps;\n}\n\n/**\n * A rich-text block: the same HTML payload as `text`, authored through a real editor.\n *\n * WHY A SEPARATE TYPE RATHER THAN CHANGING `text`. Every `text` block already on a live page\n * holds an HTML string that the delivery renderer injects as-is. Repurposing that type would\n * mean migrating published content, and getting it wrong renders visible markup to visitors.\n * A new type costs nothing at rest and leaves existing pages untouched.\n *\n * The payload is deliberately IDENTICAL to TextProps (an HTML string) so the two are\n * interchangeable at the renderer: delivery treats them the same, and the difference is\n * entirely in how an author edits them — `text` is a plain field, `richtext` gets the\n * formatting surface.\n */\n/**\n * A Portable Text node — the structured form of rich text.\n *\n * Kept alongside `html` rather than replacing it, so nothing already published moves. The\n * structure exists because an HTML string cannot carry INTENT: a colour is a hex with no\n * notion of which brand token produced it, an embedded component is a div with no reference\n * to resolve, and neither can be read back by tooling. Nodes can carry all of that.\n */\nexport interface PortableTextNode {\n _type: string;\n _key?: string;\n /** Block style — \"normal\", \"h2\", \"blockquote\". */\n style?: string;\n text?: string;\n children?: PortableTextNode[];\n /** Marks on a span: \"strong\", \"em\", or a token reference like \"color:brand-accent\". */\n marks?: string[];\n /** An embedded component or reference resolves through these. */\n schemaKey?: string;\n _ref?: string;\n fields?: Record<string, unknown>;\n}\n\nexport interface PortableTextDocument {\n version: 1;\n content: PortableTextNode[];\n}\n\nexport interface RichTextProps {\n /**\n * The RENDERED CACHE. Delivery reads this, so the fast path stays a string interpolation\n * and every page published before `content` existed keeps rendering byte-identically.\n */\n html: string;\n /**\n * The SOURCE OF TRUTH, when present — `content` always wins over `html`.\n *\n * Optional on purpose: this is the same envelope the field values already use\n * (`{ format, value, html }`), where `html` is likewise derived. Any writer that sets\n * `html` alone on a block that HAS `content` must delete `content` in the same write, or\n * the stale string silently shadows the newer structure.\n */\n content?: PortableTextDocument;\n /**\n * Render the rich copy AS `<h1>`–`<h6>` instead of a paragraph container, so a title keeps\n * its inline marks (a brand-coloured span) AND its heading semantics. Absent ⇒ ordinary rich\n * text, as before. Set ⇒ the value must be ONE line of inline copy; the write schema refuses\n * more. A component prop of type `number` or `select` can target `props.level`.\n */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface RichTextBlock {\n type: \"richtext\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: RichTextProps;\n}\n\n// ── Image ────────────────────────────────────────────────────────────────────\n\nexport interface ImageProps {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n caption?: string;\n}\n\nexport interface ImageBlock {\n type: \"image\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ImageProps;\n}\n\n// ── Button ───────────────────────────────────────────────────────────────────\n\nexport interface ButtonProps {\n text: string;\n href: string;\n variant?: \"primary\" | \"secondary\";\n}\n\nexport interface ButtonBlock {\n type: \"button\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ButtonProps;\n}\n\n// ── Spacer ───────────────────────────────────────────────────────────────────\n\nexport interface SpacerProps {\n height: number; // in px\n}\n\nexport interface SpacerBlock {\n type: \"spacer\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SpacerProps;\n}\n\n// ── Columns ───────────────────────────────────────────────────────────────────\n\nexport interface ColumnsProps {\n columns: ContentBlock[][]; // array of column slots, each slot is an array of blocks\n gap?: number; // in px\n}\n\nexport interface ColumnsBlock {\n type: \"columns\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ColumnsProps;\n}\n\n// ── Video ────────────────────────────────────────────────────────────────────\n\nexport interface VideoProps {\n url: string;\n poster?: string;\n autoplay?: boolean;\n loop?: boolean;\n /**\n * What is said in the video (CPO-093). The block carries its own because its url may be a\n * pasted provider link with no library asset to hang one from. Rendered as <details> after\n * the player and published in the .md twin.\n */\n transcript?: string;\n}\n\nexport interface VideoBlock {\n type: \"video\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: VideoProps;\n}\n\n// ── Form ─────────────────────────────────────────────────────────────────────\n\nexport interface FormProps {\n formId: string; // references forms.id (a nanoid). Resolved against delivered forms at render time.\n}\n\nexport interface FormBlock {\n type: \"form\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: FormProps;\n}\n\n// ── Section (recursive container) ──────────────────────────────────────────────\n\nexport interface SectionProps {\n children: ContentBlock[];\n background?: string;\n paddingY?: number; // in px\n maxWidth?: number; // in px\n}\n\nexport interface SectionBlock {\n type: \"section\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SectionProps;\n}\n\n// ── Navbar ─────────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavbarProps {\n logo?: { src: string; alt: string; href?: string };\n logoAlt?: string;\n links: NavLink[];\n mobileMenu?: boolean;\n cta?: { text: string; href: string };\n}\n\nexport interface NavbarBlock {\n type: \"navbar\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: NavbarProps;\n}\n\n// ── Footer ─────────────────────────────────────────────────────────────────────\n\nexport interface FooterColumn {\n heading?: string;\n links: NavLink[];\n}\n\nexport interface FooterProps {\n columns: FooterColumn[];\n copyright?: string;\n}\n\nexport interface FooterBlock {\n type: \"footer\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: FooterProps;\n}\n\n// ── Slider / Carousel (recursive container, client-hydrated) ────────────────────\n\nexport interface SlideItem {\n id: string;\n children: ContentBlock[];\n}\n\nexport interface SliderProps {\n slides: SlideItem[];\n autoplay?: boolean;\n interval?: number; // in ms\n loop?: boolean;\n}\n\nexport interface SliderBlock {\n type: \"slider\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SliderProps;\n}\n\n// ── Tabs (recursive container, client-hydrated) ─────────────────────────────────\n\nexport interface TabItem {\n id: string;\n label: string;\n children: ContentBlock[];\n}\n\nexport interface TabsProps {\n tabs: TabItem[];\n}\n\nexport interface TabsBlock {\n type: \"tabs\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: TabsProps;\n}\n\n// ── Component instance (Webflow-style reusable symbol) ──────────────────────────\n// References a reusable component by id. `overrides` maps a component prop key\n// (declared in the component's `props[]` allowlist) to a value, applied to the\n// component's block tree at render time. Resolved against delivered components.\n\nexport interface ComponentProps {\n componentId: string;\n overrides?: Record<string, unknown>;\n /** Phase A: the page field group this placement renders (its copy + bindings live there). */\n bind?: string;\n /**\n * Phase B: where each override's copy CAME FROM — `{ <propKey>: \"<page field path>\" }`.\n *\n * Written when a placement takes ownership of its copy (`bind` is deleted at the same moment),\n * and it is not decoration:\n * - the COVERAGE METER counts a block-lane declaration\n * (`data-bcms-block=\"<id>\"` + `data-bcms-field=\"<id>__overrides.<propKey>\"`) as bound for\n * the page path named here, so a converted page does not read as a site that lost its\n * bindings;\n * - it is how the componentize lane still recognises WHICH GROUP an instance renders once\n * `bind` is gone — without it a second run would mint a second instance for the same band.\n * A `table` prop names its repeater's path (`faq.items`); every row path under it is that one\n * declaration's, because the prop holds every row.\n */\n source?: Record<string, string>;\n}\n\nexport interface ComponentBlock {\n type: \"component\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ComponentProps;\n}\n\n// ── Collection (the entries of the page this block sits on) ─────────────────────\n//\n// LANE-AWARE, and that is the whole idea. A dynamic page's `blockJson` is BOTH what\n// `/blog` renders and the template interpolated into every `/blog/<slug>`. One array\n// cannot be an index and a post layout — unless the one block that differs between them\n// knows which lane it is in. The route supplies that (see CollectionCtx in render-page.ts):\n//\n// /blog → this block renders a card per published entry\n// /blog/my-post → this block renders THAT entry's detail; every other block in the\n// array is interpolated with {{placeholders}} exactly as before\n//\n// So no second template column, no migration, and a page without a collection block\n// behaves byte-identically to before.\n//\n// Scope is IMPLIED, never configured: a collection lists the entries of the page it sits\n// on, which is precisely the set whose detail URLs are /<thisPage>/<slug>. There is no\n// model picker because there is no other correct answer.\n\nexport interface CollectionProps {\n /** Component rendered once per entry, interpolated with {{field}} and {{url}}. Omit for a built-in card. */\n cardComponentId?: string;\n /** Component rendered for the single entry on a detail URL. Omit to fall back to the generic field layout. */\n detailComponentId?: string;\n /** Built-in card only. Defaults to \"title\" / no excerpt. */\n titleField?: string;\n excerptField?: string;\n /** Max cards to render. Defaults to 20. */\n limit?: number;\n /** \"newest\" (default) reverses the reader's created_at ordering. */\n order?: \"newest\" | \"oldest\";\n emptyText?: string;\n}\n\nexport interface CollectionBlock {\n type: \"collection\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: CollectionProps;\n}\n\n// ── Union ─────────────────────────────────────────────────────────────────────\n\nexport type ContentBlock =\n | CollectionBlock\n | HeadingBlock\n | TextBlock\n | RichTextBlock\n | ImageBlock\n | ButtonBlock\n | SpacerBlock\n | ColumnsBlock\n | VideoBlock\n | FormBlock\n | SectionBlock\n | NavbarBlock\n | FooterBlock\n | SliderBlock\n | TabsBlock\n | ComponentBlock;\n\n/** Literal union of all block type discriminators. */\nexport type BlockType = ContentBlock[\"type\"];\n\n/**\n * Type guard — narrows an unknown block to `ContentBlock`.\n *\n * @example\n * const block = maybeBlock as unknown;\n * if (isBlock(block)) {\n * // block is ContentBlock here\n * }\n */\nexport function isBlock(value: unknown): value is ContentBlock {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n typeof (value as Record<string, unknown>)[\"type\"] === \"string\"\n );\n}\n\n/**\n * Extract the `type` discriminator from a block, or `null` if not a block.\n *\n * @example\n * const block = { type: \"heading\", id: \"1\", props: { text: \"Hi\" } };\n * getBlockType(block); // \"heading\"\n * getBlockType({ not: \"a block\" }); // null\n */\nexport function getBlockType(value: unknown): BlockType | null {\n if (isBlock(value)) return value.type;\n return null;\n}\n","/**\n * The ONE declaration of which block props the Visual Editor can address.\n *\n * Four renderers stamp `data-bcms-field` — the hosted renderer, the Next SDK, the Astro SDK\n * and (for minting keys rather than markup) the dashboard's `buildBlockPageDoc`. Until this\n * file existed each carried its own hand-written list, they disagreed by two props, and the\n * dashboard's copy said so in a comment while having nothing to enforce it. A block listed in\n * one and missing from another does not error: it simply never binds, or it binds to a node\n * that resolves to no field. Both failures are silent, which is why they survived.\n *\n * This file is the declaration. The renderers remain the implementation — only they know which\n * ELEMENT carries a value — and `block-binding-coverage.test.ts` asserts the two agree.\n *\n * ── Two kinds of address, because an element is not an attribute ────────────────────────────\n *\n * `data-bcms-field` addresses ONE element. That is enough for a heading's text or an image's\n * src, and not enough for an image's `alt`: the `<img>` already carries a binding, and an\n * element cannot hold two. Entries that name an `attr` are therefore emitted on a SECOND\n * attribute, `data-bcms-props`, whose grammar is:\n *\n * <address>|<kind>|<domAttribute>[;<address>|<kind>|<domAttribute>]*\n *\n * No JSON, because the values are already constrained: an address is grammar A\n * (`[A-Za-z0-9_$-]`, `.`, `[n]`), and kinds and attributes are plain identifiers. A split on\n * two characters parses it, in any language, with no escaping.\n *\n * ── Path templates ──────────────────────────────────────────────────────────────────────────\n *\n * `[]` marks an array the renderer walks. `expandBlockBindings` substitutes real indices from a\n * block's actual props, so `links[].label` on a three-link navbar yields three concrete\n * addresses and on an empty one yields none. `parseFieldPath`/`setFieldPath` in the dashboard\n * have handled N indices since FLO-949; the cap was in what the renderer offered, not in what\n * the writer could persist.\n */\nimport type { ContentBlock, BlockType } from \"./block.js\";\n\n/**\n * How the editor paints a value, and whether it may take a caret.\n *\n * `text`/`richtext` are inline-editable. `image` selects and swaps through the media picker.\n * `url` never takes a caret — a URL typed onto the page has nowhere to report a malformed\n * value — so it is edited in the element toolbar. `array` is a repeater slot: selectable and\n * locatable, edited in the dock.\n *\n * `document` is a whole Portable Text body: selectable as ONE container, repainted whole from the\n * form, and edited per keyed block inside it. It is not a longer `richtext` — a Body stamped\n * `richtext` goes into the rich-text lane, where an opt-out rewrites the value as an `{html}`\n * envelope and the document's own block structure is destroyed.\n */\nexport type BindingKind = \"text\" | \"richtext\" | \"image\" | \"document\" | \"url\" | \"number\" | \"array\";\n\nexport interface BlockBinding {\n /** Path template in grammar A, relative to the block's `props`. `[]` = an array to walk. */\n readonly path: string;\n readonly kind: BindingKind;\n /**\n * The DOM attribute this value lives in, when it is not the element's own text or `src`.\n * Present ⇒ the renderer emits it on `data-bcms-props`, never on `data-bcms-field`.\n */\n readonly attr?: string;\n}\n\n/**\n * Props deliberately absent, and still absent for the original reason:\n *\n * `spacer.height`, `columns.gap`, `section.background` and every `style` token — design, not\n * content. They are edited in the Design accordion, where a slider can express a bounded\n * range that free typing on the page cannot.\n *\n * `text.html` when Portable Text is present — `html` is a cache derived from `content`, so\n * advertising it would persist an ignored sibling and the next frame would read as a revert.\n * The renderer suppresses it; the expander cannot see `content`, so the branch stays there.\n *\n * `component.overrides.*` — instance-scoped, so it cannot be a static template. The renderer\n * derives those addresses per instance from the definition's declared props.\n */\nexport const BLOCK_BINDINGS: Partial<Record<BlockType, readonly BlockBinding[]>> = {\n heading: [{ path: \"text\", kind: \"text\" }],\n text: [{ path: \"html\", kind: \"richtext\" }],\n richtext: [{ path: \"html\", kind: \"richtext\" }],\n image: [\n { path: \"src\", kind: \"image\" },\n { path: \"caption\", kind: \"text\" },\n { path: \"alt\", kind: \"text\", attr: \"alt\" },\n ],\n button: [\n { path: \"text\", kind: \"text\" },\n { path: \"href\", kind: \"url\", attr: \"href\" },\n ],\n video: [\n { path: \"url\", kind: \"url\", attr: \"src\" },\n { path: \"poster\", kind: \"url\", attr: \"poster\" },\n ],\n navbar: [\n { path: \"logo.src\", kind: \"image\" },\n { path: \"logo.alt\", kind: \"text\", attr: \"alt\" },\n { path: \"links[].label\", kind: \"text\" },\n { path: \"links[].href\", kind: \"url\", attr: \"href\" },\n { path: \"cta.text\", kind: \"text\" },\n { path: \"cta.href\", kind: \"url\", attr: \"href\" },\n ],\n footer: [\n { path: \"copyright\", kind: \"text\" },\n { path: \"columns[].heading\", kind: \"text\" },\n { path: \"columns[].links[].label\", kind: \"text\" },\n { path: \"columns[].links[].href\", kind: \"url\", attr: \"href\" },\n ],\n tabs: [{ path: \"tabs[].label\", kind: \"text\" }],\n};\n\n/** One concrete, writable address on one block. */\nexport interface ExpandedBinding extends BlockBinding {\n /** The template with every `[]` replaced by a real index, e.g. `links[2].href`. */\n readonly path: string;\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/**\n * Read a grammar-A path — dotted object keys and zero or more `[n]` indices.\n *\n * Positional, exactly like the dashboard's `parseFieldPath`: a dotted segment is always an\n * object key and a bracketed one always an index, so `links.0` reads the string key \"0\" and\n * misses, rather than being quietly treated as `links[0]`. Any miss returns undefined; nothing\n * here throws, because a template that does not resolve must yield no address, not an error.\n *\n * EXPORTED because a second reader of this grammar now exists: `@bettercms-ai/convert` commits a\n * build-time helper into a customer's repository, and that helper must resolve a path exactly the\n * way the editor does or a converted template renders a fallback where a value exists. The helper\n * itself carries an inlined copy (it lands in a repo where our packages do not exist) and a parity\n * test pins the copy to this original.\n */\nexport function readPath(root: unknown, path: string): unknown {\n let cursor: unknown = root;\n for (const segment of path.split(\".\")) {\n if (!segment) return undefined;\n const key = segment.replace(/\\[\\d+\\]/g, \"\");\n if (key) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n for (const index of segment.matchAll(/\\[(\\d+)\\]/g)) {\n if (!Array.isArray(cursor)) return undefined;\n cursor = cursor[Number(index[1])];\n }\n }\n return cursor;\n}\n\n/** Substitute the FIRST `[]` with every real index, then recurse for any deeper array. */\nfunction expandTemplate(binding: BlockBinding, props: unknown, path: string): ExpandedBinding[] {\n const at = path.indexOf(\"[]\");\n if (at < 0) return [{ ...binding, path }];\n\n const head = path.slice(0, at);\n const tail = path.slice(at + 2);\n const array = readPath(props, head);\n if (!Array.isArray(array)) return [];\n\n return array.flatMap((_item, index) =>\n expandTemplate(binding, props, `${head}[${index}]${tail}`),\n );\n}\n\n/**\n * Every concrete address a block actually offers right now.\n *\n * Array templates expand against the array's real length, so an address is only ever minted\n * for an element that exists. That is the load-bearing property: `setFieldPath` refuses to\n * fabricate an array member, so an address for `links[3]` on a two-link navbar would be a\n * binding the writer rejects — the \"advertises an edit that silently fails\" failure this whole\n * grammar exists to avoid.\n *\n * A prop whose KEY is absent does NOT expand, and that is not a nicety. `setFieldPath` refuses\n * to create a final key unless `createMissingObjects` is set, which only component overrides\n * pass — so an address for a key the block does not carry is a write the editor would reject.\n * An empty string still expands: `\"\"` is a value, and clearing a heading must not make it\n * uneditable.\n */\nexport function expandBlockBindings(block: ContentBlock): ExpandedBinding[] {\n const declared = BLOCK_BINDINGS[block.type];\n if (!declared) return [];\n const props = (block as { props?: unknown }).props;\n if (!isRecord(props)) return [];\n return declared\n .flatMap((binding) => expandTemplate(binding, props, binding.path))\n .filter((binding) => readPath(props, binding.path) !== undefined);\n}\n\n/** The `data-bcms-props` value for a block's attribute bindings, or \"\" when it has none. */\nexport function formatPropsAttribute(\n entries: readonly { address: string; kind: BindingKind; attr: string }[],\n): string {\n return entries.map((e) => `${e.address}|${e.kind}|${e.attr}`).join(\";\");\n}\n\n/** Parse a `data-bcms-props` value. Malformed entries are dropped, never guessed at. */\nexport function parsePropsAttribute(\n value: string | null | undefined,\n): { address: string; kind: BindingKind; attr: string }[] {\n if (!value) return [];\n return value\n .split(\";\")\n .map((entry) => entry.split(\"|\"))\n .filter((parts): parts is [string, BindingKind, string] => parts.length === 3 && parts.every(Boolean))\n .map(([address, kind, attr]) => ({ address, kind, attr }));\n}\n\n/** The shape of a declared component prop this module needs: where it points, and its key. */\ninterface PropTarget {\n key?: string;\n target?: { blockId?: string; path?: string };\n}\n\n/**\n * `<defBlockId>__<prop>` → `<instanceBlockId>__overrides.<propKey>`, for one placed component.\n *\n * Shared by every renderer, because the mapping is a property of the DEFINITION and not of any\n * one output format. A component's block ids belong to the definition and are shared by every\n * instance of it, so `<defBlockId>__text` addresses no instance's value — which is why component\n * subtrees used to render unannotated, and why the SDKs (which never had that suppression)\n * stamped definition-scoped addresses that resolve to no field and, on a component placed twice,\n * collide into a duplicate that drops BOTH copies.\n *\n * The definition already states the mapping in `props[].target`. This only re-keys that\n * statement into the address the editor writes through. Nothing is inferred: a prop with no\n * target produces no entry, so it keeps its dock control and stays uneditable on the canvas,\n * which is the truthful outcome rather than a broken one.\n */\n/**\n * The definition-scoped key a declared prop POINTS AT — `<defBlockId>__<path>`, the same\n * grammar `expandBlockBindings` produces for a block's own bindings.\n *\n * Exported so the \"which leaves does no prop reach?\" check and the address minter below read\n * the key from ONE place. They ask opposite questions of the same mapping, and two spellings\n * of `.replace(/^props\\./, \"\")` is precisely how a leaf ends up counted as bound by one and\n * unbound by the other. Null when the prop declares no target — which is the honest answer:\n * such a prop reaches nothing.\n */\nexport function componentPropTargetKey(prop: PropTarget | undefined): string | null {\n if (!prop?.key || !prop.target?.blockId) return null;\n return `${prop.target.blockId}__${String(prop.target.path ?? \"\").replace(/^props\\./, \"\")}`;\n}\n\n/**\n * `owner` is the address of the rich-text field an instance is EMBEDDED in. Its `_key` is unique\n * only within that field, so the instance is named `<owner>#<_key>` — the same grammar a\n * rich-text node's own address uses — giving `<owner>#<_key>__overrides.<propKey>`.\n */\nexport function componentInstanceAddresses(\n instanceBlockId: string,\n props: readonly PropTarget[] | undefined,\n owner?: string,\n): Map<string, string> {\n const instance = owner ? `${owner}#${instanceBlockId}` : instanceBlockId;\n const out = new Map<string, string>();\n for (const prop of props ?? []) {\n if (!prop?.key || !prop.target?.blockId) continue;\n const from = componentPropTargetKey(prop)!;\n // Two props aimed at one target would make the address ambiguous; first declaration wins\n // and the duplicate is dropped rather than silently overwriting it.\n if (!out.has(from)) out.set(from, `${instance}__overrides.${prop.key}`);\n }\n return out;\n}\n","/**\n * Section spacing as TOKEN STEPS — the ONE list of names and default sizes, shared by the save\n * schema and every renderer. A stored value is always a token (`section-space-large`), never a\n * pixel; it renders as `var(--bcms-section-space-large,96px)`, so a site with a token registry\n * restyles every section at once and a site without one still gets the default rhythm.\n *\n * 🔴 The px table is twinned with the dashboard's `tokenScales.ts` preview table. Change both.\n */\nexport const SECTION_SPACE_TOKENS = [\n \"section-space-none\",\n \"section-space-small\",\n \"section-space-medium\",\n \"section-space-large\",\n \"section-space-xlarge\",\n \"section-space-nav-overlap\",\n] as const;\nexport const SPACE_STEP_TOKENS = [\"space-none\", \"space-s\", \"space-m\", \"space-l\", \"space-xl\"] as const;\n\nexport type SectionSpaceToken = (typeof SECTION_SPACE_TOKENS)[number];\nexport type SpaceStepToken = (typeof SPACE_STEP_TOKENS)[number];\n\n/** A negative band that pulls content under the nav makes sense at the TOP of a section only. */\nexport const SPACE_BOTTOM_TOKENS = SECTION_SPACE_TOKENS.filter(\n (t): t is Exclude<SectionSpaceToken, \"section-space-nav-overlap\"> => t !== \"section-space-nav-overlap\",\n);\n\nconst SPACE_TOKEN_PX: Record<SectionSpaceToken | SpaceStepToken, string> = {\n \"section-space-none\": \"0px\",\n \"section-space-small\": \"32px\",\n \"section-space-medium\": \"64px\",\n \"section-space-large\": \"96px\",\n \"section-space-xlarge\": \"144px\",\n \"section-space-nav-overlap\": \"-72px\",\n \"space-none\": \"0px\",\n \"space-s\": \"8px\",\n \"space-m\": \"16px\",\n \"space-l\": \"32px\",\n \"space-xl\": \"64px\",\n};\n\n/** `var(--bcms-<token>,<px>)`, or \"\" for anything that is not a known token (closed set). */\nexport function spaceTokenCss(token: unknown): string {\n const px = typeof token === \"string\" ? SPACE_TOKEN_PX[token as SectionSpaceToken] : undefined;\n return px ? `var(--bcms-${token},${px})` : \"\";\n}\n","/**\n * FLO-264 — bounded block-style tokens → CSS. Framework-agnostic (returns a plain\n * declaration object, no React types) so every renderer shares ONE mapping: the\n * headless @bettercms-ai/next adapter, @bettercms-ai/ui, and (string form) the hosted\n * render-page.ts. Unknown tokens are dropped — closed set, no arbitrary CSS.\n */\nimport type { BlockStyle } from \"./block.js\";\nimport { SPACE_BOTTOM_TOKENS, spaceTokenCss } from \"./sectionSpace.js\";\n\nconst SPACE_PX: Record<string, string> = { none: \"0\", xs: \"4px\", sm: \"8px\", md: \"16px\", lg: \"32px\", xl: \"64px\" };\nconst FONT_SIZE_REM: Record<string, string> = { sm: \"0.875rem\", base: \"1rem\", lg: \"1.25rem\", xl: \"1.5rem\", \"2xl\": \"2rem\" };\nconst WEIGHT: Record<string, number> = { normal: 400, medium: 500, semibold: 600, bold: 700 };\nconst RADIUS_PX: Record<string, string> = { none: \"0\", sm: \"4px\", md: \"8px\", lg: \"16px\", full: \"9999px\" };\nconst COLOR_HEX: Record<string, string> = { white: \"#ffffff\", black: \"#111111\", muted: \"#6b7280\", mutedBg: \"#f3f4f6\", primary: \"#111111\", accent: \"#4f46e5\" };\n\n/** A CSS declaration object (key → value) usable as a React `style` prop, or undefined when empty. */\nexport function blockStyleToCss(style: BlockStyle | undefined): Record<string, string | number> | undefined {\n if (!style || typeof style !== \"object\") return undefined;\n const s = style as Record<string, string>;\n const css: Record<string, string | number> = {};\n if (s.paddingY && SPACE_PX[s.paddingY] != null) { css.paddingTop = SPACE_PX[s.paddingY]!; css.paddingBottom = SPACE_PX[s.paddingY]!; }\n if (s.paddingX && SPACE_PX[s.paddingX] != null) { css.paddingLeft = SPACE_PX[s.paddingX]!; css.paddingRight = SPACE_PX[s.paddingX]!; }\n // Token steps win over the legacy padding above: they are what the section design panel writes.\n const top = spaceTokenCss(s.spaceTop);\n const bottom = (SPACE_BOTTOM_TOKENS as readonly string[]).includes(s.spaceBottom ?? \"\") ? spaceTokenCss(s.spaceBottom) : \"\";\n const sides = spaceTokenCss(s.spaceSides);\n if (top) css.paddingTop = top;\n if (bottom) css.paddingBottom = bottom;\n if (sides) { css.paddingLeft = sides; css.paddingRight = sides; }\n if (s.marginTop && SPACE_PX[s.marginTop] != null) css.marginTop = SPACE_PX[s.marginTop]!;\n if (s.marginBottom && SPACE_PX[s.marginBottom] != null) css.marginBottom = SPACE_PX[s.marginBottom]!;\n if (s.background && COLOR_HEX[s.background]) css.background = COLOR_HEX[s.background]!;\n if (s.textColor && COLOR_HEX[s.textColor]) css.color = COLOR_HEX[s.textColor]!;\n if (s.align === \"left\" || s.align === \"center\" || s.align === \"right\") css.textAlign = s.align;\n if (s.fontSize && FONT_SIZE_REM[s.fontSize]) css.fontSize = FONT_SIZE_REM[s.fontSize]!;\n if (s.weight && WEIGHT[s.weight] != null) css.fontWeight = WEIGHT[s.weight]!;\n if (s.radius && RADIUS_PX[s.radius] != null) css.borderRadius = RADIUS_PX[s.radius]!;\n if ((style as BlockStyle).border === true) css.border = \"1px solid currentColor\";\n return Object.keys(css).length ? css : undefined;\n}\n","/**\n * Component — a reusable, Webflow-style block tree (a \"symbol\").\n *\n * A component is authored once and placed across pages via `component` blocks\n * (see `ComponentBlock` in `./block.ts`). Its definition lives in `blockJson`;\n * `props` declares a flat allowlist of values an instance may override.\n */\nimport type { ContentBlock } from \"./block.js\";\nimport type { ContentModelFieldUi } from \"./content-model.js\";\nimport type { VariantInputMapping } from \"./layout.js\";\n\n/**\n * The category a component belongs to (drives library grouping + icons). The first eight\n * are structural (what the component IS); the last four are the \"Add a section\" library\n * tabs (where it appears). One varchar column, not a PG enum — widening is code-only.\n */\n/**\n * 🔴 THE STRUCTURE DOCTRINE — one sentence, one home, spliced into every surface that builds a page.\n *\n * It lives HERE, beside the component contract it describes, because there are THREE places that teach\n * an agent how to build a page and they drifted apart:\n * • `packages/mcp/src/tools.ts` — the MCP tool descriptions (external agents)\n * • `src/lib/ai/agent.ts` — the in-product Studio Agent's system prompt\n * • `packages/mcp/src/prompts.ts` — the authoring playbook, which a tool call does not carry\n *\n * Only the playbook explained sections. `create_page` taught the SCHEMA axis in detail (\"each visual\n * section becomes a nested field\") and said nothing about STRUCTURE; the Studio Agent's prompt named\n * \"pages & reusable components (structure/layout)\" without ever mentioning `sectionType`.\n *\n * Measured consequence, production 2026-08-18: project `acme` has three components, ALL with\n * `section_type = (none)`, and its home page is 18 loose top-level blocks with ZERO sections. Every\n * generated page came out flat, so the visual editor's section lane — outline, name, move, duplicate,\n * delete, variant swap — had nothing to attach to. The editor was faithfully showing pages that were\n * never built out of sections.\n *\n * A constant rather than three paraphrases, because updating some of them is exactly how this happened.\n */\nexport const SECTION_DOCTRINE =\n \"STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks — they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` — see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas — each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP — WITH A `target` — for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. Do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId — hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section — never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.\";\n\nexport type ComponentCategory =\n | \"navbar\"\n | \"footer\"\n | \"button\"\n | \"section\"\n | \"slider\"\n | \"tabs\"\n | \"form\"\n | \"custom\"\n | \"hero\"\n | \"content\"\n | \"social-proof\"\n | \"conversion\";\n\n/**\n * A single overridable field on a component. `target` points at the block + JSON\n * path inside `blockJson` the override writes to (e.g. blockId \"cta\", path\n * \"props.text\"). Keeping overrides a declared allowlist (not arbitrary nested\n * rewrites) keeps instance data small and the contract explicit.\n */\n/**\n * THE prop vocabulary. One list, imported everywhere a prop type is enumerated.\n *\n * It exists as a value (not just a union) because four places used to spell it out by hand —\n * this file, the Drizzle schema, `COMPONENT_PROP_TYPES` in the backend's Zod schemas, and the\n * MCP tool shape — and the MCP copy is the dangerous one: `update_component` REPLACES the whole\n * `props` array, so a type its enum omits cannot be echoed back, and an agent that reads a\n * component and writes it straight back DESTROYS every prop of that type with a 200.\n *\n * Order is not semantic; append rather than re-sort, so a diff stays readable.\n */\nexport const COMPONENT_PROP_TYPES = [\n \"text\",\n \"richtext\",\n \"image\",\n \"url\",\n \"boolean\",\n \"number\",\n \"select\",\n \"group\",\n \"table\",\n \"slot\",\n \"form\",\n] as const;\n\nexport type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];\n\n/**\n * The value a `form` prop STORES: just the id. The form itself is a Form document and stays the\n * single source of truth for its fields — a component references one, it never re-declares it.\n *\n * `.strict()` at the write boundary, so a client that POSTs a hydrated form object alongside the\n * id gets a 400 rather than a silent strip.\n *\n * There is deliberately NO resolved twin of this shape. Every renderer already receives forms the\n * same way — a catalogue beside the blocks (`BcmsBlocks({blocks, forms})`, the site renderer's\n * forms map) — and looks the id up in it. A hydrated `{formId, form}` prop value would be a shape\n * that exists nowhere in delivery.\n */\nexport interface ComponentFormPropRef {\n formId: string;\n}\n\nexport interface ComponentPropDef {\n key: string;\n label: string;\n target: { blockId: string; path: string };\n /**\n * `slot` holds ONE nested component instance — the component-level twin of the\n * content-model field type `component-ref` (see content-model.ts), named differently for\n * the same reason that one is: `component` already means a BLOCK type. Its value is\n * `{ componentId, overrides }` and its `target.path` is `props`, so filling a slot writes\n * that object over an empty `component` block's props.\n *\n * On a PAGE a slot fill is a LIVE reference; a published ENTRY freezes it (resolveDeep).\n */\n /**\n * The EDITOR contract, not a storage one: `applyOverrides` writes the value at\n * `target.path` whatever its shape, so `type` decides which control the inspector renders\n * and what shape that control produces (FLO-1020).\n *\n * number → a number (heading.level, columns.count)\n * select → one string from `config.options`\n * group → an object keyed by `config.fields`\n * table → an array of such objects (slider.slides)\n *\n * `reference` is absent on purpose: nothing resolves a content-entry id at component render\n * time, so such a prop would save cleanly and render as nothing.\n */\n type: ComponentPropType;\n defaultValue?: unknown;\n /**\n * EDITOR HINTS (playbook §12). Stored in the props JSON, so no migration.\n *\n * 🔴 `required` IS NOT ENFORCED AT WRITE TIME, deliberately. Nothing on the write path\n * refuses an override that omits a required prop — a placement saves either way — because\n * the alternative is a component definition that can retroactively make already-saved pages\n * unsaveable. It is a marker the dashboard renders and `get_site_composition` counts, which\n * is the honest shape: the receipt names what is missing instead of the write refusing it.\n */\n required?: boolean;\n /** Hint shown under the control, muted. */\n helpText?: string;\n /** Ghost text inside a text-ish control. */\n placeholder?: string;\n /** Per-type settings; the save schema enforces that each is present on the type needing it. */\n config?: {\n /** `slot` — a pick allowlist. */\n componentIds?: string[];\n /**\n * `select` — the choices. Required, and a default must be one of them. `{ label, value }`\n * when the stored value is not what an author should read (a component id, for instance).\n */\n options?: Array<string | { label: string; value: string }>;\n /** `group` / `table` — the sub-shape, nestable to 3 levels. */\n fields?: ComponentSubField[];\n /** `number` — bounds for the control. */\n min?: number;\n max?: number;\n step?: number;\n } & Record<string, unknown>;\n /**\n * AUTHORING CHROME — the same object a content-model FIELD carries ({@link ContentModelFieldUi}),\n * deliberately: an agent that has learned `ui` once has learned it on both lanes.\n *\n * A SIBLING of `config`, not a member of it. `config` is a loose bag, so a `config.ui` already\n * survived the write — and that is the problem this key fixes: surviving is not declared, and\n * an undeclared prop is a typo that saves cleanly and renders as nothing.\n *\n * WHERE EACH KEY IS LEGAL differs from the field lane, because the vocabulary does:\n * `preview`/`layout` on `group`, `table` and `slot`; `reorderable` on `table` ALONE, the only\n * prop type whose value is a list. The save schema refuses the rest with the valid set named.\n */\n ui?: ContentModelFieldUi;\n}\n\n/** One field inside a `group` prop or a `table` row. Recursive, capped at 3 levels deep. */\nexport interface ComponentSubField {\n key: string;\n label: string;\n /** No `slot`: a nested component instance belongs on the prop itself, not inside a row. */\n // `slot` and `form` are reference-shaped props: they belong ON a prop, never inside a row of\n // one. A form in a table row would mean N form documents per component with no way to author\n // them — the second field model this design exists to avoid.\n type: Exclude<ComponentPropDef[\"type\"], \"slot\" | \"form\">;\n defaultValue?: unknown;\n /** The same editor hints as the prop above, one level down. @see ComponentPropDef */\n required?: boolean;\n helpText?: string;\n placeholder?: string;\n options?: string[];\n /** CANONICAL. A nested `group`/`table`'s own sub-shape. */\n fields?: ComponentSubField[];\n /**\n * A READ-ONLY MIRROR of `options`/`fields`, in the shape `ComponentPropDef` puts them in.\n *\n * 🔴 WHY A SECOND COPY EXISTS AT ALL. A `group`/`table` PROP declares its sub-shape under\n * `config.fields`; a sub-field of one declares its own under a bare `fields`. So a consumer\n * walking a nested table has to switch shape after the first level, and the componentize lane's\n * repo half (`@bettercms-ai/convert --componentize`) walks exactly that — it reads one node\n * shape at every depth. Mirroring the sub-shape here lets it, without the CMS having to\n * describe a nested table differently from a top-level one.\n *\n * `fields` is the authority. The save schema REFUSES a node whose mirror disagrees with it\n * (`componentPropDefSchema`), because two copies that may drift are worse than one awkward\n * shape — an editor that rewrote `fields` alone would leave a stale row description behind.\n */\n config?: { fields?: ComponentSubField[]; options?: string[] } & Record<string, unknown>;\n}\n\n/** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */\nexport interface SlotValue {\n componentId: string;\n overrides?: Record<string, unknown>;\n}\n\n/**\n * A component is a DRAFT until published; only the published copy reaches a visitor.\n * Mirrors pages and entries. See migration 0186_component_draft_live_split.sql.\n */\nexport type ComponentStatus = \"draft\" | \"published\";\n\n/**\n * Archive state (FLO-1012), deliberately SEPARATE from `ComponentStatus`.\n *\n * Archive takes a component out of the working set — hidden from the components list by\n * default, not offered in the visual editor's insert surfaces — while every existing usage\n * keeps serving. It is not unpublish (which pulls the live copy and re-bakes every page that\n * embeds it) and it is not delete.\n *\n * It is a timestamp rather than a third `status` value because a component can be published\n * AND archived; collapsing the two would lose the bit restore has to put back.\n */\n\nexport interface Component {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n category: ComponentCategory;\n /**\n * Section library: the family this component is a LAYOUT of, e.g. \"Hero\". `name` is the\n * layout label (\"Centered\"), so components sharing a sectionType are selectable variants\n * of one section. Null/absent = an ordinary component, not shown in the section library.\n */\n sectionType?: string | null;\n /** First-class variant family membership; exact workspace/project scope is enforced in DB. */\n variantGroupId?: string | null;\n variantInputMappings?: VariantInputMapping[];\n /** Placement governance: `*`, `slug:<page-slug>`, and/or `type:<page-type>`. */\n allowedOn: string[];\n description?: string | null;\n /** The DRAFT definition. Every builder/autosave/import write path targets these two. */\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n status: ComponentStatus;\n /** When it left the working set, or null/absent while active. @see ComponentStatus */\n archivedAt?: string | Date | null;\n /** Derived from `archivedAt`, so a client never has to know the column. */\n archived?: boolean;\n /**\n * The LIVE snapshot get_components_by_handle() serves. Null until the first publish.\n * Returned by GET-one (the Compare view needs it), omitted from list rows for payload.\n */\n publishedBlockJson?: ContentBlock[] | null;\n publishedProps?: ComponentPropDef[] | null;\n publishedAt?: string | null; // ISO 8601\n /**\n * Computed in SQL on list/get, never stored:\n * status='published' AND (blockJson or props has diverged from its published copy).\n * An exact jsonb compare, so it self-clears when an edit is reverted.\n */\n pendingChanges?: boolean;\n thumbnail?: string | null;\n createdAt: string; // ISO 8601\n updatedAt: string; // ISO 8601\n}\n\n/**\n * Public/delivery projection — the fields a renderer needs to resolve instances.\n *\n * DELIBERATELY UNCHANGED by the 0186 draft/live split: delivery aliases\n * publishedBlockJson -> blockJson, so every already-deployed site and every\n * bcms-content.json on disk keeps a byte-identical wire shape. Do not add `status` here —\n * delivery only ever returns published rows, so it would always be the same constant.\n */\nexport interface DeliveryComponent {\n id: string;\n name: string;\n slug: string;\n category: ComponentCategory;\n sectionType?: string | null;\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n}\n","/**\n * Generated from lucide-react@1.8.0 dynamic icon names.\n * Legacy CamelCase identifiers remain valid for existing Layout documents.\n */\nexport const LAYOUT_SECTION_ICONS: readonly string[] = Object.freeze([\n \"LayoutPanelTop\",\n \"PanelTop\",\n \"PanelBottom\",\n \"Menu\",\n \"Navigation\",\n \"Megaphone\",\n \"GalleryHorizontal\",\n \"Rows3\",\n \"Grid2X2\",\n \"FileText\",\n \"Link\",\n \"Contact\",\n \"BadgeInfo\",\n \"Sparkles\",\n \"a-arrow-down\",\n \"a-arrow-up\",\n \"a-large-small\",\n \"accessibility\",\n \"activity\",\n \"air-vent\",\n \"airplay\",\n \"alarm-clock-check\",\n \"alarm-check\",\n \"alarm-clock-minus\",\n \"alarm-minus\",\n \"alarm-clock-off\",\n \"alarm-clock-plus\",\n \"alarm-plus\",\n \"alarm-clock\",\n \"alarm-smoke\",\n \"album\",\n \"align-center-horizontal\",\n \"align-center-vertical\",\n \"align-end-horizontal\",\n \"align-end-vertical\",\n \"align-horizontal-distribute-center\",\n \"align-horizontal-distribute-end\",\n \"align-horizontal-distribute-start\",\n \"align-horizontal-justify-center\",\n \"align-horizontal-justify-end\",\n \"align-horizontal-justify-start\",\n \"align-horizontal-space-around\",\n \"align-horizontal-space-between\",\n \"align-start-horizontal\",\n \"align-start-vertical\",\n \"align-vertical-distribute-center\",\n \"align-vertical-distribute-end\",\n \"align-vertical-distribute-start\",\n \"align-vertical-justify-center\",\n \"align-vertical-justify-end\",\n \"align-vertical-justify-start\",\n \"align-vertical-space-around\",\n \"align-vertical-space-between\",\n \"ambulance\",\n \"ampersand\",\n \"ampersands\",\n \"amphora\",\n \"anchor\",\n \"angry\",\n \"annoyed\",\n \"antenna\",\n \"anvil\",\n \"aperture\",\n \"app-window-mac\",\n \"app-window\",\n \"apple\",\n \"archive-restore\",\n \"archive-x\",\n \"archive\",\n \"armchair\",\n \"arrow-big-down-dash\",\n \"arrow-big-down\",\n \"arrow-big-left-dash\",\n \"arrow-big-left\",\n \"arrow-big-right-dash\",\n \"arrow-big-right\",\n \"arrow-big-up-dash\",\n \"arrow-big-up\",\n \"arrow-down-0-1\",\n \"arrow-down-01\",\n \"arrow-down-1-0\",\n \"arrow-down-10\",\n \"arrow-down-a-z\",\n \"arrow-down-az\",\n \"arrow-down-from-line\",\n \"arrow-down-left\",\n \"arrow-down-narrow-wide\",\n \"arrow-down-right\",\n \"arrow-down-to-dot\",\n \"arrow-down-to-line\",\n \"arrow-down-up\",\n \"arrow-down-wide-narrow\",\n \"sort-desc\",\n \"arrow-down-z-a\",\n \"arrow-down-za\",\n \"arrow-down\",\n \"arrow-left-from-line\",\n \"arrow-left-right\",\n \"arrow-left-to-line\",\n \"arrow-left\",\n \"arrow-right-from-line\",\n \"arrow-right-left\",\n \"arrow-right-to-line\",\n \"arrow-right\",\n \"arrow-up-0-1\",\n \"arrow-up-01\",\n \"arrow-up-1-0\",\n \"arrow-up-10\",\n \"arrow-up-a-z\",\n \"arrow-up-az\",\n \"arrow-up-down\",\n \"arrow-up-from-dot\",\n \"arrow-up-from-line\",\n \"arrow-up-left\",\n \"arrow-up-narrow-wide\",\n \"sort-asc\",\n \"arrow-up-right\",\n \"arrow-up-to-line\",\n \"arrow-up-wide-narrow\",\n \"arrow-up-z-a\",\n \"arrow-up-za\",\n \"arrow-up\",\n \"arrows-up-from-line\",\n \"asterisk\",\n \"at-sign\",\n \"atom\",\n \"audio-lines\",\n \"audio-waveform\",\n \"award\",\n \"axe\",\n \"axis-3d\",\n \"axis-3-d\",\n \"baby\",\n \"backpack\",\n \"badge-alert\",\n \"badge-cent\",\n \"badge-check\",\n \"verified\",\n \"badge-dollar-sign\",\n \"badge-euro\",\n \"badge-indian-rupee\",\n \"badge-info\",\n \"badge-japanese-yen\",\n \"badge-minus\",\n \"badge-percent\",\n \"badge-plus\",\n \"badge-pound-sterling\",\n \"badge-question-mark\",\n \"badge-help\",\n \"badge-russian-ruble\",\n \"badge-swiss-franc\",\n \"badge-turkish-lira\",\n \"badge-x\",\n \"badge\",\n \"baggage-claim\",\n \"balloon\",\n \"ban\",\n \"banana\",\n \"bandage\",\n \"banknote-arrow-down\",\n \"banknote-arrow-up\",\n \"banknote-x\",\n \"banknote\",\n \"barcode\",\n \"barrel\",\n \"baseline\",\n \"bath\",\n \"battery-charging\",\n \"battery-full\",\n \"battery-low\",\n \"battery-medium\",\n \"battery-plus\",\n \"battery-warning\",\n \"battery\",\n \"beaker\",\n \"bean-off\",\n \"bean\",\n \"bed-double\",\n \"bed-single\",\n \"bed\",\n \"beef-off\",\n \"beef\",\n \"beer-off\",\n \"beer\",\n \"bell-dot\",\n \"bell-electric\",\n \"bell-minus\",\n \"bell-off\",\n \"bell-plus\",\n \"bell-ring\",\n \"bell\",\n \"between-horizontal-end\",\n \"between-horizonal-end\",\n \"between-horizontal-start\",\n \"between-horizonal-start\",\n \"between-vertical-end\",\n \"between-vertical-start\",\n \"biceps-flexed\",\n \"bike\",\n \"binary\",\n \"binoculars\",\n \"biohazard\",\n \"bird\",\n \"birdhouse\",\n \"bitcoin\",\n \"blend\",\n \"blinds\",\n \"blocks\",\n \"bluetooth-connected\",\n \"bluetooth-off\",\n \"bluetooth-searching\",\n \"bluetooth\",\n \"bold\",\n \"bolt\",\n \"bomb\",\n \"bone\",\n \"book-a\",\n \"book-alert\",\n \"book-audio\",\n \"book-check\",\n \"book-copy\",\n \"book-dashed\",\n \"book-template\",\n \"book-down\",\n \"book-headphones\",\n \"book-heart\",\n \"book-image\",\n \"book-key\",\n \"book-lock\",\n \"book-marked\",\n \"book-minus\",\n \"book-open-check\",\n \"book-open-text\",\n \"book-open\",\n \"book-plus\",\n \"book-search\",\n \"book-text\",\n \"book-type\",\n \"book-up-2\",\n \"book-up\",\n \"book-user\",\n \"book-x\",\n \"book\",\n \"bookmark-check\",\n \"bookmark-minus\",\n \"bookmark-off\",\n \"bookmark-plus\",\n \"bookmark-x\",\n \"bookmark\",\n \"boom-box\",\n \"bot-message-square\",\n \"bot-off\",\n \"bot\",\n \"bottle-wine\",\n \"bow-arrow\",\n \"box\",\n \"boxes\",\n \"braces\",\n \"curly-braces\",\n \"brackets\",\n \"brain-circuit\",\n \"brain-cog\",\n \"brain\",\n \"brick-wall-fire\",\n \"brick-wall-shield\",\n \"brick-wall\",\n \"briefcase-business\",\n \"briefcase-conveyor-belt\",\n \"briefcase-medical\",\n \"briefcase\",\n \"bring-to-front\",\n \"brush-cleaning\",\n \"brush\",\n \"bubbles\",\n \"bug-off\",\n \"bug-play\",\n \"bug\",\n \"building-2\",\n \"building\",\n \"bus-front\",\n \"bus\",\n \"cable-car\",\n \"cable\",\n \"cake-slice\",\n \"cake\",\n \"calculator\",\n \"calendar-1\",\n \"calendar-arrow-down\",\n \"calendar-arrow-up\",\n \"calendar-check-2\",\n \"calendar-check\",\n \"calendar-clock\",\n \"calendar-cog\",\n \"calendar-days\",\n \"calendar-fold\",\n \"calendar-heart\",\n \"calendar-minus-2\",\n \"calendar-minus\",\n \"calendar-off\",\n \"calendar-plus-2\",\n \"calendar-plus\",\n \"calendar-range\",\n \"calendar-search\",\n \"calendar-sync\",\n \"calendar-x-2\",\n \"calendar-x\",\n \"calendar\",\n \"calendars\",\n \"camera-off\",\n \"camera\",\n \"candy-cane\",\n \"candy-off\",\n \"candy\",\n \"cannabis-off\",\n \"cannabis\",\n \"captions-off\",\n \"captions\",\n \"subtitles\",\n \"car-front\",\n \"car-taxi-front\",\n \"car\",\n \"caravan\",\n \"card-sim\",\n \"carrot\",\n \"case-lower\",\n \"case-sensitive\",\n \"case-upper\",\n \"cassette-tape\",\n \"cast\",\n \"castle\",\n \"cat\",\n \"cctv-off\",\n \"cctv\",\n \"chart-area\",\n \"area-chart\",\n \"chart-bar-big\",\n \"bar-chart-horizontal-big\",\n \"chart-bar-decreasing\",\n \"chart-bar-increasing\",\n \"chart-bar-stacked\",\n \"chart-bar\",\n \"bar-chart-horizontal\",\n \"chart-candlestick\",\n \"candlestick-chart\",\n \"chart-column-big\",\n \"bar-chart-big\",\n \"chart-column-decreasing\",\n \"chart-column-increasing\",\n \"bar-chart-4\",\n \"chart-column-stacked\",\n \"chart-column\",\n \"bar-chart-3\",\n \"chart-gantt\",\n \"chart-line\",\n \"line-chart\",\n \"chart-network\",\n \"chart-no-axes-column-decreasing\",\n \"chart-no-axes-column-increasing\",\n \"bar-chart\",\n \"chart-no-axes-column\",\n \"bar-chart-2\",\n \"chart-no-axes-combined\",\n \"chart-no-axes-gantt\",\n \"gantt-chart\",\n \"chart-pie\",\n \"pie-chart\",\n \"chart-scatter\",\n \"scatter-chart\",\n \"chart-spline\",\n \"check-check\",\n \"check-line\",\n \"check\",\n \"chef-hat\",\n \"cherry\",\n \"chess-bishop\",\n \"chess-king\",\n \"chess-knight\",\n \"chess-pawn\",\n \"chess-queen\",\n \"chess-rook\",\n \"chevron-down\",\n \"chevron-first\",\n \"chevron-last\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"chevrons-down-up\",\n \"chevrons-down\",\n \"chevrons-left-right-ellipsis\",\n \"chevrons-left-right\",\n \"chevrons-left\",\n \"chevrons-right-left\",\n \"chevrons-right\",\n \"chevrons-up-down\",\n \"chevrons-up\",\n \"church\",\n \"cigarette-off\",\n \"cigarette\",\n \"circle-alert\",\n \"alert-circle\",\n \"circle-arrow-down\",\n \"arrow-down-circle\",\n \"circle-arrow-left\",\n \"arrow-left-circle\",\n \"circle-arrow-out-down-left\",\n \"arrow-down-left-from-circle\",\n \"circle-arrow-out-down-right\",\n \"arrow-down-right-from-circle\",\n \"circle-arrow-out-up-left\",\n \"arrow-up-left-from-circle\",\n \"circle-arrow-out-up-right\",\n \"arrow-up-right-from-circle\",\n \"circle-arrow-right\",\n \"arrow-right-circle\",\n \"circle-arrow-up\",\n \"arrow-up-circle\",\n \"circle-check-big\",\n \"check-circle\",\n \"circle-check\",\n \"check-circle-2\",\n \"circle-chevron-down\",\n \"chevron-down-circle\",\n \"circle-chevron-left\",\n \"chevron-left-circle\",\n \"circle-chevron-right\",\n \"chevron-right-circle\",\n \"circle-chevron-up\",\n \"chevron-up-circle\",\n \"circle-dashed\",\n \"circle-divide\",\n \"divide-circle\",\n \"circle-dollar-sign\",\n \"circle-dot-dashed\",\n \"circle-dot\",\n \"circle-ellipsis\",\n \"circle-equal\",\n \"circle-fading-arrow-up\",\n \"circle-fading-plus\",\n \"circle-gauge\",\n \"gauge-circle\",\n \"circle-minus\",\n \"minus-circle\",\n \"circle-off\",\n \"circle-parking-off\",\n \"parking-circle-off\",\n \"circle-parking\",\n \"parking-circle\",\n \"circle-pause\",\n \"pause-circle\",\n \"circle-percent\",\n \"percent-circle\",\n \"circle-pile\",\n \"circle-play\",\n \"play-circle\",\n \"circle-plus\",\n \"plus-circle\",\n \"circle-pound-sterling\",\n \"circle-power\",\n \"power-circle\",\n \"circle-question-mark\",\n \"help-circle\",\n \"circle-help\",\n \"circle-slash-2\",\n \"circle-slashed\",\n \"circle-slash\",\n \"circle-small\",\n \"circle-star\",\n \"circle-stop\",\n \"stop-circle\",\n \"circle-user-round\",\n \"user-circle-2\",\n \"circle-user\",\n \"user-circle\",\n \"circle-x\",\n \"x-circle\",\n \"circle\",\n \"circuit-board\",\n \"citrus\",\n \"clapperboard\",\n \"clipboard-check\",\n \"clipboard-clock\",\n \"clipboard-copy\",\n \"clipboard-list\",\n \"clipboard-minus\",\n \"clipboard-paste\",\n \"clipboard-pen-line\",\n \"clipboard-signature\",\n \"clipboard-pen\",\n \"clipboard-edit\",\n \"clipboard-plus\",\n \"clipboard-type\",\n \"clipboard-x\",\n \"clipboard\",\n \"clock-1\",\n \"clock-10\",\n \"clock-11\",\n \"clock-12\",\n \"clock-2\",\n \"clock-3\",\n \"clock-4\",\n \"clock-5\",\n \"clock-6\",\n \"clock-7\",\n \"clock-8\",\n \"clock-9\",\n \"clock-alert\",\n \"clock-arrow-down\",\n \"clock-arrow-up\",\n \"clock-check\",\n \"clock-fading\",\n \"clock-plus\",\n \"clock\",\n \"closed-caption\",\n \"cloud-alert\",\n \"cloud-backup\",\n \"cloud-check\",\n \"cloud-cog\",\n \"cloud-download\",\n \"download-cloud\",\n \"cloud-drizzle\",\n \"cloud-fog\",\n \"cloud-hail\",\n \"cloud-lightning\",\n \"cloud-moon-rain\",\n \"cloud-moon\",\n \"cloud-off\",\n \"cloud-rain-wind\",\n \"cloud-rain\",\n \"cloud-snow\",\n \"cloud-sun-rain\",\n \"cloud-sun\",\n \"cloud-sync\",\n \"cloud-upload\",\n \"upload-cloud\",\n \"cloud\",\n \"cloudy\",\n \"clover\",\n \"club\",\n \"code-xml\",\n \"code-2\",\n \"code\",\n \"coffee\",\n \"cog\",\n \"coins\",\n \"columns-2\",\n \"columns\",\n \"columns-3-cog\",\n \"columns-settings\",\n \"table-config\",\n \"columns-3\",\n \"panels-left-right\",\n \"columns-4\",\n \"combine\",\n \"command\",\n \"compass\",\n \"component\",\n \"computer\",\n \"concierge-bell\",\n \"cone\",\n \"construction\",\n \"contact-round\",\n \"contact-2\",\n \"contact\",\n \"container\",\n \"contrast\",\n \"cookie\",\n \"cooking-pot\",\n \"copy-check\",\n \"copy-minus\",\n \"copy-plus\",\n \"copy-slash\",\n \"copy-x\",\n \"copy\",\n \"copyleft\",\n \"copyright\",\n \"corner-down-left\",\n \"corner-down-right\",\n \"corner-left-down\",\n \"corner-left-up\",\n \"corner-right-down\",\n \"corner-right-up\",\n \"corner-up-left\",\n \"corner-up-right\",\n \"cpu\",\n \"creative-commons\",\n \"credit-card\",\n \"croissant\",\n \"crop\",\n \"cross\",\n \"crosshair\",\n \"crown\",\n \"cuboid\",\n \"cup-soda\",\n \"currency\",\n \"cylinder\",\n \"dam\",\n \"database-backup\",\n \"database-search\",\n \"database-zap\",\n \"database\",\n \"decimals-arrow-left\",\n \"decimals-arrow-right\",\n \"delete\",\n \"dessert\",\n \"diameter\",\n \"diamond-minus\",\n \"diamond-percent\",\n \"percent-diamond\",\n \"diamond-plus\",\n \"diamond\",\n \"dice-1\",\n \"dice-2\",\n \"dice-3\",\n \"dice-4\",\n \"dice-5\",\n \"dice-6\",\n \"dices\",\n \"diff\",\n \"disc-2\",\n \"disc-3\",\n \"disc-album\",\n \"disc\",\n \"divide\",\n \"dna-off\",\n \"dna\",\n \"dock\",\n \"dog\",\n \"dollar-sign\",\n \"donut\",\n \"door-closed-locked\",\n \"door-closed\",\n \"door-open\",\n \"dot\",\n \"download\",\n \"drafting-compass\",\n \"drama\",\n \"drill\",\n \"drone\",\n \"droplet-off\",\n \"droplet\",\n \"droplets\",\n \"drum\",\n \"drumstick\",\n \"dumbbell\",\n \"ear-off\",\n \"ear\",\n \"earth-lock\",\n \"earth\",\n \"globe-2\",\n \"eclipse\",\n \"egg-fried\",\n \"egg-off\",\n \"egg\",\n \"ellipse\",\n \"ellipsis-vertical\",\n \"more-vertical\",\n \"ellipsis\",\n \"more-horizontal\",\n \"equal-approximately\",\n \"equal-not\",\n \"equal\",\n \"eraser\",\n \"ethernet-port\",\n \"euro\",\n \"ev-charger\",\n \"expand\",\n \"external-link\",\n \"eye-closed\",\n \"eye-off\",\n \"eye\",\n \"factory\",\n \"fan\",\n \"fast-forward\",\n \"feather\",\n \"fence\",\n \"ferris-wheel\",\n \"file-archive\",\n \"file-axis-3d\",\n \"file-axis-3-d\",\n \"file-badge\",\n \"file-badge-2\",\n \"file-box\",\n \"file-braces-corner\",\n \"file-json-2\",\n \"file-braces\",\n \"file-json\",\n \"file-chart-column-increasing\",\n \"file-bar-chart\",\n \"file-chart-column\",\n \"file-bar-chart-2\",\n \"file-chart-line\",\n \"file-line-chart\",\n \"file-chart-pie\",\n \"file-pie-chart\",\n \"file-check-corner\",\n \"file-check-2\",\n \"file-check\",\n \"file-clock\",\n \"file-code-corner\",\n \"file-code-2\",\n \"file-code\",\n \"file-cog\",\n \"file-cog-2\",\n \"file-diff\",\n \"file-digit\",\n \"file-down\",\n \"file-exclamation-point\",\n \"file-warning\",\n \"file-headphone\",\n \"file-audio\",\n \"file-audio-2\",\n \"file-heart\",\n \"file-image\",\n \"file-input\",\n \"file-key\",\n \"file-key-2\",\n \"file-lock\",\n \"file-lock-2\",\n \"file-minus-corner\",\n \"file-minus-2\",\n \"file-minus\",\n \"file-music\",\n \"file-output\",\n \"file-pen-line\",\n \"file-signature\",\n \"file-pen\",\n \"file-edit\",\n \"file-play\",\n \"file-video\",\n \"file-plus-corner\",\n \"file-plus-2\",\n \"file-plus\",\n \"file-question-mark\",\n \"file-question\",\n \"file-scan\",\n \"file-search-corner\",\n \"file-search-2\",\n \"file-search\",\n \"file-signal\",\n \"file-volume-2\",\n \"file-sliders\",\n \"file-spreadsheet\",\n \"file-stack\",\n \"file-symlink\",\n \"file-terminal\",\n \"file-text\",\n \"file-type-corner\",\n \"file-type-2\",\n \"file-type\",\n \"file-up\",\n \"file-user\",\n \"file-video-camera\",\n \"file-video-2\",\n \"file-volume\",\n \"file-x-corner\",\n \"file-x-2\",\n \"file-x\",\n \"file\",\n \"files\",\n \"film\",\n \"fingerprint-pattern\",\n \"fingerprint\",\n \"fire-extinguisher\",\n \"fish-off\",\n \"fish-symbol\",\n \"fish\",\n \"fishing-hook\",\n \"fishing-rod\",\n \"flag-off\",\n \"flag-triangle-left\",\n \"flag-triangle-right\",\n \"flag\",\n \"flame-kindling\",\n \"flame\",\n \"flashlight-off\",\n \"flashlight\",\n \"flask-conical-off\",\n \"flask-conical\",\n \"flask-round\",\n \"flip-horizontal-2\",\n \"flip-vertical-2\",\n \"flower-2\",\n \"flower\",\n \"focus\",\n \"fold-horizontal\",\n \"fold-vertical\",\n \"folder-archive\",\n \"folder-check\",\n \"folder-clock\",\n \"folder-closed\",\n \"folder-code\",\n \"folder-cog\",\n \"folder-cog-2\",\n \"folder-dot\",\n \"folder-down\",\n \"folder-git-2\",\n \"folder-git\",\n \"folder-heart\",\n \"folder-input\",\n \"folder-kanban\",\n \"folder-key\",\n \"folder-lock\",\n \"folder-minus\",\n \"folder-open-dot\",\n \"folder-open\",\n \"folder-output\",\n \"folder-pen\",\n \"folder-edit\",\n \"folder-plus\",\n \"folder-root\",\n \"folder-search-2\",\n \"folder-search\",\n \"folder-symlink\",\n \"folder-sync\",\n \"folder-tree\",\n \"folder-up\",\n \"folder-x\",\n \"folder\",\n \"folders\",\n \"footprints\",\n \"forklift\",\n \"form\",\n \"forward\",\n \"frame\",\n \"frown\",\n \"fuel\",\n \"fullscreen\",\n \"funnel-plus\",\n \"funnel-x\",\n \"filter-x\",\n \"funnel\",\n \"filter\",\n \"gallery-horizontal-end\",\n \"gallery-horizontal\",\n \"gallery-thumbnails\",\n \"gallery-vertical-end\",\n \"gallery-vertical\",\n \"gamepad-2\",\n \"gamepad-directional\",\n \"gamepad\",\n \"gauge\",\n \"gavel\",\n \"gem\",\n \"georgian-lari\",\n \"ghost\",\n \"gift\",\n \"git-branch-minus\",\n \"git-branch-plus\",\n \"git-branch\",\n \"git-commit-horizontal\",\n \"git-commit\",\n \"git-commit-vertical\",\n \"git-compare-arrows\",\n \"git-compare\",\n \"git-fork\",\n \"git-graph\",\n \"git-merge-conflict\",\n \"git-merge\",\n \"git-pull-request-arrow\",\n \"git-pull-request-closed\",\n \"git-pull-request-create-arrow\",\n \"git-pull-request-create\",\n \"git-pull-request-draft\",\n \"git-pull-request\",\n \"glass-water\",\n \"glasses\",\n \"globe-lock\",\n \"globe-off\",\n \"globe-x\",\n \"globe\",\n \"goal\",\n \"gpu\",\n \"graduation-cap\",\n \"grape\",\n \"grid-2x2-check\",\n \"grid-2-x-2-check\",\n \"grid-2x2-plus\",\n \"grid-2-x-2-plus\",\n \"grid-2x2-x\",\n \"grid-2-x-2-x\",\n \"grid-2x2\",\n \"grid-2-x-2\",\n \"grid-3x2\",\n \"grid-3x3\",\n \"grid\",\n \"grid-3-x-3\",\n \"grip-horizontal\",\n \"grip-vertical\",\n \"grip\",\n \"group\",\n \"guitar\",\n \"ham\",\n \"hamburger\",\n \"hammer\",\n \"hand-coins\",\n \"hand-fist\",\n \"hand-grab\",\n \"grab\",\n \"hand-heart\",\n \"hand-helping\",\n \"helping-hand\",\n \"hand-metal\",\n \"hand-platter\",\n \"hand\",\n \"handbag\",\n \"handshake\",\n \"hard-drive-download\",\n \"hard-drive-upload\",\n \"hard-drive\",\n \"hard-hat\",\n \"hash\",\n \"hat-glasses\",\n \"haze\",\n \"hd\",\n \"hdmi-port\",\n \"heading-1\",\n \"heading-2\",\n \"heading-3\",\n \"heading-4\",\n \"heading-5\",\n \"heading-6\",\n \"heading\",\n \"headphone-off\",\n \"headphones\",\n \"headset\",\n \"heart-crack\",\n \"heart-handshake\",\n \"heart-minus\",\n \"heart-off\",\n \"heart-plus\",\n \"heart-pulse\",\n \"heart\",\n \"heater\",\n \"helicopter\",\n \"hexagon\",\n \"highlighter\",\n \"history\",\n \"hop-off\",\n \"hop\",\n \"hospital\",\n \"hotel\",\n \"hourglass\",\n \"house-heart\",\n \"house-plug\",\n \"house-plus\",\n \"house-wifi\",\n \"house\",\n \"home\",\n \"ice-cream-bowl\",\n \"ice-cream-2\",\n \"ice-cream-cone\",\n \"ice-cream\",\n \"id-card-lanyard\",\n \"id-card\",\n \"image-down\",\n \"image-minus\",\n \"image-off\",\n \"image-play\",\n \"image-plus\",\n \"image-up\",\n \"image-upscale\",\n \"image\",\n \"images\",\n \"import\",\n \"inbox\",\n \"indian-rupee\",\n \"infinity\",\n \"info\",\n \"inspection-panel\",\n \"italic\",\n \"iteration-ccw\",\n \"iteration-cw\",\n \"japanese-yen\",\n \"joystick\",\n \"kanban\",\n \"kayak\",\n \"key-round\",\n \"key-square\",\n \"key\",\n \"keyboard-music\",\n \"keyboard-off\",\n \"keyboard\",\n \"lamp-ceiling\",\n \"lamp-desk\",\n \"lamp-floor\",\n \"lamp-wall-down\",\n \"lamp-wall-up\",\n \"lamp\",\n \"land-plot\",\n \"landmark\",\n \"languages\",\n \"laptop-minimal-check\",\n \"laptop-minimal\",\n \"laptop-2\",\n \"laptop\",\n \"lasso-select\",\n \"lasso\",\n \"laugh\",\n \"layers-2\",\n \"layers-plus\",\n \"layers\",\n \"layers-3\",\n \"layout-dashboard\",\n \"layout-grid\",\n \"layout-list\",\n \"layout-panel-left\",\n \"layout-panel-top\",\n \"layout-template\",\n \"leaf\",\n \"leafy-green\",\n \"lectern\",\n \"lens-concave\",\n \"lens-convex\",\n \"library-big\",\n \"library\",\n \"life-buoy\",\n \"ligature\",\n \"lightbulb-off\",\n \"lightbulb\",\n \"line-dot-right-horizontal\",\n \"line-squiggle\",\n \"line-style\",\n \"link-2-off\",\n \"link-2\",\n \"link\",\n \"list-check\",\n \"list-checks\",\n \"list-chevrons-down-up\",\n \"list-chevrons-up-down\",\n \"list-collapse\",\n \"list-end\",\n \"list-filter-plus\",\n \"list-filter\",\n \"list-indent-decrease\",\n \"outdent\",\n \"indent-decrease\",\n \"list-indent-increase\",\n \"indent\",\n \"indent-increase\",\n \"list-minus\",\n \"list-music\",\n \"list-ordered\",\n \"list-plus\",\n \"list-restart\",\n \"list-start\",\n \"list-todo\",\n \"list-tree\",\n \"list-video\",\n \"list-x\",\n \"list\",\n \"loader-circle\",\n \"loader-2\",\n \"loader-pinwheel\",\n \"loader\",\n \"locate-fixed\",\n \"locate-off\",\n \"locate\",\n \"lock-keyhole-open\",\n \"unlock-keyhole\",\n \"lock-keyhole\",\n \"lock-open\",\n \"unlock\",\n \"lock\",\n \"log-in\",\n \"log-out\",\n \"logs\",\n \"lollipop\",\n \"luggage\",\n \"magnet\",\n \"mail-check\",\n \"mail-minus\",\n \"mail-open\",\n \"mail-plus\",\n \"mail-question-mark\",\n \"mail-question\",\n \"mail-search\",\n \"mail-warning\",\n \"mail-x\",\n \"mail\",\n \"mailbox\",\n \"mails\",\n \"map-minus\",\n \"map-pin-check-inside\",\n \"map-pin-check\",\n \"map-pin-house\",\n \"map-pin-minus-inside\",\n \"map-pin-minus\",\n \"map-pin-off\",\n \"map-pin-pen\",\n \"location-edit\",\n \"map-pin-plus-inside\",\n \"map-pin-plus\",\n \"map-pin-search\",\n \"map-pin-x-inside\",\n \"map-pin-x\",\n \"map-pin\",\n \"map-pinned\",\n \"map-plus\",\n \"map\",\n \"mars-stroke\",\n \"mars\",\n \"martini\",\n \"maximize-2\",\n \"maximize\",\n \"medal\",\n \"megaphone-off\",\n \"megaphone\",\n \"meh\",\n \"memory-stick\",\n \"menu\",\n \"merge\",\n \"message-circle-check\",\n \"message-circle-code\",\n \"message-circle-dashed\",\n \"message-circle-heart\",\n \"message-circle-more\",\n \"message-circle-off\",\n \"message-circle-plus\",\n \"message-circle-question-mark\",\n \"message-circle-question\",\n \"message-circle-reply\",\n \"message-circle-warning\",\n \"message-circle-x\",\n \"message-circle\",\n \"message-square-check\",\n \"message-square-code\",\n \"message-square-dashed\",\n \"message-square-diff\",\n \"message-square-dot\",\n \"message-square-heart\",\n \"message-square-lock\",\n \"message-square-more\",\n \"message-square-off\",\n \"message-square-plus\",\n \"message-square-quote\",\n \"message-square-reply\",\n \"message-square-share\",\n \"message-square-text\",\n \"message-square-warning\",\n \"message-square-x\",\n \"message-square\",\n \"messages-square\",\n \"metronome\",\n \"mic-off\",\n \"mic-vocal\",\n \"mic-2\",\n \"mic\",\n \"microchip\",\n \"microscope\",\n \"microwave\",\n \"milestone\",\n \"milk-off\",\n \"milk\",\n \"minimize-2\",\n \"minimize\",\n \"minus\",\n \"mirror-rectangular\",\n \"mirror-round\",\n \"monitor-check\",\n \"monitor-cloud\",\n \"monitor-cog\",\n \"monitor-dot\",\n \"monitor-down\",\n \"monitor-off\",\n \"monitor-pause\",\n \"monitor-play\",\n \"monitor-smartphone\",\n \"monitor-speaker\",\n \"monitor-stop\",\n \"monitor-up\",\n \"monitor-x\",\n \"monitor\",\n \"moon-star\",\n \"moon\",\n \"motorbike\",\n \"mountain-snow\",\n \"mountain\",\n \"mouse-left\",\n \"mouse-off\",\n \"mouse-pointer-2-off\",\n \"mouse-pointer-2\",\n \"mouse-pointer-ban\",\n \"mouse-pointer-click\",\n \"mouse-pointer\",\n \"mouse-right\",\n \"mouse\",\n \"move-3d\",\n \"move-3-d\",\n \"move-diagonal-2\",\n \"move-diagonal\",\n \"move-down-left\",\n \"move-down-right\",\n \"move-down\",\n \"move-horizontal\",\n \"move-left\",\n \"move-right\",\n \"move-up-left\",\n \"move-up-right\",\n \"move-up\",\n \"move-vertical\",\n \"move\",\n \"music-2\",\n \"music-3\",\n \"music-4\",\n \"music\",\n \"navigation-2-off\",\n \"navigation-2\",\n \"navigation-off\",\n \"navigation\",\n \"network\",\n \"newspaper\",\n \"nfc\",\n \"non-binary\",\n \"notebook-pen\",\n \"notebook-tabs\",\n \"notebook-text\",\n \"notebook\",\n \"notepad-text-dashed\",\n \"notepad-text\",\n \"nut-off\",\n \"nut\",\n \"octagon-alert\",\n \"alert-octagon\",\n \"octagon-minus\",\n \"octagon-pause\",\n \"pause-octagon\",\n \"octagon-x\",\n \"x-octagon\",\n \"octagon\",\n \"omega\",\n \"option\",\n \"orbit\",\n \"origami\",\n \"package-2\",\n \"package-check\",\n \"package-minus\",\n \"package-open\",\n \"package-plus\",\n \"package-search\",\n \"package-x\",\n \"package\",\n \"paint-bucket\",\n \"paint-roller\",\n \"paintbrush-vertical\",\n \"paintbrush-2\",\n \"paintbrush\",\n \"palette\",\n \"panda\",\n \"panel-bottom-close\",\n \"panel-bottom-dashed\",\n \"panel-bottom-inactive\",\n \"panel-bottom-open\",\n \"panel-bottom\",\n \"panel-left-close\",\n \"sidebar-close\",\n \"panel-left-dashed\",\n \"panel-left-inactive\",\n \"panel-left-open\",\n \"sidebar-open\",\n \"panel-left-right-dashed\",\n \"panel-left\",\n \"sidebar\",\n \"panel-right-close\",\n \"panel-right-dashed\",\n \"panel-right-inactive\",\n \"panel-right-open\",\n \"panel-right\",\n \"panel-top-bottom-dashed\",\n \"panel-top-close\",\n \"panel-top-dashed\",\n \"panel-top-inactive\",\n \"panel-top-open\",\n \"panel-top\",\n \"panels-left-bottom\",\n \"panels-right-bottom\",\n \"panels-top-left\",\n \"layout\",\n \"paperclip\",\n \"parentheses\",\n \"parking-meter\",\n \"party-popper\",\n \"pause\",\n \"paw-print\",\n \"pc-case\",\n \"pen-line\",\n \"edit-3\",\n \"pen-off\",\n \"pen-tool\",\n \"pen\",\n \"edit-2\",\n \"pencil-line\",\n \"pencil-off\",\n \"pencil-ruler\",\n \"pencil\",\n \"pentagon\",\n \"percent\",\n \"person-standing\",\n \"philippine-peso\",\n \"phone-call\",\n \"phone-forwarded\",\n \"phone-incoming\",\n \"phone-missed\",\n \"phone-off\",\n \"phone-outgoing\",\n \"phone\",\n \"pi\",\n \"piano\",\n \"pickaxe\",\n \"picture-in-picture-2\",\n \"picture-in-picture\",\n \"piggy-bank\",\n \"pilcrow-left\",\n \"pilcrow-right\",\n \"pilcrow\",\n \"pill-bottle\",\n \"pill\",\n \"pin-off\",\n \"pin\",\n \"pipette\",\n \"pizza\",\n \"plane-landing\",\n \"plane-takeoff\",\n \"plane\",\n \"play\",\n \"plug-2\",\n \"plug-zap\",\n \"plug-zap-2\",\n \"plug\",\n \"plus\",\n \"pocket-knife\",\n \"podcast\",\n \"pointer-off\",\n \"pointer\",\n \"popcorn\",\n \"popsicle\",\n \"pound-sterling\",\n \"power-off\",\n \"power\",\n \"presentation\",\n \"printer-check\",\n \"printer-x\",\n \"printer\",\n \"projector\",\n \"proportions\",\n \"puzzle\",\n \"pyramid\",\n \"qr-code\",\n \"quote\",\n \"rabbit\",\n \"radar\",\n \"radiation\",\n \"radical\",\n \"radio-off\",\n \"radio-receiver\",\n \"radio-tower\",\n \"radio\",\n \"radius\",\n \"rainbow\",\n \"rat\",\n \"ratio\",\n \"receipt-cent\",\n \"receipt-euro\",\n \"receipt-indian-rupee\",\n \"receipt-japanese-yen\",\n \"receipt-pound-sterling\",\n \"receipt-russian-ruble\",\n \"receipt-swiss-franc\",\n \"receipt-text\",\n \"receipt-turkish-lira\",\n \"receipt\",\n \"rectangle-circle\",\n \"rectangle-ellipsis\",\n \"form-input\",\n \"rectangle-goggles\",\n \"rectangle-horizontal\",\n \"rectangle-vertical\",\n \"recycle\",\n \"redo-2\",\n \"redo-dot\",\n \"redo\",\n \"refresh-ccw-dot\",\n \"refresh-ccw\",\n \"refresh-cw-off\",\n \"refresh-cw\",\n \"refrigerator\",\n \"regex\",\n \"remove-formatting\",\n \"repeat-1\",\n \"repeat-2\",\n \"repeat\",\n \"replace-all\",\n \"replace\",\n \"reply-all\",\n \"reply\",\n \"rewind\",\n \"ribbon\",\n \"road\",\n \"rocket\",\n \"rocking-chair\",\n \"roller-coaster\",\n \"rose\",\n \"rotate-3d\",\n \"rotate-3-d\",\n \"rotate-ccw-key\",\n \"rotate-ccw-square\",\n \"rotate-ccw\",\n \"rotate-cw-square\",\n \"rotate-cw\",\n \"route-off\",\n \"route\",\n \"router\",\n \"rows-2\",\n \"rows\",\n \"rows-3\",\n \"panels-top-bottom\",\n \"rows-4\",\n \"rss\",\n \"ruler-dimension-line\",\n \"ruler\",\n \"russian-ruble\",\n \"sailboat\",\n \"salad\",\n \"sandwich\",\n \"satellite-dish\",\n \"satellite\",\n \"saudi-riyal\",\n \"save-all\",\n \"save-off\",\n \"save\",\n \"scale-3d\",\n \"scale-3-d\",\n \"scale\",\n \"scaling\",\n \"scan-barcode\",\n \"scan-eye\",\n \"scan-face\",\n \"scan-heart\",\n \"scan-line\",\n \"scan-qr-code\",\n \"scan-search\",\n \"scan-text\",\n \"scan\",\n \"school\",\n \"scissors-line-dashed\",\n \"scissors\",\n \"scooter\",\n \"screen-share-off\",\n \"screen-share\",\n \"scroll-text\",\n \"scroll\",\n \"search-alert\",\n \"search-check\",\n \"search-code\",\n \"search-slash\",\n \"search-x\",\n \"search\",\n \"section\",\n \"send-horizontal\",\n \"send-horizonal\",\n \"send-to-back\",\n \"send\",\n \"separator-horizontal\",\n \"separator-vertical\",\n \"server-cog\",\n \"server-crash\",\n \"server-off\",\n \"server\",\n \"settings-2\",\n \"settings\",\n \"shapes\",\n \"share-2\",\n \"share\",\n \"sheet\",\n \"shell\",\n \"shelving-unit\",\n \"shield-alert\",\n \"shield-ban\",\n \"shield-check\",\n \"shield-cog-corner\",\n \"shield-cog\",\n \"shield-ellipsis\",\n \"shield-half\",\n \"shield-minus\",\n \"shield-off\",\n \"shield-plus\",\n \"shield-question-mark\",\n \"shield-question\",\n \"shield-user\",\n \"shield-x\",\n \"shield-close\",\n \"shield\",\n \"ship-wheel\",\n \"ship\",\n \"shirt\",\n \"shopping-bag\",\n \"shopping-basket\",\n \"shopping-cart\",\n \"shovel\",\n \"shower-head\",\n \"shredder\",\n \"shrimp\",\n \"shrink\",\n \"shrub\",\n \"shuffle\",\n \"sigma\",\n \"signal-high\",\n \"signal-low\",\n \"signal-medium\",\n \"signal-zero\",\n \"signal\",\n \"signature\",\n \"signpost-big\",\n \"signpost\",\n \"siren\",\n \"skip-back\",\n \"skip-forward\",\n \"skull\",\n \"slash\",\n \"slice\",\n \"sliders-horizontal\",\n \"sliders-vertical\",\n \"sliders\",\n \"smartphone-charging\",\n \"smartphone-nfc\",\n \"smartphone\",\n \"smile-plus\",\n \"smile\",\n \"snail\",\n \"snowflake\",\n \"soap-dispenser-droplet\",\n \"sofa\",\n \"solar-panel\",\n \"soup\",\n \"space\",\n \"spade\",\n \"sparkle\",\n \"sparkles\",\n \"stars\",\n \"speaker\",\n \"speech\",\n \"spell-check-2\",\n \"spell-check\",\n \"spline-pointer\",\n \"spline\",\n \"split\",\n \"spool\",\n \"sport-shoe\",\n \"spotlight\",\n \"spray-can\",\n \"sprout\",\n \"square-activity\",\n \"activity-square\",\n \"square-arrow-down-left\",\n \"arrow-down-left-square\",\n \"square-arrow-down-right\",\n \"arrow-down-right-square\",\n \"square-arrow-down\",\n \"arrow-down-square\",\n \"square-arrow-left\",\n \"arrow-left-square\",\n \"square-arrow-out-down-left\",\n \"arrow-down-left-from-square\",\n \"square-arrow-out-down-right\",\n \"arrow-down-right-from-square\",\n \"square-arrow-out-up-left\",\n \"arrow-up-left-from-square\",\n \"square-arrow-out-up-right\",\n \"arrow-up-right-from-square\",\n \"square-arrow-right-enter\",\n \"square-arrow-right-exit\",\n \"square-arrow-right\",\n \"arrow-right-square\",\n \"square-arrow-up-left\",\n \"arrow-up-left-square\",\n \"square-arrow-up-right\",\n \"arrow-up-right-square\",\n \"square-arrow-up\",\n \"arrow-up-square\",\n \"square-asterisk\",\n \"asterisk-square\",\n \"square-bottom-dashed-scissors\",\n \"scissors-square-dashed-bottom\",\n \"square-centerline-dashed-horizontal\",\n \"flip-horizontal\",\n \"square-centerline-dashed-vertical\",\n \"flip-vertical\",\n \"square-chart-gantt\",\n \"gantt-chart-square\",\n \"square-gantt-chart\",\n \"square-check-big\",\n \"check-square\",\n \"square-check\",\n \"check-square-2\",\n \"square-chevron-down\",\n \"chevron-down-square\",\n \"square-chevron-left\",\n \"chevron-left-square\",\n \"square-chevron-right\",\n \"chevron-right-square\",\n \"square-chevron-up\",\n \"chevron-up-square\",\n \"square-code\",\n \"code-square\",\n \"square-dashed-bottom-code\",\n \"square-dashed-bottom\",\n \"square-dashed-kanban\",\n \"kanban-square-dashed\",\n \"square-dashed-mouse-pointer\",\n \"mouse-pointer-square-dashed\",\n \"square-dashed-text\",\n \"text-selection\",\n \"text-select\",\n \"square-dashed-top-solid\",\n \"square-dashed\",\n \"box-select\",\n \"square-divide\",\n \"divide-square\",\n \"square-dot\",\n \"dot-square\",\n \"square-equal\",\n \"equal-square\",\n \"square-function\",\n \"function-square\",\n \"square-kanban\",\n \"kanban-square\",\n \"square-library\",\n \"library-square\",\n \"square-m\",\n \"m-square\",\n \"square-menu\",\n \"menu-square\",\n \"square-minus\",\n \"minus-square\",\n \"square-mouse-pointer\",\n \"inspect\",\n \"square-parking-off\",\n \"parking-square-off\",\n \"square-parking\",\n \"parking-square\",\n \"square-pause\",\n \"square-pen\",\n \"pen-box\",\n \"edit\",\n \"pen-square\",\n \"square-percent\",\n \"percent-square\",\n \"square-pi\",\n \"pi-square\",\n \"square-pilcrow\",\n \"pilcrow-square\",\n \"square-play\",\n \"play-square\",\n \"square-plus\",\n \"plus-square\",\n \"square-power\",\n \"power-square\",\n \"square-radical\",\n \"square-round-corner\",\n \"square-scissors\",\n \"scissors-square\",\n \"square-sigma\",\n \"sigma-square\",\n \"square-slash\",\n \"slash-square\",\n \"square-split-horizontal\",\n \"split-square-horizontal\",\n \"square-split-vertical\",\n \"split-square-vertical\",\n \"square-square\",\n \"square-stack\",\n \"square-star\",\n \"square-stop\",\n \"square-terminal\",\n \"terminal-square\",\n \"square-user-round\",\n \"user-square-2\",\n \"square-user\",\n \"user-square\",\n \"square-x\",\n \"x-square\",\n \"square\",\n \"squares-exclude\",\n \"squares-intersect\",\n \"squares-subtract\",\n \"squares-unite\",\n \"squircle-dashed\",\n \"squircle\",\n \"squirrel\",\n \"stamp\",\n \"star-half\",\n \"star-off\",\n \"star\",\n \"step-back\",\n \"step-forward\",\n \"stethoscope\",\n \"sticker\",\n \"sticky-note\",\n \"stone\",\n \"store\",\n \"stretch-horizontal\",\n \"stretch-vertical\",\n \"strikethrough\",\n \"subscript\",\n \"sun-dim\",\n \"sun-medium\",\n \"sun-moon\",\n \"sun-snow\",\n \"sun\",\n \"sunrise\",\n \"sunset\",\n \"superscript\",\n \"swatch-book\",\n \"swiss-franc\",\n \"switch-camera\",\n \"sword\",\n \"swords\",\n \"syringe\",\n \"table-2\",\n \"table-cells-merge\",\n \"table-cells-split\",\n \"table-columns-split\",\n \"table-of-contents\",\n \"table-properties\",\n \"table-rows-split\",\n \"table\",\n \"tablet-smartphone\",\n \"tablet\",\n \"tablets\",\n \"tag\",\n \"tags\",\n \"tally-1\",\n \"tally-2\",\n \"tally-3\",\n \"tally-4\",\n \"tally-5\",\n \"tangent\",\n \"target\",\n \"telescope\",\n \"tent-tree\",\n \"tent\",\n \"terminal\",\n \"test-tube-diagonal\",\n \"test-tube-2\",\n \"test-tube\",\n \"test-tubes\",\n \"text-align-center\",\n \"align-center\",\n \"text-align-end\",\n \"align-right\",\n \"text-align-justify\",\n \"align-justify\",\n \"text-align-start\",\n \"text\",\n \"align-left\",\n \"text-cursor-input\",\n \"text-cursor\",\n \"text-initial\",\n \"letter-text\",\n \"text-quote\",\n \"text-search\",\n \"text-wrap\",\n \"wrap-text\",\n \"theater\",\n \"thermometer-snowflake\",\n \"thermometer-sun\",\n \"thermometer\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"ticket-check\",\n \"ticket-minus\",\n \"ticket-percent\",\n \"ticket-plus\",\n \"ticket-slash\",\n \"ticket-x\",\n \"ticket\",\n \"tickets-plane\",\n \"tickets\",\n \"timer-off\",\n \"timer-reset\",\n \"timer\",\n \"toggle-left\",\n \"toggle-right\",\n \"toilet\",\n \"tool-case\",\n \"toolbox\",\n \"tornado\",\n \"torus\",\n \"touchpad-off\",\n \"touchpad\",\n \"towel-rack\",\n \"tower-control\",\n \"toy-brick\",\n \"tractor\",\n \"traffic-cone\",\n \"train-front-tunnel\",\n \"train-front\",\n \"train-track\",\n \"tram-front\",\n \"train\",\n \"transgender\",\n \"trash-2\",\n \"trash\",\n \"tree-deciduous\",\n \"tree-palm\",\n \"palmtree\",\n \"tree-pine\",\n \"trees\",\n \"trending-down\",\n \"trending-up-down\",\n \"trending-up\",\n \"triangle-alert\",\n \"alert-triangle\",\n \"triangle-dashed\",\n \"triangle-right\",\n \"triangle\",\n \"trophy\",\n \"truck-electric\",\n \"truck\",\n \"turkish-lira\",\n \"turntable\",\n \"turtle\",\n \"tv-minimal-play\",\n \"tv-minimal\",\n \"tv-2\",\n \"tv\",\n \"type-outline\",\n \"type\",\n \"umbrella-off\",\n \"umbrella\",\n \"underline\",\n \"undo-2\",\n \"undo-dot\",\n \"undo\",\n \"unfold-horizontal\",\n \"unfold-vertical\",\n \"ungroup\",\n \"university\",\n \"school-2\",\n \"unlink-2\",\n \"unlink\",\n \"unplug\",\n \"upload\",\n \"usb\",\n \"user-check\",\n \"user-cog\",\n \"user-key\",\n \"user-lock\",\n \"user-minus\",\n \"user-pen\",\n \"user-plus\",\n \"user-round-check\",\n \"user-check-2\",\n \"user-round-cog\",\n \"user-cog-2\",\n \"user-round-key\",\n \"user-round-minus\",\n \"user-minus-2\",\n \"user-round-pen\",\n \"user-round-plus\",\n \"user-plus-2\",\n \"user-round-search\",\n \"user-round-x\",\n \"user-x-2\",\n \"user-round\",\n \"user-2\",\n \"user-search\",\n \"user-star\",\n \"user-x\",\n \"user\",\n \"users-round\",\n \"users-2\",\n \"users\",\n \"utensils-crossed\",\n \"fork-knife-crossed\",\n \"utensils\",\n \"fork-knife\",\n \"utility-pole\",\n \"van\",\n \"variable\",\n \"vault\",\n \"vector-square\",\n \"vegan\",\n \"venetian-mask\",\n \"venus-and-mars\",\n \"venus\",\n \"vibrate-off\",\n \"vibrate\",\n \"video-off\",\n \"video\",\n \"videotape\",\n \"view\",\n \"voicemail\",\n \"volleyball\",\n \"volume-1\",\n \"volume-2\",\n \"volume-off\",\n \"volume-x\",\n \"volume\",\n \"vote\",\n \"wallet-cards\",\n \"wallet-minimal\",\n \"wallet-2\",\n \"wallet\",\n \"wallpaper\",\n \"wand-sparkles\",\n \"wand-2\",\n \"wand\",\n \"warehouse\",\n \"washing-machine\",\n \"watch\",\n \"waves-arrow-down\",\n \"waves-arrow-up\",\n \"waves-ladder\",\n \"waves\",\n \"waypoints\",\n \"webcam\",\n \"webhook-off\",\n \"webhook\",\n \"weight-tilde\",\n \"weight\",\n \"wheat-off\",\n \"wheat\",\n \"whole-word\",\n \"wifi-cog\",\n \"wifi-high\",\n \"wifi-low\",\n \"wifi-off\",\n \"wifi-pen\",\n \"wifi-sync\",\n \"wifi-zero\",\n \"wifi\",\n \"wind-arrow-down\",\n \"wind\",\n \"wine-off\",\n \"wine\",\n \"workflow\",\n \"worm\",\n \"wrench\",\n \"x-line-top\",\n \"x\",\n \"zap-off\",\n \"zap\",\n \"zodiac-aquarius\",\n \"zodiac-aries\",\n \"zodiac-cancer\",\n \"zodiac-capricorn\",\n \"zodiac-gemini\",\n \"zodiac-leo\",\n \"zodiac-libra\",\n \"zodiac-ophiuchus\",\n \"zodiac-pisces\",\n \"zodiac-sagittarius\",\n \"zodiac-scorpio\",\n \"zodiac-taurus\",\n \"zodiac-virgo\",\n \"zoom-in\",\n \"zoom-out\",\n]);\n\nexport const LAYOUT_SECTION_ICON_SET: ReadonlySet<string> = new Set(LAYOUT_SECTION_ICONS);\nexport type LayoutSectionIcon = string;\n","/** Stable identifiers used by every project and page layout document. */\nexport const PAGE_CONTENT_ANCHOR_ID = \"page-content\" as const;\nexport const NAVIGATION_SECTION_ID = \"navigation\" as const;\nexport const FOOTER_SECTION_ID = \"footer\" as const;\n\n/** Locked transport/validation set shared by authoring surfaces and the server. */\nexport {\n LAYOUT_SECTION_ICONS,\n LAYOUT_SECTION_ICON_SET,\n type LayoutSectionIcon,\n} from \"./layout-lucide-icons.js\";\nimport type { LayoutSectionIcon } from \"./layout-lucide-icons.js\";\n\nexport type LayoutZone = \"above-page-content\" | \"below-page-content\";\nexport type ReservedLayoutSection = \"navigation\" | \"footer\";\n\nexport type LayoutScalarFieldType =\n | \"text\"\n | \"longtext\"\n | \"richtext\"\n | \"number\"\n | \"toggle\"\n | \"date\"\n | \"image\"\n | \"file\"\n | \"link\"\n | \"email\"\n | \"phone\"\n | \"select\"\n | \"color\"\n | \"json\"\n | \"reference\"\n | \"multi-reference\";\n\nexport type LayoutFieldType = LayoutScalarFieldType | \"group\" | \"repeater\";\n\n/** A recursive, stable-ID field contract shared by Sections and variant inputs. */\nexport interface LayoutFieldDefinition {\n id: string;\n slug: string;\n label: string;\n type: LayoutFieldType;\n required?: boolean;\n defaultValue?: unknown;\n config?: {\n options?: Array<{ label: string; value: string }>;\n referenceModelId?: string;\n minItems?: number;\n maxItems?: number;\n } & Record<string, unknown>;\n /** Required for group/repeater; forbidden for scalar fields. */\n fields?: LayoutFieldDefinition[];\n}\n\n/** The canonical public input contract all variants in a group implement. */\nexport type CanonicalInputDefinition = LayoutFieldDefinition;\n\n/** Maps one canonical input onto one or more internal component prop paths. */\nexport interface VariantInputMapping {\n inputId: string;\n targets: Array<{ blockId: string; path: string }>;\n}\n\nexport interface ComponentVariantGroup {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n canonicalInputs: CanonicalInputDefinition[];\n status: \"draft\" | \"published\";\n}\n\nexport interface LayoutFieldItem {\n id: string;\n kind: \"field\";\n fieldId: string;\n}\n\nexport interface LayoutComponentItem {\n id: string;\n kind: \"component\";\n componentId: string;\n variantGroupId?: string;\n bindings: Array<{ inputId: string; fieldId: string }>;\n literalValues?: Record<string, unknown>;\n}\n\nexport type LayoutSectionItem = LayoutFieldItem | LayoutComponentItem;\n\nexport interface LayoutSection {\n id: string;\n name: string;\n slug: string;\n icon: string;\n zone: LayoutZone;\n orderKey: string;\n reserved?: ReservedLayoutSection;\n fields: LayoutFieldDefinition[];\n items: LayoutSectionItem[];\n /**\n * The language this Section is a VARIANT for — BCP-47, lowercase (`fr`, `pt-br`).\n *\n * A localized site renders ONE header per route, not two: `/fr/*` shows the French header in\n * the slot the base header holds everywhere else. So a variant is not a Section of its own in\n * the render order. It never renders unless a resolver is handed its locale, and then it takes\n * its base's place — zone, order and reserved slot included — rather than sitting beside it.\n * Set together with `variantOf`; `validateLayout` names every way the pair can be malformed.\n */\n locale?: string;\n /** The stable id of the base Section this variant replaces on routes in `locale`. */\n variantOf?: string;\n}\n\nexport interface LayoutStructureDocument {\n version: 1;\n pageContentAnchor: { id: typeof PAGE_CONTENT_ANCHOR_ID };\n sections: LayoutSection[];\n}\n\nexport interface LayoutDataDocument {\n version: 1;\n sections: Record<string, { fields: Record<string, unknown> }>;\n}\n\nexport type PageLayoutOverrideState =\n | \"inherit\"\n | \"override-content\"\n | \"customize-structure\"\n | \"disable\";\n\nexport interface PageSectionPlacement {\n zone: LayoutZone;\n afterSectionId?: string;\n beforeSectionId?: string;\n localOrderKey: string;\n}\n\nexport type PageLayoutSectionOverride =\n | { sectionId: string; state: \"inherit\" }\n | { sectionId: string; state: \"override-content\"; values: Record<string, unknown> }\n | {\n sectionId: string;\n state: \"customize-structure\";\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n /** Retained when the inherited Section is later deleted. */\n placement: PageSectionPlacement;\n }\n | { sectionId: string; state: \"disable\" };\n\nexport interface PageOnlyLayoutSection {\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n placement: PageSectionPlacement;\n}\n\nexport type PageLayoutSectionStructureOverride =\n | { sectionId: string; state: \"inherit\" }\n | { sectionId: string; state: \"override-content\" }\n | { sectionId: string; state: \"customize-structure\"; section: LayoutSection; placement: PageSectionPlacement }\n | { sectionId: string; state: \"disable\" };\n\n/** Persisted in pages.layout_override_structure_json. */\nexport interface PageLayoutOverrideStructureDocument {\n version: 1;\n sections: PageLayoutSectionStructureOverride[];\n pageOnlySections: Array<{ section: LayoutSection; placement: PageSectionPlacement }>;\n}\n\n/** Persisted independently so values can be patched without rewriting structure. */\nexport interface PageLayoutOverrideDataDocument {\n version: 1;\n sections: Record<string, { fields: Record<string, unknown> }>;\n pageOnlySections: Record<string, { fields: Record<string, unknown> }>;\n}\n\n/** Canonical in-memory form consumed by the pure resolver. */\nexport interface PageLayoutOverrideDocument {\n version: 1;\n sections: PageLayoutSectionOverride[];\n pageOnlySections: PageOnlyLayoutSection[];\n}\n\n/** Canonical, discriminated Management/MCP authoring transport. Authority is derived from type. */\nexport type ManagementLayoutCommand =\n | { type: \"set-section-values\"; sectionId: string; values: Record<string, unknown> }\n | { type: \"set-field-value\"; sectionId: string; fieldId: string; value: unknown }\n | { type: \"add-component\"; sectionId: string; componentId: string; variantGroupId?: string; bindings?: LayoutComponentItem[\"bindings\"]; literalValues?: Record<string, unknown> }\n | { type: \"remove-item\"; sectionId: string; itemId: string }\n | { type: \"move-component\"; sectionId: string; itemId: string; index: number }\n | { type: \"move-item\"; sectionId: string; itemId: string; index: number }\n | { type: \"swap-component-variant\"; sectionId: string; itemId: string; componentId: string }\n | { type: \"set-page-state\"; sectionId: string; state: PageLayoutOverrideState | \"reset\" }\n | { type: \"set-section-state\"; sectionId: string; state: PageLayoutOverrideState | \"reset\" }\n | { type: \"add-section\"; name: string; icon: LayoutSectionIcon; zone: \"before_page\" | \"after_page\" }\n | { type: \"restore-section\"; section: LayoutSection; data: { fields: Record<string, unknown> }; placement?: PageSectionPlacement }\n | { type: \"update-section\"; sectionId: string; name?: string; icon?: LayoutSectionIcon; slug?: string; zone?: LayoutZone; orderKey?: string }\n | { type: \"remove-section\"; sectionId: string }\n | { type: \"move-section\"; sectionId: string; afterId?: string | null; beforeId?: string | null }\n | { type: \"add-field\"; sectionId: string; parentFieldId?: string; field?: LayoutFieldDefinition; fieldType?: LayoutFieldType }\n | { type: \"update-field\"; sectionId: string; fieldId: string; patch: Partial<Omit<LayoutFieldDefinition, \"id\">> }\n | { type: \"remove-field\"; sectionId: string; fieldId: string }\n | { type: \"move-field\"; sectionId: string; itemId: string; index: number }\n | { type: \"set-bindings\"; sectionId: string; itemId: string; bindings: LayoutComponentItem[\"bindings\"]; literalValues?: Record<string, unknown> };\n\nexport type ResolvedLayoutNode =\n | { kind: \"page-content\"; id: typeof PAGE_CONTENT_ANCHOR_ID }\n | {\n kind: \"section\";\n id: string;\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n source: \"inherit\" | \"override-content\" | \"customize-structure\" | \"page-only\" | \"detached\";\n };\n\nexport interface DeliveredLayout {\n version: 1;\n nodes: Array<\n | { kind: \"page-content\"; id: typeof PAGE_CONTENT_ANCHOR_ID }\n | { kind: \"section\"; id: string; slug: string; name: string; source: Extract<ResolvedLayoutNode, { kind: \"section\" }>[\"source\"] }\n >;\n sections: Record<string, {\n id: string;\n slug: string;\n name: string;\n /**\n * Present ONLY on a locale variant (`LayoutSection.locale`/`variantOf`), so a base entry is\n * byte-identical to what it was before variants existed. The Global Layout delivers every\n * variant under its own slug beside the bases; a page delivers the variant its route's\n * locale swapped in, under the SLOT's slug — the one its `nodes` entry names.\n */\n locale?: string;\n variantOf?: string;\n fields: Record<string, unknown>;\n items: Array<\n | { id: string; kind: \"field\"; fieldId: string; value: unknown }\n | {\n id: string;\n kind: \"component\";\n componentId: string;\n variantGroupId?: string;\n canonicalInputs: CanonicalInputDefinition[];\n bindings: LayoutComponentItem[\"bindings\"];\n canonicalValues: Record<string, unknown>;\n resolvedProps: Record<string, unknown>;\n /**\n * `prop.key` → canonical `inputId` — the relation `resolvedProps` consumes and throws\n * away (`output[prop.key] = canonicalValues[mapping.inputId]`).\n *\n * Without it a renderer holds a component prop key and NO address: `logoAlt`/`links`/\n * `cta` are the component's own bare keys, and nothing relates them back to the layout\n * field a write must land on. With it the chain closes — `prop.key` → `inputId` →\n * (`bindings`, already delivered above) → `fieldId` → `set-field-value(sectionId,\n * fieldId)`. That is what makes global chrome click-to-edit (FLO-1179).\n *\n * Additive and always present (`{}` when the item has no variant mappings), so an\n * older consumer that ignores it is byte-identical to before.\n */\n propInputs: Record<string, string>;\n blocks: unknown[];\n }\n >;\n }>;\n}\n","/**\n * WHERE an element was on a built page, so a later pass can find it again.\n *\n * This lives in the shared package because BOTH ends of the comparison have to spell an address\n * the same way: the backend derives it from a JSDOM tree at import time, the dashboard computes\n * it from a live iframe tree when a person clicks an unbound element. Two implementations of\n * \"the ancestor chain down from the nearest landmark\" is one implementation too many — the first\n * time they disagree by one tag, a click binds the wrong element.\n *\n * The DOM is typed STRUCTURALLY (`ElementLike`, `LandmarkHost`) so this package needs no DOM lib\n * and stays importable from a node-only build.\n */\n\n/** The landmark tags an address is anchored at, as one CSS selector and as one tag set. */\nexport const LANDMARK_SELECTOR = \"header,nav,footer\";\nconst LANDMARK_TAGS = new Set([\"HEADER\", \"NAV\", \"FOOTER\"]);\n\n/**\n * The THIRD region — a modal, a cookie banner, a pop-up — behind a per-project gate.\n *\n * A `<dialog>` or a `[role=\"dialog\"]` sits at BODY level, outside every landmark, so a banner\n * byte-identical on twelve routes derived twelve copies of itself. It is NOT a stop for\n * `locatorFor`: `region` already names which dialog an element is in, and a second gated rule\n * about where the ancestor chain ends would make the same element's locator differ between a\n * project that derived it as chrome and one that did not.\n */\nexport const DIALOG_SELECTOR = 'dialog,[role=\"dialog\"]';\n\n/**\n * The page's own content. A landmark INSIDE it is the page's, not the site's — under the v2\n * grammar only. @see isChromeLandmark\n */\nexport const MAIN_SELECTOR = 'main,[role=\"main\"]';\n\n/**\n * Which address grammar a page was derived in — the two per-project gates that change what a\n * REGION is. Both off is the original grammar, and `{}` must keep meaning exactly that: every\n * locator stored before a gate existed was spelled in it.\n *\n * `dialogs` — a `<dialog>`/`[role=\"dialog\"]` is a region of its own (the chrome grammar).\n * `landmarks` — landmark grammar v2. @see isChromeLandmark, and `landmarkRegions` for rule (ii).\n */\nexport interface LocatorGrammar {\n dialogs?: boolean;\n landmarks?: boolean;\n}\n\n/**\n * Is this element a landmark that holds SITE chrome — a header, nav or footer that earns a region\n * and a `nav-`/`footer-` key?\n *\n * 🔴 A LANDMARK INSIDE `<main>` IS PAGE COPY. HTML allows a `<nav>` anywhere, and a built page\n * uses one for whatever it likes: a features band's `<nav role=\"tablist\">`, a docs page's\n * prev/next pager in a `<footer>` inside the article. Counted as chrome, the home page's tab list\n * minted nine `nav-` keys that are really the section's copy — keys the Layout's Header section\n * claims by prefix the moment two routes render that band alike, and that componentize reads as\n * chrome everywhere else. The `<main>` is the page saying \"everything in here is mine\", and v2\n * believes it.\n *\n * Gated (`landmarks`), because it moves keys AND regions: a project whose pages were derived\n * with that tab list as `nav#0` holds values under `nav-…` keys, and re-reading them as section\n * copy would strand every one of them.\n */\nexport function isChromeLandmark(\n el: { tagName: string; parentElement: { closest(selectors: string): unknown } | null },\n landmarks: boolean,\n): boolean {\n return LANDMARK_TAGS.has(el.tagName) && (!landmarks || !el.parentElement?.closest(MAIN_SELECTOR));\n}\n\n/**\n * Best-effort by construction — built-DOM positions do not survive component expansion or\n * conditional rendering — so a consumer that finds no exact match, or finds several, falls back\n * to ambiguity rather than to a guess. The ancestor chain is compared EXACTLY (`atLocator`,\n * annotate-static.ts): a chain that merely contains the stored one is a different element.\n */\nexport interface DerivedLocator {\n /** The landmark it lives in — `header#0`, `nav#1`, `footer#0` — or null for the page body. */\n region: string | null;\n /** Tag names from the nearest landmark (or `<body>`) down to the element's parent. */\n ancestors: string[];\n /** Its index among its parent's element children. */\n siblingIndex: number;\n /**\n * The element's own lower-cased tag name.\n *\n * The cheapest fact that separates two elements a chain-and-index pair calls identical — a\n * `<h2>` and the `<a>` beside it in a rebuilt layout — and the only one a resolver can use to\n * NARROW its candidate list before comparing anything. Absent on locators stored before it\n * existed; a comparer must treat a missing tag as \"matches\".\n */\n tag: string;\n /**\n * The repeater row this value belongs to.\n *\n * On a leaf's field DEFINITION the index is 0 — one definition serves every row — and the\n * brief overrides it with the row it is actually describing (`cards[2].title` → index 2).\n */\n repeat?: { groupKey: string; index: number };\n}\n\n/** The DOM surface `locatorFor` reads. `Element` satisfies it; so does a plain object. */\nexport interface ElementLike {\n tagName: string;\n parentElement: ElementLike | null;\n children: ArrayLike<ElementLike>;\n}\n\n/**\n * `ElementLike` plus the one DOM call the v2 chain needs — whether a landmark sits inside\n * `<main>` (@see isChromeLandmark). `Element` satisfies it. Only the backend derives in v2, so\n * the plain-object surface above stays all the original grammar asks for.\n */\nexport interface LandmarkChainElement extends ElementLike {\n parentElement: LandmarkChainElement | null;\n closest(selectors: string): unknown;\n}\n\n/**\n * The structural address of one element: its ancestor tags and its position among its siblings.\n *\n * Stops at the nearest LANDMARK because that is where a page's structure stops being comparable\n * — a header's internals are the same on every route while the body's are not — and `region`\n * already names which landmark it was.\n *\n * 🔴 UNDER v2 (`landmarks`) THE CHAIN STOPS ONLY AT A CHROME LANDMARK. The stop is only sound\n * because `region` names the landmark it stopped at, and a `<nav>` inside `<main>` names no\n * region under v2. Stopping there anyway threw away the only structure that told two of them\n * apart: two sections' `<nav><a>` both addressed as `{region: null, ancestors: [], 0, a}` — the\n * address of a link sitting directly in `<body>` — where the original grammar said `nav#0` and\n * `nav#1`. So the chain runs on to `<body>` like every other element of the page's copy. An\n * element outside every in-`<main>` landmark stops exactly where it always did, which is what\n * keeps every locator whose region v2 did not move byte-identical. Two landmarks of one shape in\n * two sections of one shape still collide, as two cards always have; every reader refuses an\n * address that names several elements (`atLocator`, the pin replay, `bindElement`).\n */\nexport function locatorFor(el: ElementLike, region: string | null): DerivedLocator;\nexport function locatorFor(el: LandmarkChainElement, region: string | null, landmarks: boolean): DerivedLocator;\nexport function locatorFor(el: ElementLike, region: string | null, landmarks = false): DerivedLocator {\n const ancestors: string[] = [];\n for (\n let parent = el.parentElement;\n // The cast is the overloads' promise: `landmarks` is only ever true for a `LandmarkChainElement`,\n // and `isChromeLandmark` never reads past the tag with it false.\n parent && parent.tagName !== \"BODY\" && !isChromeLandmark(parent as LandmarkChainElement, landmarks);\n parent = parent.parentElement\n ) {\n ancestors.unshift(parent.tagName.toLowerCase());\n }\n const siblings = el.parentElement ? Array.from(el.parentElement.children) : [];\n return {\n region,\n ancestors,\n siblingIndex: Math.max(siblings.indexOf(el), 0),\n tag: el.tagName.toLowerCase(),\n };\n}\n\n/** The DOM surface `landmarkRegions` reads of each element it considers. */\nexport interface LandmarkElement {\n tagName: string;\n parentElement: { closest(selectors: string): unknown } | null;\n matches(selectors: string): boolean;\n}\n\n/**\n * A page's landmark regions: the OUTERMOST `header`/`nav`/`footer` elements, in document order.\n *\n * Outermost, because a `<nav>` inside a `<header>` is one region a visitor sees as one thing —\n * and promoting the two separately would let a site's masthead be half layout, half page.\n *\n * Under the v2 grammar (`landmarks`) regions may NEST, in exactly one way — a dialog inside a\n * landmark is its own region — so a consumer must ask {@link regionOf} which one an element is\n * in, never take the first region that contains it.\n */\nexport function landmarkRegions<E extends LandmarkElement>(\n doc: { querySelectorAll(selectors: string): Iterable<E> },\n /**\n * Count a dialog as a region too — the per-project chrome grammar.\n *\n * OFF by default, and not merely for symmetry: a region name is part of every field's LOCATOR,\n * and a project whose stored locators say `region: null` for a modal's copy must keep being\n * read the same way.\n */\n dialogs = false,\n /**\n * Landmark grammar v2 — the per-project `landmarks` gate. Two rules change, both OFF by default\n * for the reason `dialogs` is:\n *\n * (i) a landmark inside `<main>`/`[role=\"main\"]` is no region. @see isChromeLandmark\n * (ii) a dialog inside a landmark is its OWN region. The auth modals a masthead carries are\n * the commonest dialogs on the web, and outermost-only folded all three into `header#0`:\n * their copy promoted as the header's, and the header could only promote when every\n * route's modals did too. A dialog still folds into an enclosing DIALOG, and a landmark\n * into anything enclosing it — nothing else nests.\n */\n landmarks = false,\n): { slot: string; el: E }[] {\n const counts = new Map<string, number>();\n const out: { slot: string; el: E }[] = [];\n const selector = dialogs ? `${LANDMARK_SELECTOR},${DIALOG_SELECTOR}` : LANDMARK_SELECTOR;\n for (const el of doc.querySelectorAll(selector)) {\n if (!landmarks) {\n if (el.parentElement?.closest(selector)) continue;\n } else if (LANDMARK_TAGS.has(el.tagName)) {\n // A landmark outside `<main>` has no ancestor inside it either, so anything enclosing it is\n // a region — the outermost rule, unchanged.\n if (!isChromeLandmark(el, true) || el.parentElement?.closest(selector)) continue;\n } else if (el.parentElement?.closest(DIALOG_SELECTOR)) {\n continue;\n }\n // The NAME, not the tag: a `[role=\"dialog\"]` is usually a `<div>`, and slotting it as\n // `div#0` would make one site's modal and another's wrapper the same kind of region.\n const name = !LANDMARK_TAGS.has(el.tagName) && el.matches(DIALOG_SELECTOR)\n ? \"dialog\"\n : el.tagName.toLowerCase();\n const n = counts.get(name) ?? 0;\n counts.set(name, n + 1);\n out.push({ slot: `${name}#${n}`, el });\n }\n return out;\n}\n\n/**\n * The region an element is in: the INNERMOST region that contains it, or null for the page body.\n *\n * The last match rather than the first, because regions are in document order and an enclosing\n * region opens before the one nested inside it (v2's dialog in a header). Under every other\n * grammar regions are disjoint and first and last are the same region — which is what keeps a\n * resolver built on this byte-identical for every locator stored before v2.\n */\nexport function regionOf<E extends { contains(other: unknown): boolean }>(\n regions: readonly { slot: string; el: E }[],\n el: unknown,\n): string | null {\n let slot: string | null = null;\n for (const r of regions) if (r.el.contains(el)) slot = r.slot;\n return slot;\n}\n"],"mappings":"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A;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAC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","names":[]}
1
+ {"version":3,"sources":["../src/block.ts","../src/block-bindings.ts","../src/sectionSpace.ts","../src/blockStyle.ts","../src/component.ts","../src/layout-lucide-icons.ts","../src/layout.ts","../src/locator.ts"],"sourcesContent":["/**\n * ContentBlock — a discriminated union of all CMS block types.\n * Each block has a `type` discriminator and a `props` object\n * whose shape matches the block type.\n */\n\nimport type { SectionSpaceToken, SpaceStepToken } from \"./sectionSpace.js\";\n\n// ── Block style (FLO-264) ──────────────────────────────────────────────────────\n// A uniform, BOUNDED set of design tokens any block may carry (sibling to `props`).\n// Tokens map to fixed CSS values in the renderer (`styleTokensToCss`) so styling\n// reaches the live site WITHOUT arbitrary CSS. Additive + fully optional.\n\nexport type SpaceToken = \"none\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type ColorToken = \"none\" | \"white\" | \"black\" | \"muted\" | \"mutedBg\" | \"primary\" | \"accent\";\nexport type AlignToken = \"left\" | \"center\" | \"right\";\nexport type FontSizeToken = \"sm\" | \"base\" | \"lg\" | \"xl\" | \"2xl\";\nexport type WeightToken = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\nexport type RadiusToken = \"none\" | \"sm\" | \"md\" | \"lg\" | \"full\";\n\n// Section design (task 4) — the per-instance design a section carries on the page.\nexport type ThemeToken = \"inherit\" | \"light\" | \"dark\";\nexport type BgToken = \"none\" | \"surface\" | \"muted\" | \"accent\" | \"dark\" | \"custom\";\nexport type ContentWidthToken = \"narrow\" | \"default\" | \"wide\" | \"full\";\nexport type CornerToken = \"0\" | \"s\" | \"m\" | \"l\" | \"xl\" | \"2xl\";\nexport type ShadowToken = \"0\" | \"s\" | \"m\" | \"l\" | \"xl\";\n\nexport interface BlockStyle {\n // Legacy token set (FLO-264). Where these overlap the section fields below\n // (background, radius, padding), the section field WINS in the renderer.\n paddingY?: SpaceToken;\n paddingX?: SpaceToken;\n marginTop?: SpaceToken;\n marginBottom?: SpaceToken;\n background?: ColorToken;\n textColor?: ColorToken;\n align?: AlignToken;\n fontSize?: FontSizeToken;\n weight?: WeightToken;\n radius?: RadiusToken;\n\n // Section design (task 4).\n theme?: ThemeToken;\n bg?: BgToken;\n /** Only read when `bg === \"custom\"`. Hex only. */\n bgCustom?: string;\n /** Padding sliders, in px (0–240). Legacy: a `space*` token below wins where both are set. */\n paddingTop?: number;\n paddingBottom?: number;\n paddingSides?: number;\n /** Section spacing as token steps (see sectionSpace.ts). Only the top may pull under the nav. */\n spaceTop?: SectionSpaceToken;\n spaceBottom?: Exclude<SectionSpaceToken, \"section-space-nav-overlap\">;\n spaceSides?: SpaceStepToken;\n contentWidth?: ContentWidthToken;\n /**\n * Where the constrained content column sits, when `contentWidth` constrains it.\n *\n * Split out of `align`, which still means text alignment and is still the fallback when this\n * is unset — so everything written before the split renders byte-identically. The two were one\n * token until anything MEASURED a section's text alignment: copying a source site's\n * `text-align: left` would otherwise also shove its column to the page edge.\n */\n contentAlign?: AlignToken;\n fullHeight?: boolean;\n /** 0–100. */\n opacity?: number;\n corner?: CornerToken;\n shadow?: ShadowToken;\n borderTop?: boolean;\n borderBottom?: boolean;\n /** All four sides, `1px solid currentColor` — an outline button's border follows its text colour. */\n border?: boolean;\n /** 🔴 The one free-form string. MUST go through `safeCssUrl()` before reaching CSS. */\n bgImage?: string;\n /** A button's look while the pointer is over it. Only the paint changes; unset keys keep the rest. */\n hover?: BlockHoverStyle;\n}\n\n/** The paint a button swaps to on hover: fill, text colour, and the all-round border. */\nexport interface BlockHoverStyle {\n bg?: BgToken;\n bgCustom?: string;\n textColor?: ColorToken;\n border?: boolean;\n}\n\n// ── Heading ──────────────────────────────────────────────────────────────────\n\nexport interface HeadingProps {\n text: string;\n level?: 1 | 2 | 3;\n}\n\nexport interface HeadingBlock {\n type: \"heading\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: HeadingProps;\n}\n\n// ── Text ─────────────────────────────────────────────────────────────────────\n\nexport interface TextProps {\n html: string;\n /** @see RichTextProps.level — the same payload takes the same level. */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface TextBlock {\n type: \"text\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: TextProps;\n}\n\n/**\n * A rich-text block: the same HTML payload as `text`, authored through a real editor.\n *\n * WHY A SEPARATE TYPE RATHER THAN CHANGING `text`. Every `text` block already on a live page\n * holds an HTML string that the delivery renderer injects as-is. Repurposing that type would\n * mean migrating published content, and getting it wrong renders visible markup to visitors.\n * A new type costs nothing at rest and leaves existing pages untouched.\n *\n * The payload is deliberately IDENTICAL to TextProps (an HTML string) so the two are\n * interchangeable at the renderer: delivery treats them the same, and the difference is\n * entirely in how an author edits them — `text` is a plain field, `richtext` gets the\n * formatting surface.\n */\n/**\n * A Portable Text node — the structured form of rich text.\n *\n * Kept alongside `html` rather than replacing it, so nothing already published moves. The\n * structure exists because an HTML string cannot carry INTENT: a colour is a hex with no\n * notion of which brand token produced it, an embedded component is a div with no reference\n * to resolve, and neither can be read back by tooling. Nodes can carry all of that.\n */\nexport interface PortableTextNode {\n _type: string;\n _key?: string;\n /** Block style — \"normal\", \"h2\", \"blockquote\". */\n style?: string;\n text?: string;\n children?: PortableTextNode[];\n /** Marks on a span: \"strong\", \"em\", or a token reference like \"color:brand-accent\". */\n marks?: string[];\n /** An embedded component or reference resolves through these. */\n schemaKey?: string;\n _ref?: string;\n fields?: Record<string, unknown>;\n}\n\nexport interface PortableTextDocument {\n version: 1;\n content: PortableTextNode[];\n}\n\nexport interface RichTextProps {\n /**\n * The RENDERED CACHE. Delivery reads this, so the fast path stays a string interpolation\n * and every page published before `content` existed keeps rendering byte-identically.\n */\n html: string;\n /**\n * The SOURCE OF TRUTH, when present — `content` always wins over `html`.\n *\n * Optional on purpose: this is the same envelope the field values already use\n * (`{ format, value, html }`), where `html` is likewise derived. Any writer that sets\n * `html` alone on a block that HAS `content` must delete `content` in the same write, or\n * the stale string silently shadows the newer structure.\n */\n content?: PortableTextDocument;\n /**\n * Render the rich copy AS `<h1>`–`<h6>` instead of a paragraph container, so a title keeps\n * its inline marks (a brand-coloured span) AND its heading semantics. Absent ⇒ ordinary rich\n * text, as before. Set ⇒ the value must be ONE line of inline copy; the write schema refuses\n * more. A component prop of type `number` or `select` can target `props.level`.\n */\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface RichTextBlock {\n type: \"richtext\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: RichTextProps;\n}\n\n// ── Image ────────────────────────────────────────────────────────────────────\n\nexport interface ImageProps {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n caption?: string;\n}\n\nexport interface ImageBlock {\n type: \"image\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ImageProps;\n}\n\n// ── Button ───────────────────────────────────────────────────────────────────\n\nexport interface ButtonProps {\n text: string;\n href: string;\n variant?: \"primary\" | \"secondary\";\n}\n\nexport interface ButtonBlock {\n type: \"button\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ButtonProps;\n}\n\n// ── Spacer ───────────────────────────────────────────────────────────────────\n\nexport interface SpacerProps {\n height: number; // in px\n}\n\nexport interface SpacerBlock {\n type: \"spacer\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SpacerProps;\n}\n\n// ── Columns ───────────────────────────────────────────────────────────────────\n\nexport interface ColumnsProps {\n columns: ContentBlock[][]; // array of column slots, each slot is an array of blocks\n gap?: number; // in px\n}\n\nexport interface ColumnsBlock {\n type: \"columns\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ColumnsProps;\n}\n\n// ── Video ────────────────────────────────────────────────────────────────────\n\nexport interface VideoProps {\n url: string;\n poster?: string;\n autoplay?: boolean;\n loop?: boolean;\n /**\n * What is said in the video (CPO-093). The block carries its own because its url may be a\n * pasted provider link with no library asset to hang one from. Rendered as <details> after\n * the player and published in the .md twin.\n */\n transcript?: string;\n}\n\nexport interface VideoBlock {\n type: \"video\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: VideoProps;\n}\n\n// ── Form ─────────────────────────────────────────────────────────────────────\n\nexport interface FormProps {\n formId: string; // references forms.id (a nanoid). Resolved against delivered forms at render time.\n}\n\nexport interface FormBlock {\n type: \"form\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: FormProps;\n}\n\n// ── Section (recursive container) ──────────────────────────────────────────────\n\nexport interface SectionProps {\n children: ContentBlock[];\n background?: string;\n paddingY?: number; // in px\n maxWidth?: number; // in px\n}\n\nexport interface SectionBlock {\n type: \"section\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SectionProps;\n}\n\n// ── Navbar ─────────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavbarProps {\n logo?: { src: string; alt: string; href?: string };\n logoAlt?: string;\n links: NavLink[];\n mobileMenu?: boolean;\n cta?: { text: string; href: string };\n}\n\nexport interface NavbarBlock {\n type: \"navbar\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: NavbarProps;\n}\n\n// ── Footer ─────────────────────────────────────────────────────────────────────\n\nexport interface FooterColumn {\n heading?: string;\n links: NavLink[];\n}\n\nexport interface FooterProps {\n columns: FooterColumn[];\n copyright?: string;\n}\n\nexport interface FooterBlock {\n type: \"footer\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: FooterProps;\n}\n\n// ── Slider / Carousel (recursive container, client-hydrated) ────────────────────\n\nexport interface SlideItem {\n id: string;\n children: ContentBlock[];\n}\n\nexport interface SliderProps {\n slides: SlideItem[];\n autoplay?: boolean;\n interval?: number; // in ms\n loop?: boolean;\n}\n\nexport interface SliderBlock {\n type: \"slider\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: SliderProps;\n}\n\n// ── Tabs (recursive container, client-hydrated) ─────────────────────────────────\n\nexport interface TabItem {\n id: string;\n label: string;\n children: ContentBlock[];\n}\n\nexport interface TabsProps {\n tabs: TabItem[];\n}\n\nexport interface TabsBlock {\n type: \"tabs\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: TabsProps;\n}\n\n// ── Component instance (Webflow-style reusable symbol) ──────────────────────────\n// References a reusable component by id. `overrides` maps a component prop key\n// (declared in the component's `props[]` allowlist) to a value, applied to the\n// component's block tree at render time. Resolved against delivered components.\n\nexport interface ComponentProps {\n componentId: string;\n overrides?: Record<string, unknown>;\n /** Phase A: the page field group this placement renders (its copy + bindings live there). */\n bind?: string;\n /**\n * Phase B: where each override's copy CAME FROM — `{ <propKey>: \"<page field path>\" }`.\n *\n * Written when a placement takes ownership of its copy (`bind` is deleted at the same moment),\n * and it is not decoration:\n * - the COVERAGE METER counts a block-lane declaration\n * (`data-bcms-block=\"<id>\"` + `data-bcms-field=\"<id>__overrides.<propKey>\"`) as bound for\n * the page path named here, so a converted page does not read as a site that lost its\n * bindings;\n * - it is how the componentize lane still recognises WHICH GROUP an instance renders once\n * `bind` is gone — without it a second run would mint a second instance for the same band.\n * A `table` prop names its repeater's path (`faq.items`); every row path under it is that one\n * declaration's, because the prop holds every row.\n */\n source?: Record<string, string>;\n}\n\nexport interface ComponentBlock {\n type: \"component\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: ComponentProps;\n}\n\n// ── Collection (the entries of the page this block sits on) ─────────────────────\n//\n// LANE-AWARE, and that is the whole idea. A dynamic page's `blockJson` is BOTH what\n// `/blog` renders and the template interpolated into every `/blog/<slug>`. One array\n// cannot be an index and a post layout — unless the one block that differs between them\n// knows which lane it is in. The route supplies that (see CollectionCtx in render-page.ts):\n//\n// /blog → this block renders a card per published entry\n// /blog/my-post → this block renders THAT entry's detail; every other block in the\n// array is interpolated with {{placeholders}} exactly as before\n//\n// So no second template column, no migration, and a page without a collection block\n// behaves byte-identically to before.\n//\n// Scope is IMPLIED, never configured: a collection lists the entries of the page it sits\n// on, which is precisely the set whose detail URLs are /<thisPage>/<slug>. There is no\n// model picker because there is no other correct answer.\n\nexport interface CollectionProps {\n /** Component rendered once per entry, interpolated with {{field}} and {{url}}. Omit for a built-in card. */\n cardComponentId?: string;\n /** Component rendered for the single entry on a detail URL. Omit to fall back to the generic field layout. */\n detailComponentId?: string;\n /** Built-in card only. Defaults to \"title\" / no excerpt. */\n titleField?: string;\n excerptField?: string;\n /** Max cards to render. Defaults to 20. */\n limit?: number;\n /** \"newest\" (default) reverses the reader's created_at ordering. */\n order?: \"newest\" | \"oldest\";\n emptyText?: string;\n}\n\nexport interface CollectionBlock {\n type: \"collection\";\n id: string;\n style?: BlockStyle;\n /** Editor-facing display name for this block's dock card. Not rendered. */\n label?: string;\n props: CollectionProps;\n}\n\n// ── Union ─────────────────────────────────────────────────────────────────────\n\nexport type ContentBlock =\n | CollectionBlock\n | HeadingBlock\n | TextBlock\n | RichTextBlock\n | ImageBlock\n | ButtonBlock\n | SpacerBlock\n | ColumnsBlock\n | VideoBlock\n | FormBlock\n | SectionBlock\n | NavbarBlock\n | FooterBlock\n | SliderBlock\n | TabsBlock\n | ComponentBlock;\n\n/** Literal union of all block type discriminators. */\nexport type BlockType = ContentBlock[\"type\"];\n\n/**\n * Type guard — narrows an unknown block to `ContentBlock`.\n *\n * @example\n * const block = maybeBlock as unknown;\n * if (isBlock(block)) {\n * // block is ContentBlock here\n * }\n */\nexport function isBlock(value: unknown): value is ContentBlock {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n typeof (value as Record<string, unknown>)[\"type\"] === \"string\"\n );\n}\n\n/**\n * Extract the `type` discriminator from a block, or `null` if not a block.\n *\n * @example\n * const block = { type: \"heading\", id: \"1\", props: { text: \"Hi\" } };\n * getBlockType(block); // \"heading\"\n * getBlockType({ not: \"a block\" }); // null\n */\nexport function getBlockType(value: unknown): BlockType | null {\n if (isBlock(value)) return value.type;\n return null;\n}\n","/**\n * The ONE declaration of which block props the Visual Editor can address.\n *\n * Four renderers stamp `data-bcms-field` — the hosted renderer, the Next SDK, the Astro SDK\n * and (for minting keys rather than markup) the dashboard's `buildBlockPageDoc`. Until this\n * file existed each carried its own hand-written list, they disagreed by two props, and the\n * dashboard's copy said so in a comment while having nothing to enforce it. A block listed in\n * one and missing from another does not error: it simply never binds, or it binds to a node\n * that resolves to no field. Both failures are silent, which is why they survived.\n *\n * This file is the declaration. The renderers remain the implementation — only they know which\n * ELEMENT carries a value — and `block-binding-coverage.test.ts` asserts the two agree.\n *\n * ── Two kinds of address, because an element is not an attribute ────────────────────────────\n *\n * `data-bcms-field` addresses ONE element. That is enough for a heading's text or an image's\n * src, and not enough for an image's `alt`: the `<img>` already carries a binding, and an\n * element cannot hold two. Entries that name an `attr` are therefore emitted on a SECOND\n * attribute, `data-bcms-props`, whose grammar is:\n *\n * <address>|<kind>|<domAttribute>[;<address>|<kind>|<domAttribute>]*\n *\n * No JSON, because the values are already constrained: an address is grammar A\n * (`[A-Za-z0-9_$-]`, `.`, `[n]`), and kinds and attributes are plain identifiers. A split on\n * two characters parses it, in any language, with no escaping.\n *\n * ── Path templates ──────────────────────────────────────────────────────────────────────────\n *\n * `[]` marks an array the renderer walks. `expandBlockBindings` substitutes real indices from a\n * block's actual props, so `links[].label` on a three-link navbar yields three concrete\n * addresses and on an empty one yields none. `parseFieldPath`/`setFieldPath` in the dashboard\n * have handled N indices since FLO-949; the cap was in what the renderer offered, not in what\n * the writer could persist.\n */\nimport type { ContentBlock, BlockType } from \"./block.js\";\n\n/**\n * How the editor paints a value, and whether it may take a caret.\n *\n * `text`/`richtext` are inline-editable. `image` selects and swaps through the media picker.\n * `url` never takes a caret — a URL typed onto the page has nowhere to report a malformed\n * value — so it is edited in the element toolbar. `array` is a repeater slot: selectable and\n * locatable, edited in the dock.\n *\n * `document` is a whole Portable Text body: selectable as ONE container, repainted whole from the\n * form, and edited per keyed block inside it. It is not a longer `richtext` — a Body stamped\n * `richtext` goes into the rich-text lane, where an opt-out rewrites the value as an `{html}`\n * envelope and the document's own block structure is destroyed.\n */\nexport type BindingKind = \"text\" | \"richtext\" | \"image\" | \"document\" | \"url\" | \"number\" | \"array\";\n\nexport interface BlockBinding {\n /** Path template in grammar A, relative to the block's `props`. `[]` = an array to walk. */\n readonly path: string;\n readonly kind: BindingKind;\n /**\n * The DOM attribute this value lives in, when it is not the element's own text or `src`.\n * Present ⇒ the renderer emits it on `data-bcms-props`, never on `data-bcms-field`.\n */\n readonly attr?: string;\n}\n\n/**\n * Props deliberately absent, and still absent for the original reason:\n *\n * `spacer.height`, `columns.gap`, `section.background` and every `style` token — design, not\n * content. They are edited in the Design accordion, where a slider can express a bounded\n * range that free typing on the page cannot.\n *\n * `text.html` when Portable Text is present — `html` is a cache derived from `content`, so\n * advertising it would persist an ignored sibling and the next frame would read as a revert.\n * The renderer suppresses it; the expander cannot see `content`, so the branch stays there.\n *\n * `component.overrides.*` — instance-scoped, so it cannot be a static template. The renderer\n * derives those addresses per instance from the definition's declared props.\n */\nexport const BLOCK_BINDINGS: Partial<Record<BlockType, readonly BlockBinding[]>> = {\n heading: [{ path: \"text\", kind: \"text\" }],\n text: [{ path: \"html\", kind: \"richtext\" }],\n richtext: [{ path: \"html\", kind: \"richtext\" }],\n image: [\n { path: \"src\", kind: \"image\" },\n { path: \"caption\", kind: \"text\" },\n { path: \"alt\", kind: \"text\", attr: \"alt\" },\n ],\n button: [\n { path: \"text\", kind: \"text\" },\n { path: \"href\", kind: \"url\", attr: \"href\" },\n ],\n video: [\n { path: \"url\", kind: \"url\", attr: \"src\" },\n { path: \"poster\", kind: \"url\", attr: \"poster\" },\n ],\n navbar: [\n { path: \"logo.src\", kind: \"image\" },\n { path: \"logo.alt\", kind: \"text\", attr: \"alt\" },\n { path: \"links[].label\", kind: \"text\" },\n { path: \"links[].href\", kind: \"url\", attr: \"href\" },\n { path: \"cta.text\", kind: \"text\" },\n { path: \"cta.href\", kind: \"url\", attr: \"href\" },\n ],\n footer: [\n { path: \"copyright\", kind: \"text\" },\n { path: \"columns[].heading\", kind: \"text\" },\n { path: \"columns[].links[].label\", kind: \"text\" },\n { path: \"columns[].links[].href\", kind: \"url\", attr: \"href\" },\n ],\n tabs: [{ path: \"tabs[].label\", kind: \"text\" }],\n};\n\n/** One concrete, writable address on one block. */\nexport interface ExpandedBinding extends BlockBinding {\n /** The template with every `[]` replaced by a real index, e.g. `links[2].href`. */\n readonly path: string;\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/**\n * Read a grammar-A path — dotted object keys and zero or more `[n]` indices.\n *\n * Positional, exactly like the dashboard's `parseFieldPath`: a dotted segment is always an\n * object key and a bracketed one always an index, so `links.0` reads the string key \"0\" and\n * misses, rather than being quietly treated as `links[0]`. Any miss returns undefined; nothing\n * here throws, because a template that does not resolve must yield no address, not an error.\n *\n * EXPORTED because a second reader of this grammar now exists: `@bettercms-ai/convert` commits a\n * build-time helper into a customer's repository, and that helper must resolve a path exactly the\n * way the editor does or a converted template renders a fallback where a value exists. The helper\n * itself carries an inlined copy (it lands in a repo where our packages do not exist) and a parity\n * test pins the copy to this original.\n */\nexport function readPath(root: unknown, path: string): unknown {\n let cursor: unknown = root;\n for (const segment of path.split(\".\")) {\n if (!segment) return undefined;\n const key = segment.replace(/\\[\\d+\\]/g, \"\");\n if (key) {\n if (!isRecord(cursor)) return undefined;\n cursor = cursor[key];\n }\n for (const index of segment.matchAll(/\\[(\\d+)\\]/g)) {\n if (!Array.isArray(cursor)) return undefined;\n cursor = cursor[Number(index[1])];\n }\n }\n return cursor;\n}\n\n/** Substitute the FIRST `[]` with every real index, then recurse for any deeper array. */\nfunction expandTemplate(binding: BlockBinding, props: unknown, path: string): ExpandedBinding[] {\n const at = path.indexOf(\"[]\");\n if (at < 0) return [{ ...binding, path }];\n\n const head = path.slice(0, at);\n const tail = path.slice(at + 2);\n const array = readPath(props, head);\n if (!Array.isArray(array)) return [];\n\n return array.flatMap((_item, index) =>\n expandTemplate(binding, props, `${head}[${index}]${tail}`),\n );\n}\n\n/**\n * Every concrete address a block actually offers right now.\n *\n * Array templates expand against the array's real length, so an address is only ever minted\n * for an element that exists. That is the load-bearing property: `setFieldPath` refuses to\n * fabricate an array member, so an address for `links[3]` on a two-link navbar would be a\n * binding the writer rejects — the \"advertises an edit that silently fails\" failure this whole\n * grammar exists to avoid.\n *\n * A prop whose KEY is absent does NOT expand, and that is not a nicety. `setFieldPath` refuses\n * to create a final key unless `createMissingObjects` is set, which only component overrides\n * pass — so an address for a key the block does not carry is a write the editor would reject.\n * An empty string still expands: `\"\"` is a value, and clearing a heading must not make it\n * uneditable.\n */\nexport function expandBlockBindings(block: ContentBlock): ExpandedBinding[] {\n const declared = BLOCK_BINDINGS[block.type];\n if (!declared) return [];\n const props = (block as { props?: unknown }).props;\n if (!isRecord(props)) return [];\n return declared\n .flatMap((binding) => expandTemplate(binding, props, binding.path))\n .filter((binding) => readPath(props, binding.path) !== undefined);\n}\n\n/** The `data-bcms-props` value for a block's attribute bindings, or \"\" when it has none. */\nexport function formatPropsAttribute(\n entries: readonly { address: string; kind: BindingKind; attr: string }[],\n): string {\n return entries.map((e) => `${e.address}|${e.kind}|${e.attr}`).join(\";\");\n}\n\n/** Parse a `data-bcms-props` value. Malformed entries are dropped, never guessed at. */\nexport function parsePropsAttribute(\n value: string | null | undefined,\n): { address: string; kind: BindingKind; attr: string }[] {\n if (!value) return [];\n return value\n .split(\";\")\n .map((entry) => entry.split(\"|\"))\n .filter((parts): parts is [string, BindingKind, string] => parts.length === 3 && parts.every(Boolean))\n .map(([address, kind, attr]) => ({ address, kind, attr }));\n}\n\n/** The shape of a declared component prop this module needs: where it points, and its key. */\ninterface PropTarget {\n key?: string;\n target?: { blockId?: string; path?: string };\n}\n\n/**\n * `<defBlockId>__<prop>` → `<instanceBlockId>__overrides.<propKey>`, for one placed component.\n *\n * Shared by every renderer, because the mapping is a property of the DEFINITION and not of any\n * one output format. A component's block ids belong to the definition and are shared by every\n * instance of it, so `<defBlockId>__text` addresses no instance's value — which is why component\n * subtrees used to render unannotated, and why the SDKs (which never had that suppression)\n * stamped definition-scoped addresses that resolve to no field and, on a component placed twice,\n * collide into a duplicate that drops BOTH copies.\n *\n * The definition already states the mapping in `props[].target`. This only re-keys that\n * statement into the address the editor writes through. Nothing is inferred: a prop with no\n * target produces no entry, so it keeps its dock control and stays uneditable on the canvas,\n * which is the truthful outcome rather than a broken one.\n */\n/**\n * The definition-scoped key a declared prop POINTS AT — `<defBlockId>__<path>`, the same\n * grammar `expandBlockBindings` produces for a block's own bindings.\n *\n * Exported so the \"which leaves does no prop reach?\" check and the address minter below read\n * the key from ONE place. They ask opposite questions of the same mapping, and two spellings\n * of `.replace(/^props\\./, \"\")` is precisely how a leaf ends up counted as bound by one and\n * unbound by the other. Null when the prop declares no target — which is the honest answer:\n * such a prop reaches nothing.\n */\nexport function componentPropTargetKey(prop: PropTarget | undefined): string | null {\n if (!prop?.key || !prop.target?.blockId) return null;\n return `${prop.target.blockId}__${String(prop.target.path ?? \"\").replace(/^props\\./, \"\")}`;\n}\n\n/**\n * `owner` is the address of the rich-text field an instance is EMBEDDED in. Its `_key` is unique\n * only within that field, so the instance is named `<owner>#<_key>` — the same grammar a\n * rich-text node's own address uses — giving `<owner>#<_key>__overrides.<propKey>`.\n */\nexport function componentInstanceAddresses(\n instanceBlockId: string,\n props: readonly PropTarget[] | undefined,\n owner?: string,\n): Map<string, string> {\n const instance = owner ? `${owner}#${instanceBlockId}` : instanceBlockId;\n const out = new Map<string, string>();\n for (const prop of props ?? []) {\n if (!prop?.key || !prop.target?.blockId) continue;\n const from = componentPropTargetKey(prop)!;\n // Two props aimed at one target would make the address ambiguous; first declaration wins\n // and the duplicate is dropped rather than silently overwriting it.\n if (!out.has(from)) out.set(from, `${instance}__overrides.${prop.key}`);\n }\n return out;\n}\n","/**\n * Section spacing as TOKEN STEPS — the ONE list of names and default sizes, shared by the save\n * schema and every renderer. A stored value is always a token (`section-space-large`), never a\n * pixel; it renders as `var(--bcms-section-space-large,96px)`, so a site with a token registry\n * restyles every section at once and a site without one still gets the default rhythm.\n *\n * 🔴 The px table is twinned with the dashboard's `tokenScales.ts` preview table. Change both.\n */\nexport const SECTION_SPACE_TOKENS = [\n \"section-space-none\",\n \"section-space-small\",\n \"section-space-medium\",\n \"section-space-large\",\n \"section-space-xlarge\",\n \"section-space-nav-overlap\",\n] as const;\nexport const SPACE_STEP_TOKENS = [\"space-none\", \"space-s\", \"space-m\", \"space-l\", \"space-xl\"] as const;\n\nexport type SectionSpaceToken = (typeof SECTION_SPACE_TOKENS)[number];\nexport type SpaceStepToken = (typeof SPACE_STEP_TOKENS)[number];\n\n/** A negative band that pulls content under the nav makes sense at the TOP of a section only. */\nexport const SPACE_BOTTOM_TOKENS = SECTION_SPACE_TOKENS.filter(\n (t): t is Exclude<SectionSpaceToken, \"section-space-nav-overlap\"> => t !== \"section-space-nav-overlap\",\n);\n\nconst SPACE_TOKEN_PX: Record<SectionSpaceToken | SpaceStepToken, string> = {\n \"section-space-none\": \"0px\",\n \"section-space-small\": \"32px\",\n \"section-space-medium\": \"64px\",\n \"section-space-large\": \"96px\",\n \"section-space-xlarge\": \"144px\",\n \"section-space-nav-overlap\": \"-72px\",\n \"space-none\": \"0px\",\n \"space-s\": \"8px\",\n \"space-m\": \"16px\",\n \"space-l\": \"32px\",\n \"space-xl\": \"64px\",\n};\n\n/** `var(--bcms-<token>,<px>)`, or \"\" for anything that is not a known token (closed set). */\nexport function spaceTokenCss(token: unknown): string {\n const px = typeof token === \"string\" ? SPACE_TOKEN_PX[token as SectionSpaceToken] : undefined;\n return px ? `var(--bcms-${token},${px})` : \"\";\n}\n","/**\n * FLO-264 — bounded block-style tokens → CSS. Framework-agnostic (returns a plain\n * declaration object, no React types) so every renderer shares ONE mapping: the\n * headless @bettercms-ai/next adapter, @bettercms-ai/ui, and (string form) the hosted\n * render-page.ts. Unknown tokens are dropped — closed set, no arbitrary CSS.\n */\nimport type { BlockStyle } from \"./block.js\";\nimport { SPACE_BOTTOM_TOKENS, spaceTokenCss } from \"./sectionSpace.js\";\n\nconst SPACE_PX: Record<string, string> = { none: \"0\", xs: \"4px\", sm: \"8px\", md: \"16px\", lg: \"32px\", xl: \"64px\" };\nconst FONT_SIZE_REM: Record<string, string> = { sm: \"0.875rem\", base: \"1rem\", lg: \"1.25rem\", xl: \"1.5rem\", \"2xl\": \"2rem\" };\nconst WEIGHT: Record<string, number> = { normal: 400, medium: 500, semibold: 600, bold: 700 };\nconst RADIUS_PX: Record<string, string> = { none: \"0\", sm: \"4px\", md: \"8px\", lg: \"16px\", full: \"9999px\" };\nconst COLOR_HEX: Record<string, string> = { white: \"#ffffff\", black: \"#111111\", muted: \"#6b7280\", mutedBg: \"#f3f4f6\", primary: \"#111111\", accent: \"#4f46e5\" };\n\n/** A CSS declaration object (key → value) usable as a React `style` prop, or undefined when empty. */\nexport function blockStyleToCss(style: BlockStyle | undefined): Record<string, string | number> | undefined {\n if (!style || typeof style !== \"object\") return undefined;\n const s = style as Record<string, string>;\n const css: Record<string, string | number> = {};\n if (s.paddingY && SPACE_PX[s.paddingY] != null) { css.paddingTop = SPACE_PX[s.paddingY]!; css.paddingBottom = SPACE_PX[s.paddingY]!; }\n if (s.paddingX && SPACE_PX[s.paddingX] != null) { css.paddingLeft = SPACE_PX[s.paddingX]!; css.paddingRight = SPACE_PX[s.paddingX]!; }\n // Token steps win over the legacy padding above: they are what the section design panel writes.\n const top = spaceTokenCss(s.spaceTop);\n const bottom = (SPACE_BOTTOM_TOKENS as readonly string[]).includes(s.spaceBottom ?? \"\") ? spaceTokenCss(s.spaceBottom) : \"\";\n const sides = spaceTokenCss(s.spaceSides);\n const navOverlap = s.spaceTop === \"section-space-nav-overlap\";\n if (top && !navOverlap) css.paddingTop = top;\n if (bottom) css.paddingBottom = bottom;\n if (sides) { css.paddingLeft = sides; css.paddingRight = sides; }\n if (s.marginTop && SPACE_PX[s.marginTop] != null) css.marginTop = SPACE_PX[s.marginTop]!;\n // Nav-overlap is the one NEGATIVE step, and negative padding is invalid (computes 0): under a\n // sticky nav the background slides up (negative margin, set after the legacy margin so the token\n // wins) and the content clears it (the same length back as padding), as in `styleTokensToCss`.\n if (top && navOverlap) { css.marginTop = top; css.paddingTop = `calc(-1 * ${top})`; }\n if (s.marginBottom && SPACE_PX[s.marginBottom] != null) css.marginBottom = SPACE_PX[s.marginBottom]!;\n if (s.background && COLOR_HEX[s.background]) css.background = COLOR_HEX[s.background]!;\n if (s.textColor && COLOR_HEX[s.textColor]) css.color = COLOR_HEX[s.textColor]!;\n if (s.align === \"left\" || s.align === \"center\" || s.align === \"right\") css.textAlign = s.align;\n if (s.fontSize && FONT_SIZE_REM[s.fontSize]) css.fontSize = FONT_SIZE_REM[s.fontSize]!;\n if (s.weight && WEIGHT[s.weight] != null) css.fontWeight = WEIGHT[s.weight]!;\n if (s.radius && RADIUS_PX[s.radius] != null) css.borderRadius = RADIUS_PX[s.radius]!;\n if ((style as BlockStyle).border === true) css.border = \"1px solid currentColor\";\n return Object.keys(css).length ? css : undefined;\n}\n","/**\n * Component — a reusable, Webflow-style block tree (a \"symbol\").\n *\n * A component is authored once and placed across pages via `component` blocks\n * (see `ComponentBlock` in `./block.ts`). Its definition lives in `blockJson`;\n * `props` declares a flat allowlist of values an instance may override.\n */\nimport type { ContentBlock } from \"./block.js\";\nimport type { ContentModelFieldUi } from \"./content-model.js\";\nimport type { VariantInputMapping } from \"./layout.js\";\n\n/**\n * The category a component belongs to (drives library grouping + icons). The first eight\n * are structural (what the component IS); the last four are the \"Add a section\" library\n * tabs (where it appears). One varchar column, not a PG enum — widening is code-only.\n */\n/**\n * 🔴 THE STRUCTURE DOCTRINE — one sentence, one home, spliced into every surface that builds a page.\n *\n * It lives HERE, beside the component contract it describes, because there are THREE places that teach\n * an agent how to build a page and they drifted apart:\n * • `packages/mcp/src/tools.ts` — the MCP tool descriptions (external agents)\n * • `src/lib/ai/agent.ts` — the in-product Studio Agent's system prompt\n * • `packages/mcp/src/prompts.ts` — the authoring playbook, which a tool call does not carry\n *\n * Only the playbook explained sections. `create_page` taught the SCHEMA axis in detail (\"each visual\n * section becomes a nested field\") and said nothing about STRUCTURE; the Studio Agent's prompt named\n * \"pages & reusable components (structure/layout)\" without ever mentioning `sectionType`.\n *\n * Measured consequence, production 2026-08-18: project `acme` has three components, ALL with\n * `section_type = (none)`, and its home page is 18 loose top-level blocks with ZERO sections. Every\n * generated page came out flat, so the visual editor's section lane — outline, name, move, duplicate,\n * delete, variant swap — had nothing to attach to. The editor was faithfully showing pages that were\n * never built out of sections.\n *\n * A constant rather than three paraphrases, because updating some of them is exactly how this happened.\n */\nexport const SECTION_DOCTRINE =\n \"STRUCTURE (separate from schema): a page is composed of SECTIONS. NEVER build a page out of loose top-level heading/text/image/button/spacer blocks — they cannot be moved, duplicated or swapped as a unit, the visual editor cannot outline or name them, and every one of them becomes its own section in the editor. A hero of a headline, a lede and two CTAs is ONE section, not four. TWO SHAPES, and the choice is about REUSE. (1) A band that appears on more than one page, or that needs layout variants, is a COMPONENT with a `sectionType` — see create_component. Components sharing a `sectionType` are that section's VARIANTS (one Hero: 'Centered' for the home page and 'Two-column' for about, same prop keys so a swap keeps the content). This is also the only shape the editor's 'Add a section' picker can insert, and the only one that gets a family name and a variant switcher. (2) A genuinely one-off band on a single page is a `section` BLOCK whose `props.children` hold its blocks. THE TRADEOFF, stated in the present tense because it is real today: inside a component, ONLY the leaves a declared prop TARGETS are click-to-edit on the canvas — each declared prop's `target` is re-keyed to that PLACEMENT's own override address, so editing it changes this page and not the shared definition. A prop with no `target` still SHOWS as a dock control, but its override reaches no rendered slot, so editing it changes nothing on the page. Copy that no prop points at is worse still: no binding and no control, unreachable from click-to-edit AND from the dock, changeable only by editing the component definition, which rewrites every page that places it. A `section` block's children stay click-to-edit unconditionally. So when you choose a component, DECLARE A PROP — WITH A `target` — for every string, link and image a marketer will ever touch; a component with un-propped editable copy is the defect, not the component. In the dock an unset prop shows EMPTY and inherits the definition's default, so set props explicitly when you want the current copy visible there. Do not hand-write a band's JSON: start from a built-in section blueprint (list_components returns locked `builtin:*` blueprints with no projectId — hero-centered, hero-split, feature-grid-three, cta-banner and nine more), each already rooted in a `section` block with its editable leaves declared as props. INLINE its blockJson as a `section` block for a one-off band; for a recurring band, materialize the blueprint with create_component so it becomes project-scoped before implementation validation, Output or publication. Direct `builtin:*` component references exist only for legacy delivery compatibility. Two consecutive call-to-action buttons are two sibling `button` blocks inside the same section — never a `columns` block, which is a `repeat(N,1fr)` grid and would stretch each CTA to half the container. Buttons are inline-level and flow side by side on their own.\";\n\nexport type ComponentCategory =\n | \"navbar\"\n | \"footer\"\n | \"button\"\n | \"section\"\n | \"slider\"\n | \"tabs\"\n | \"form\"\n | \"custom\"\n | \"hero\"\n | \"content\"\n | \"social-proof\"\n | \"conversion\";\n\n/**\n * A single overridable field on a component. `target` points at the block + JSON\n * path inside `blockJson` the override writes to (e.g. blockId \"cta\", path\n * \"props.text\"). Keeping overrides a declared allowlist (not arbitrary nested\n * rewrites) keeps instance data small and the contract explicit.\n */\n/**\n * THE prop vocabulary. One list, imported everywhere a prop type is enumerated.\n *\n * It exists as a value (not just a union) because four places used to spell it out by hand —\n * this file, the Drizzle schema, `COMPONENT_PROP_TYPES` in the backend's Zod schemas, and the\n * MCP tool shape — and the MCP copy is the dangerous one: `update_component` REPLACES the whole\n * `props` array, so a type its enum omits cannot be echoed back, and an agent that reads a\n * component and writes it straight back DESTROYS every prop of that type with a 200.\n *\n * Order is not semantic; append rather than re-sort, so a diff stays readable.\n */\nexport const COMPONENT_PROP_TYPES = [\n \"text\",\n \"richtext\",\n \"image\",\n \"url\",\n \"boolean\",\n \"number\",\n \"select\",\n \"group\",\n \"table\",\n \"slot\",\n \"form\",\n] as const;\n\nexport type ComponentPropType = (typeof COMPONENT_PROP_TYPES)[number];\n\n/**\n * The value a `form` prop STORES: just the id. The form itself is a Form document and stays the\n * single source of truth for its fields — a component references one, it never re-declares it.\n *\n * `.strict()` at the write boundary, so a client that POSTs a hydrated form object alongside the\n * id gets a 400 rather than a silent strip.\n *\n * There is deliberately NO resolved twin of this shape. Every renderer already receives forms the\n * same way — a catalogue beside the blocks (`BcmsBlocks({blocks, forms})`, the site renderer's\n * forms map) — and looks the id up in it. A hydrated `{formId, form}` prop value would be a shape\n * that exists nowhere in delivery.\n */\nexport interface ComponentFormPropRef {\n formId: string;\n}\n\nexport interface ComponentPropDef {\n key: string;\n label: string;\n target: { blockId: string; path: string };\n /**\n * `slot` holds ONE nested component instance — the component-level twin of the\n * content-model field type `component-ref` (see content-model.ts), named differently for\n * the same reason that one is: `component` already means a BLOCK type. Its value is\n * `{ componentId, overrides }` and its `target.path` is `props`, so filling a slot writes\n * that object over an empty `component` block's props.\n *\n * On a PAGE a slot fill is a LIVE reference; a published ENTRY freezes it (resolveDeep).\n */\n /**\n * The EDITOR contract, not a storage one: `applyOverrides` writes the value at\n * `target.path` whatever its shape, so `type` decides which control the inspector renders\n * and what shape that control produces (FLO-1020).\n *\n * number → a number (heading.level, columns.count)\n * select → one string from `config.options`\n * group → an object keyed by `config.fields`\n * table → an array of such objects (slider.slides)\n *\n * `reference` is absent on purpose: nothing resolves a content-entry id at component render\n * time, so such a prop would save cleanly and render as nothing.\n */\n type: ComponentPropType;\n defaultValue?: unknown;\n /**\n * EDITOR HINTS (playbook §12). Stored in the props JSON, so no migration.\n *\n * 🔴 `required` IS NOT ENFORCED AT WRITE TIME, deliberately. Nothing on the write path\n * refuses an override that omits a required prop — a placement saves either way — because\n * the alternative is a component definition that can retroactively make already-saved pages\n * unsaveable. It is a marker the dashboard renders and `get_site_composition` counts, which\n * is the honest shape: the receipt names what is missing instead of the write refusing it.\n */\n required?: boolean;\n /** Hint shown under the control, muted. */\n helpText?: string;\n /** Ghost text inside a text-ish control. */\n placeholder?: string;\n /** Per-type settings; the save schema enforces that each is present on the type needing it. */\n config?: {\n /** `slot` — a pick allowlist. */\n componentIds?: string[];\n /**\n * `select` — the choices. Required, and a default must be one of them. `{ label, value }`\n * when the stored value is not what an author should read (a component id, for instance).\n */\n options?: Array<string | { label: string; value: string }>;\n /** `group` / `table` — the sub-shape, nestable to 3 levels. */\n fields?: ComponentSubField[];\n /** `number` — bounds for the control. */\n min?: number;\n max?: number;\n step?: number;\n } & Record<string, unknown>;\n /**\n * AUTHORING CHROME — the same object a content-model FIELD carries ({@link ContentModelFieldUi}),\n * deliberately: an agent that has learned `ui` once has learned it on both lanes.\n *\n * A SIBLING of `config`, not a member of it. `config` is a loose bag, so a `config.ui` already\n * survived the write — and that is the problem this key fixes: surviving is not declared, and\n * an undeclared prop is a typo that saves cleanly and renders as nothing.\n *\n * WHERE EACH KEY IS LEGAL differs from the field lane, because the vocabulary does:\n * `preview`/`layout` on `group`, `table` and `slot`; `reorderable` on `table` ALONE, the only\n * prop type whose value is a list. The save schema refuses the rest with the valid set named.\n */\n ui?: ContentModelFieldUi;\n}\n\n/** One field inside a `group` prop or a `table` row. Recursive, capped at 3 levels deep. */\nexport interface ComponentSubField {\n key: string;\n label: string;\n /** No `slot`: a nested component instance belongs on the prop itself, not inside a row. */\n // `slot` and `form` are reference-shaped props: they belong ON a prop, never inside a row of\n // one. A form in a table row would mean N form documents per component with no way to author\n // them — the second field model this design exists to avoid.\n type: Exclude<ComponentPropDef[\"type\"], \"slot\" | \"form\">;\n defaultValue?: unknown;\n /** The same editor hints as the prop above, one level down. @see ComponentPropDef */\n required?: boolean;\n helpText?: string;\n placeholder?: string;\n options?: string[];\n /** CANONICAL. A nested `group`/`table`'s own sub-shape. */\n fields?: ComponentSubField[];\n /**\n * A READ-ONLY MIRROR of `options`/`fields`, in the shape `ComponentPropDef` puts them in.\n *\n * 🔴 WHY A SECOND COPY EXISTS AT ALL. A `group`/`table` PROP declares its sub-shape under\n * `config.fields`; a sub-field of one declares its own under a bare `fields`. So a consumer\n * walking a nested table has to switch shape after the first level, and the componentize lane's\n * repo half (`@bettercms-ai/convert --componentize`) walks exactly that — it reads one node\n * shape at every depth. Mirroring the sub-shape here lets it, without the CMS having to\n * describe a nested table differently from a top-level one.\n *\n * `fields` is the authority. The save schema REFUSES a node whose mirror disagrees with it\n * (`componentPropDefSchema`), because two copies that may drift are worse than one awkward\n * shape — an editor that rewrote `fields` alone would leave a stale row description behind.\n */\n config?: { fields?: ComponentSubField[]; options?: string[] } & Record<string, unknown>;\n}\n\n/** The value a `slot` prop holds — the draft half of a `component-ref`, deliberately. */\nexport interface SlotValue {\n componentId: string;\n overrides?: Record<string, unknown>;\n}\n\n/**\n * A component is a DRAFT until published; only the published copy reaches a visitor.\n * Mirrors pages and entries. See migration 0186_component_draft_live_split.sql.\n */\nexport type ComponentStatus = \"draft\" | \"published\";\n\n/**\n * Archive state (FLO-1012), deliberately SEPARATE from `ComponentStatus`.\n *\n * Archive takes a component out of the working set — hidden from the components list by\n * default, not offered in the visual editor's insert surfaces — while every existing usage\n * keeps serving. It is not unpublish (which pulls the live copy and re-bakes every page that\n * embeds it) and it is not delete.\n *\n * It is a timestamp rather than a third `status` value because a component can be published\n * AND archived; collapsing the two would lose the bit restore has to put back.\n */\n\nexport interface Component {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n category: ComponentCategory;\n /**\n * Section library: the family this component is a LAYOUT of, e.g. \"Hero\". `name` is the\n * layout label (\"Centered\"), so components sharing a sectionType are selectable variants\n * of one section. Null/absent = an ordinary component, not shown in the section library.\n */\n sectionType?: string | null;\n /** First-class variant family membership; exact workspace/project scope is enforced in DB. */\n variantGroupId?: string | null;\n variantInputMappings?: VariantInputMapping[];\n /** Placement governance: `*`, `slug:<page-slug>`, and/or `type:<page-type>`. */\n allowedOn: string[];\n description?: string | null;\n /** The DRAFT definition. Every builder/autosave/import write path targets these two. */\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n status: ComponentStatus;\n /** When it left the working set, or null/absent while active. @see ComponentStatus */\n archivedAt?: string | Date | null;\n /** Derived from `archivedAt`, so a client never has to know the column. */\n archived?: boolean;\n /**\n * The LIVE snapshot get_components_by_handle() serves. Null until the first publish.\n * Returned by GET-one (the Compare view needs it), omitted from list rows for payload.\n */\n publishedBlockJson?: ContentBlock[] | null;\n publishedProps?: ComponentPropDef[] | null;\n publishedAt?: string | null; // ISO 8601\n /**\n * Computed in SQL on list/get, never stored:\n * status='published' AND (blockJson or props has diverged from its published copy).\n * An exact jsonb compare, so it self-clears when an edit is reverted.\n */\n pendingChanges?: boolean;\n thumbnail?: string | null;\n createdAt: string; // ISO 8601\n updatedAt: string; // ISO 8601\n}\n\n/**\n * Public/delivery projection — the fields a renderer needs to resolve instances.\n *\n * DELIBERATELY UNCHANGED by the 0186 draft/live split: delivery aliases\n * publishedBlockJson -> blockJson, so every already-deployed site and every\n * bcms-content.json on disk keeps a byte-identical wire shape. Do not add `status` here —\n * delivery only ever returns published rows, so it would always be the same constant.\n */\nexport interface DeliveryComponent {\n id: string;\n name: string;\n slug: string;\n category: ComponentCategory;\n sectionType?: string | null;\n blockJson: ContentBlock[];\n props: ComponentPropDef[];\n}\n","/**\n * Generated from lucide-react@1.8.0 dynamic icon names.\n * Legacy CamelCase identifiers remain valid for existing Layout documents.\n */\nexport const LAYOUT_SECTION_ICONS: readonly string[] = Object.freeze([\n \"LayoutPanelTop\",\n \"PanelTop\",\n \"PanelBottom\",\n \"Menu\",\n \"Navigation\",\n \"Megaphone\",\n \"GalleryHorizontal\",\n \"Rows3\",\n \"Grid2X2\",\n \"FileText\",\n \"Link\",\n \"Contact\",\n \"BadgeInfo\",\n \"Sparkles\",\n \"a-arrow-down\",\n \"a-arrow-up\",\n \"a-large-small\",\n \"accessibility\",\n \"activity\",\n \"air-vent\",\n \"airplay\",\n \"alarm-clock-check\",\n \"alarm-check\",\n \"alarm-clock-minus\",\n \"alarm-minus\",\n \"alarm-clock-off\",\n \"alarm-clock-plus\",\n \"alarm-plus\",\n \"alarm-clock\",\n \"alarm-smoke\",\n \"album\",\n \"align-center-horizontal\",\n \"align-center-vertical\",\n \"align-end-horizontal\",\n \"align-end-vertical\",\n \"align-horizontal-distribute-center\",\n \"align-horizontal-distribute-end\",\n \"align-horizontal-distribute-start\",\n \"align-horizontal-justify-center\",\n \"align-horizontal-justify-end\",\n \"align-horizontal-justify-start\",\n \"align-horizontal-space-around\",\n \"align-horizontal-space-between\",\n \"align-start-horizontal\",\n \"align-start-vertical\",\n \"align-vertical-distribute-center\",\n \"align-vertical-distribute-end\",\n \"align-vertical-distribute-start\",\n \"align-vertical-justify-center\",\n \"align-vertical-justify-end\",\n \"align-vertical-justify-start\",\n \"align-vertical-space-around\",\n \"align-vertical-space-between\",\n \"ambulance\",\n \"ampersand\",\n \"ampersands\",\n \"amphora\",\n \"anchor\",\n \"angry\",\n \"annoyed\",\n \"antenna\",\n \"anvil\",\n \"aperture\",\n \"app-window-mac\",\n \"app-window\",\n \"apple\",\n \"archive-restore\",\n \"archive-x\",\n \"archive\",\n \"armchair\",\n \"arrow-big-down-dash\",\n \"arrow-big-down\",\n \"arrow-big-left-dash\",\n \"arrow-big-left\",\n \"arrow-big-right-dash\",\n \"arrow-big-right\",\n \"arrow-big-up-dash\",\n \"arrow-big-up\",\n \"arrow-down-0-1\",\n \"arrow-down-01\",\n \"arrow-down-1-0\",\n \"arrow-down-10\",\n \"arrow-down-a-z\",\n \"arrow-down-az\",\n \"arrow-down-from-line\",\n \"arrow-down-left\",\n \"arrow-down-narrow-wide\",\n \"arrow-down-right\",\n \"arrow-down-to-dot\",\n \"arrow-down-to-line\",\n \"arrow-down-up\",\n \"arrow-down-wide-narrow\",\n \"sort-desc\",\n \"arrow-down-z-a\",\n \"arrow-down-za\",\n \"arrow-down\",\n \"arrow-left-from-line\",\n \"arrow-left-right\",\n \"arrow-left-to-line\",\n \"arrow-left\",\n \"arrow-right-from-line\",\n \"arrow-right-left\",\n \"arrow-right-to-line\",\n \"arrow-right\",\n \"arrow-up-0-1\",\n \"arrow-up-01\",\n \"arrow-up-1-0\",\n \"arrow-up-10\",\n \"arrow-up-a-z\",\n \"arrow-up-az\",\n \"arrow-up-down\",\n \"arrow-up-from-dot\",\n \"arrow-up-from-line\",\n \"arrow-up-left\",\n \"arrow-up-narrow-wide\",\n \"sort-asc\",\n \"arrow-up-right\",\n \"arrow-up-to-line\",\n \"arrow-up-wide-narrow\",\n \"arrow-up-z-a\",\n \"arrow-up-za\",\n \"arrow-up\",\n \"arrows-up-from-line\",\n \"asterisk\",\n \"at-sign\",\n \"atom\",\n \"audio-lines\",\n \"audio-waveform\",\n \"award\",\n \"axe\",\n \"axis-3d\",\n \"axis-3-d\",\n \"baby\",\n \"backpack\",\n \"badge-alert\",\n \"badge-cent\",\n \"badge-check\",\n \"verified\",\n \"badge-dollar-sign\",\n \"badge-euro\",\n \"badge-indian-rupee\",\n \"badge-info\",\n \"badge-japanese-yen\",\n \"badge-minus\",\n \"badge-percent\",\n \"badge-plus\",\n \"badge-pound-sterling\",\n \"badge-question-mark\",\n \"badge-help\",\n \"badge-russian-ruble\",\n \"badge-swiss-franc\",\n \"badge-turkish-lira\",\n \"badge-x\",\n \"badge\",\n \"baggage-claim\",\n \"balloon\",\n \"ban\",\n \"banana\",\n \"bandage\",\n \"banknote-arrow-down\",\n \"banknote-arrow-up\",\n \"banknote-x\",\n \"banknote\",\n \"barcode\",\n \"barrel\",\n \"baseline\",\n \"bath\",\n \"battery-charging\",\n \"battery-full\",\n \"battery-low\",\n \"battery-medium\",\n \"battery-plus\",\n \"battery-warning\",\n \"battery\",\n \"beaker\",\n \"bean-off\",\n \"bean\",\n \"bed-double\",\n \"bed-single\",\n \"bed\",\n \"beef-off\",\n \"beef\",\n \"beer-off\",\n \"beer\",\n \"bell-dot\",\n \"bell-electric\",\n \"bell-minus\",\n \"bell-off\",\n \"bell-plus\",\n \"bell-ring\",\n \"bell\",\n \"between-horizontal-end\",\n \"between-horizonal-end\",\n \"between-horizontal-start\",\n \"between-horizonal-start\",\n \"between-vertical-end\",\n \"between-vertical-start\",\n \"biceps-flexed\",\n \"bike\",\n \"binary\",\n \"binoculars\",\n \"biohazard\",\n \"bird\",\n \"birdhouse\",\n \"bitcoin\",\n \"blend\",\n \"blinds\",\n \"blocks\",\n \"bluetooth-connected\",\n \"bluetooth-off\",\n \"bluetooth-searching\",\n \"bluetooth\",\n \"bold\",\n \"bolt\",\n \"bomb\",\n \"bone\",\n \"book-a\",\n \"book-alert\",\n \"book-audio\",\n \"book-check\",\n \"book-copy\",\n \"book-dashed\",\n \"book-template\",\n \"book-down\",\n \"book-headphones\",\n \"book-heart\",\n \"book-image\",\n \"book-key\",\n \"book-lock\",\n \"book-marked\",\n \"book-minus\",\n \"book-open-check\",\n \"book-open-text\",\n \"book-open\",\n \"book-plus\",\n \"book-search\",\n \"book-text\",\n \"book-type\",\n \"book-up-2\",\n \"book-up\",\n \"book-user\",\n \"book-x\",\n \"book\",\n \"bookmark-check\",\n \"bookmark-minus\",\n \"bookmark-off\",\n \"bookmark-plus\",\n \"bookmark-x\",\n \"bookmark\",\n \"boom-box\",\n \"bot-message-square\",\n \"bot-off\",\n \"bot\",\n \"bottle-wine\",\n \"bow-arrow\",\n \"box\",\n \"boxes\",\n \"braces\",\n \"curly-braces\",\n \"brackets\",\n \"brain-circuit\",\n \"brain-cog\",\n \"brain\",\n \"brick-wall-fire\",\n \"brick-wall-shield\",\n \"brick-wall\",\n \"briefcase-business\",\n \"briefcase-conveyor-belt\",\n \"briefcase-medical\",\n \"briefcase\",\n \"bring-to-front\",\n \"brush-cleaning\",\n \"brush\",\n \"bubbles\",\n \"bug-off\",\n \"bug-play\",\n \"bug\",\n \"building-2\",\n \"building\",\n \"bus-front\",\n \"bus\",\n \"cable-car\",\n \"cable\",\n \"cake-slice\",\n \"cake\",\n \"calculator\",\n \"calendar-1\",\n \"calendar-arrow-down\",\n \"calendar-arrow-up\",\n \"calendar-check-2\",\n \"calendar-check\",\n \"calendar-clock\",\n \"calendar-cog\",\n \"calendar-days\",\n \"calendar-fold\",\n \"calendar-heart\",\n \"calendar-minus-2\",\n \"calendar-minus\",\n \"calendar-off\",\n \"calendar-plus-2\",\n \"calendar-plus\",\n \"calendar-range\",\n \"calendar-search\",\n \"calendar-sync\",\n \"calendar-x-2\",\n \"calendar-x\",\n \"calendar\",\n \"calendars\",\n \"camera-off\",\n \"camera\",\n \"candy-cane\",\n \"candy-off\",\n \"candy\",\n \"cannabis-off\",\n \"cannabis\",\n \"captions-off\",\n \"captions\",\n \"subtitles\",\n \"car-front\",\n \"car-taxi-front\",\n \"car\",\n \"caravan\",\n \"card-sim\",\n \"carrot\",\n \"case-lower\",\n \"case-sensitive\",\n \"case-upper\",\n \"cassette-tape\",\n \"cast\",\n \"castle\",\n \"cat\",\n \"cctv-off\",\n \"cctv\",\n \"chart-area\",\n \"area-chart\",\n \"chart-bar-big\",\n \"bar-chart-horizontal-big\",\n \"chart-bar-decreasing\",\n \"chart-bar-increasing\",\n \"chart-bar-stacked\",\n \"chart-bar\",\n \"bar-chart-horizontal\",\n \"chart-candlestick\",\n \"candlestick-chart\",\n \"chart-column-big\",\n \"bar-chart-big\",\n \"chart-column-decreasing\",\n \"chart-column-increasing\",\n \"bar-chart-4\",\n \"chart-column-stacked\",\n \"chart-column\",\n \"bar-chart-3\",\n \"chart-gantt\",\n \"chart-line\",\n \"line-chart\",\n \"chart-network\",\n \"chart-no-axes-column-decreasing\",\n \"chart-no-axes-column-increasing\",\n \"bar-chart\",\n \"chart-no-axes-column\",\n \"bar-chart-2\",\n \"chart-no-axes-combined\",\n \"chart-no-axes-gantt\",\n \"gantt-chart\",\n \"chart-pie\",\n \"pie-chart\",\n \"chart-scatter\",\n \"scatter-chart\",\n \"chart-spline\",\n \"check-check\",\n \"check-line\",\n \"check\",\n \"chef-hat\",\n \"cherry\",\n \"chess-bishop\",\n \"chess-king\",\n \"chess-knight\",\n \"chess-pawn\",\n \"chess-queen\",\n \"chess-rook\",\n \"chevron-down\",\n \"chevron-first\",\n \"chevron-last\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"chevrons-down-up\",\n \"chevrons-down\",\n \"chevrons-left-right-ellipsis\",\n \"chevrons-left-right\",\n \"chevrons-left\",\n \"chevrons-right-left\",\n \"chevrons-right\",\n \"chevrons-up-down\",\n \"chevrons-up\",\n \"church\",\n \"cigarette-off\",\n \"cigarette\",\n \"circle-alert\",\n \"alert-circle\",\n \"circle-arrow-down\",\n \"arrow-down-circle\",\n \"circle-arrow-left\",\n \"arrow-left-circle\",\n \"circle-arrow-out-down-left\",\n \"arrow-down-left-from-circle\",\n \"circle-arrow-out-down-right\",\n \"arrow-down-right-from-circle\",\n \"circle-arrow-out-up-left\",\n \"arrow-up-left-from-circle\",\n \"circle-arrow-out-up-right\",\n \"arrow-up-right-from-circle\",\n \"circle-arrow-right\",\n \"arrow-right-circle\",\n \"circle-arrow-up\",\n \"arrow-up-circle\",\n \"circle-check-big\",\n \"check-circle\",\n \"circle-check\",\n \"check-circle-2\",\n \"circle-chevron-down\",\n \"chevron-down-circle\",\n \"circle-chevron-left\",\n \"chevron-left-circle\",\n \"circle-chevron-right\",\n \"chevron-right-circle\",\n \"circle-chevron-up\",\n \"chevron-up-circle\",\n \"circle-dashed\",\n \"circle-divide\",\n \"divide-circle\",\n \"circle-dollar-sign\",\n \"circle-dot-dashed\",\n \"circle-dot\",\n \"circle-ellipsis\",\n \"circle-equal\",\n \"circle-fading-arrow-up\",\n \"circle-fading-plus\",\n \"circle-gauge\",\n \"gauge-circle\",\n \"circle-minus\",\n \"minus-circle\",\n \"circle-off\",\n \"circle-parking-off\",\n \"parking-circle-off\",\n \"circle-parking\",\n \"parking-circle\",\n \"circle-pause\",\n \"pause-circle\",\n \"circle-percent\",\n \"percent-circle\",\n \"circle-pile\",\n \"circle-play\",\n \"play-circle\",\n \"circle-plus\",\n \"plus-circle\",\n \"circle-pound-sterling\",\n \"circle-power\",\n \"power-circle\",\n \"circle-question-mark\",\n \"help-circle\",\n \"circle-help\",\n \"circle-slash-2\",\n \"circle-slashed\",\n \"circle-slash\",\n \"circle-small\",\n \"circle-star\",\n \"circle-stop\",\n \"stop-circle\",\n \"circle-user-round\",\n \"user-circle-2\",\n \"circle-user\",\n \"user-circle\",\n \"circle-x\",\n \"x-circle\",\n \"circle\",\n \"circuit-board\",\n \"citrus\",\n \"clapperboard\",\n \"clipboard-check\",\n \"clipboard-clock\",\n \"clipboard-copy\",\n \"clipboard-list\",\n \"clipboard-minus\",\n \"clipboard-paste\",\n \"clipboard-pen-line\",\n \"clipboard-signature\",\n \"clipboard-pen\",\n \"clipboard-edit\",\n \"clipboard-plus\",\n \"clipboard-type\",\n \"clipboard-x\",\n \"clipboard\",\n \"clock-1\",\n \"clock-10\",\n \"clock-11\",\n \"clock-12\",\n \"clock-2\",\n \"clock-3\",\n \"clock-4\",\n \"clock-5\",\n \"clock-6\",\n \"clock-7\",\n \"clock-8\",\n \"clock-9\",\n \"clock-alert\",\n \"clock-arrow-down\",\n \"clock-arrow-up\",\n \"clock-check\",\n \"clock-fading\",\n \"clock-plus\",\n \"clock\",\n \"closed-caption\",\n \"cloud-alert\",\n \"cloud-backup\",\n \"cloud-check\",\n \"cloud-cog\",\n \"cloud-download\",\n \"download-cloud\",\n \"cloud-drizzle\",\n \"cloud-fog\",\n \"cloud-hail\",\n \"cloud-lightning\",\n \"cloud-moon-rain\",\n \"cloud-moon\",\n \"cloud-off\",\n \"cloud-rain-wind\",\n \"cloud-rain\",\n \"cloud-snow\",\n \"cloud-sun-rain\",\n \"cloud-sun\",\n \"cloud-sync\",\n \"cloud-upload\",\n \"upload-cloud\",\n \"cloud\",\n \"cloudy\",\n \"clover\",\n \"club\",\n \"code-xml\",\n \"code-2\",\n \"code\",\n \"coffee\",\n \"cog\",\n \"coins\",\n \"columns-2\",\n \"columns\",\n \"columns-3-cog\",\n \"columns-settings\",\n \"table-config\",\n \"columns-3\",\n \"panels-left-right\",\n \"columns-4\",\n \"combine\",\n \"command\",\n \"compass\",\n \"component\",\n \"computer\",\n \"concierge-bell\",\n \"cone\",\n \"construction\",\n \"contact-round\",\n \"contact-2\",\n \"contact\",\n \"container\",\n \"contrast\",\n \"cookie\",\n \"cooking-pot\",\n \"copy-check\",\n \"copy-minus\",\n \"copy-plus\",\n \"copy-slash\",\n \"copy-x\",\n \"copy\",\n \"copyleft\",\n \"copyright\",\n \"corner-down-left\",\n \"corner-down-right\",\n \"corner-left-down\",\n \"corner-left-up\",\n \"corner-right-down\",\n \"corner-right-up\",\n \"corner-up-left\",\n \"corner-up-right\",\n \"cpu\",\n \"creative-commons\",\n \"credit-card\",\n \"croissant\",\n \"crop\",\n \"cross\",\n \"crosshair\",\n \"crown\",\n \"cuboid\",\n \"cup-soda\",\n \"currency\",\n \"cylinder\",\n \"dam\",\n \"database-backup\",\n \"database-search\",\n \"database-zap\",\n \"database\",\n \"decimals-arrow-left\",\n \"decimals-arrow-right\",\n \"delete\",\n \"dessert\",\n \"diameter\",\n \"diamond-minus\",\n \"diamond-percent\",\n \"percent-diamond\",\n \"diamond-plus\",\n \"diamond\",\n \"dice-1\",\n \"dice-2\",\n \"dice-3\",\n \"dice-4\",\n \"dice-5\",\n \"dice-6\",\n \"dices\",\n \"diff\",\n \"disc-2\",\n \"disc-3\",\n \"disc-album\",\n \"disc\",\n \"divide\",\n \"dna-off\",\n \"dna\",\n \"dock\",\n \"dog\",\n \"dollar-sign\",\n \"donut\",\n \"door-closed-locked\",\n \"door-closed\",\n \"door-open\",\n \"dot\",\n \"download\",\n \"drafting-compass\",\n \"drama\",\n \"drill\",\n \"drone\",\n \"droplet-off\",\n \"droplet\",\n \"droplets\",\n \"drum\",\n \"drumstick\",\n \"dumbbell\",\n \"ear-off\",\n \"ear\",\n \"earth-lock\",\n \"earth\",\n \"globe-2\",\n \"eclipse\",\n \"egg-fried\",\n \"egg-off\",\n \"egg\",\n \"ellipse\",\n \"ellipsis-vertical\",\n \"more-vertical\",\n \"ellipsis\",\n \"more-horizontal\",\n \"equal-approximately\",\n \"equal-not\",\n \"equal\",\n \"eraser\",\n \"ethernet-port\",\n \"euro\",\n \"ev-charger\",\n \"expand\",\n \"external-link\",\n \"eye-closed\",\n \"eye-off\",\n \"eye\",\n \"factory\",\n \"fan\",\n \"fast-forward\",\n \"feather\",\n \"fence\",\n \"ferris-wheel\",\n \"file-archive\",\n \"file-axis-3d\",\n \"file-axis-3-d\",\n \"file-badge\",\n \"file-badge-2\",\n \"file-box\",\n \"file-braces-corner\",\n \"file-json-2\",\n \"file-braces\",\n \"file-json\",\n \"file-chart-column-increasing\",\n \"file-bar-chart\",\n \"file-chart-column\",\n \"file-bar-chart-2\",\n \"file-chart-line\",\n \"file-line-chart\",\n \"file-chart-pie\",\n \"file-pie-chart\",\n \"file-check-corner\",\n \"file-check-2\",\n \"file-check\",\n \"file-clock\",\n \"file-code-corner\",\n \"file-code-2\",\n \"file-code\",\n \"file-cog\",\n \"file-cog-2\",\n \"file-diff\",\n \"file-digit\",\n \"file-down\",\n \"file-exclamation-point\",\n \"file-warning\",\n \"file-headphone\",\n \"file-audio\",\n \"file-audio-2\",\n \"file-heart\",\n \"file-image\",\n \"file-input\",\n \"file-key\",\n \"file-key-2\",\n \"file-lock\",\n \"file-lock-2\",\n \"file-minus-corner\",\n \"file-minus-2\",\n \"file-minus\",\n \"file-music\",\n \"file-output\",\n \"file-pen-line\",\n \"file-signature\",\n \"file-pen\",\n \"file-edit\",\n \"file-play\",\n \"file-video\",\n \"file-plus-corner\",\n \"file-plus-2\",\n \"file-plus\",\n \"file-question-mark\",\n \"file-question\",\n \"file-scan\",\n \"file-search-corner\",\n \"file-search-2\",\n \"file-search\",\n \"file-signal\",\n \"file-volume-2\",\n \"file-sliders\",\n \"file-spreadsheet\",\n \"file-stack\",\n \"file-symlink\",\n \"file-terminal\",\n \"file-text\",\n \"file-type-corner\",\n \"file-type-2\",\n \"file-type\",\n \"file-up\",\n \"file-user\",\n \"file-video-camera\",\n \"file-video-2\",\n \"file-volume\",\n \"file-x-corner\",\n \"file-x-2\",\n \"file-x\",\n \"file\",\n \"files\",\n \"film\",\n \"fingerprint-pattern\",\n \"fingerprint\",\n \"fire-extinguisher\",\n \"fish-off\",\n \"fish-symbol\",\n \"fish\",\n \"fishing-hook\",\n \"fishing-rod\",\n \"flag-off\",\n \"flag-triangle-left\",\n \"flag-triangle-right\",\n \"flag\",\n \"flame-kindling\",\n \"flame\",\n \"flashlight-off\",\n \"flashlight\",\n \"flask-conical-off\",\n \"flask-conical\",\n \"flask-round\",\n \"flip-horizontal-2\",\n \"flip-vertical-2\",\n \"flower-2\",\n \"flower\",\n \"focus\",\n \"fold-horizontal\",\n \"fold-vertical\",\n \"folder-archive\",\n \"folder-check\",\n \"folder-clock\",\n \"folder-closed\",\n \"folder-code\",\n \"folder-cog\",\n \"folder-cog-2\",\n \"folder-dot\",\n \"folder-down\",\n \"folder-git-2\",\n \"folder-git\",\n \"folder-heart\",\n \"folder-input\",\n \"folder-kanban\",\n \"folder-key\",\n \"folder-lock\",\n \"folder-minus\",\n \"folder-open-dot\",\n \"folder-open\",\n \"folder-output\",\n \"folder-pen\",\n \"folder-edit\",\n \"folder-plus\",\n \"folder-root\",\n \"folder-search-2\",\n \"folder-search\",\n \"folder-symlink\",\n \"folder-sync\",\n \"folder-tree\",\n \"folder-up\",\n \"folder-x\",\n \"folder\",\n \"folders\",\n \"footprints\",\n \"forklift\",\n \"form\",\n \"forward\",\n \"frame\",\n \"frown\",\n \"fuel\",\n \"fullscreen\",\n \"funnel-plus\",\n \"funnel-x\",\n \"filter-x\",\n \"funnel\",\n \"filter\",\n \"gallery-horizontal-end\",\n \"gallery-horizontal\",\n \"gallery-thumbnails\",\n \"gallery-vertical-end\",\n \"gallery-vertical\",\n \"gamepad-2\",\n \"gamepad-directional\",\n \"gamepad\",\n \"gauge\",\n \"gavel\",\n \"gem\",\n \"georgian-lari\",\n \"ghost\",\n \"gift\",\n \"git-branch-minus\",\n \"git-branch-plus\",\n \"git-branch\",\n \"git-commit-horizontal\",\n \"git-commit\",\n \"git-commit-vertical\",\n \"git-compare-arrows\",\n \"git-compare\",\n \"git-fork\",\n \"git-graph\",\n \"git-merge-conflict\",\n \"git-merge\",\n \"git-pull-request-arrow\",\n \"git-pull-request-closed\",\n \"git-pull-request-create-arrow\",\n \"git-pull-request-create\",\n \"git-pull-request-draft\",\n \"git-pull-request\",\n \"glass-water\",\n \"glasses\",\n \"globe-lock\",\n \"globe-off\",\n \"globe-x\",\n \"globe\",\n \"goal\",\n \"gpu\",\n \"graduation-cap\",\n \"grape\",\n \"grid-2x2-check\",\n \"grid-2-x-2-check\",\n \"grid-2x2-plus\",\n \"grid-2-x-2-plus\",\n \"grid-2x2-x\",\n \"grid-2-x-2-x\",\n \"grid-2x2\",\n \"grid-2-x-2\",\n \"grid-3x2\",\n \"grid-3x3\",\n \"grid\",\n \"grid-3-x-3\",\n \"grip-horizontal\",\n \"grip-vertical\",\n \"grip\",\n \"group\",\n \"guitar\",\n \"ham\",\n \"hamburger\",\n \"hammer\",\n \"hand-coins\",\n \"hand-fist\",\n \"hand-grab\",\n \"grab\",\n \"hand-heart\",\n \"hand-helping\",\n \"helping-hand\",\n \"hand-metal\",\n \"hand-platter\",\n \"hand\",\n \"handbag\",\n \"handshake\",\n \"hard-drive-download\",\n \"hard-drive-upload\",\n \"hard-drive\",\n \"hard-hat\",\n \"hash\",\n \"hat-glasses\",\n \"haze\",\n \"hd\",\n \"hdmi-port\",\n \"heading-1\",\n \"heading-2\",\n \"heading-3\",\n \"heading-4\",\n \"heading-5\",\n \"heading-6\",\n \"heading\",\n \"headphone-off\",\n \"headphones\",\n \"headset\",\n \"heart-crack\",\n \"heart-handshake\",\n \"heart-minus\",\n \"heart-off\",\n \"heart-plus\",\n \"heart-pulse\",\n \"heart\",\n \"heater\",\n \"helicopter\",\n \"hexagon\",\n \"highlighter\",\n \"history\",\n \"hop-off\",\n \"hop\",\n \"hospital\",\n \"hotel\",\n \"hourglass\",\n \"house-heart\",\n \"house-plug\",\n \"house-plus\",\n \"house-wifi\",\n \"house\",\n \"home\",\n \"ice-cream-bowl\",\n \"ice-cream-2\",\n \"ice-cream-cone\",\n \"ice-cream\",\n \"id-card-lanyard\",\n \"id-card\",\n \"image-down\",\n \"image-minus\",\n \"image-off\",\n \"image-play\",\n \"image-plus\",\n \"image-up\",\n \"image-upscale\",\n \"image\",\n \"images\",\n \"import\",\n \"inbox\",\n \"indian-rupee\",\n \"infinity\",\n \"info\",\n \"inspection-panel\",\n \"italic\",\n \"iteration-ccw\",\n \"iteration-cw\",\n \"japanese-yen\",\n \"joystick\",\n \"kanban\",\n \"kayak\",\n \"key-round\",\n \"key-square\",\n \"key\",\n \"keyboard-music\",\n \"keyboard-off\",\n \"keyboard\",\n \"lamp-ceiling\",\n \"lamp-desk\",\n \"lamp-floor\",\n \"lamp-wall-down\",\n \"lamp-wall-up\",\n \"lamp\",\n \"land-plot\",\n \"landmark\",\n \"languages\",\n \"laptop-minimal-check\",\n \"laptop-minimal\",\n \"laptop-2\",\n \"laptop\",\n \"lasso-select\",\n \"lasso\",\n \"laugh\",\n \"layers-2\",\n \"layers-plus\",\n \"layers\",\n \"layers-3\",\n \"layout-dashboard\",\n \"layout-grid\",\n \"layout-list\",\n \"layout-panel-left\",\n \"layout-panel-top\",\n \"layout-template\",\n \"leaf\",\n \"leafy-green\",\n \"lectern\",\n \"lens-concave\",\n \"lens-convex\",\n \"library-big\",\n \"library\",\n \"life-buoy\",\n \"ligature\",\n \"lightbulb-off\",\n \"lightbulb\",\n \"line-dot-right-horizontal\",\n \"line-squiggle\",\n \"line-style\",\n \"link-2-off\",\n \"link-2\",\n \"link\",\n \"list-check\",\n \"list-checks\",\n \"list-chevrons-down-up\",\n \"list-chevrons-up-down\",\n \"list-collapse\",\n \"list-end\",\n \"list-filter-plus\",\n \"list-filter\",\n \"list-indent-decrease\",\n \"outdent\",\n \"indent-decrease\",\n \"list-indent-increase\",\n \"indent\",\n \"indent-increase\",\n \"list-minus\",\n \"list-music\",\n \"list-ordered\",\n \"list-plus\",\n \"list-restart\",\n \"list-start\",\n \"list-todo\",\n \"list-tree\",\n \"list-video\",\n \"list-x\",\n \"list\",\n \"loader-circle\",\n \"loader-2\",\n \"loader-pinwheel\",\n \"loader\",\n \"locate-fixed\",\n \"locate-off\",\n \"locate\",\n \"lock-keyhole-open\",\n \"unlock-keyhole\",\n \"lock-keyhole\",\n \"lock-open\",\n \"unlock\",\n \"lock\",\n \"log-in\",\n \"log-out\",\n \"logs\",\n \"lollipop\",\n \"luggage\",\n \"magnet\",\n \"mail-check\",\n \"mail-minus\",\n \"mail-open\",\n \"mail-plus\",\n \"mail-question-mark\",\n \"mail-question\",\n \"mail-search\",\n \"mail-warning\",\n \"mail-x\",\n \"mail\",\n \"mailbox\",\n \"mails\",\n \"map-minus\",\n \"map-pin-check-inside\",\n \"map-pin-check\",\n \"map-pin-house\",\n \"map-pin-minus-inside\",\n \"map-pin-minus\",\n \"map-pin-off\",\n \"map-pin-pen\",\n \"location-edit\",\n \"map-pin-plus-inside\",\n \"map-pin-plus\",\n \"map-pin-search\",\n \"map-pin-x-inside\",\n \"map-pin-x\",\n \"map-pin\",\n \"map-pinned\",\n \"map-plus\",\n \"map\",\n \"mars-stroke\",\n \"mars\",\n \"martini\",\n \"maximize-2\",\n \"maximize\",\n \"medal\",\n \"megaphone-off\",\n \"megaphone\",\n \"meh\",\n \"memory-stick\",\n \"menu\",\n \"merge\",\n \"message-circle-check\",\n \"message-circle-code\",\n \"message-circle-dashed\",\n \"message-circle-heart\",\n \"message-circle-more\",\n \"message-circle-off\",\n \"message-circle-plus\",\n \"message-circle-question-mark\",\n \"message-circle-question\",\n \"message-circle-reply\",\n \"message-circle-warning\",\n \"message-circle-x\",\n \"message-circle\",\n \"message-square-check\",\n \"message-square-code\",\n \"message-square-dashed\",\n \"message-square-diff\",\n \"message-square-dot\",\n \"message-square-heart\",\n \"message-square-lock\",\n \"message-square-more\",\n \"message-square-off\",\n \"message-square-plus\",\n \"message-square-quote\",\n \"message-square-reply\",\n \"message-square-share\",\n \"message-square-text\",\n \"message-square-warning\",\n \"message-square-x\",\n \"message-square\",\n \"messages-square\",\n \"metronome\",\n \"mic-off\",\n \"mic-vocal\",\n \"mic-2\",\n \"mic\",\n \"microchip\",\n \"microscope\",\n \"microwave\",\n \"milestone\",\n \"milk-off\",\n \"milk\",\n \"minimize-2\",\n \"minimize\",\n \"minus\",\n \"mirror-rectangular\",\n \"mirror-round\",\n \"monitor-check\",\n \"monitor-cloud\",\n \"monitor-cog\",\n \"monitor-dot\",\n \"monitor-down\",\n \"monitor-off\",\n \"monitor-pause\",\n \"monitor-play\",\n \"monitor-smartphone\",\n \"monitor-speaker\",\n \"monitor-stop\",\n \"monitor-up\",\n \"monitor-x\",\n \"monitor\",\n \"moon-star\",\n \"moon\",\n \"motorbike\",\n \"mountain-snow\",\n \"mountain\",\n \"mouse-left\",\n \"mouse-off\",\n \"mouse-pointer-2-off\",\n \"mouse-pointer-2\",\n \"mouse-pointer-ban\",\n \"mouse-pointer-click\",\n \"mouse-pointer\",\n \"mouse-right\",\n \"mouse\",\n \"move-3d\",\n \"move-3-d\",\n \"move-diagonal-2\",\n \"move-diagonal\",\n \"move-down-left\",\n \"move-down-right\",\n \"move-down\",\n \"move-horizontal\",\n \"move-left\",\n \"move-right\",\n \"move-up-left\",\n \"move-up-right\",\n \"move-up\",\n \"move-vertical\",\n \"move\",\n \"music-2\",\n \"music-3\",\n \"music-4\",\n \"music\",\n \"navigation-2-off\",\n \"navigation-2\",\n \"navigation-off\",\n \"navigation\",\n \"network\",\n \"newspaper\",\n \"nfc\",\n \"non-binary\",\n \"notebook-pen\",\n \"notebook-tabs\",\n \"notebook-text\",\n \"notebook\",\n \"notepad-text-dashed\",\n \"notepad-text\",\n \"nut-off\",\n \"nut\",\n \"octagon-alert\",\n \"alert-octagon\",\n \"octagon-minus\",\n \"octagon-pause\",\n \"pause-octagon\",\n \"octagon-x\",\n \"x-octagon\",\n \"octagon\",\n \"omega\",\n \"option\",\n \"orbit\",\n \"origami\",\n \"package-2\",\n \"package-check\",\n \"package-minus\",\n \"package-open\",\n \"package-plus\",\n \"package-search\",\n \"package-x\",\n \"package\",\n \"paint-bucket\",\n \"paint-roller\",\n \"paintbrush-vertical\",\n \"paintbrush-2\",\n \"paintbrush\",\n \"palette\",\n \"panda\",\n \"panel-bottom-close\",\n \"panel-bottom-dashed\",\n \"panel-bottom-inactive\",\n \"panel-bottom-open\",\n \"panel-bottom\",\n \"panel-left-close\",\n \"sidebar-close\",\n \"panel-left-dashed\",\n \"panel-left-inactive\",\n \"panel-left-open\",\n \"sidebar-open\",\n \"panel-left-right-dashed\",\n \"panel-left\",\n \"sidebar\",\n \"panel-right-close\",\n \"panel-right-dashed\",\n \"panel-right-inactive\",\n \"panel-right-open\",\n \"panel-right\",\n \"panel-top-bottom-dashed\",\n \"panel-top-close\",\n \"panel-top-dashed\",\n \"panel-top-inactive\",\n \"panel-top-open\",\n \"panel-top\",\n \"panels-left-bottom\",\n \"panels-right-bottom\",\n \"panels-top-left\",\n \"layout\",\n \"paperclip\",\n \"parentheses\",\n \"parking-meter\",\n \"party-popper\",\n \"pause\",\n \"paw-print\",\n \"pc-case\",\n \"pen-line\",\n \"edit-3\",\n \"pen-off\",\n \"pen-tool\",\n \"pen\",\n \"edit-2\",\n \"pencil-line\",\n \"pencil-off\",\n \"pencil-ruler\",\n \"pencil\",\n \"pentagon\",\n \"percent\",\n \"person-standing\",\n \"philippine-peso\",\n \"phone-call\",\n \"phone-forwarded\",\n \"phone-incoming\",\n \"phone-missed\",\n \"phone-off\",\n \"phone-outgoing\",\n \"phone\",\n \"pi\",\n \"piano\",\n \"pickaxe\",\n \"picture-in-picture-2\",\n \"picture-in-picture\",\n \"piggy-bank\",\n \"pilcrow-left\",\n \"pilcrow-right\",\n \"pilcrow\",\n \"pill-bottle\",\n \"pill\",\n \"pin-off\",\n \"pin\",\n \"pipette\",\n \"pizza\",\n \"plane-landing\",\n \"plane-takeoff\",\n \"plane\",\n \"play\",\n \"plug-2\",\n \"plug-zap\",\n \"plug-zap-2\",\n \"plug\",\n \"plus\",\n \"pocket-knife\",\n \"podcast\",\n \"pointer-off\",\n \"pointer\",\n \"popcorn\",\n \"popsicle\",\n \"pound-sterling\",\n \"power-off\",\n \"power\",\n \"presentation\",\n \"printer-check\",\n \"printer-x\",\n \"printer\",\n \"projector\",\n \"proportions\",\n \"puzzle\",\n \"pyramid\",\n \"qr-code\",\n \"quote\",\n \"rabbit\",\n \"radar\",\n \"radiation\",\n \"radical\",\n \"radio-off\",\n \"radio-receiver\",\n \"radio-tower\",\n \"radio\",\n \"radius\",\n \"rainbow\",\n \"rat\",\n \"ratio\",\n \"receipt-cent\",\n \"receipt-euro\",\n \"receipt-indian-rupee\",\n \"receipt-japanese-yen\",\n \"receipt-pound-sterling\",\n \"receipt-russian-ruble\",\n \"receipt-swiss-franc\",\n \"receipt-text\",\n \"receipt-turkish-lira\",\n \"receipt\",\n \"rectangle-circle\",\n \"rectangle-ellipsis\",\n \"form-input\",\n \"rectangle-goggles\",\n \"rectangle-horizontal\",\n \"rectangle-vertical\",\n \"recycle\",\n \"redo-2\",\n \"redo-dot\",\n \"redo\",\n \"refresh-ccw-dot\",\n \"refresh-ccw\",\n \"refresh-cw-off\",\n \"refresh-cw\",\n \"refrigerator\",\n \"regex\",\n \"remove-formatting\",\n \"repeat-1\",\n \"repeat-2\",\n \"repeat\",\n \"replace-all\",\n \"replace\",\n \"reply-all\",\n \"reply\",\n \"rewind\",\n \"ribbon\",\n \"road\",\n \"rocket\",\n \"rocking-chair\",\n \"roller-coaster\",\n \"rose\",\n \"rotate-3d\",\n \"rotate-3-d\",\n \"rotate-ccw-key\",\n \"rotate-ccw-square\",\n \"rotate-ccw\",\n \"rotate-cw-square\",\n \"rotate-cw\",\n \"route-off\",\n \"route\",\n \"router\",\n \"rows-2\",\n \"rows\",\n \"rows-3\",\n \"panels-top-bottom\",\n \"rows-4\",\n \"rss\",\n \"ruler-dimension-line\",\n \"ruler\",\n \"russian-ruble\",\n \"sailboat\",\n \"salad\",\n \"sandwich\",\n \"satellite-dish\",\n \"satellite\",\n \"saudi-riyal\",\n \"save-all\",\n \"save-off\",\n \"save\",\n \"scale-3d\",\n \"scale-3-d\",\n \"scale\",\n \"scaling\",\n \"scan-barcode\",\n \"scan-eye\",\n \"scan-face\",\n \"scan-heart\",\n \"scan-line\",\n \"scan-qr-code\",\n \"scan-search\",\n \"scan-text\",\n \"scan\",\n \"school\",\n \"scissors-line-dashed\",\n \"scissors\",\n \"scooter\",\n \"screen-share-off\",\n \"screen-share\",\n \"scroll-text\",\n \"scroll\",\n \"search-alert\",\n \"search-check\",\n \"search-code\",\n \"search-slash\",\n \"search-x\",\n \"search\",\n \"section\",\n \"send-horizontal\",\n \"send-horizonal\",\n \"send-to-back\",\n \"send\",\n \"separator-horizontal\",\n \"separator-vertical\",\n \"server-cog\",\n \"server-crash\",\n \"server-off\",\n \"server\",\n \"settings-2\",\n \"settings\",\n \"shapes\",\n \"share-2\",\n \"share\",\n \"sheet\",\n \"shell\",\n \"shelving-unit\",\n \"shield-alert\",\n \"shield-ban\",\n \"shield-check\",\n \"shield-cog-corner\",\n \"shield-cog\",\n \"shield-ellipsis\",\n \"shield-half\",\n \"shield-minus\",\n \"shield-off\",\n \"shield-plus\",\n \"shield-question-mark\",\n \"shield-question\",\n \"shield-user\",\n \"shield-x\",\n \"shield-close\",\n \"shield\",\n \"ship-wheel\",\n \"ship\",\n \"shirt\",\n \"shopping-bag\",\n \"shopping-basket\",\n \"shopping-cart\",\n \"shovel\",\n \"shower-head\",\n \"shredder\",\n \"shrimp\",\n \"shrink\",\n \"shrub\",\n \"shuffle\",\n \"sigma\",\n \"signal-high\",\n \"signal-low\",\n \"signal-medium\",\n \"signal-zero\",\n \"signal\",\n \"signature\",\n \"signpost-big\",\n \"signpost\",\n \"siren\",\n \"skip-back\",\n \"skip-forward\",\n \"skull\",\n \"slash\",\n \"slice\",\n \"sliders-horizontal\",\n \"sliders-vertical\",\n \"sliders\",\n \"smartphone-charging\",\n \"smartphone-nfc\",\n \"smartphone\",\n \"smile-plus\",\n \"smile\",\n \"snail\",\n \"snowflake\",\n \"soap-dispenser-droplet\",\n \"sofa\",\n \"solar-panel\",\n \"soup\",\n \"space\",\n \"spade\",\n \"sparkle\",\n \"sparkles\",\n \"stars\",\n \"speaker\",\n \"speech\",\n \"spell-check-2\",\n \"spell-check\",\n \"spline-pointer\",\n \"spline\",\n \"split\",\n \"spool\",\n \"sport-shoe\",\n \"spotlight\",\n \"spray-can\",\n \"sprout\",\n \"square-activity\",\n \"activity-square\",\n \"square-arrow-down-left\",\n \"arrow-down-left-square\",\n \"square-arrow-down-right\",\n \"arrow-down-right-square\",\n \"square-arrow-down\",\n \"arrow-down-square\",\n \"square-arrow-left\",\n \"arrow-left-square\",\n \"square-arrow-out-down-left\",\n \"arrow-down-left-from-square\",\n \"square-arrow-out-down-right\",\n \"arrow-down-right-from-square\",\n \"square-arrow-out-up-left\",\n \"arrow-up-left-from-square\",\n \"square-arrow-out-up-right\",\n \"arrow-up-right-from-square\",\n \"square-arrow-right-enter\",\n \"square-arrow-right-exit\",\n \"square-arrow-right\",\n \"arrow-right-square\",\n \"square-arrow-up-left\",\n \"arrow-up-left-square\",\n \"square-arrow-up-right\",\n \"arrow-up-right-square\",\n \"square-arrow-up\",\n \"arrow-up-square\",\n \"square-asterisk\",\n \"asterisk-square\",\n \"square-bottom-dashed-scissors\",\n \"scissors-square-dashed-bottom\",\n \"square-centerline-dashed-horizontal\",\n \"flip-horizontal\",\n \"square-centerline-dashed-vertical\",\n \"flip-vertical\",\n \"square-chart-gantt\",\n \"gantt-chart-square\",\n \"square-gantt-chart\",\n \"square-check-big\",\n \"check-square\",\n \"square-check\",\n \"check-square-2\",\n \"square-chevron-down\",\n \"chevron-down-square\",\n \"square-chevron-left\",\n \"chevron-left-square\",\n \"square-chevron-right\",\n \"chevron-right-square\",\n \"square-chevron-up\",\n \"chevron-up-square\",\n \"square-code\",\n \"code-square\",\n \"square-dashed-bottom-code\",\n \"square-dashed-bottom\",\n \"square-dashed-kanban\",\n \"kanban-square-dashed\",\n \"square-dashed-mouse-pointer\",\n \"mouse-pointer-square-dashed\",\n \"square-dashed-text\",\n \"text-selection\",\n \"text-select\",\n \"square-dashed-top-solid\",\n \"square-dashed\",\n \"box-select\",\n \"square-divide\",\n \"divide-square\",\n \"square-dot\",\n \"dot-square\",\n \"square-equal\",\n \"equal-square\",\n \"square-function\",\n \"function-square\",\n \"square-kanban\",\n \"kanban-square\",\n \"square-library\",\n \"library-square\",\n \"square-m\",\n \"m-square\",\n \"square-menu\",\n \"menu-square\",\n \"square-minus\",\n \"minus-square\",\n \"square-mouse-pointer\",\n \"inspect\",\n \"square-parking-off\",\n \"parking-square-off\",\n \"square-parking\",\n \"parking-square\",\n \"square-pause\",\n \"square-pen\",\n \"pen-box\",\n \"edit\",\n \"pen-square\",\n \"square-percent\",\n \"percent-square\",\n \"square-pi\",\n \"pi-square\",\n \"square-pilcrow\",\n \"pilcrow-square\",\n \"square-play\",\n \"play-square\",\n \"square-plus\",\n \"plus-square\",\n \"square-power\",\n \"power-square\",\n \"square-radical\",\n \"square-round-corner\",\n \"square-scissors\",\n \"scissors-square\",\n \"square-sigma\",\n \"sigma-square\",\n \"square-slash\",\n \"slash-square\",\n \"square-split-horizontal\",\n \"split-square-horizontal\",\n \"square-split-vertical\",\n \"split-square-vertical\",\n \"square-square\",\n \"square-stack\",\n \"square-star\",\n \"square-stop\",\n \"square-terminal\",\n \"terminal-square\",\n \"square-user-round\",\n \"user-square-2\",\n \"square-user\",\n \"user-square\",\n \"square-x\",\n \"x-square\",\n \"square\",\n \"squares-exclude\",\n \"squares-intersect\",\n \"squares-subtract\",\n \"squares-unite\",\n \"squircle-dashed\",\n \"squircle\",\n \"squirrel\",\n \"stamp\",\n \"star-half\",\n \"star-off\",\n \"star\",\n \"step-back\",\n \"step-forward\",\n \"stethoscope\",\n \"sticker\",\n \"sticky-note\",\n \"stone\",\n \"store\",\n \"stretch-horizontal\",\n \"stretch-vertical\",\n \"strikethrough\",\n \"subscript\",\n \"sun-dim\",\n \"sun-medium\",\n \"sun-moon\",\n \"sun-snow\",\n \"sun\",\n \"sunrise\",\n \"sunset\",\n \"superscript\",\n \"swatch-book\",\n \"swiss-franc\",\n \"switch-camera\",\n \"sword\",\n \"swords\",\n \"syringe\",\n \"table-2\",\n \"table-cells-merge\",\n \"table-cells-split\",\n \"table-columns-split\",\n \"table-of-contents\",\n \"table-properties\",\n \"table-rows-split\",\n \"table\",\n \"tablet-smartphone\",\n \"tablet\",\n \"tablets\",\n \"tag\",\n \"tags\",\n \"tally-1\",\n \"tally-2\",\n \"tally-3\",\n \"tally-4\",\n \"tally-5\",\n \"tangent\",\n \"target\",\n \"telescope\",\n \"tent-tree\",\n \"tent\",\n \"terminal\",\n \"test-tube-diagonal\",\n \"test-tube-2\",\n \"test-tube\",\n \"test-tubes\",\n \"text-align-center\",\n \"align-center\",\n \"text-align-end\",\n \"align-right\",\n \"text-align-justify\",\n \"align-justify\",\n \"text-align-start\",\n \"text\",\n \"align-left\",\n \"text-cursor-input\",\n \"text-cursor\",\n \"text-initial\",\n \"letter-text\",\n \"text-quote\",\n \"text-search\",\n \"text-wrap\",\n \"wrap-text\",\n \"theater\",\n \"thermometer-snowflake\",\n \"thermometer-sun\",\n \"thermometer\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"ticket-check\",\n \"ticket-minus\",\n \"ticket-percent\",\n \"ticket-plus\",\n \"ticket-slash\",\n \"ticket-x\",\n \"ticket\",\n \"tickets-plane\",\n \"tickets\",\n \"timer-off\",\n \"timer-reset\",\n \"timer\",\n \"toggle-left\",\n \"toggle-right\",\n \"toilet\",\n \"tool-case\",\n \"toolbox\",\n \"tornado\",\n \"torus\",\n \"touchpad-off\",\n \"touchpad\",\n \"towel-rack\",\n \"tower-control\",\n \"toy-brick\",\n \"tractor\",\n \"traffic-cone\",\n \"train-front-tunnel\",\n \"train-front\",\n \"train-track\",\n \"tram-front\",\n \"train\",\n \"transgender\",\n \"trash-2\",\n \"trash\",\n \"tree-deciduous\",\n \"tree-palm\",\n \"palmtree\",\n \"tree-pine\",\n \"trees\",\n \"trending-down\",\n \"trending-up-down\",\n \"trending-up\",\n \"triangle-alert\",\n \"alert-triangle\",\n \"triangle-dashed\",\n \"triangle-right\",\n \"triangle\",\n \"trophy\",\n \"truck-electric\",\n \"truck\",\n \"turkish-lira\",\n \"turntable\",\n \"turtle\",\n \"tv-minimal-play\",\n \"tv-minimal\",\n \"tv-2\",\n \"tv\",\n \"type-outline\",\n \"type\",\n \"umbrella-off\",\n \"umbrella\",\n \"underline\",\n \"undo-2\",\n \"undo-dot\",\n \"undo\",\n \"unfold-horizontal\",\n \"unfold-vertical\",\n \"ungroup\",\n \"university\",\n \"school-2\",\n \"unlink-2\",\n \"unlink\",\n \"unplug\",\n \"upload\",\n \"usb\",\n \"user-check\",\n \"user-cog\",\n \"user-key\",\n \"user-lock\",\n \"user-minus\",\n \"user-pen\",\n \"user-plus\",\n \"user-round-check\",\n \"user-check-2\",\n \"user-round-cog\",\n \"user-cog-2\",\n \"user-round-key\",\n \"user-round-minus\",\n \"user-minus-2\",\n \"user-round-pen\",\n \"user-round-plus\",\n \"user-plus-2\",\n \"user-round-search\",\n \"user-round-x\",\n \"user-x-2\",\n \"user-round\",\n \"user-2\",\n \"user-search\",\n \"user-star\",\n \"user-x\",\n \"user\",\n \"users-round\",\n \"users-2\",\n \"users\",\n \"utensils-crossed\",\n \"fork-knife-crossed\",\n \"utensils\",\n \"fork-knife\",\n \"utility-pole\",\n \"van\",\n \"variable\",\n \"vault\",\n \"vector-square\",\n \"vegan\",\n \"venetian-mask\",\n \"venus-and-mars\",\n \"venus\",\n \"vibrate-off\",\n \"vibrate\",\n \"video-off\",\n \"video\",\n \"videotape\",\n \"view\",\n \"voicemail\",\n \"volleyball\",\n \"volume-1\",\n \"volume-2\",\n \"volume-off\",\n \"volume-x\",\n \"volume\",\n \"vote\",\n \"wallet-cards\",\n \"wallet-minimal\",\n \"wallet-2\",\n \"wallet\",\n \"wallpaper\",\n \"wand-sparkles\",\n \"wand-2\",\n \"wand\",\n \"warehouse\",\n \"washing-machine\",\n \"watch\",\n \"waves-arrow-down\",\n \"waves-arrow-up\",\n \"waves-ladder\",\n \"waves\",\n \"waypoints\",\n \"webcam\",\n \"webhook-off\",\n \"webhook\",\n \"weight-tilde\",\n \"weight\",\n \"wheat-off\",\n \"wheat\",\n \"whole-word\",\n \"wifi-cog\",\n \"wifi-high\",\n \"wifi-low\",\n \"wifi-off\",\n \"wifi-pen\",\n \"wifi-sync\",\n \"wifi-zero\",\n \"wifi\",\n \"wind-arrow-down\",\n \"wind\",\n \"wine-off\",\n \"wine\",\n \"workflow\",\n \"worm\",\n \"wrench\",\n \"x-line-top\",\n \"x\",\n \"zap-off\",\n \"zap\",\n \"zodiac-aquarius\",\n \"zodiac-aries\",\n \"zodiac-cancer\",\n \"zodiac-capricorn\",\n \"zodiac-gemini\",\n \"zodiac-leo\",\n \"zodiac-libra\",\n \"zodiac-ophiuchus\",\n \"zodiac-pisces\",\n \"zodiac-sagittarius\",\n \"zodiac-scorpio\",\n \"zodiac-taurus\",\n \"zodiac-virgo\",\n \"zoom-in\",\n \"zoom-out\",\n]);\n\nexport const LAYOUT_SECTION_ICON_SET: ReadonlySet<string> = new Set(LAYOUT_SECTION_ICONS);\nexport type LayoutSectionIcon = string;\n","/** Stable identifiers used by every project and page layout document. */\nexport const PAGE_CONTENT_ANCHOR_ID = \"page-content\" as const;\nexport const NAVIGATION_SECTION_ID = \"navigation\" as const;\nexport const FOOTER_SECTION_ID = \"footer\" as const;\n\n/** Locked transport/validation set shared by authoring surfaces and the server. */\nexport {\n LAYOUT_SECTION_ICONS,\n LAYOUT_SECTION_ICON_SET,\n type LayoutSectionIcon,\n} from \"./layout-lucide-icons.js\";\nimport type { LayoutSectionIcon } from \"./layout-lucide-icons.js\";\n\nexport type LayoutZone = \"above-page-content\" | \"below-page-content\";\nexport type ReservedLayoutSection = \"navigation\" | \"footer\";\n\nexport type LayoutScalarFieldType =\n | \"text\"\n | \"longtext\"\n | \"richtext\"\n | \"number\"\n | \"toggle\"\n | \"date\"\n | \"image\"\n | \"file\"\n | \"link\"\n | \"email\"\n | \"phone\"\n | \"select\"\n | \"color\"\n | \"json\"\n | \"reference\"\n | \"multi-reference\";\n\nexport type LayoutFieldType = LayoutScalarFieldType | \"group\" | \"repeater\";\n\n/** A recursive, stable-ID field contract shared by Sections and variant inputs. */\nexport interface LayoutFieldDefinition {\n id: string;\n slug: string;\n label: string;\n type: LayoutFieldType;\n required?: boolean;\n defaultValue?: unknown;\n config?: {\n options?: Array<{ label: string; value: string }>;\n referenceModelId?: string;\n minItems?: number;\n maxItems?: number;\n } & Record<string, unknown>;\n /** Required for group/repeater; forbidden for scalar fields. */\n fields?: LayoutFieldDefinition[];\n}\n\n/** The canonical public input contract all variants in a group implement. */\nexport type CanonicalInputDefinition = LayoutFieldDefinition;\n\n/** Maps one canonical input onto one or more internal component prop paths. */\nexport interface VariantInputMapping {\n inputId: string;\n targets: Array<{ blockId: string; path: string }>;\n}\n\nexport interface ComponentVariantGroup {\n id: string;\n workspaceId: string;\n projectId?: string | null;\n name: string;\n slug: string;\n canonicalInputs: CanonicalInputDefinition[];\n status: \"draft\" | \"published\";\n}\n\nexport interface LayoutFieldItem {\n id: string;\n kind: \"field\";\n fieldId: string;\n}\n\nexport interface LayoutComponentItem {\n id: string;\n kind: \"component\";\n componentId: string;\n variantGroupId?: string;\n bindings: Array<{ inputId: string; fieldId: string }>;\n literalValues?: Record<string, unknown>;\n}\n\nexport type LayoutSectionItem = LayoutFieldItem | LayoutComponentItem;\n\nexport interface LayoutSection {\n id: string;\n name: string;\n slug: string;\n icon: string;\n zone: LayoutZone;\n orderKey: string;\n reserved?: ReservedLayoutSection;\n fields: LayoutFieldDefinition[];\n items: LayoutSectionItem[];\n /**\n * The language this Section is a VARIANT for — BCP-47, lowercase (`fr`, `pt-br`).\n *\n * A localized site renders ONE header per route, not two: `/fr/*` shows the French header in\n * the slot the base header holds everywhere else. So a variant is not a Section of its own in\n * the render order. It never renders unless a resolver is handed its locale, and then it takes\n * its base's place — zone, order and reserved slot included — rather than sitting beside it.\n * Set together with `variantOf`; `validateLayout` names every way the pair can be malformed.\n */\n locale?: string;\n /** The stable id of the base Section this variant replaces on routes in `locale`. */\n variantOf?: string;\n}\n\nexport interface LayoutStructureDocument {\n version: 1;\n pageContentAnchor: { id: typeof PAGE_CONTENT_ANCHOR_ID };\n sections: LayoutSection[];\n}\n\nexport interface LayoutDataDocument {\n version: 1;\n sections: Record<string, { fields: Record<string, unknown> }>;\n}\n\nexport type PageLayoutOverrideState =\n | \"inherit\"\n | \"override-content\"\n | \"customize-structure\"\n | \"disable\";\n\nexport interface PageSectionPlacement {\n zone: LayoutZone;\n afterSectionId?: string;\n beforeSectionId?: string;\n localOrderKey: string;\n}\n\nexport type PageLayoutSectionOverride =\n | { sectionId: string; state: \"inherit\" }\n | { sectionId: string; state: \"override-content\"; values: Record<string, unknown> }\n | {\n sectionId: string;\n state: \"customize-structure\";\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n /** Retained when the inherited Section is later deleted. */\n placement: PageSectionPlacement;\n }\n | { sectionId: string; state: \"disable\" };\n\nexport interface PageOnlyLayoutSection {\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n placement: PageSectionPlacement;\n}\n\nexport type PageLayoutSectionStructureOverride =\n | { sectionId: string; state: \"inherit\" }\n | { sectionId: string; state: \"override-content\" }\n | { sectionId: string; state: \"customize-structure\"; section: LayoutSection; placement: PageSectionPlacement }\n | { sectionId: string; state: \"disable\" };\n\n/** Persisted in pages.layout_override_structure_json. */\nexport interface PageLayoutOverrideStructureDocument {\n version: 1;\n sections: PageLayoutSectionStructureOverride[];\n pageOnlySections: Array<{ section: LayoutSection; placement: PageSectionPlacement }>;\n}\n\n/** Persisted independently so values can be patched without rewriting structure. */\nexport interface PageLayoutOverrideDataDocument {\n version: 1;\n sections: Record<string, { fields: Record<string, unknown> }>;\n pageOnlySections: Record<string, { fields: Record<string, unknown> }>;\n}\n\n/** Canonical in-memory form consumed by the pure resolver. */\nexport interface PageLayoutOverrideDocument {\n version: 1;\n sections: PageLayoutSectionOverride[];\n pageOnlySections: PageOnlyLayoutSection[];\n}\n\n/** Canonical, discriminated Management/MCP authoring transport. Authority is derived from type. */\nexport type ManagementLayoutCommand =\n | { type: \"set-section-values\"; sectionId: string; values: Record<string, unknown> }\n | { type: \"set-field-value\"; sectionId: string; fieldId: string; value: unknown }\n | { type: \"add-component\"; sectionId: string; componentId: string; variantGroupId?: string; bindings?: LayoutComponentItem[\"bindings\"]; literalValues?: Record<string, unknown> }\n | { type: \"remove-item\"; sectionId: string; itemId: string }\n | { type: \"move-component\"; sectionId: string; itemId: string; index: number }\n | { type: \"move-item\"; sectionId: string; itemId: string; index: number }\n | { type: \"swap-component-variant\"; sectionId: string; itemId: string; componentId: string }\n | { type: \"set-page-state\"; sectionId: string; state: PageLayoutOverrideState | \"reset\" }\n | { type: \"set-section-state\"; sectionId: string; state: PageLayoutOverrideState | \"reset\" }\n | { type: \"add-section\"; name: string; icon: LayoutSectionIcon; zone: \"before_page\" | \"after_page\" }\n | { type: \"restore-section\"; section: LayoutSection; data: { fields: Record<string, unknown> }; placement?: PageSectionPlacement }\n | { type: \"update-section\"; sectionId: string; name?: string; icon?: LayoutSectionIcon; slug?: string; zone?: LayoutZone; orderKey?: string }\n | { type: \"remove-section\"; sectionId: string }\n | { type: \"move-section\"; sectionId: string; afterId?: string | null; beforeId?: string | null }\n | { type: \"add-field\"; sectionId: string; parentFieldId?: string; field?: LayoutFieldDefinition; fieldType?: LayoutFieldType }\n | { type: \"update-field\"; sectionId: string; fieldId: string; patch: Partial<Omit<LayoutFieldDefinition, \"id\">> }\n | { type: \"remove-field\"; sectionId: string; fieldId: string }\n | { type: \"move-field\"; sectionId: string; itemId: string; index: number }\n | { type: \"set-bindings\"; sectionId: string; itemId: string; bindings: LayoutComponentItem[\"bindings\"]; literalValues?: Record<string, unknown> };\n\nexport type ResolvedLayoutNode =\n | { kind: \"page-content\"; id: typeof PAGE_CONTENT_ANCHOR_ID }\n | {\n kind: \"section\";\n id: string;\n section: LayoutSection;\n data: { fields: Record<string, unknown> };\n source: \"inherit\" | \"override-content\" | \"customize-structure\" | \"page-only\" | \"detached\";\n };\n\nexport interface DeliveredLayout {\n version: 1;\n nodes: Array<\n | { kind: \"page-content\"; id: typeof PAGE_CONTENT_ANCHOR_ID }\n | { kind: \"section\"; id: string; slug: string; name: string; source: Extract<ResolvedLayoutNode, { kind: \"section\" }>[\"source\"] }\n >;\n sections: Record<string, {\n id: string;\n slug: string;\n name: string;\n /**\n * Present ONLY on a locale variant (`LayoutSection.locale`/`variantOf`), so a base entry is\n * byte-identical to what it was before variants existed. The Global Layout delivers every\n * variant under its own slug beside the bases; a page delivers the variant its route's\n * locale swapped in, under the SLOT's slug — the one its `nodes` entry names.\n */\n locale?: string;\n variantOf?: string;\n fields: Record<string, unknown>;\n items: Array<\n | { id: string; kind: \"field\"; fieldId: string; value: unknown }\n | {\n id: string;\n kind: \"component\";\n componentId: string;\n variantGroupId?: string;\n canonicalInputs: CanonicalInputDefinition[];\n bindings: LayoutComponentItem[\"bindings\"];\n canonicalValues: Record<string, unknown>;\n resolvedProps: Record<string, unknown>;\n /**\n * `prop.key` → canonical `inputId` — the relation `resolvedProps` consumes and throws\n * away (`output[prop.key] = canonicalValues[mapping.inputId]`).\n *\n * Without it a renderer holds a component prop key and NO address: `logoAlt`/`links`/\n * `cta` are the component's own bare keys, and nothing relates them back to the layout\n * field a write must land on. With it the chain closes — `prop.key` → `inputId` →\n * (`bindings`, already delivered above) → `fieldId` → `set-field-value(sectionId,\n * fieldId)`. That is what makes global chrome click-to-edit (FLO-1179).\n *\n * Additive and always present (`{}` when the item has no variant mappings), so an\n * older consumer that ignores it is byte-identical to before.\n */\n propInputs: Record<string, string>;\n blocks: unknown[];\n }\n >;\n }>;\n}\n","/**\n * WHERE an element was on a built page, so a later pass can find it again.\n *\n * This lives in the shared package because BOTH ends of the comparison have to spell an address\n * the same way: the backend derives it from a JSDOM tree at import time, the dashboard computes\n * it from a live iframe tree when a person clicks an unbound element. Two implementations of\n * \"the ancestor chain down from the nearest landmark\" is one implementation too many — the first\n * time they disagree by one tag, a click binds the wrong element.\n *\n * The DOM is typed STRUCTURALLY (`ElementLike`, `LandmarkHost`) so this package needs no DOM lib\n * and stays importable from a node-only build.\n */\n\n/** The landmark tags an address is anchored at, as one CSS selector and as one tag set. */\nexport const LANDMARK_SELECTOR = \"header,nav,footer\";\nconst LANDMARK_TAGS = new Set([\"HEADER\", \"NAV\", \"FOOTER\"]);\n\n/**\n * The THIRD region — a modal, a cookie banner, a pop-up — behind a per-project gate.\n *\n * A `<dialog>` or a `[role=\"dialog\"]` sits at BODY level, outside every landmark, so a banner\n * byte-identical on twelve routes derived twelve copies of itself. It is NOT a stop for\n * `locatorFor`: `region` already names which dialog an element is in, and a second gated rule\n * about where the ancestor chain ends would make the same element's locator differ between a\n * project that derived it as chrome and one that did not.\n */\nexport const DIALOG_SELECTOR = 'dialog,[role=\"dialog\"]';\n\n/**\n * The page's own content. A landmark INSIDE it is the page's, not the site's — under the v2\n * grammar only. @see isChromeLandmark\n */\nexport const MAIN_SELECTOR = 'main,[role=\"main\"]';\n\n/**\n * Which address grammar a page was derived in — the two per-project gates that change what a\n * REGION is. Both off is the original grammar, and `{}` must keep meaning exactly that: every\n * locator stored before a gate existed was spelled in it.\n *\n * `dialogs` — a `<dialog>`/`[role=\"dialog\"]` is a region of its own (the chrome grammar).\n * `landmarks` — landmark grammar v2. @see isChromeLandmark, and `landmarkRegions` for rule (ii).\n */\nexport interface LocatorGrammar {\n dialogs?: boolean;\n landmarks?: boolean;\n}\n\n/**\n * Is this element a landmark that holds SITE chrome — a header, nav or footer that earns a region\n * and a `nav-`/`footer-` key?\n *\n * 🔴 A LANDMARK INSIDE `<main>` IS PAGE COPY. HTML allows a `<nav>` anywhere, and a built page\n * uses one for whatever it likes: a features band's `<nav role=\"tablist\">`, a docs page's\n * prev/next pager in a `<footer>` inside the article. Counted as chrome, the home page's tab list\n * minted nine `nav-` keys that are really the section's copy — keys the Layout's Header section\n * claims by prefix the moment two routes render that band alike, and that componentize reads as\n * chrome everywhere else. The `<main>` is the page saying \"everything in here is mine\", and v2\n * believes it.\n *\n * Gated (`landmarks`), because it moves keys AND regions: a project whose pages were derived\n * with that tab list as `nav#0` holds values under `nav-…` keys, and re-reading them as section\n * copy would strand every one of them.\n *\n * EXCEPT A `<main>` THAT IS THE PAGE SHELL. Plenty of layouts wrap the whole page in it —\n * `<main><Navbar/>{children}<Footer/></main>`, or `role=\"main\"` on the app root — and there the\n * fence would take the site's real masthead and footer away: no region, no `nav-`/`footer-` keys,\n * nothing for the Layout to claim, and a copy of the nav minted into every route. A `<main>` that\n * OPENS with a header/nav and CLOSES with a footer is framing the site, not holding page copy, so\n * its own direct-child landmarks stay chrome. A landmark deeper inside it (a section's tab list)\n * is still page copy, and a `<main>` that only opens with a header (a changelog's title) still\n * fences it.\n */\nexport function isChromeLandmark(\n el: { tagName: string; parentElement: { closest(selectors: string): unknown } | null },\n landmarks: boolean,\n): boolean {\n if (!LANDMARK_TAGS.has(el.tagName)) return false;\n if (!landmarks) return true;\n const fence = el.parentElement?.closest(MAIN_SELECTOR) as ShellCandidate | null | undefined;\n return !fence || ((fence as unknown) === el.parentElement && isPageShell(fence));\n}\n\n/** Tags a framework appends around content that say nothing about the page's shape. */\nconst INERT_TAGS = new Set([\"SCRIPT\", \"STYLE\", \"TEMPLATE\", \"NOSCRIPT\", \"LINK\"]);\ntype ShellCandidate = { children: ArrayLike<{ tagName: string }> };\n\n/** Opens with the masthead (header/nav) and closes with the footer, ignoring inert tags. */\nfunction isPageShell(main: ShellCandidate): boolean {\n const kids = Array.from(main.children).filter((k) => !INERT_TAGS.has(k.tagName));\n const first = kids[0]?.tagName;\n return (first === \"HEADER\" || first === \"NAV\") && kids.length > 1 && kids[kids.length - 1]!.tagName === \"FOOTER\";\n}\n\n/**\n * Best-effort by construction — built-DOM positions do not survive component expansion or\n * conditional rendering — so a consumer that finds no exact match, or finds several, falls back\n * to ambiguity rather than to a guess. The ancestor chain is compared EXACTLY (`atLocator`,\n * annotate-static.ts): a chain that merely contains the stored one is a different element.\n */\nexport interface DerivedLocator {\n /** The landmark it lives in — `header#0`, `nav#1`, `footer#0` — or null for the page body. */\n region: string | null;\n /** Tag names from the nearest landmark (or `<body>`) down to the element's parent. */\n ancestors: string[];\n /** Its index among its parent's element children. */\n siblingIndex: number;\n /**\n * The element's own lower-cased tag name.\n *\n * The cheapest fact that separates two elements a chain-and-index pair calls identical — a\n * `<h2>` and the `<a>` beside it in a rebuilt layout — and the only one a resolver can use to\n * NARROW its candidate list before comparing anything. Absent on locators stored before it\n * existed; a comparer must treat a missing tag as \"matches\".\n */\n tag: string;\n /**\n * The repeater row this value belongs to.\n *\n * On a leaf's field DEFINITION the index is 0 — one definition serves every row — and the\n * brief overrides it with the row it is actually describing (`cards[2].title` → index 2).\n */\n repeat?: { groupKey: string; index: number };\n}\n\n/** The DOM surface `locatorFor` reads. `Element` satisfies it; so does a plain object. */\nexport interface ElementLike {\n tagName: string;\n parentElement: ElementLike | null;\n children: ArrayLike<ElementLike>;\n}\n\n/**\n * `ElementLike` plus the one DOM call the v2 chain needs — whether a landmark sits inside\n * `<main>` (@see isChromeLandmark). `Element` satisfies it. Only the backend derives in v2, so\n * the plain-object surface above stays all the original grammar asks for.\n */\nexport interface LandmarkChainElement extends ElementLike {\n parentElement: LandmarkChainElement | null;\n closest(selectors: string): unknown;\n}\n\n/**\n * The structural address of one element: its ancestor tags and its position among its siblings.\n *\n * Stops at the nearest LANDMARK because that is where a page's structure stops being comparable\n * — a header's internals are the same on every route while the body's are not — and `region`\n * already names which landmark it was.\n *\n * 🔴 UNDER v2 (`landmarks`) THE CHAIN STOPS ONLY AT A CHROME LANDMARK. The stop is only sound\n * because `region` names the landmark it stopped at, and a `<nav>` inside `<main>` names no\n * region under v2. Stopping there anyway threw away the only structure that told two of them\n * apart: two sections' `<nav><a>` both addressed as `{region: null, ancestors: [], 0, a}` — the\n * address of a link sitting directly in `<body>` — where the original grammar said `nav#0` and\n * `nav#1`. So the chain runs on to `<body>` like every other element of the page's copy. An\n * element outside every in-`<main>` landmark stops exactly where it always did, which is what\n * keeps every locator whose region v2 did not move byte-identical. Two landmarks of one shape in\n * two sections of one shape still collide, as two cards always have; every reader refuses an\n * address that names several elements (`atLocator`, the pin replay, `bindElement`).\n */\nexport function locatorFor(el: ElementLike, region: string | null): DerivedLocator;\nexport function locatorFor(el: LandmarkChainElement, region: string | null, landmarks: boolean): DerivedLocator;\nexport function locatorFor(el: ElementLike, region: string | null, landmarks = false): DerivedLocator {\n const ancestors: string[] = [];\n for (\n let parent = el.parentElement;\n // The cast is the overloads' promise: `landmarks` is only ever true for a `LandmarkChainElement`,\n // and `isChromeLandmark` never reads past the tag with it false.\n parent && parent.tagName !== \"BODY\" && !isChromeLandmark(parent as LandmarkChainElement, landmarks);\n parent = parent.parentElement\n ) {\n ancestors.unshift(parent.tagName.toLowerCase());\n }\n const siblings = el.parentElement ? Array.from(el.parentElement.children) : [];\n return {\n region,\n ancestors,\n siblingIndex: Math.max(siblings.indexOf(el), 0),\n tag: el.tagName.toLowerCase(),\n };\n}\n\n/** The DOM surface `landmarkRegions` reads of each element it considers. */\nexport interface LandmarkElement {\n tagName: string;\n parentElement: { closest(selectors: string): unknown } | null;\n matches(selectors: string): boolean;\n}\n\n/**\n * A page's landmark regions: the OUTERMOST `header`/`nav`/`footer` elements, in document order.\n *\n * Outermost, because a `<nav>` inside a `<header>` is one region a visitor sees as one thing —\n * and promoting the two separately would let a site's masthead be half layout, half page.\n *\n * Under the v2 grammar (`landmarks`) regions may NEST, in exactly one way — a dialog inside a\n * landmark is its own region — so a consumer must ask {@link regionOf} which one an element is\n * in, never take the first region that contains it.\n */\nexport function landmarkRegions<E extends LandmarkElement>(\n doc: { querySelectorAll(selectors: string): Iterable<E> },\n /**\n * Count a dialog as a region too — the per-project chrome grammar.\n *\n * OFF by default, and not merely for symmetry: a region name is part of every field's LOCATOR,\n * and a project whose stored locators say `region: null` for a modal's copy must keep being\n * read the same way.\n */\n dialogs = false,\n /**\n * Landmark grammar v2 — the per-project `landmarks` gate. Two rules change, both OFF by default\n * for the reason `dialogs` is:\n *\n * (i) a landmark inside `<main>`/`[role=\"main\"]` is no region. @see isChromeLandmark\n * (ii) a dialog inside a landmark is its OWN region. The auth modals a masthead carries are\n * the commonest dialogs on the web, and outermost-only folded all three into `header#0`:\n * their copy promoted as the header's, and the header could only promote when every\n * route's modals did too. A dialog still folds into an enclosing DIALOG, and a landmark\n * into anything enclosing it — nothing else nests.\n */\n landmarks = false,\n): { slot: string; el: E }[] {\n const counts = new Map<string, number>();\n const out: { slot: string; el: E }[] = [];\n const selector = dialogs ? `${LANDMARK_SELECTOR},${DIALOG_SELECTOR}` : LANDMARK_SELECTOR;\n for (const el of doc.querySelectorAll(selector)) {\n if (!landmarks) {\n if (el.parentElement?.closest(selector)) continue;\n } else if (LANDMARK_TAGS.has(el.tagName)) {\n // A landmark outside `<main>` has no ancestor inside it either, so anything enclosing it is\n // a region — the outermost rule, unchanged.\n if (!isChromeLandmark(el, true) || el.parentElement?.closest(selector)) continue;\n } else if (el.parentElement?.closest(DIALOG_SELECTOR)) {\n continue;\n }\n // The NAME, not the tag: a `[role=\"dialog\"]` is usually a `<div>`, and slotting it as\n // `div#0` would make one site's modal and another's wrapper the same kind of region.\n const name = !LANDMARK_TAGS.has(el.tagName) && el.matches(DIALOG_SELECTOR)\n ? \"dialog\"\n : el.tagName.toLowerCase();\n const n = counts.get(name) ?? 0;\n counts.set(name, n + 1);\n out.push({ slot: `${name}#${n}`, el });\n }\n return out;\n}\n\n/**\n * The region an element is in: the INNERMOST region that contains it, or null for the page body.\n *\n * The last match rather than the first, because regions are in document order and an enclosing\n * region opens before the one nested inside it (v2's dialog in a header). Under every other\n * grammar regions are disjoint and first and last are the same region — which is what keeps a\n * resolver built on this byte-identical for every locator stored before v2.\n */\nexport function regionOf<E extends { contains(other: unknown): boolean }>(\n regions: readonly { slot: string; el: E }[],\n el: unknown,\n): string | null {\n let slot: string | null = null;\n for (const r of regions) if (r.el.contains(el)) slot = r.slot;\n return slot;\n}\n"],"mappings":"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AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,0BAA+C,IAAI,IAAI,oBAAoB;;;AC36DjF,IAAM,yBAAyB;AAC/B,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;;;ACW1B,IAAM,oBAAoB;AACjC,IAAM,gBAAgB,oBAAI,IAAI,CAAC,UAAU,OAAO,QAAQ,CAAC;AAWlD,IAAM,kBAAkB;AAMxB,IAAM,gBAAgB;AAwCtB,SAAS,iBACd,IACA,WACS;AACT,MAAI,CAAC,cAAc,IAAI,GAAG,OAAO,EAAG,QAAO;AAC3C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,QAAQ,GAAG,eAAe,QAAQ,aAAa;AACrD,SAAO,CAAC,SAAW,UAAsB,GAAG,iBAAiB,YAAY,KAAK;AAChF;AAGA,IAAM,aAAa,oBAAI,IAAI,CAAC,UAAU,SAAS,YAAY,YAAY,MAAM,CAAC;AAI9E,SAAS,YAAY,MAA+B;AAClD,QAAM,OAAO,MAAM,KAAK,KAAK,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,OAAO,CAAC;AAC/E,QAAM,QAAQ,KAAK,CAAC,GAAG;AACvB,UAAQ,UAAU,YAAY,UAAU,UAAU,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,CAAC,EAAG,YAAY;AAC1G;AAsEO,SAAS,WAAW,IAAiB,QAAuB,YAAY,OAAuB;AACpG,QAAM,YAAsB,CAAC;AAC7B;AAAA,QACM,SAAS,GAAG;AAAA;AAAA;AAAA,IAGhB,UAAU,OAAO,YAAY,UAAU,CAAC,iBAAiB,QAAgC,SAAS;AAAA,IAClG,SAAS,OAAO;AAAA,IAChB;AACA,cAAU,QAAQ,OAAO,QAAQ,YAAY,CAAC;AAAA,EAChD;AACA,QAAM,WAAW,GAAG,gBAAgB,MAAM,KAAK,GAAG,cAAc,QAAQ,IAAI,CAAC;AAC7E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAc,KAAK,IAAI,SAAS,QAAQ,EAAE,GAAG,CAAC;AAAA,IAC9C,KAAK,GAAG,QAAQ,YAAY;AAAA,EAC9B;AACF;AAmBO,SAAS,gBACd,KAQA,UAAU,OAYV,YAAY,OACe;AAC3B,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,MAAiC,CAAC;AACxC,QAAM,WAAW,UAAU,GAAG,iBAAiB,IAAI,eAAe,KAAK;AACvE,aAAW,MAAM,IAAI,iBAAiB,QAAQ,GAAG;AAC/C,QAAI,CAAC,WAAW;AACd,UAAI,GAAG,eAAe,QAAQ,QAAQ,EAAG;AAAA,IAC3C,WAAW,cAAc,IAAI,GAAG,OAAO,GAAG;AAGxC,UAAI,CAAC,iBAAiB,IAAI,IAAI,KAAK,GAAG,eAAe,QAAQ,QAAQ,EAAG;AAAA,IAC1E,WAAW,GAAG,eAAe,QAAQ,eAAe,GAAG;AACrD;AAAA,IACF;AAGA,UAAM,OAAO,CAAC,cAAc,IAAI,GAAG,OAAO,KAAK,GAAG,QAAQ,eAAe,IACrE,WACA,GAAG,QAAQ,YAAY;AAC3B,UAAM,IAAI,OAAO,IAAI,IAAI,KAAK;AAC9B,WAAO,IAAI,MAAM,IAAI,CAAC;AACtB,QAAI,KAAK,EAAE,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;AAAA,EACvC;AACA,SAAO;AACT;AAUO,SAAS,SACd,SACA,IACe;AACf,MAAI,OAAsB;AAC1B,aAAW,KAAK,QAAS,KAAI,EAAE,GAAG,SAAS,EAAE,EAAG,QAAO,EAAE;AACzD,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettercms-ai/types",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",