@bettercms-ai/types 1.25.0 → 1.26.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
@@ -326,6 +326,44 @@ declare const SPACE_BOTTOM_TOKENS: ("section-space-none" | "section-space-small"
326
326
  /** `var(--bcms-<token>,<px>)`, or "" for anything that is not a known token (closed set). */
327
327
  declare function spaceTokenCss(token: unknown): string;
328
328
 
329
+ /**
330
+ * A button block's LOOK beyond size: its variant, an optional leading icon and an optional
331
+ * trailing arrow. The ONE source of the names and the icon markup: the renderer draws from it,
332
+ * the validation schema allow-lists from it, and the dashboard's copy is pinned to it by a
333
+ * parity test.
334
+ *
335
+ * <a class="bcms-btn bcms-btn-{variant}">[<svg class="bcms-btn-icon">]Text[<svg class="bcms-btn-arrow">]</a>
336
+ */
337
+ declare const BUTTON_VARIANTS: readonly ["primary", "secondary", "tertiary", "brand", "dark", "light", "outline", "link"];
338
+ type ButtonVariant = (typeof BUTTON_VARIANTS)[number];
339
+ /** Inner markup of each icon: lucide-react 1.8.0 paths (ISC), 24×24, stroke-drawn. */
340
+ declare const BUTTON_ICONS: {
341
+ readonly "arrow-right": "<path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/>";
342
+ readonly "arrow-up-right": "<path d=\"M7 7h10v10\"/><path d=\"M7 17 17 7\"/>";
343
+ readonly "chevron-right": "<path d=\"m9 18 6-6-6-6\"/>";
344
+ readonly plus: "<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>";
345
+ readonly check: "<path d=\"M20 6 9 17l-5-5\"/>";
346
+ readonly download: "<path d=\"M12 15V3\"/><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><path d=\"m7 10 5 5 5-5\"/>";
347
+ readonly "external-link": "<path d=\"M15 3h6v6\"/><path d=\"M10 14 21 3\"/><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>";
348
+ readonly mail: "<path d=\"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"/><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/>";
349
+ readonly phone: "<path d=\"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\"/>";
350
+ readonly calendar: "<path d=\"M8 2v4\"/><path d=\"M16 2v4\"/><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"/><path d=\"M3 10h18\"/>";
351
+ readonly play: "<path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/>";
352
+ readonly search: "<path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/>";
353
+ readonly "shopping-cart": "<circle cx=\"8\" cy=\"21\" r=\"1\"/><circle cx=\"19\" cy=\"21\" r=\"1\"/><path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\"/>";
354
+ readonly star: "<path d=\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\"/>";
355
+ readonly sparkles: "<path d=\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\"/><path d=\"M20 2v4\"/><path d=\"M22 4h-4\"/><circle cx=\"4\" cy=\"20\" r=\"2\"/>";
356
+ readonly zap: "<path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\"/>";
357
+ };
358
+ type ButtonIcon = keyof typeof BUTTON_ICONS;
359
+ declare const BUTTON_ICON_NAMES: [ButtonIcon, ...ButtonIcon[]];
360
+ /** A stored variant as it renders: anything off the list is Primary. */
361
+ declare function buttonVariantOf(value: unknown): ButtonVariant;
362
+ /** A stored icon as it renders: anything off the list is no icon. */
363
+ declare function buttonIconOf(value: unknown): ButtonIcon | null;
364
+ /** One icon as inline SVG sized to the button's text, hidden from assistive tech (the label names the button). */
365
+ declare function buttonIconSvg(name: ButtonIcon, cls: "bcms-btn-icon" | "bcms-btn-arrow"): string;
366
+
329
367
  /**
330
368
  * ContentBlock — a discriminated union of all CMS block types.
331
369
  * Each block has a `type` discriminator and a `props` object
@@ -510,11 +548,16 @@ interface ImageBlock {
510
548
  interface ButtonProps {
511
549
  text: string;
512
550
  href: string;
513
- variant?: "primary" | "secondary";
551
+ /** Absent or off the list ⇒ "primary". Renders `bcms-btn-{variant}`. */
552
+ variant?: ButtonVariant;
514
553
  /** Padding + font-size step. Absent ⇒ "md", today's button. sm/lg render `bcms-btn-sm|lg`. */
515
554
  size?: "sm" | "md" | "lg";
516
555
  /** Stretch to the column's width. Absent ⇒ false. true renders `bcms-btn-full`. */
517
556
  fullWidth?: boolean;
557
+ /** Draw a trailing arrow after the text. Absent ⇒ false. */
558
+ arrow?: boolean;
559
+ /** A leading icon from `BUTTON_ICONS`. Absent, null or off the list ⇒ none. */
560
+ icon?: ButtonIcon | null;
518
561
  }
519
562
  interface ButtonBlock {
520
563
  type: "button";
@@ -2308,4 +2351,4 @@ declare function regionOf<E extends {
2308
2351
  el: E;
2309
2352
  }[], el: unknown): string | null;
2310
2353
 
2311
- 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 ButtonLinkCandidate, 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 ComponentPropUi, 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, DOCK_BUDGET, DOCK_ICON_NAMES, DOCK_ICON_NAME_SET, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type DockBudget, type DockFieldLike, type DockFieldsetLike, type DockIconName, type DockLane, type DockNode, type DockPropGroupLike, type DockScreen, type ElementLike, type ExpandedBinding, FOOTER_SECTION_ID, type FieldConfig, type Fieldset, type FieldsetKind, type FieldsetUiBefore, 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 PropGroup, 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 UiBefore, type UiOrigin, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, buttonLinkPairs, candidateRole, componentInstanceAddresses, componentPropTargetKey, dockBudget, dockScreens, expandBlockBindings, formatPropsAttribute, getBlockType, isBlock, isChromeLandmark, keyWords, landmarkRegions, locatorFor, parsePropsAttribute, readPath, regionOf, spaceTokenCss };
2354
+ export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, BLOCK_BINDINGS, BUTTON_ICONS, BUTTON_ICON_NAMES, BUTTON_VARIANTS, type BetterCMSErrorCode, type BgToken, type BindingKind, type BlockBinding, type BlockHoverStyle, type BlockStyle, type BlockType, type ButtonBlock, type ButtonIcon, type ButtonLinkCandidate, type ButtonProps, type ButtonVariant, 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 ComponentPropUi, 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, DOCK_BUDGET, DOCK_ICON_NAMES, DOCK_ICON_NAME_SET, type DeepReadonly, type DeliveredLayout, type DeliveryComponent, type DeliveryEntry, type DeliveryEntrySeo, type DeliveryList, type DeliveryPage, type DerivedLocator, type DockBudget, type DockFieldLike, type DockFieldsetLike, type DockIconName, type DockLane, type DockNode, type DockPropGroupLike, type DockScreen, type ElementLike, type ExpandedBinding, FOOTER_SECTION_ID, type FieldConfig, type Fieldset, type FieldsetKind, type FieldsetUiBefore, 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 PropGroup, 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 UiBefore, type UiOrigin, type VariantInputMapping, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, buttonIconOf, buttonIconSvg, buttonLinkPairs, buttonVariantOf, candidateRole, componentInstanceAddresses, componentPropTargetKey, dockBudget, dockScreens, expandBlockBindings, formatPropsAttribute, getBlockType, isBlock, isChromeLandmark, keyWords, landmarkRegions, locatorFor, parsePropsAttribute, readPath, regionOf, spaceTokenCss };
package/dist/index.js CHANGED
@@ -2601,6 +2601,37 @@ function buttonLinkPairs(candidates) {
2601
2601
  return [...proposals.values()].filter(([t, l]) => !ambiguous.has(t) && !ambiguous.has(l) && uses.get(t) === 1 && uses.get(l) === 1).sort((a, b) => Math.min(...a) - Math.min(...b));
2602
2602
  }
2603
2603
 
2604
+ // src/button-look.ts
2605
+ var BUTTON_VARIANTS = ["primary", "secondary", "tertiary", "brand", "dark", "light", "outline", "link"];
2606
+ var BUTTON_ICONS = {
2607
+ "arrow-right": '<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',
2608
+ "arrow-up-right": '<path d="M7 7h10v10"/><path d="M7 17 17 7"/>',
2609
+ "chevron-right": '<path d="m9 18 6-6-6-6"/>',
2610
+ plus: '<path d="M5 12h14"/><path d="M12 5v14"/>',
2611
+ check: '<path d="M20 6 9 17l-5-5"/>',
2612
+ download: '<path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/>',
2613
+ "external-link": '<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',
2614
+ mail: '<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"/><rect x="2" y="4" width="20" height="16" rx="2"/>',
2615
+ phone: '<path d="M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384"/>',
2616
+ calendar: '<path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/>',
2617
+ play: '<path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"/>',
2618
+ search: '<path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/>',
2619
+ "shopping-cart": '<circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/>',
2620
+ star: '<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/>',
2621
+ sparkles: '<path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/><path d="M20 2v4"/><path d="M22 4h-4"/><circle cx="4" cy="20" r="2"/>',
2622
+ zap: '<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>'
2623
+ };
2624
+ var BUTTON_ICON_NAMES = Object.keys(BUTTON_ICONS);
2625
+ function buttonVariantOf(value) {
2626
+ return BUTTON_VARIANTS.includes(value) ? value : "primary";
2627
+ }
2628
+ function buttonIconOf(value) {
2629
+ return BUTTON_ICON_NAMES.includes(value) ? value : null;
2630
+ }
2631
+ function buttonIconSvg(name, cls) {
2632
+ return `<svg class="${cls}" viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${BUTTON_ICONS[name]}</svg>`;
2633
+ }
2634
+
2604
2635
  // src/locator.ts
2605
2636
  var LANDMARK_SELECTOR = "header,nav,footer";
2606
2637
  var LANDMARK_TAGS = /* @__PURE__ */ new Set(["HEADER", "NAV", "FOOTER"]);
@@ -2663,6 +2694,9 @@ function regionOf(regions, el) {
2663
2694
  }
2664
2695
  export {
2665
2696
  BLOCK_BINDINGS,
2697
+ BUTTON_ICONS,
2698
+ BUTTON_ICON_NAMES,
2699
+ BUTTON_VARIANTS,
2666
2700
  COMPONENT_PROP_TYPES,
2667
2701
  DIALOG_SELECTOR,
2668
2702
  DOCK_BUDGET,
@@ -2680,7 +2714,10 @@ export {
2680
2714
  SPACE_BOTTOM_TOKENS,
2681
2715
  SPACE_STEP_TOKENS,
2682
2716
  blockStyleToCss,
2717
+ buttonIconOf,
2718
+ buttonIconSvg,
2683
2719
  buttonLinkPairs,
2720
+ buttonVariantOf,
2684
2721
  candidateRole,
2685
2722
  componentInstanceAddresses,
2686
2723
  componentPropTargetKey,
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/dock-icon-names.ts","../src/dock-budget.ts","../src/button-link-pairing.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 /** Padding + font-size step. Absent ⇒ \"md\", today's button. sm/lg render `bcms-btn-sm|lg`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Stretch to the column's width. Absent ⇒ false. true renders `bcms-btn-full`. */\n fullWidth?: boolean;\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 * A bound placement whose page spells its fields differently from the component's props — a\n * locale copy (`/fr`) placed on its default-locale twin's component: `{ <propKey>: \"<this page's\n * field path>\" }`. Readers resolve a prop's copy through it before `bind`, since the twin's own\n * group keys (`personnalisez-titre`) are not the component's (`customize-title`). Written only\n * while `bind` is; dropped with it when the instance takes its copy.\n */\n bindPaths?: 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, FieldsetKind, UiBefore, UiOrigin } from \"./content-model.js\";\nimport type { DockIconName } from \"./dock-icon-names.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?: ComponentPropUi;\n /** Server-owned provenance of this prop's chrome. @see UiOrigin */\n uiOrigin?: UiOrigin;\n /** Server-owned revert point. @see UiBefore */\n uiBefore?: UiBefore;\n}\n\n/**\n * A top-level prop's dock group. Props have no fieldsets column, so the group rides inline: the\n * first prop to carry an `id` defines it (label, kind, icon, collapsed), later props name `{id}`.\n */\nexport interface PropGroup {\n id: string;\n /** 1–32 chars. Required on the defining prop. */\n label?: string;\n kind?: Exclude<FieldsetKind, \"tab\">;\n icon?: DockIconName;\n collapsed?: boolean;\n}\n\n/** A prop's `ui`: the field-lane chrome plus its inline {@link PropGroup}. */\nexport type ComponentPropUi = ContentModelFieldUi & { group?: PropGroup };\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 * Generated by scripts/gen-dock-icon-names.mjs from the vendored icon tarball\n * (sha256 0691620e50bdf453c2fed06224d9dc52d521574ab254a149eba47664b92fb889).\n * Do not edit by hand: rerun the script (`--check` fails CI on drift).\n *\n * The closed vocabulary for `ui.icon` (field ui, fieldsets, prop ui.group). `as const` because a\n * z.enum needs the literal tuple; a `readonly string[]` would type every string as valid.\n */\nexport const DOCK_ICON_NAMES = [\n \"access-denied\",\n \"activity\",\n \"add\",\n \"add-circle\",\n \"add-comment\",\n \"add-document\",\n \"add-user\",\n \"api\",\n \"archive\",\n \"arrow-down\",\n \"arrow-left\",\n \"arrow-right\",\n \"arrow-top-right\",\n \"arrow-up\",\n \"asterisk\",\n \"bar-chart\",\n \"basket\",\n \"bell\",\n \"bill\",\n \"binary-document\",\n \"block-content\",\n \"block-element\",\n \"blockquote\",\n \"bold\",\n \"bolt\",\n \"book\",\n \"bookmark\",\n \"bookmark-filled\",\n \"bottle\",\n \"bug\",\n \"bulb-filled\",\n \"bulb-outline\",\n \"calendar\",\n \"case\",\n \"chart-upward\",\n \"checkmark\",\n \"checkmark-circle\",\n \"chevron-down\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"circle\",\n \"clipboard\",\n \"clipboard-image\",\n \"clock\",\n \"close\",\n \"close-circle\",\n \"code\",\n \"code-block\",\n \"cog\",\n \"collapse\",\n \"color-wheel\",\n \"comment\",\n \"component\",\n \"compose\",\n \"compose-sparkles\",\n \"confetti\",\n \"controls\",\n \"copy\",\n \"credit-card\",\n \"crop\",\n \"cube\",\n \"dashboard\",\n \"database\",\n \"desktop\",\n \"diamond\",\n \"document\",\n \"document-pdf\",\n \"document-remove\",\n \"document-sheet\",\n \"document-text\",\n \"document-video\",\n \"document-word\",\n \"document-zip\",\n \"documents\",\n \"dot\",\n \"double-chevron-down\",\n \"double-chevron-left\",\n \"double-chevron-right\",\n \"double-chevron-up\",\n \"double-quote\",\n \"download\",\n \"drag-handle\",\n \"drop\",\n \"earth-americas\",\n \"earth-globe\",\n \"edit\",\n \"ellipsis-horizontal\",\n \"ellipsis-vertical\",\n \"empty\",\n \"enter\",\n \"enter-right\",\n \"envelope\",\n \"equal\",\n \"error-filled\",\n \"error-outline\",\n \"error-screen\",\n \"expand\",\n \"eye-closed\",\n \"eye-open\",\n \"face-happy\",\n \"face-indifferent\",\n \"face-sad\",\n \"feedback\",\n \"filter\",\n \"folder\",\n \"generate\",\n \"github\",\n \"groq\",\n \"hash\",\n \"heart\",\n \"heart-filled\",\n \"help-circle\",\n \"highlight\",\n \"home\",\n \"ice-cream\",\n \"image\",\n \"image-remove\",\n \"images\",\n \"inbox\",\n \"info-filled\",\n \"info-outline\",\n \"inline\",\n \"inline-element\",\n \"insert-above\",\n \"insert-below\",\n \"italic\",\n \"joystick\",\n \"json\",\n \"launch\",\n \"leave\",\n \"lemon\",\n \"link\",\n \"link-removed\",\n \"linkedin\",\n \"list\",\n \"lock\",\n \"logo-js\",\n \"logo-ts\",\n \"marker\",\n \"marker-removed\",\n \"master-detail\",\n \"menu\",\n \"microphone\",\n \"microphone-slash\",\n \"mobile-device\",\n \"moon\",\n \"number\",\n \"ok-hand\",\n \"olist\",\n \"overage\",\n \"package\",\n \"panel-left\",\n \"panel-right\",\n \"pause\",\n \"pin\",\n \"pin-filled\",\n \"pin-removed\",\n \"play\",\n \"plug\",\n \"presentation\",\n \"progress-50\",\n \"progress-75\",\n \"projects\",\n \"publish\",\n \"read-only\",\n \"redo\",\n \"refresh\",\n \"remove\",\n \"remove-circle\",\n \"reset\",\n \"restore\",\n \"retrieve\",\n \"retry\",\n \"revert\",\n \"robot\",\n \"rocket\",\n \"schema\",\n \"search\",\n \"select\",\n \"share\",\n \"sort\",\n \"sparkle\",\n \"sparkles\",\n \"spinner\",\n \"split-horizontal\",\n \"split-vertical\",\n \"square\",\n \"stack\",\n \"stack-compact\",\n \"star\",\n \"star-filled\",\n \"stop\",\n \"strikethrough\",\n \"string\",\n \"sun\",\n \"sync\",\n \"tablet-device\",\n \"tag\",\n \"tags\",\n \"target\",\n \"task\",\n \"terminal\",\n \"text\",\n \"th-large\",\n \"th-list\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"tiers\",\n \"timeline\",\n \"toggle-arrow-right\",\n \"token\",\n \"transfer\",\n \"translate\",\n \"trash\",\n \"trend-upward\",\n \"triangle-outline\",\n \"trolley\",\n \"truncate\",\n \"twitter\",\n \"ulist\",\n \"unarchive\",\n \"underline\",\n \"undo\",\n \"unknown\",\n \"unlink\",\n \"unlock\",\n \"unpublish\",\n \"upload\",\n \"user\",\n \"users\",\n \"versions\",\n \"video\",\n \"warning-filled\",\n \"warning-outline\",\n \"wrench\",\n] as const;\n\nexport type DockIconName = (typeof DOCK_ICON_NAMES)[number];\n\nexport const DOCK_ICON_NAME_SET: ReadonlySet<string> = new Set<string>(DOCK_ICON_NAMES);\n","/**\n * The dock's click budget, as ONE pure function both ends read (V9): the backend's next-steps\n * rules call it on live data, and the dashboard's reach test measures its RENDERED dock against the\n * golden this module emits (src/__tests__/fixtures/dock-budget.golden.json). No dependencies.\n *\n * A SCREEN is one navigation level of the dock, modelled on what the dock renders:\n * - `root` the lane's first screen: the page fields, a page section, or a component's props;\n * - `list` a repeatable's items, one branch hop below the row that opens it (a repeater, an\n * `array` with a repeatable zone, a `table` prop, `modular`);\n * - `item` one item of that list, a second hop. `modular` has no item screen: its items are\n * other models.\n * A non-repeatable zone (`group`, `array` + zones.nonRepeatable, a `group` prop) is NOT a screen.\n * It renders inline as a group, collapsed only when its own `ui.collapsed` is true.\n *\n * On a screen:\n * - fieldsets with no `kind` are FLAT (V2): members render ungrouped, in document order;\n * - `kind:\"group\"` is a disclosure placed at its first member; `collapsed` costs 1 activation;\n * - `kind:\"row\"` is ONE leaf, however many members it holds;\n * - `kind:\"tab\"`, root screens only: a strip renders only with ≥2 non-empty tabs. Tab 1 is the\n * first panel, each later tab costs 1 activation, untabbed fields are PINNED above the strip,\n * and a group/row with `tab: <id>` sits in that tab. Below the root a tab reference is flat.\n * - component props join a group through `ui.group`; the first prop naming an id defines it.\n *\n * Budget, per screen (DOCK_BUDGET holds the limits):\n * - ungroupedLeaves: rows outside any group (a leaf, a row fieldset, a branch), as the max over\n * panels of pinned + panel. No picker term: tabs are capped at 3, so the strip never overflows.\n * - maxGroupLeaves: the largest group's own rows (a nested group counts in its own entry).\n * - depth: branch hops from the lane's root screen.\n * - maxActivations: the dearest value on the screen counted from the lane's root: +1 per branch\n * hop, +1 per collapsed group, +1 for a non-first tab. A screen with no values costs its entry.\n */\n\nexport const DOCK_BUDGET = { ungrouped: 8, group: 12, depth: 3, activations: 2 } as const;\n\nexport type DockLane = \"page-fields\" | \"page-section\" | \"component\";\n\nexport interface DockBudget {\n ungroupedLeaves: number;\n maxGroupLeaves: number;\n depth: number;\n maxActivations: number;\n}\n\n/** One row on a screen. Keys are paths from the screen's own fields (`hero.title`). */\nexport type DockNode =\n | { kind: \"leaf\"; key: string }\n | { kind: \"row\"; id: string; keys: string[] }\n | { kind: \"branch\"; key: string }\n | { kind: \"group\"; id: string; collapsed: boolean; nodes: DockNode[] };\n\nexport interface DockScreen {\n /** `<lane>`, then `/<branch key>` per list and `/item` per item: `page-fields/quotes/item`. */\n id: string;\n lane: DockLane;\n kind: \"root\" | \"list\" | \"item\";\n title: string;\n depth: number;\n /** Activations spent reaching this screen from the lane's root. */\n entry: number;\n pinned: DockNode[];\n /** One panel per tab, in fieldset order. Empty when no strip renders. */\n tabs: DockNode[][];\n}\n\n/** The structural subset of a model field or component prop that this module reads. */\nexport interface DockFieldLike {\n key: string;\n label?: string;\n type: string;\n fieldsetId?: string;\n ui?: { collapsed?: boolean; group?: DockPropGroupLike } | null;\n config?: unknown;\n /** Legacy `group`/`repeater` children, and a component sub-field's own children. */\n fields?: DockFieldLike[];\n}\n\nexport interface DockFieldsetLike {\n id: string;\n name?: string;\n kind?: \"group\" | \"row\" | \"tab\";\n collapsed?: boolean;\n tab?: string;\n}\n\nexport interface DockPropGroupLike {\n id: string;\n label?: string;\n kind?: \"group\" | \"row\";\n collapsed?: boolean;\n}\n\ntype Config = {\n fields?: DockFieldLike[];\n zones?: { nonRepeatable?: DockFieldLike[]; repeatable?: { fields?: DockFieldLike[] } };\n};\n\n/** A repeatable's item fields (null: no item screen), or undefined when the field is no list. */\nfunction listItems(f: DockFieldLike): DockFieldLike[] | null | undefined {\n const c = (f.config ?? {}) as Config;\n if (f.type === \"repeater\") return f.fields ?? [];\n if (f.type === \"table\") return c.fields ?? f.fields ?? [];\n if (f.type === \"array\" && c.zones?.repeatable) return c.zones.repeatable.fields ?? [];\n if (f.type === \"modular\") return null;\n return undefined;\n}\n\n/** An inline zone's fields, or undefined when the field is not one. */\nfunction zoneFields(f: DockFieldLike): DockFieldLike[] | undefined {\n const c = (f.config ?? {}) as Config;\n if (f.type === \"group\") return c.fields ?? f.fields ?? [];\n if (f.type === \"array\" && c.zones?.nonRepeatable) return c.zones.nonRepeatable;\n return undefined;\n}\n\ninterface Branch {\n key: string;\n field: DockFieldLike;\n items: DockFieldLike[] | null;\n}\n\n/**\n * Lay one sibling level out into pinned rows and tab panels. `branches` collects every branch row\n * with the in-screen cost of reaching it, so the caller can open its screens.\n */\nfunction layout(\n fields: DockFieldLike[],\n fieldsets: DockFieldsetLike[],\n root: boolean,\n): { pinned: DockNode[]; tabs: DockNode[][]; branches: Map<string, Branch> } {\n const byId = new Map(fieldsets.map((s) => [s.id, s]));\n const tabIds = root ? fieldsets.filter((s) => s.kind === \"tab\").map((s) => s.id) : [];\n const tabOf = (s: DockFieldsetLike | undefined): string | undefined =>\n s?.kind === \"tab\" ? s.id : s?.tab !== undefined && byId.get(s.tab)?.kind === \"tab\" ? s.tab : undefined;\n const nonEmpty = new Set(\n fields.map((f) => tabOf(byId.get(f.fieldsetId ?? \"\"))).filter((t) => t && tabIds.includes(t)),\n );\n const strip = nonEmpty.size >= 2;\n\n const branches = new Map<string, Branch>();\n const nodeFor = (f: DockFieldLike, path: string): DockNode => {\n const key = `${path}${f.key}`;\n const zone = zoneFields(f);\n if (zone) {\n return { kind: \"group\", id: key, collapsed: f.ui?.collapsed === true, nodes: zone.map((z) => nodeFor(z, `${key}.`)) };\n }\n const items = listItems(f);\n if (items !== undefined) {\n branches.set(key, { key, field: f, items });\n return { kind: \"branch\", key };\n }\n return { kind: \"leaf\", key };\n };\n\n const pinned: DockNode[] = [];\n const panels = new Map<string, DockNode[]>(strip ? tabIds.filter((t) => nonEmpty.has(t)).map((t) => [t, []]) : []);\n const containers = new Map<string, DockNode>();\n for (const f of fields) {\n const node = nodeFor(f, \"\");\n const set = byId.get(f.fieldsetId ?? \"\");\n const target = (strip && panels.get(tabOf(set) ?? \"\")) || pinned;\n if (set?.kind !== \"group\" && set?.kind !== \"row\") {\n target.push(node);\n continue;\n }\n let box = containers.get(set.id);\n if (!box) {\n box =\n set.kind === \"row\"\n ? { kind: \"row\", id: set.id, keys: [] }\n : { kind: \"group\", id: set.id, collapsed: set.collapsed === true, nodes: [] };\n containers.set(set.id, box);\n target.push(box);\n }\n if (box.kind === \"row\") box.keys.push(f.key);\n else if (box.kind === \"group\") box.nodes.push(node);\n }\n return { pinned, tabs: [...panels.values()], branches };\n}\n\n/** Cheapest in-screen cost of each value and branch row, keyed by node key. */\nfunction walkCosts(screen: DockScreen): { values: number[]; branchCost: Map<string, number> } {\n const values: number[] = [];\n const branchCost = new Map<string, number>();\n const walk = (nodes: DockNode[], cost: number): void => {\n for (const n of nodes) {\n if (n.kind === \"group\") walk(n.nodes, cost + (n.collapsed ? 1 : 0));\n else if (n.kind === \"branch\") branchCost.set(n.key, cost);\n else values.push(cost);\n }\n };\n walk(screen.pinned, 0);\n screen.tabs.forEach((panel, i) => walk(panel, i === 0 ? 0 : 1));\n return { values, branchCost };\n}\n\n/**\n * Every screen of one lane, root first. Pass `props` for a component lane (its `fields` and\n * `fieldsets` are then ignored): a prop's `ui.group` becomes the fieldset it joins.\n */\nexport function dockScreens(\n source: { fields?: DockFieldLike[] | null; fieldsets?: DockFieldsetLike[] | null },\n lane: DockLane,\n props?: DockFieldLike[] | null,\n): DockScreen[] {\n let fields = source.fields ?? [];\n let fieldsets = source.fieldsets ?? [];\n if (props) {\n fieldsets = [];\n fields = props.map((p) => {\n const g = p.ui?.group;\n if (!g) return p;\n if (!fieldsets.some((s) => s.id === g.id)) {\n fieldsets.push({ id: g.id, name: g.label, kind: g.kind ?? \"group\", collapsed: g.collapsed });\n }\n return { ...p, fieldsetId: g.id };\n });\n }\n\n const screens: DockScreen[] = [];\n const open = (\n id: string,\n kind: DockScreen[\"kind\"],\n title: string,\n depth: number,\n entry: number,\n level: DockFieldLike[] | null,\n ): void => {\n const laid = level ? layout(level, fieldsets, kind === \"root\") : null;\n const screen: DockScreen = {\n id,\n lane,\n kind,\n title,\n depth,\n entry,\n pinned: laid?.pinned ?? [],\n tabs: laid?.tabs ?? [],\n };\n screens.push(screen);\n if (!laid) return;\n const { branchCost } = walkCosts(screen);\n for (const b of laid.branches.values()) {\n const listId = `${id}/${b.key}`;\n const listEntry = entry + (branchCost.get(b.key) ?? 0) + 1;\n const label = b.field.label ?? b.field.key;\n open(listId, \"list\", label, depth + 1, listEntry, null);\n if (b.items) open(`${listId}/item`, \"item\", `${label} item`, depth + 2, listEntry + 1, b.items);\n }\n };\n open(lane, \"root\", lane === \"component\" ? \"Component\" : lane === \"page-fields\" ? \"Page fields\" : \"Section\", 0, 0, fields);\n return screens;\n}\n\nexport function dockBudget(screen: DockScreen): DockBudget {\n const rows = (nodes: DockNode[]): number => nodes.filter((n) => n.kind !== \"group\").length;\n let maxGroupLeaves = 0;\n const groups = (nodes: DockNode[]): void => {\n for (const n of nodes) {\n if (n.kind !== \"group\") continue;\n maxGroupLeaves = Math.max(maxGroupLeaves, rows(n.nodes));\n groups(n.nodes);\n }\n };\n groups(screen.pinned);\n screen.tabs.forEach(groups);\n const pinned = rows(screen.pinned);\n const { values } = walkCosts(screen);\n return {\n ungroupedLeaves: screen.tabs.length ? Math.max(...screen.tabs.map((p) => pinned + rows(p))) : pinned,\n maxGroupLeaves,\n depth: screen.depth,\n maxActivations: screen.entry + (values.length ? Math.max(...values) : 0),\n };\n}\n","/**\n * THE button-link pairing rule, pure: which two sibling fields render as ONE button unit (the words\n * on the button + where it goes). The dashboard folds them together; the backend refuses a write\n * that splits such a pair across fieldsets (`pair_split`). One copy, so both ends agree.\n *\n * Presentation only: a pair keeps its own keys, values and writers.\n *\n * 1. A key is split into words whatever its spelling (`hero_cta_label`, `ctaText`, `button-link`);\n * a dotted path counts only its last segment.\n * 2. The LAST word is the role: `label text title cta button btn name` are TEXT roles, `href link\n * url to` LINK roles. Everything before it is the STEM.\n * 3. A text candidate is a text-typed field (`text`, `string`) with a text role. A key that is a\n * button noun (`cta`, `primaryButton`) also offers its full key as a stem.\n * 4. A link candidate is a link-typed field (`link`, `url`), or a text-typed field with a link role\n * that is not a media address (`image_url`). A link-typed field whose last word is not a link\n * role offers both its stem and its full key.\n * 5. Two fields pair when their stem holds EXACTLY one text and one link candidate. Three or more\n * candidates on a stem: none pair. A field that would pair two ways pairs neither way.\n *\n * When the key's words say nothing, the visible LABEL is read the same way, its stems namespaced\n * (`label:`) so a label reading only ever meets another label reading.\n */\n\nconst TEXT_ROLES: ReadonlySet<string> = new Set([\"label\", \"text\", \"title\", \"cta\", \"button\", \"btn\", \"name\"]);\nconst LINK_ROLES: ReadonlySet<string> = new Set([\"href\", \"link\", \"url\", \"to\"]);\nconst BUTTON_NOUNS: ReadonlySet<string> = new Set([\"cta\", \"button\", \"btn\"]);\nconst TEXT_TYPES: ReadonlySet<string> = new Set([\"text\", \"string\"]);\nconst LINK_TYPES: ReadonlySet<string> = new Set([\"link\", \"url\"]);\nconst MEDIA = /image|img|photo|video|avatar|logo|icon|thumb|poster|embed|src|og|favicon/i;\n\n/** What the rule needs to know about one field. */\nexport interface ButtonLinkCandidate {\n key: string;\n type?: string;\n label?: string;\n /** The current value, when known: a structured value never pairs as text. */\n value?: unknown;\n}\n\n/** `hero_cta_primary_label` / `ctaText` / `primaryButton-link` → lowercase words. */\nexport function keyWords(key: string): string[] {\n const leaf = key.split(\".\").pop() ?? \"\";\n return leaf\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n}\n\ntype Role = { role: \"text\" | \"link\"; stems: string[] };\n\nfunction roleFromWords(candidate: ButtonLinkCandidate, words: string[]): Role | null {\n const type = (candidate.type ?? \"\").toLowerCase();\n const value = candidate.value;\n if (!(value === undefined || value === null || typeof value === \"string\")) return null;\n if (!words.length) return null;\n const last = words[words.length - 1]!;\n const stem = words.slice(0, -1).join(\"_\");\n const full = words.join(\"_\");\n if (LINK_TYPES.has(type)) return { role: \"link\", stems: LINK_ROLES.has(last) ? [stem] : [stem, full] };\n if (!TEXT_TYPES.has(type)) return null;\n if (LINK_ROLES.has(last)) {\n if (MEDIA.test(candidate.key) || MEDIA.test(candidate.label ?? \"\")) return null;\n return { role: \"link\", stems: [stem] };\n }\n if (TEXT_ROLES.has(last)) return { role: \"text\", stems: BUTTON_NOUNS.has(last) ? [stem, full] : [stem] };\n return null;\n}\n\n/** The role one field plays, with every stem it offers, or null. */\nexport function candidateRole(candidate: ButtonLinkCandidate): Role | null {\n const fromKey = roleFromWords(candidate, keyWords(candidate.key));\n if (fromKey) return fromKey;\n const label = candidate.label?.trim();\n if (!label) return null;\n const fromLabel = roleFromWords(candidate, keyWords(label.replace(/\\s+/g, \"_\")));\n return fromLabel ? { role: fromLabel.role, stems: fromLabel.stems.map((stem) => `label:${stem}`) } : null;\n}\n\n/** Every unambiguous pair in one sibling list, as `[textIndex, linkIndex]`, in list order. */\nexport function buttonLinkPairs(candidates: readonly ButtonLinkCandidate[]): Array<[number, number]> {\n const roles = candidates.map(candidateRole);\n const byStem = new Map<string, { text: Set<number>; link: Set<number> }>();\n roles.forEach((role, index) => {\n if (!role) return;\n for (const stem of new Set(role.stems)) {\n const bucket = byStem.get(stem) ?? { text: new Set<number>(), link: new Set<number>() };\n bucket[role.role].add(index);\n byStem.set(stem, bucket);\n }\n });\n\n const ambiguous = new Set<number>();\n const proposals = new Map<string, [number, number]>();\n for (const bucket of byStem.values()) {\n if (bucket.text.size + bucket.link.size >= 3) {\n for (const index of [...bucket.text, ...bucket.link]) ambiguous.add(index);\n continue;\n }\n if (bucket.text.size === 1 && bucket.link.size === 1) {\n const pair: [number, number] = [[...bucket.text][0]!, [...bucket.link][0]!];\n proposals.set(pair.join(\":\"), pair);\n }\n }\n\n const uses = new Map<number, number>();\n for (const [text, link] of proposals.values()) {\n uses.set(text, (uses.get(text) ?? 0) + 1);\n uses.set(link, (uses.get(link) ?? 0) + 1);\n }\n return [...proposals.values()]\n .filter(([t, l]) => !ambiguous.has(t) && !ambiguous.has(l) && uses.get(t) === 1 && uses.get(l) === 1)\n .sort((a, b) => Math.min(...a) - Math.min(...b));\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;;;ACK1B,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA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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/dock-icon-names.ts","../src/dock-budget.ts","../src/button-link-pairing.ts","../src/button-look.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\";\nimport type { ButtonIcon, ButtonVariant } from \"./button-look.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 /** Absent or off the list ⇒ \"primary\". Renders `bcms-btn-{variant}`. */\n variant?: ButtonVariant;\n /** Padding + font-size step. Absent ⇒ \"md\", today's button. sm/lg render `bcms-btn-sm|lg`. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Stretch to the column's width. Absent ⇒ false. true renders `bcms-btn-full`. */\n fullWidth?: boolean;\n /** Draw a trailing arrow after the text. Absent ⇒ false. */\n arrow?: boolean;\n /** A leading icon from `BUTTON_ICONS`. Absent, null or off the list ⇒ none. */\n icon?: ButtonIcon | null;\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 * A bound placement whose page spells its fields differently from the component's props — a\n * locale copy (`/fr`) placed on its default-locale twin's component: `{ <propKey>: \"<this page's\n * field path>\" }`. Readers resolve a prop's copy through it before `bind`, since the twin's own\n * group keys (`personnalisez-titre`) are not the component's (`customize-title`). Written only\n * while `bind` is; dropped with it when the instance takes its copy.\n */\n bindPaths?: 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, FieldsetKind, UiBefore, UiOrigin } from \"./content-model.js\";\nimport type { DockIconName } from \"./dock-icon-names.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?: ComponentPropUi;\n /** Server-owned provenance of this prop's chrome. @see UiOrigin */\n uiOrigin?: UiOrigin;\n /** Server-owned revert point. @see UiBefore */\n uiBefore?: UiBefore;\n}\n\n/**\n * A top-level prop's dock group. Props have no fieldsets column, so the group rides inline: the\n * first prop to carry an `id` defines it (label, kind, icon, collapsed), later props name `{id}`.\n */\nexport interface PropGroup {\n id: string;\n /** 1–32 chars. Required on the defining prop. */\n label?: string;\n kind?: Exclude<FieldsetKind, \"tab\">;\n icon?: DockIconName;\n collapsed?: boolean;\n}\n\n/** A prop's `ui`: the field-lane chrome plus its inline {@link PropGroup}. */\nexport type ComponentPropUi = ContentModelFieldUi & { group?: PropGroup };\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 * Generated by scripts/gen-dock-icon-names.mjs from the vendored icon tarball\n * (sha256 0691620e50bdf453c2fed06224d9dc52d521574ab254a149eba47664b92fb889).\n * Do not edit by hand: rerun the script (`--check` fails CI on drift).\n *\n * The closed vocabulary for `ui.icon` (field ui, fieldsets, prop ui.group). `as const` because a\n * z.enum needs the literal tuple; a `readonly string[]` would type every string as valid.\n */\nexport const DOCK_ICON_NAMES = [\n \"access-denied\",\n \"activity\",\n \"add\",\n \"add-circle\",\n \"add-comment\",\n \"add-document\",\n \"add-user\",\n \"api\",\n \"archive\",\n \"arrow-down\",\n \"arrow-left\",\n \"arrow-right\",\n \"arrow-top-right\",\n \"arrow-up\",\n \"asterisk\",\n \"bar-chart\",\n \"basket\",\n \"bell\",\n \"bill\",\n \"binary-document\",\n \"block-content\",\n \"block-element\",\n \"blockquote\",\n \"bold\",\n \"bolt\",\n \"book\",\n \"bookmark\",\n \"bookmark-filled\",\n \"bottle\",\n \"bug\",\n \"bulb-filled\",\n \"bulb-outline\",\n \"calendar\",\n \"case\",\n \"chart-upward\",\n \"checkmark\",\n \"checkmark-circle\",\n \"chevron-down\",\n \"chevron-left\",\n \"chevron-right\",\n \"chevron-up\",\n \"circle\",\n \"clipboard\",\n \"clipboard-image\",\n \"clock\",\n \"close\",\n \"close-circle\",\n \"code\",\n \"code-block\",\n \"cog\",\n \"collapse\",\n \"color-wheel\",\n \"comment\",\n \"component\",\n \"compose\",\n \"compose-sparkles\",\n \"confetti\",\n \"controls\",\n \"copy\",\n \"credit-card\",\n \"crop\",\n \"cube\",\n \"dashboard\",\n \"database\",\n \"desktop\",\n \"diamond\",\n \"document\",\n \"document-pdf\",\n \"document-remove\",\n \"document-sheet\",\n \"document-text\",\n \"document-video\",\n \"document-word\",\n \"document-zip\",\n \"documents\",\n \"dot\",\n \"double-chevron-down\",\n \"double-chevron-left\",\n \"double-chevron-right\",\n \"double-chevron-up\",\n \"double-quote\",\n \"download\",\n \"drag-handle\",\n \"drop\",\n \"earth-americas\",\n \"earth-globe\",\n \"edit\",\n \"ellipsis-horizontal\",\n \"ellipsis-vertical\",\n \"empty\",\n \"enter\",\n \"enter-right\",\n \"envelope\",\n \"equal\",\n \"error-filled\",\n \"error-outline\",\n \"error-screen\",\n \"expand\",\n \"eye-closed\",\n \"eye-open\",\n \"face-happy\",\n \"face-indifferent\",\n \"face-sad\",\n \"feedback\",\n \"filter\",\n \"folder\",\n \"generate\",\n \"github\",\n \"groq\",\n \"hash\",\n \"heart\",\n \"heart-filled\",\n \"help-circle\",\n \"highlight\",\n \"home\",\n \"ice-cream\",\n \"image\",\n \"image-remove\",\n \"images\",\n \"inbox\",\n \"info-filled\",\n \"info-outline\",\n \"inline\",\n \"inline-element\",\n \"insert-above\",\n \"insert-below\",\n \"italic\",\n \"joystick\",\n \"json\",\n \"launch\",\n \"leave\",\n \"lemon\",\n \"link\",\n \"link-removed\",\n \"linkedin\",\n \"list\",\n \"lock\",\n \"logo-js\",\n \"logo-ts\",\n \"marker\",\n \"marker-removed\",\n \"master-detail\",\n \"menu\",\n \"microphone\",\n \"microphone-slash\",\n \"mobile-device\",\n \"moon\",\n \"number\",\n \"ok-hand\",\n \"olist\",\n \"overage\",\n \"package\",\n \"panel-left\",\n \"panel-right\",\n \"pause\",\n \"pin\",\n \"pin-filled\",\n \"pin-removed\",\n \"play\",\n \"plug\",\n \"presentation\",\n \"progress-50\",\n \"progress-75\",\n \"projects\",\n \"publish\",\n \"read-only\",\n \"redo\",\n \"refresh\",\n \"remove\",\n \"remove-circle\",\n \"reset\",\n \"restore\",\n \"retrieve\",\n \"retry\",\n \"revert\",\n \"robot\",\n \"rocket\",\n \"schema\",\n \"search\",\n \"select\",\n \"share\",\n \"sort\",\n \"sparkle\",\n \"sparkles\",\n \"spinner\",\n \"split-horizontal\",\n \"split-vertical\",\n \"square\",\n \"stack\",\n \"stack-compact\",\n \"star\",\n \"star-filled\",\n \"stop\",\n \"strikethrough\",\n \"string\",\n \"sun\",\n \"sync\",\n \"tablet-device\",\n \"tag\",\n \"tags\",\n \"target\",\n \"task\",\n \"terminal\",\n \"text\",\n \"th-large\",\n \"th-list\",\n \"thumbs-down\",\n \"thumbs-up\",\n \"tiers\",\n \"timeline\",\n \"toggle-arrow-right\",\n \"token\",\n \"transfer\",\n \"translate\",\n \"trash\",\n \"trend-upward\",\n \"triangle-outline\",\n \"trolley\",\n \"truncate\",\n \"twitter\",\n \"ulist\",\n \"unarchive\",\n \"underline\",\n \"undo\",\n \"unknown\",\n \"unlink\",\n \"unlock\",\n \"unpublish\",\n \"upload\",\n \"user\",\n \"users\",\n \"versions\",\n \"video\",\n \"warning-filled\",\n \"warning-outline\",\n \"wrench\",\n] as const;\n\nexport type DockIconName = (typeof DOCK_ICON_NAMES)[number];\n\nexport const DOCK_ICON_NAME_SET: ReadonlySet<string> = new Set<string>(DOCK_ICON_NAMES);\n","/**\n * The dock's click budget, as ONE pure function both ends read (V9): the backend's next-steps\n * rules call it on live data, and the dashboard's reach test measures its RENDERED dock against the\n * golden this module emits (src/__tests__/fixtures/dock-budget.golden.json). No dependencies.\n *\n * A SCREEN is one navigation level of the dock, modelled on what the dock renders:\n * - `root` the lane's first screen: the page fields, a page section, or a component's props;\n * - `list` a repeatable's items, one branch hop below the row that opens it (a repeater, an\n * `array` with a repeatable zone, a `table` prop, `modular`);\n * - `item` one item of that list, a second hop. `modular` has no item screen: its items are\n * other models.\n * A non-repeatable zone (`group`, `array` + zones.nonRepeatable, a `group` prop) is NOT a screen.\n * It renders inline as a group, collapsed only when its own `ui.collapsed` is true.\n *\n * On a screen:\n * - fieldsets with no `kind` are FLAT (V2): members render ungrouped, in document order;\n * - `kind:\"group\"` is a disclosure placed at its first member; `collapsed` costs 1 activation;\n * - `kind:\"row\"` is ONE leaf, however many members it holds;\n * - `kind:\"tab\"`, root screens only: a strip renders only with ≥2 non-empty tabs. Tab 1 is the\n * first panel, each later tab costs 1 activation, untabbed fields are PINNED above the strip,\n * and a group/row with `tab: <id>` sits in that tab. Below the root a tab reference is flat.\n * - component props join a group through `ui.group`; the first prop naming an id defines it.\n *\n * Budget, per screen (DOCK_BUDGET holds the limits):\n * - ungroupedLeaves: rows outside any group (a leaf, a row fieldset, a branch), as the max over\n * panels of pinned + panel. No picker term: tabs are capped at 3, so the strip never overflows.\n * - maxGroupLeaves: the largest group's own rows (a nested group counts in its own entry).\n * - depth: branch hops from the lane's root screen.\n * - maxActivations: the dearest value on the screen counted from the lane's root: +1 per branch\n * hop, +1 per collapsed group, +1 for a non-first tab. A screen with no values costs its entry.\n */\n\nexport const DOCK_BUDGET = { ungrouped: 8, group: 12, depth: 3, activations: 2 } as const;\n\nexport type DockLane = \"page-fields\" | \"page-section\" | \"component\";\n\nexport interface DockBudget {\n ungroupedLeaves: number;\n maxGroupLeaves: number;\n depth: number;\n maxActivations: number;\n}\n\n/** One row on a screen. Keys are paths from the screen's own fields (`hero.title`). */\nexport type DockNode =\n | { kind: \"leaf\"; key: string }\n | { kind: \"row\"; id: string; keys: string[] }\n | { kind: \"branch\"; key: string }\n | { kind: \"group\"; id: string; collapsed: boolean; nodes: DockNode[] };\n\nexport interface DockScreen {\n /** `<lane>`, then `/<branch key>` per list and `/item` per item: `page-fields/quotes/item`. */\n id: string;\n lane: DockLane;\n kind: \"root\" | \"list\" | \"item\";\n title: string;\n depth: number;\n /** Activations spent reaching this screen from the lane's root. */\n entry: number;\n pinned: DockNode[];\n /** One panel per tab, in fieldset order. Empty when no strip renders. */\n tabs: DockNode[][];\n}\n\n/** The structural subset of a model field or component prop that this module reads. */\nexport interface DockFieldLike {\n key: string;\n label?: string;\n type: string;\n fieldsetId?: string;\n ui?: { collapsed?: boolean; group?: DockPropGroupLike } | null;\n config?: unknown;\n /** Legacy `group`/`repeater` children, and a component sub-field's own children. */\n fields?: DockFieldLike[];\n}\n\nexport interface DockFieldsetLike {\n id: string;\n name?: string;\n kind?: \"group\" | \"row\" | \"tab\";\n collapsed?: boolean;\n tab?: string;\n}\n\nexport interface DockPropGroupLike {\n id: string;\n label?: string;\n kind?: \"group\" | \"row\";\n collapsed?: boolean;\n}\n\ntype Config = {\n fields?: DockFieldLike[];\n zones?: { nonRepeatable?: DockFieldLike[]; repeatable?: { fields?: DockFieldLike[] } };\n};\n\n/** A repeatable's item fields (null: no item screen), or undefined when the field is no list. */\nfunction listItems(f: DockFieldLike): DockFieldLike[] | null | undefined {\n const c = (f.config ?? {}) as Config;\n if (f.type === \"repeater\") return f.fields ?? [];\n if (f.type === \"table\") return c.fields ?? f.fields ?? [];\n if (f.type === \"array\" && c.zones?.repeatable) return c.zones.repeatable.fields ?? [];\n if (f.type === \"modular\") return null;\n return undefined;\n}\n\n/** An inline zone's fields, or undefined when the field is not one. */\nfunction zoneFields(f: DockFieldLike): DockFieldLike[] | undefined {\n const c = (f.config ?? {}) as Config;\n if (f.type === \"group\") return c.fields ?? f.fields ?? [];\n if (f.type === \"array\" && c.zones?.nonRepeatable) return c.zones.nonRepeatable;\n return undefined;\n}\n\ninterface Branch {\n key: string;\n field: DockFieldLike;\n items: DockFieldLike[] | null;\n}\n\n/**\n * Lay one sibling level out into pinned rows and tab panels. `branches` collects every branch row\n * with the in-screen cost of reaching it, so the caller can open its screens.\n */\nfunction layout(\n fields: DockFieldLike[],\n fieldsets: DockFieldsetLike[],\n root: boolean,\n): { pinned: DockNode[]; tabs: DockNode[][]; branches: Map<string, Branch> } {\n const byId = new Map(fieldsets.map((s) => [s.id, s]));\n const tabIds = root ? fieldsets.filter((s) => s.kind === \"tab\").map((s) => s.id) : [];\n const tabOf = (s: DockFieldsetLike | undefined): string | undefined =>\n s?.kind === \"tab\" ? s.id : s?.tab !== undefined && byId.get(s.tab)?.kind === \"tab\" ? s.tab : undefined;\n const nonEmpty = new Set(\n fields.map((f) => tabOf(byId.get(f.fieldsetId ?? \"\"))).filter((t) => t && tabIds.includes(t)),\n );\n const strip = nonEmpty.size >= 2;\n\n const branches = new Map<string, Branch>();\n const nodeFor = (f: DockFieldLike, path: string): DockNode => {\n const key = `${path}${f.key}`;\n const zone = zoneFields(f);\n if (zone) {\n return { kind: \"group\", id: key, collapsed: f.ui?.collapsed === true, nodes: zone.map((z) => nodeFor(z, `${key}.`)) };\n }\n const items = listItems(f);\n if (items !== undefined) {\n branches.set(key, { key, field: f, items });\n return { kind: \"branch\", key };\n }\n return { kind: \"leaf\", key };\n };\n\n const pinned: DockNode[] = [];\n const panels = new Map<string, DockNode[]>(strip ? tabIds.filter((t) => nonEmpty.has(t)).map((t) => [t, []]) : []);\n const containers = new Map<string, DockNode>();\n for (const f of fields) {\n const node = nodeFor(f, \"\");\n const set = byId.get(f.fieldsetId ?? \"\");\n const target = (strip && panels.get(tabOf(set) ?? \"\")) || pinned;\n if (set?.kind !== \"group\" && set?.kind !== \"row\") {\n target.push(node);\n continue;\n }\n let box = containers.get(set.id);\n if (!box) {\n box =\n set.kind === \"row\"\n ? { kind: \"row\", id: set.id, keys: [] }\n : { kind: \"group\", id: set.id, collapsed: set.collapsed === true, nodes: [] };\n containers.set(set.id, box);\n target.push(box);\n }\n if (box.kind === \"row\") box.keys.push(f.key);\n else if (box.kind === \"group\") box.nodes.push(node);\n }\n return { pinned, tabs: [...panels.values()], branches };\n}\n\n/** Cheapest in-screen cost of each value and branch row, keyed by node key. */\nfunction walkCosts(screen: DockScreen): { values: number[]; branchCost: Map<string, number> } {\n const values: number[] = [];\n const branchCost = new Map<string, number>();\n const walk = (nodes: DockNode[], cost: number): void => {\n for (const n of nodes) {\n if (n.kind === \"group\") walk(n.nodes, cost + (n.collapsed ? 1 : 0));\n else if (n.kind === \"branch\") branchCost.set(n.key, cost);\n else values.push(cost);\n }\n };\n walk(screen.pinned, 0);\n screen.tabs.forEach((panel, i) => walk(panel, i === 0 ? 0 : 1));\n return { values, branchCost };\n}\n\n/**\n * Every screen of one lane, root first. Pass `props` for a component lane (its `fields` and\n * `fieldsets` are then ignored): a prop's `ui.group` becomes the fieldset it joins.\n */\nexport function dockScreens(\n source: { fields?: DockFieldLike[] | null; fieldsets?: DockFieldsetLike[] | null },\n lane: DockLane,\n props?: DockFieldLike[] | null,\n): DockScreen[] {\n let fields = source.fields ?? [];\n let fieldsets = source.fieldsets ?? [];\n if (props) {\n fieldsets = [];\n fields = props.map((p) => {\n const g = p.ui?.group;\n if (!g) return p;\n if (!fieldsets.some((s) => s.id === g.id)) {\n fieldsets.push({ id: g.id, name: g.label, kind: g.kind ?? \"group\", collapsed: g.collapsed });\n }\n return { ...p, fieldsetId: g.id };\n });\n }\n\n const screens: DockScreen[] = [];\n const open = (\n id: string,\n kind: DockScreen[\"kind\"],\n title: string,\n depth: number,\n entry: number,\n level: DockFieldLike[] | null,\n ): void => {\n const laid = level ? layout(level, fieldsets, kind === \"root\") : null;\n const screen: DockScreen = {\n id,\n lane,\n kind,\n title,\n depth,\n entry,\n pinned: laid?.pinned ?? [],\n tabs: laid?.tabs ?? [],\n };\n screens.push(screen);\n if (!laid) return;\n const { branchCost } = walkCosts(screen);\n for (const b of laid.branches.values()) {\n const listId = `${id}/${b.key}`;\n const listEntry = entry + (branchCost.get(b.key) ?? 0) + 1;\n const label = b.field.label ?? b.field.key;\n open(listId, \"list\", label, depth + 1, listEntry, null);\n if (b.items) open(`${listId}/item`, \"item\", `${label} item`, depth + 2, listEntry + 1, b.items);\n }\n };\n open(lane, \"root\", lane === \"component\" ? \"Component\" : lane === \"page-fields\" ? \"Page fields\" : \"Section\", 0, 0, fields);\n return screens;\n}\n\nexport function dockBudget(screen: DockScreen): DockBudget {\n const rows = (nodes: DockNode[]): number => nodes.filter((n) => n.kind !== \"group\").length;\n let maxGroupLeaves = 0;\n const groups = (nodes: DockNode[]): void => {\n for (const n of nodes) {\n if (n.kind !== \"group\") continue;\n maxGroupLeaves = Math.max(maxGroupLeaves, rows(n.nodes));\n groups(n.nodes);\n }\n };\n groups(screen.pinned);\n screen.tabs.forEach(groups);\n const pinned = rows(screen.pinned);\n const { values } = walkCosts(screen);\n return {\n ungroupedLeaves: screen.tabs.length ? Math.max(...screen.tabs.map((p) => pinned + rows(p))) : pinned,\n maxGroupLeaves,\n depth: screen.depth,\n maxActivations: screen.entry + (values.length ? Math.max(...values) : 0),\n };\n}\n","/**\n * THE button-link pairing rule, pure: which two sibling fields render as ONE button unit (the words\n * on the button + where it goes). The dashboard folds them together; the backend refuses a write\n * that splits such a pair across fieldsets (`pair_split`). One copy, so both ends agree.\n *\n * Presentation only: a pair keeps its own keys, values and writers.\n *\n * 1. A key is split into words whatever its spelling (`hero_cta_label`, `ctaText`, `button-link`);\n * a dotted path counts only its last segment.\n * 2. The LAST word is the role: `label text title cta button btn name` are TEXT roles, `href link\n * url to` LINK roles. Everything before it is the STEM.\n * 3. A text candidate is a text-typed field (`text`, `string`) with a text role. A key that is a\n * button noun (`cta`, `primaryButton`) also offers its full key as a stem.\n * 4. A link candidate is a link-typed field (`link`, `url`), or a text-typed field with a link role\n * that is not a media address (`image_url`). A link-typed field whose last word is not a link\n * role offers both its stem and its full key.\n * 5. Two fields pair when their stem holds EXACTLY one text and one link candidate. Three or more\n * candidates on a stem: none pair. A field that would pair two ways pairs neither way.\n *\n * When the key's words say nothing, the visible LABEL is read the same way, its stems namespaced\n * (`label:`) so a label reading only ever meets another label reading.\n */\n\nconst TEXT_ROLES: ReadonlySet<string> = new Set([\"label\", \"text\", \"title\", \"cta\", \"button\", \"btn\", \"name\"]);\nconst LINK_ROLES: ReadonlySet<string> = new Set([\"href\", \"link\", \"url\", \"to\"]);\nconst BUTTON_NOUNS: ReadonlySet<string> = new Set([\"cta\", \"button\", \"btn\"]);\nconst TEXT_TYPES: ReadonlySet<string> = new Set([\"text\", \"string\"]);\nconst LINK_TYPES: ReadonlySet<string> = new Set([\"link\", \"url\"]);\nconst MEDIA = /image|img|photo|video|avatar|logo|icon|thumb|poster|embed|src|og|favicon/i;\n\n/** What the rule needs to know about one field. */\nexport interface ButtonLinkCandidate {\n key: string;\n type?: string;\n label?: string;\n /** The current value, when known: a structured value never pairs as text. */\n value?: unknown;\n}\n\n/** `hero_cta_primary_label` / `ctaText` / `primaryButton-link` → lowercase words. */\nexport function keyWords(key: string): string[] {\n const leaf = key.split(\".\").pop() ?? \"\";\n return leaf\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .split(/[\\s_-]+/)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n}\n\ntype Role = { role: \"text\" | \"link\"; stems: string[] };\n\nfunction roleFromWords(candidate: ButtonLinkCandidate, words: string[]): Role | null {\n const type = (candidate.type ?? \"\").toLowerCase();\n const value = candidate.value;\n if (!(value === undefined || value === null || typeof value === \"string\")) return null;\n if (!words.length) return null;\n const last = words[words.length - 1]!;\n const stem = words.slice(0, -1).join(\"_\");\n const full = words.join(\"_\");\n if (LINK_TYPES.has(type)) return { role: \"link\", stems: LINK_ROLES.has(last) ? [stem] : [stem, full] };\n if (!TEXT_TYPES.has(type)) return null;\n if (LINK_ROLES.has(last)) {\n if (MEDIA.test(candidate.key) || MEDIA.test(candidate.label ?? \"\")) return null;\n return { role: \"link\", stems: [stem] };\n }\n if (TEXT_ROLES.has(last)) return { role: \"text\", stems: BUTTON_NOUNS.has(last) ? [stem, full] : [stem] };\n return null;\n}\n\n/** The role one field plays, with every stem it offers, or null. */\nexport function candidateRole(candidate: ButtonLinkCandidate): Role | null {\n const fromKey = roleFromWords(candidate, keyWords(candidate.key));\n if (fromKey) return fromKey;\n const label = candidate.label?.trim();\n if (!label) return null;\n const fromLabel = roleFromWords(candidate, keyWords(label.replace(/\\s+/g, \"_\")));\n return fromLabel ? { role: fromLabel.role, stems: fromLabel.stems.map((stem) => `label:${stem}`) } : null;\n}\n\n/** Every unambiguous pair in one sibling list, as `[textIndex, linkIndex]`, in list order. */\nexport function buttonLinkPairs(candidates: readonly ButtonLinkCandidate[]): Array<[number, number]> {\n const roles = candidates.map(candidateRole);\n const byStem = new Map<string, { text: Set<number>; link: Set<number> }>();\n roles.forEach((role, index) => {\n if (!role) return;\n for (const stem of new Set(role.stems)) {\n const bucket = byStem.get(stem) ?? { text: new Set<number>(), link: new Set<number>() };\n bucket[role.role].add(index);\n byStem.set(stem, bucket);\n }\n });\n\n const ambiguous = new Set<number>();\n const proposals = new Map<string, [number, number]>();\n for (const bucket of byStem.values()) {\n if (bucket.text.size + bucket.link.size >= 3) {\n for (const index of [...bucket.text, ...bucket.link]) ambiguous.add(index);\n continue;\n }\n if (bucket.text.size === 1 && bucket.link.size === 1) {\n const pair: [number, number] = [[...bucket.text][0]!, [...bucket.link][0]!];\n proposals.set(pair.join(\":\"), pair);\n }\n }\n\n const uses = new Map<number, number>();\n for (const [text, link] of proposals.values()) {\n uses.set(text, (uses.get(text) ?? 0) + 1);\n uses.set(link, (uses.get(link) ?? 0) + 1);\n }\n return [...proposals.values()]\n .filter(([t, l]) => !ambiguous.has(t) && !ambiguous.has(l) && uses.get(t) === 1 && uses.get(l) === 1)\n .sort((a, b) => Math.min(...a) - Math.min(...b));\n}\n","/**\n * A button block's LOOK beyond size: its variant, an optional leading icon and an optional\n * trailing arrow. The ONE source of the names and the icon markup: the renderer draws from it,\n * the validation schema allow-lists from it, and the dashboard's copy is pinned to it by a\n * parity test.\n *\n * <a class=\"bcms-btn bcms-btn-{variant}\">[<svg class=\"bcms-btn-icon\">]Text[<svg class=\"bcms-btn-arrow\">]</a>\n */\n\nexport const BUTTON_VARIANTS = [\"primary\", \"secondary\", \"tertiary\", \"brand\", \"dark\", \"light\", \"outline\", \"link\"] as const;\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\n\n/** Inner markup of each icon: lucide-react 1.8.0 paths (ISC), 24×24, stroke-drawn. */\nexport const BUTTON_ICONS = {\n \"arrow-right\": '<path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/>',\n \"arrow-up-right\": '<path d=\"M7 7h10v10\"/><path d=\"M7 17 17 7\"/>',\n \"chevron-right\": '<path d=\"m9 18 6-6-6-6\"/>',\n plus: '<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>',\n check: '<path d=\"M20 6 9 17l-5-5\"/>',\n download: '<path d=\"M12 15V3\"/><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><path d=\"m7 10 5 5 5-5\"/>',\n \"external-link\": '<path d=\"M15 3h6v6\"/><path d=\"M10 14 21 3\"/><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>',\n mail: '<path d=\"m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"/><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/>',\n phone: '<path d=\"M13.832 16.568a1 1 0 0 0 1.213-.303l.355-.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2A18 18 0 0 1 2 4a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-.8 1.6l-.468.351a1 1 0 0 0-.292 1.233 14 14 0 0 0 6.392 6.384\"/>',\n calendar: '<path d=\"M8 2v4\"/><path d=\"M16 2v4\"/><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"/><path d=\"M3 10h18\"/>',\n play: '<path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/>',\n search: '<path d=\"m21 21-4.34-4.34\"/><circle cx=\"11\" cy=\"11\" r=\"8\"/>',\n \"shopping-cart\": '<circle cx=\"8\" cy=\"21\" r=\"1\"/><circle cx=\"19\" cy=\"21\" r=\"1\"/><path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\"/>',\n star: '<path d=\"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z\"/>',\n sparkles: '<path d=\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\"/><path d=\"M20 2v4\"/><path d=\"M22 4h-4\"/><circle cx=\"4\" cy=\"20\" r=\"2\"/>',\n zap: '<path d=\"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\"/>',\n} as const;\nexport type ButtonIcon = keyof typeof BUTTON_ICONS;\nexport const BUTTON_ICON_NAMES = Object.keys(BUTTON_ICONS) as [ButtonIcon, ...ButtonIcon[]];\n\n/** A stored variant as it renders: anything off the list is Primary. */\nexport function buttonVariantOf(value: unknown): ButtonVariant {\n return BUTTON_VARIANTS.includes(value as ButtonVariant) ? (value as ButtonVariant) : \"primary\";\n}\n\n/** A stored icon as it renders: anything off the list is no icon. */\nexport function buttonIconOf(value: unknown): ButtonIcon | null {\n return BUTTON_ICON_NAMES.includes(value as ButtonIcon) ? (value as ButtonIcon) : null;\n}\n\n/** One icon as inline SVG sized to the button's text, hidden from assistive tech (the label names the button). */\nexport function buttonIconSvg(name: ButtonIcon, cls: \"bcms-btn-icon\" | \"bcms-btn-arrow\"): string {\n return `<svg class=\"${cls}\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">${BUTTON_ICONS[name]}</svg>`;\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;;;ACK1B,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EA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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bettercms-ai/types",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",