@aglyn/plugins-ai 1.0.0 → 1.2.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/package.json +17 -17
- package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
- package/src/lib/components/ai-site-start-card.component.js +40 -13
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +17 -1
- package/src/lib/components/ai-site-start-steps.component.js +30 -7
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +8 -12
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +3 -0
- package/src/lib/jobs/ai-job-drafts.js +5 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-language.d.ts +10 -0
- package/src/lib/jobs/ai-job-layout-language.js +38 -2
- package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +3 -3
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-site-import-compile.js +15 -7
- package/src/lib/jobs/ai-site-import-compile.js.map +1 -1
- package/src/lib/layout-language/ai-layout-compiler.js +39 -1
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.d.ts +6 -0
- package/src/lib/layout-language/ai-layout-frame.js +85 -30
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +5 -0
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/model/ai-site-import-fidelity.d.ts +175 -0
- package/src/lib/model/ai-site-import-fidelity.js +941 -0
- package/src/lib/model/ai-site-import-fidelity.js.map +1 -0
- package/src/lib/model/ai-site-start.d.ts +27 -0
- package/src/lib/model/ai-site-start.js +41 -0
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/assist-page-change.d.ts +26 -6
- package/src/lib/model/assist-page-change.js +32 -10
- package/src/lib/model/assist-page-change.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.js +18 -2
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/server/assist-chat.d.ts +5 -0
- package/src/lib/server/assist-chat.js +11 -2
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-page-change.d.ts +12 -0
- package/src/lib/server/assist-page-change.js +23 -1
- package/src/lib/server/assist-page-change.js.map +1 -1
- package/src/lib/site-import/fixtures/site-import-fidelity-replay.d.ts +62 -0
- package/src/lib/site-import/fixtures/site-import-fidelity-replay.js +374 -0
- package/src/lib/site-import/fixtures/site-import-fidelity-replay.js.map +1 -0
|
@@ -99,6 +99,12 @@ export interface AiLayoutFrameBrand {
|
|
|
99
99
|
logo?: {
|
|
100
100
|
src: string;
|
|
101
101
|
} | null;
|
|
102
|
+
/** The logo a dark-scheme visitor sees, where the frame draws one for each scheme (AGL-4119). */
|
|
103
|
+
logoDark?: {
|
|
104
|
+
src: string;
|
|
105
|
+
} | null;
|
|
106
|
+
/** Whether the footer opens with the logo too (AGL-4119). */
|
|
107
|
+
footer?: boolean;
|
|
102
108
|
/** Whether the header prints the name as words, beside the logo or alone. */
|
|
103
109
|
name: boolean;
|
|
104
110
|
/** The logo's words for a screen reader, as the source names it (AGL-4108); the site's name where it gave none. */
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
1
3
|
/**
|
|
2
4
|
* @license
|
|
3
5
|
* Copyright 2026 Aglyn LLC
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
16
|
* See the License for the specific language governing permissions and
|
|
15
17
|
* limitations under the License.
|
|
16
|
-
*/ import {
|
|
18
|
+
*/ import { SX_SCHEME_DARK_KEY } from "@aglyn/aglyn/app-utils/scheme-sx";
|
|
17
19
|
import { AI_ICON_LIBRARY } from "../runtime/ai-icon-library.js";
|
|
18
20
|
import { AI_LAYOUT_MAX_IMAGES, bandSx, compileFlow, compileRow, destinationProps } from "./ai-layout-compiler.js";
|
|
19
21
|
import { aiLayoutContactItems, aiLayoutContactShown } from "./ai-layout-contact.js";
|
|
@@ -93,8 +95,8 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
97
|
/** Compiles a site's header and footer, designed in the layout language, into its layout. */ export function aiCompileLayoutFrame(frame, plan, targets) {
|
|
96
|
-
var _ref, _frame_header, _header_band, _plan_source, _ref1, _ref2, _ref3;
|
|
97
|
-
var _plan_storeLinks, _plan_brand_logo, _plan_brand, _plan_brand1, _plan_brand2, _plan_brand3, _plan_brand4, _plan_storeLinks1;
|
|
98
|
+
var _ref, _frame_header, _header_band, _plan_source, _ref1, _ref2, _ref3, _ref4;
|
|
99
|
+
var _plan_storeLinks, _plan_brand_logo, _plan_brand, _plan_brand1, _plan_brand_logoDark, _plan_brand2, _plan_brand3, _plan_brand4, _plan_brand5, _plan_storeLinks1;
|
|
98
100
|
const tree = new AiLayoutTreeBuilder('lf');
|
|
99
101
|
// A store's own pages are destinations the footer's list links by path (AGL-3676).
|
|
100
102
|
const storePages = ((_ref = (_plan_storeLinks = plan.storeLinks) == null ? void 0 : _plan_storeLinks.footer) != null ? _ref : []).map((link)=>({
|
|
@@ -187,9 +189,10 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
187
189
|
const alt = ((_ref1 = (_plan_brand1 = plan.brand) == null ? void 0 : _plan_brand1.alt) != null ? _ref1 : '').replace(/\s+/g, ' ').trim().slice(0, 120) || name.slice(0, 40);
|
|
188
190
|
const brand = logo ? brandMark(tree, {
|
|
189
191
|
src: logo,
|
|
192
|
+
srcDark: (_ref2 = (_plan_brand2 = plan.brand) == null ? void 0 : (_plan_brand_logoDark = _plan_brand2.logoDark) == null ? void 0 : _plan_brand_logoDark.src) != null ? _ref2 : null,
|
|
190
193
|
name: name.slice(0, 40),
|
|
191
194
|
alt,
|
|
192
|
-
withName: ((
|
|
195
|
+
withName: ((_plan_brand3 = plan.brand) == null ? void 0 : _plan_brand3.name) === true,
|
|
193
196
|
homeId: plan.homeId,
|
|
194
197
|
centered: centeredNav,
|
|
195
198
|
grow: !source
|
|
@@ -204,9 +207,9 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
204
207
|
component: 'p'
|
|
205
208
|
}, brandSx, null, 'brand');
|
|
206
209
|
// How wide the brand is drawn, which the row is measured with (AGL-4108).
|
|
207
|
-
const aspect = ((
|
|
210
|
+
const aspect = ((_plan_brand4 = plan.brand) == null ? void 0 : _plan_brand4.aspect) && Number.isFinite(plan.brand.aspect) && plan.brand.aspect > 0 ? Math.min(plan.brand.aspect, 8) : null;
|
|
208
211
|
const logoHeight = Number.parseInt(AI_LAYOUT_LOGO_HEIGHT, 10);
|
|
209
|
-
const brandWidth = logo ? (aspect ? Math.round(aspect * logoHeight) : AI_LAYOUT_HEADER_MEASURE.logo) + (((
|
|
212
|
+
const brandWidth = logo ? (aspect ? Math.round(aspect * logoHeight) : AI_LAYOUT_HEADER_MEASURE.logo) + (((_plan_brand5 = plan.brand) == null ? void 0 : _plan_brand5.name) ? name.slice(0, 40).length * 11 + 12 : 0) : Math.min(name.length, 40) * 11;
|
|
210
213
|
// The source's own header (AGL-4108), drawn as it builds it.
|
|
211
214
|
const close = [
|
|
212
215
|
AI_LAYOUT_CLOSE_DRAWER
|
|
@@ -225,7 +228,7 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
225
228
|
})),
|
|
226
229
|
ctas: []
|
|
227
230
|
});
|
|
228
|
-
const breakpoint = (
|
|
231
|
+
const breakpoint = (_ref3 = drawn == null ? void 0 : drawn.breakpoint) != null ? _ref3 : pagesBreakpoint;
|
|
229
232
|
const nav = drawn ? drawn.nav : pages.length ? tree.add('muiStack', {
|
|
230
233
|
component: 'nav',
|
|
231
234
|
ariaLabel: 'Main',
|
|
@@ -282,7 +285,7 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
282
285
|
flexShrink: 0
|
|
283
286
|
}, null, 'cta') : null;
|
|
284
287
|
// A store's account, beside its cart and in the phone's menu (AGL-3676).
|
|
285
|
-
const accountPath = (
|
|
288
|
+
const accountPath = (_ref4 = (_plan_storeLinks1 = plan.storeLinks) == null ? void 0 : _plan_storeLinks1.account) != null ? _ref4 : null;
|
|
286
289
|
const accountLink = (role, interactions, sx)=>{
|
|
287
290
|
const id = tree.add('muiScreenLink', {
|
|
288
291
|
children: aiLayoutLabel('account', plan.language),
|
|
@@ -551,8 +554,8 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
551
554
|
* written by code: the site's pages, where the design links none of them,
|
|
552
555
|
* and the site's name under a rule.
|
|
553
556
|
*/ function compileFooter(page, footer, plan, name) {
|
|
554
|
-
var _ref, _ref1, _ref2;
|
|
555
|
-
var _plan_storeLinks;
|
|
557
|
+
var _ref, _ref1, _ref2, _ref3, _plan_brand_alt;
|
|
558
|
+
var _plan_storeLinks, _plan_brand, _plan_brand_logo, _plan_brand_logoDark;
|
|
556
559
|
const tree = page.tree;
|
|
557
560
|
const asked = (_ref = footer == null ? void 0 : footer.band) != null ? _ref : 'soft';
|
|
558
561
|
const band = plan.closesDark && (asked === 'brand' || asked === 'dark') ? 'soft' : asked;
|
|
@@ -719,9 +722,25 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
719
722
|
}, [
|
|
720
723
|
copyright
|
|
721
724
|
], 'footerBottom');
|
|
725
|
+
// The site's own logo, where the header draws it from the site (AGL-4119).
|
|
726
|
+
const footerLogo = ((_plan_brand = plan.brand) == null ? void 0 : _plan_brand.footer) && ((_plan_brand_logo = plan.brand.logo) == null ? void 0 : _plan_brand_logo.src) ? tree.add('muiBox', null, null, logoPictures(tree, {
|
|
727
|
+
src: plan.brand.logo.src,
|
|
728
|
+
srcDark: (_ref3 = (_plan_brand_logoDark = plan.brand.logoDark) == null ? void 0 : _plan_brand_logoDark.src) != null ? _ref3 : null,
|
|
729
|
+
props: {
|
|
730
|
+
alt: ((_plan_brand_alt = plan.brand.alt) != null ? _plan_brand_alt : '').trim() || name.slice(0, 40),
|
|
731
|
+
objectFit: 'contain',
|
|
732
|
+
width: 'auto',
|
|
733
|
+
height: AI_LAYOUT_LOGO_HEIGHT
|
|
734
|
+
},
|
|
735
|
+
role: 'footerLogo'
|
|
736
|
+
}), 'footerLogoBox') : null;
|
|
722
737
|
const stack = tree.add('muiStack', {
|
|
723
738
|
spacing: '6'
|
|
724
|
-
}, null, [
|
|
739
|
+
}, null, footerLogo ? [
|
|
740
|
+
footerLogo,
|
|
741
|
+
top,
|
|
742
|
+
bottom
|
|
743
|
+
] : [
|
|
725
744
|
top,
|
|
726
745
|
bottom
|
|
727
746
|
], 'footerStack');
|
|
@@ -783,38 +802,74 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
783
802
|
container
|
|
784
803
|
], 'footer');
|
|
785
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* A logo as a picture, or as a pair where the site keeps one for dark
|
|
807
|
+
* backgrounds (AGL-4119): the second takes the first's place in the dark
|
|
808
|
+
* scheme, so a visitor sees exactly one.
|
|
809
|
+
*/ function logoPictures(tree, input) {
|
|
810
|
+
const light = tree.add('image', _extends({
|
|
811
|
+
src: input.src
|
|
812
|
+
}, input.props), input.srcDark ? {
|
|
813
|
+
[SX_SCHEME_DARK_KEY]: {
|
|
814
|
+
display: 'none'
|
|
815
|
+
}
|
|
816
|
+
} : null, null, input.role);
|
|
817
|
+
if (!input.srcDark) return [
|
|
818
|
+
light
|
|
819
|
+
];
|
|
820
|
+
const _input_props = input.props, { loading: _deferred } = _input_props, props = _object_without_properties_loose(_input_props, [
|
|
821
|
+
"loading"
|
|
822
|
+
]);
|
|
823
|
+
const dark = tree.add('image', _extends({
|
|
824
|
+
src: input.srcDark
|
|
825
|
+
}, props), {
|
|
826
|
+
display: 'none',
|
|
827
|
+
[SX_SCHEME_DARK_KEY]: {
|
|
828
|
+
display: 'block'
|
|
829
|
+
}
|
|
830
|
+
}, null, `${input.role}Dark`);
|
|
831
|
+
return [
|
|
832
|
+
light,
|
|
833
|
+
dark
|
|
834
|
+
];
|
|
835
|
+
}
|
|
786
836
|
/**
|
|
787
837
|
* The header's brand drawn with the site's logo (AGL-4084), as the source's
|
|
788
838
|
* header draws it: the logo alone, named by its alt text, or the logo with
|
|
789
839
|
* the name beside it; either way the link home.
|
|
790
840
|
*/ function brandMark(tree, input) {
|
|
791
|
-
const image = (alone)=>tree
|
|
792
|
-
src: input.src
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
841
|
+
const image = (alone, linked)=>logoPictures(tree, {
|
|
842
|
+
src: input.src,
|
|
843
|
+
srcDark: input.srcDark,
|
|
844
|
+
role: 'logo',
|
|
845
|
+
props: _extends({}, alone ? {
|
|
846
|
+
alt: input.alt
|
|
847
|
+
} : {
|
|
848
|
+
decorative: true
|
|
849
|
+
}, {
|
|
850
|
+
objectFit: 'contain',
|
|
851
|
+
width: 'auto',
|
|
852
|
+
height: AI_LAYOUT_LOGO_HEIGHT,
|
|
853
|
+
loading: 'eager'
|
|
854
|
+
}, linked && input.homeId ? {
|
|
855
|
+
screenId: input.homeId
|
|
856
|
+
} : {})
|
|
857
|
+
});
|
|
805
858
|
// Never narrower than the logo (AGL-4108); it grows into the room the
|
|
806
859
|
// navigation leaves only where the navigation does not take it itself.
|
|
807
860
|
const grow = input.centered || !input.grow ? null : {
|
|
808
861
|
flexGrow: 1
|
|
809
862
|
};
|
|
810
863
|
if (!input.withName) {
|
|
811
|
-
|
|
864
|
+
// One link around a pair, so the picture out of sight is no stop in the tab order.
|
|
865
|
+
const homeLink = input.srcDark && input.homeId;
|
|
866
|
+
return tree.add(homeLink ? 'muiLinkBox' : 'muiBox', homeLink ? {
|
|
867
|
+
screenId: input.homeId
|
|
868
|
+
} : null, _extends({}, grow != null ? grow : {}, {
|
|
812
869
|
display: 'flex',
|
|
813
870
|
alignItems: 'center',
|
|
814
871
|
flexShrink: 0
|
|
815
|
-
}),
|
|
816
|
-
image(true)
|
|
817
|
-
], 'brand');
|
|
872
|
+
}), image(true, !homeLink), 'brand');
|
|
818
873
|
}
|
|
819
874
|
const words = tree.add('muiTypography', {
|
|
820
875
|
children: input.name,
|
|
@@ -829,7 +884,7 @@ import { AiLayoutTreeBuilder } from "./ai-layout-tree.js";
|
|
|
829
884
|
spacing: '1.5',
|
|
830
885
|
alignItems: 'center'
|
|
831
886
|
}, null, [
|
|
832
|
-
image(false),
|
|
887
|
+
...image(false, false),
|
|
833
888
|
words
|
|
834
889
|
], 'brandRow');
|
|
835
890
|
return input.homeId ? tree.add('muiLinkBox', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-frame.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { AiStoreFrameLinks } from '../model/ai-site-store-pages'\nimport { AI_ICON_LIBRARY } from '../runtime/ai-icon-library'\nimport {\n AI_LAYOUT_MAX_IMAGES,\n bandSx,\n compileFlow,\n compileRow,\n destinationProps,\n type PageScope,\n type SectionScope,\n} from './ai-layout-compiler'\nimport { aiLayoutContactItems, aiLayoutContactShown } from './ai-layout-contact'\nimport { aiLayoutFitText } from './ai-layout-copy'\nimport { aiLayoutRepairFrameHollows } from './ai-layout-frame-hollows'\nimport { AI_LAYOUT_CART_ELEMENT } from './ai-layout-listings'\nimport {\n AI_LAYOUT_MAX_ITEMS,\n type AiLayoutBand,\n type AiLayoutBlock,\n type AiLayoutSection,\n type AiLayoutSettlement,\n} from './ai-layout-language'\nimport { AI_LAYOUT_LABELS_EN, aiLayoutLabel } from './ai-layout-labels'\nimport {\n aiLayoutRenamedLabel,\n aiLayoutResolveLink,\n type AiLayoutPage,\n type AiLayoutTargets,\n} from './ai-layout-links'\nimport {\n AI_LAYOUT_HEADER_MEASURE,\n aiLayoutNavBreakpoint,\n aiLayoutSourceFooter,\n aiLayoutSourceHeader,\n type AiLayoutFrameSource,\n} from './ai-layout-frame-source'\nimport { AiLayoutTreeBuilder, type AiLayoutRawTree } from './ai-layout-tree'\n\n/**\n * A site's frame — the header and the footer every page renders between —\n * compiled from the layout language (AGL-3660), the same language a page is\n * designed in.\n *\n * The design is the model's: the header's band and alignment and its one\n * call to action, and the footer's columns and every word in them. What a\n * frame owes the site is the platform's, written here, so it is never wrong\n * and never invented: the site's name as the brand, linking home; its pages\n * as the navigation, a row on a wide screen and the platform's Drawer behind\n * its Menu Button on a phone; the Layout Slot, the page's one main landmark,\n * held tall enough that the footer sits at the bottom of a short page; and\n * the site's pages and name in the footer, where the design gave neither.\n *\n * Every label of the navigation is held to one line, the logo never narrower\n * than itself, and the row shows from the screen width it measures to fit\n * (`aiLayoutNavBreakpoint`), the Menu Button below it (AGL-4108: the 10/29\n * import's seven long titles wrapped from 900 px up and the logo lay over\n * \"Home\" at 1280). A site brought in from elsewhere whose menu the reader\n * found is drawn as its source builds it instead (`plan.source`,\n * `ai-layout-frame-source.ts`): its menus, its buttons, its phone menu and its\n * footer, in place of the site's pages and the design's button and footer.\n */\n\nexport interface AiLayoutFramePlan {\n /** The site's name, which the header and the footer carry as its brand. */\n siteName: string\n /** The site's home page, which the brand links; none where the site has none yet. */\n homeId: string | null\n /** The pages the navigation links, in order. */\n navPages: readonly AiLayoutPage[]\n /**\n * Whether the site's pages close on a dark photo band (AGL-3660,\n * `AiLayoutDesignChoices.coverClose`): a brand or dark footer under it\n * would read as a second loud band, so the footer takes the quiet one.\n */\n closesDark?: boolean\n /**\n * Whether the site sells (AGL-3676): its header carries the store's cart\n * button — the commerce plugin's Cart, which opens the cart in a drawer\n * from every page — beside the navigation.\n */\n cart?: boolean\n /**\n * A selling store's Shop page (AGL-3676), by its id. Its header is a\n * storefront's: the cart beside the navigation and no call-to-action button\n * repeating a link the navigation already has, and a thin announcement bar\n * above it — the line the design gave its header as a note, else one that\n * opens the shop — linking the Shop page.\n */\n shopId?: string | null\n /**\n * A store's own pages (AGL-3676), by path: the header links the account\n * beside the cart, and the footer the account and the store's policies\n * under the site's pages. They are written after the layout, so they are\n * linked by their addresses, as the blog is.\n */\n storeLinks?: AiStoreFrameLinks | null\n /** The site's language (AGL-3760): the frame's own words are in it where `ai-layout-labels.ts` lists it. */\n language?: string\n /**\n * The brand as a site brought in from elsewhere draws it (AGL-4084): its\n * logo alone, its logo with its name, or its name alone, as the source's\n * header shows it. Absent, the name alone.\n */\n brand?: AiLayoutFrameBrand | null\n /**\n * A site brought in from elsewhere whose header the reader found\n * (AGL-4108): its menu with its menus, its buttons with their own\n * addresses, its phone menu and its footer, drawn as the source has them\n * (`ai-layout-frame-source.ts`) in place of the site's pages and the\n * design's button and footer.\n */\n source?: AiLayoutFrameSource | null\n}\n\n/** A header's brand as the source shows it (AGL-4084). */\nexport interface AiLayoutFrameBrand {\n /** The logo, from the site's own media library. */\n logo?: { src: string } | null\n /** Whether the header prints the name as words, beside the logo or alone. */\n name: boolean\n /** The logo's words for a screen reader, as the source names it (AGL-4108); the site's name where it gave none. */\n alt?: string\n /** The logo's width over its height, which the header row is measured with (AGL-4108). */\n aspect?: number\n}\n\n/** The height a header's logo is drawn at: a Besigner field the owner may change. */\nexport const AI_LAYOUT_LOGO_HEIGHT = '40px'\n\n/** What the header's link to a store's account page says (AGL-3676), in English. */\nexport const AI_LAYOUT_ACCOUNT_LINK = AI_LAYOUT_LABELS_EN.account\n\n/** What a store's announcement bar says where its design gave it no line (AGL-3676): true of every store. */\nexport const AI_LAYOUT_STORE_ANNOUNCEMENT = AI_LAYOUT_LABELS_EN.storeAnnouncement\n\n/** The way into the shop beside the design's own announcement (AGL-3676). */\nexport const AI_LAYOUT_STORE_ANNOUNCEMENT_LINK = AI_LAYOUT_LABELS_EN.shopNow\n\nexport interface AiLayoutCompiledFrame {\n tree: AiLayoutRawTree\n settled: AiLayoutSettlement[]\n}\n\n/** The header's colors by band, as palette roles. */\nfunction headerLook(band: AiLayoutBand): {\n props: Record<string, unknown>\n sx: Record<string, unknown>\n} {\n if (band === 'brand')\n return { props: { color: 'primary' }, sx: { boxShadow: 'none' } }\n if (band === 'dark') {\n return {\n props: { color: 'primary' },\n sx: {\n boxShadow: 'none',\n bgcolor: 'primary.dark',\n color: 'primary.contrastText',\n },\n }\n }\n // A rule, a shadow or nothing under a plain header is the site theme's\n // MuiAppBar style (AGL-3660); the band's color stays here.\n return {\n props: { color: 'inherit' },\n sx: { bgcolor: 'background.paper' },\n }\n}\n\n/** A line that reads as a copyright notice: \"© 2026 …\", \"Copyright …\", \"All rights reserved.\" */\nexport function aiLayoutIsCopyright(text: unknown): boolean {\n return typeof text === 'string' && /^\\s*(?:©|\\(c\\)|copyright\\b)|all rights reserved/i.test(text)\n}\n\n/** What a footer leaves out: a picture slot, and the page sections a footer is no place for. */\nconst FOOTER_LEAVES_OUT: ReadonlySet<AiLayoutBlock['kind']> = new Set([\n 'image',\n 'faq',\n 'quotes',\n 'cards',\n 'steps',\n 'stats',\n 'form',\n 'component',\n])\n\n/** A frame scope: no headings of its own (a layout carries no outline), no pictures. */\nfunction frameScope(\n page: PageScope,\n at: string,\n band: AiLayoutBand,\n centered: boolean,\n): SectionScope {\n return {\n page,\n index: at === 'header' ? 0 : 1,\n at,\n band,\n centered,\n level: 2,\n headed: true,\n itemsLeft: AI_LAYOUT_MAX_ITEMS,\n frame: true,\n link: { sections: [], from: -1, formSection: null },\n }\n}\n\n/** Compiles a site's header and footer, designed in the layout language, into its layout. */\nexport function aiCompileLayoutFrame(\n frame: { header: AiLayoutSection | null; footer: AiLayoutSection | null },\n plan: AiLayoutFramePlan,\n targets: AiLayoutTargets,\n): AiLayoutCompiledFrame {\n const tree = new AiLayoutTreeBuilder('lf')\n // A store's own pages are destinations the footer's list links by path (AGL-3676).\n const storePages: AiLayoutPage[] = (plan.storeLinks?.footer ?? []).map((link) => ({\n id: `store:${link.href}`,\n label: link.label,\n slug: link.href,\n href: link.href,\n }))\n const page: PageScope = {\n tree,\n plan: { title: plan.siteName, sections: [] },\n targets: { ...targets, pages: [...targets.pages, ...storePages], pageId: null },\n // A footer is drawn compact: its lines are lines, never blocks rule 1 would ask to share.\n options: { reusableComponents: true, ...(plan.language ? { language: plan.language } : {}) },\n settled: [],\n scrollTo: {},\n // A frame's lines are its own, never a page section's items.\n itemIds: [],\n // A frame shows no picture slot: a header and a footer are the same on every page.\n images: AI_LAYOUT_MAX_IMAGES,\n strong: { brand: 0, dark: 0 },\n formSection: null,\n pageIcon: AI_ICON_LIBRARY.sparkle,\n formsPlaced: new Set(),\n // A frame is drawn the platform's one way on every site.\n design: null,\n pictures: 0,\n features: 0,\n splitAt: -2,\n quotesOnly: [],\n }\n const name = aiLayoutFitText(plan.siteName, 'heading', plan.language) || 'Home'\n const header = frame.header ?? { blocks: [] }\n const band = header.band ?? 'plain'\n const look = headerLook(band)\n const scope = frameScope(\n page,\n 'header',\n band === 'brand' || band === 'dark' ? 'brand' : 'plain',\n false,\n )\n const navLink = (\n entry: AiLayoutPage,\n role: string,\n interactions?: unknown[],\n ) => {\n const id = tree.add(\n 'muiScreenLink',\n {\n children:\n aiLayoutFitText(entry.label, 'label', plan.language) || entry.label.slice(0, 28),\n // The blog is a path, not a page (AGL-3660).\n ...(entry.href ? { href: entry.href } : { screenId: entry.id }),\n renderAs: 'link',\n color: 'inherit',\n },\n { textDecoration: 'none' },\n null,\n role,\n )\n if (interactions) tree.nodes[id].interactions = interactions\n return id\n }\n const pages = plan.navPages.filter((entry) => entry.label.trim())\n const centeredNav = header.align === 'center' && pages.length > 0\n // The brand takes the room the navigation does not, and gives way before\n // it does: a long name ends in an ellipsis rather than pushing into the links.\n // A logo never gives way: drawn narrower than itself it lay over the first\n // link (the 10/29 header at 1280, AGL-4108).\n const brandSx = {\n typography: 'h6',\n fontWeight: 800,\n textDecoration: 'none',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n minWidth: 0,\n ...(centeredNav ? {} : { flexGrow: 1 }),\n }\n const logo = plan.brand?.logo?.src ? plan.brand.logo.src : null\n const source = plan.source ?? null\n const alt = (plan.brand?.alt ?? '').replace(/\\s+/g, ' ').trim().slice(0, 120) || name.slice(0, 40)\n const brand = logo\n ? brandMark(tree, { src: logo, name: name.slice(0, 40), alt, withName: plan.brand?.name === true, homeId: plan.homeId, centered: centeredNav, grow: !source })\n : plan.homeId\n ? tree.add(\n 'muiScreenLink',\n {\n children: name.slice(0, 40),\n screenId: plan.homeId,\n renderAs: 'link',\n color: 'inherit',\n },\n brandSx,\n null,\n 'brand',\n )\n : tree.add(\n 'muiTypography',\n { children: name, variant: 'h6', component: 'p' },\n brandSx,\n null,\n 'brand',\n )\n // How wide the brand is drawn, which the row is measured with (AGL-4108).\n const aspect = plan.brand?.aspect && Number.isFinite(plan.brand.aspect) && plan.brand.aspect > 0 ? Math.min(plan.brand.aspect, 8) : null\n const logoHeight = Number.parseInt(AI_LAYOUT_LOGO_HEIGHT, 10)\n const brandWidth = logo\n ? (aspect ? Math.round(aspect * logoHeight) : AI_LAYOUT_HEADER_MEASURE.logo) + (plan.brand?.name ? name.slice(0, 40).length * 11 + 12 : 0)\n : Math.min(name.length, 40) * 11\n // The source's own header (AGL-4108), drawn as it builds it.\n const close = [AI_LAYOUT_CLOSE_DRAWER]\n const drawn = source ? aiLayoutSourceHeader(tree, source, { onBrand: band === 'brand' || band === 'dark', close, brandWidth }) : null\n // Every label on one line, and the row only on a screen it fits (AGL-4108).\n const pagesBreakpoint = aiLayoutNavBreakpoint({ brandWidth, nav: pages.map((entry) => ({ label: entry.label, menu: false })), ctas: [] })\n const breakpoint = drawn?.breakpoint ?? pagesBreakpoint\n const nav = drawn\n ? drawn.nav\n : pages.length\n ? tree.add(\n 'muiStack',\n {\n component: 'nav',\n ariaLabel: 'Main',\n direction: 'row',\n spacing: '3',\n alignItems: 'center',\n },\n { display: { xs: 'none', [breakpoint]: 'flex' }, whiteSpace: 'nowrap' },\n pages.map((entry) => navLink(entry, 'navLink')),\n 'nav',\n )\n : null\n // The design's call to action: its first button, where it goes somewhere.\n // A source's header carries its own buttons instead (AGL-4108).\n const ctaBlock = source ? undefined : header.blocks.find((block) => block.kind === 'button')\n // A store's announcement: the first short line the design gave its header (AGL-3676).\n const store = !!plan.shopId\n const noteBlock = store ? header.blocks.find((block) => block.kind === 'note' || block.kind === 'text' || block.kind === 'lede') : undefined\n for (const block of header.blocks) {\n if (block !== ctaBlock && block !== noteBlock)\n page.settled.push({\n at: 'header',\n what: `a ${block.kind} in the header; left out`,\n })\n }\n const ctaLabel = ctaBlock ? aiLayoutFitText(ctaBlock.text, 'label', plan.language) : ''\n const ctaResolved =\n ctaBlock && ctaLabel\n ? aiLayoutResolveLink(ctaBlock.to, ctaLabel, scope.link, page.targets)\n : null\n if (ctaBlock && !ctaResolved)\n page.settled.push({\n at: 'header',\n what: `the button \"${ctaLabel}\" has nowhere to go; left out`,\n })\n // A storefront's header is its navigation and its cart (AGL-3676): the\n // live Willow Wick header's \"Shop candles\" button repeated its nav's Shop.\n // A store's button that only repeats a page the navigation links is left\n // out, and a store that sells carries its cart in that place instead.\n const repeatsNav =\n ctaResolved?.kind === 'page' && pages.some((entry) => !entry.href && entry.id === ctaResolved.screenId)\n const ctaTo = ctaResolved && store && (plan.cart || repeatsNav) ? null : ctaResolved\n if (ctaResolved && !ctaTo)\n page.settled.push({\n at: 'header',\n what: `the button \"${ctaLabel}\" left out: a store's header carries its ${plan.cart ? 'cart' : 'navigation'}, not a button repeating it`,\n })\n const ctaProps = ctaTo\n ? {\n children: aiLayoutRenamedLabel(ctaLabel, ctaTo),\n variant: 'contained',\n color: scope.band === 'brand' ? 'secondary' : 'primary',\n ...destinationProps(ctaTo),\n }\n : null\n // On the smallest phones the call to action moves into the menu.\n const cta = ctaProps\n ? tree.add(\n 'muiButton',\n ctaProps,\n {\n display: { xs: 'none', sm: 'inline-flex' },\n whiteSpace: 'nowrap',\n flexShrink: 0,\n },\n null,\n 'cta',\n )\n : null\n // A store's account, beside its cart and in the phone's menu (AGL-3676).\n const accountPath = plan.storeLinks?.account ?? null\n const accountLink = (role: string, interactions?: unknown[], sx?: Record<string, unknown>) => {\n const id = tree.add(\n 'muiScreenLink',\n { children: aiLayoutLabel('account', plan.language), href: accountPath, renderAs: 'link', color: 'inherit' },\n { textDecoration: 'none', whiteSpace: 'nowrap', ...sx },\n null,\n role,\n )\n if (interactions) tree.nodes[id].interactions = interactions\n return id\n }\n // A phone's menu: the platform's Drawer, opened by its Menu Button; a link\n // followed from it closes it. A source's holds its menus, links and buttons (AGL-4108).\n const drawer = drawn?.drawer.length\n ? tree.add(\n 'muiDrawer',\n { anchor: 'right' },\n null,\n [\n tree.add(\n 'muiStack',\n { component: 'nav', ariaLabel: 'Menu' },\n { display: 'flex', flexDirection: 'column', gap: 3, p: 3 },\n [...drawn.drawer, accountPath ? accountLink('menuAccount', close) : null],\n 'menu',\n ),\n ],\n 'drawer',\n )\n : !source && pages.length\n ? tree.add(\n 'muiDrawer',\n { anchor: 'right' },\n null,\n [\n tree.add(\n 'muiStack',\n { component: 'nav', ariaLabel: 'Menu' },\n {\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n p: 3,\n typography: 'h6',\n },\n [\n ...pages.map((entry) => navLink(entry, 'menuLink', close)),\n accountPath ? accountLink('menuAccount', close) : null,\n ctaProps\n ? tree.add(\n 'muiButton',\n { ...ctaProps, fullWidth: true },\n { mt: 2 },\n null,\n 'menuCta',\n )\n : null,\n ],\n 'menu',\n ),\n ],\n 'drawer',\n )\n : null\n const toggle = drawer\n ? tree.add(\n 'muiDrawerToggle',\n { ariaLabel: 'Open the menu' },\n // Pushed to the end of the row where no button is there to push it.\n { display: { xs: 'inline-flex', [breakpoint]: 'none' }, flexShrink: 0, ...(drawn && !drawn.ctas ? { ml: 'auto' } : {}) },\n null,\n 'menuButton',\n )\n : null\n const middle =\n nav && centeredNav\n ? tree.add(\n 'muiBox',\n null,\n { flexGrow: 1, display: 'flex', justifyContent: 'center' },\n [nav],\n 'navRoom',\n )\n : nav\n // A store's cart, on every page, where a shopper looks for it (AGL-3676).\n const cart = plan.cart\n ? tree.add(AI_LAYOUT_CART_ELEMENT, { variant: 'button' }, { flexShrink: 0 }, null, 'cart')\n : null\n // On a phone the account is in the menu, and the cart stays in the bar.\n const account = accountPath ? accountLink('account', undefined, { display: { xs: 'none', [breakpoint]: 'inline-flex' }, flexShrink: 0 }) : null\n // The row lives in a Container inside the Toolbar Content, which may only sit in an App Bar.\n const row = tree.add(\n 'muiContainer',\n { maxWidth: 'lg' },\n { display: 'flex', alignItems: 'center', columnGap: 3 },\n [brand, middle, drawn ? drawn.ctas : cta, account, cart, toggle, drawer],\n 'headerRow',\n )\n const toolbar = tree.add(\n 'muiToolbar',\n { disableGutters: true },\n { minHeight: { xs: 64, md: 76 } },\n [row],\n 'toolbar',\n )\n // A source's header bar on the ground it sits on (AGL-4108): the page's own, where it is the page's.\n const barLook = source?.header === 'page' ? { props: { color: 'inherit' }, sx: { bgcolor: 'background.default' } } : look\n const bar = tree.add(\n 'muiAppBar',\n {\n ...barLook.props,\n position: 'sticky',\n // Over a page that opens with a photo cover, the bar sits on the photo (AGL-3660).\n overHero: true,\n component: 'header',\n ariaLabel: 'Site header',\n },\n barLook.sx,\n [toolbar],\n 'header',\n )\n // A selling store's announcement bar, above the header, linking its shop (AGL-3676).\n const announcement =\n store && plan.cart && plan.shopId\n ? (() => {\n const said = aiLayoutFitText(noteBlock?.text, 'note', plan.language)\n if (noteBlock && !said) page.settled.push({ at: 'header', what: 'an announcement with no words left; the shop’s own line instead' })\n // The design's line, then the way into the shop; else the way in alone.\n const link = tree.add(\n 'muiScreenLink',\n {\n children: aiLayoutLabel(said ? 'shopNow' : 'storeAnnouncement', plan.language),\n screenId: plan.shopId,\n renderAs: 'link',\n color: 'inherit',\n },\n { fontWeight: 700 },\n null,\n 'announcementLink',\n )\n const words = said\n ? tree.add('muiTypography', { children: said, variant: 'body2', component: 'p' }, null, null, 'announcementText')\n : null\n return tree.add(\n 'muiStack',\n { direction: 'row', spacing: '1.5', justifyContent: 'center', alignItems: 'baseline', useFlexGap: true, flexWrap: 'wrap' },\n { bgcolor: 'primary.main', color: 'primary.contrastText', typography: 'body2', py: 1, px: 2 },\n [words, link],\n 'announcement',\n )\n })()\n : null\n // The page grows into the room the window leaves, so a short page keeps\n // its footer at the bottom.\n const slot = tree.add(\n 'layoutSlot',\n { component: 'main' },\n { flexGrow: 1 },\n null,\n 'slot',\n )\n const footer = source?.footer ? sourceFooter(page, source, name) : compileFooter(page, frame.footer, plan, name)\n // No heading with nothing under it, no column of only a heading, columns\n // top-aligned (AGL-3735): a list under a heading can compile to nothing.\n if (aiLayoutRepairFrameHollows(tree.nodes as unknown as Record<string, unknown>)) {\n page.settled.push({ at: 'footer', what: 'a heading with nothing under it taken out, and its column with it' })\n }\n const column = tree.add(\n 'muiStack',\n null,\n { minHeight: '100vh' },\n [announcement, bar, slot, footer],\n 'frame',\n )\n tree.prune(column, new Set([slot]))\n const rootId = tree.add('div', null, null, [column], 'layout')\n return { tree: { rootId, nodes: tree.nodes }, settled: page.settled }\n}\n\n/** What a store's own column of account and policy links is headed where the footer design gave no store heading (AGL-3735). */\nexport const AI_LAYOUT_STORE_FOOTER_HEADING = AI_LAYOUT_LABELS_EN.customerCare\n\n/** A footer heading a store's account and policies belong under (AGL-3735). */\nconst STORE_HEADING = /\\b(?:shop|store|shopping|help|customer|care|support|service|orders?|account|policies|policy|legal|info|information|shipping|returns)\\b/i\n\n/**\n * The footer heading a store's account and policy links go under\n * (AGL-3735): a heading of the design's that names the store or its help\n * (\"Our shop\", \"Help\", \"Customer care\"), the first with nothing under it\n * before one with words or links of its own. Never the heading over the\n * site's pages, whose list is the site's navigation. `end` is where the\n * links go: the end of what that heading heads.\n */\nexport function aiLayoutFooterStoreHeading(\n columns: readonly AiLayoutBlock[][],\n navItems: readonly { to: string }[],\n): { column: AiLayoutBlock[]; end: number; heading: string } | null {\n const navTo = new Set(navItems.map((item) => item.to))\n const candidates: Array<{ column: AiLayoutBlock[]; end: number; heading: string; empty: boolean }> = []\n for (const column of columns) {\n column.forEach((block, at) => {\n if (block.kind !== 'heading' || !STORE_HEADING.test(block.text ?? '')) return\n let end = at + 1\n while (end < column.length && column[end].kind !== 'heading') end += 1\n const under = column.slice(at + 1, end)\n const site = under.some((one) => one.kind === 'list' && (one.items ?? []).some((item) => navTo.has(item.to ?? '')))\n if (site) return\n candidates.push({ column: column as AiLayoutBlock[], end, heading: String(block.text), empty: under.length === 0 })\n })\n }\n const pick = candidates.find((one) => one.empty) ?? candidates[0]\n return pick ? { column: pick.column, end: pick.end, heading: pick.heading } : null\n}\n\n/** A link followed from the phone menu closes it. */\nconst AI_LAYOUT_CLOSE_DRAWER = {\n id: 'ai-close-menu',\n name: 'Close the menu',\n enabled: true,\n trigger: { event: 'elementClick', everyTime: true },\n steps: [{ type: 'closeDrawer' }],\n}\n\n/**\n * The footer the design describes, with what every footer owes a visitor\n * written by code: the site's pages, where the design links none of them,\n * and the site's name under a rule.\n */\nfunction compileFooter(\n page: PageScope,\n footer: AiLayoutSection | null,\n plan: AiLayoutFramePlan,\n name: string,\n): string {\n const tree = page.tree\n const asked = footer?.band ?? 'soft'\n const band = plan.closesDark && (asked === 'brand' || asked === 'dark') ? 'soft' : asked\n if (band !== asked) page.settled.push({ at: 'footer', what: `a ${asked} footer under a dark closing band drawn soft` })\n const scope = frameScope(page, 'footer', band, footer?.align === 'center')\n // The footer's page links are the site's pages, every one, as the header's\n // are (AGL-3660): a list the model wrote of page links is drawn with them\n // in its place, and a footer with none gets one. The model places the list;\n // it never chooses which pages it holds.\n const navItems = plan.navPages.map((entry) => ({\n title: entry.label,\n text: '',\n to: `page:${entry.id}`,\n }))\n let linksPages = false\n const blocks = (footer?.blocks ?? []).flatMap((given): AiLayoutBlock[] => {\n // The bottom bar carries the frame's one copyright line; a line of the\n // answer's own that reads as one would print it twice.\n if (aiLayoutIsCopyright(given.text)) {\n page.settled.push({ at: 'footer', what: 'a copyright line; the footer writes its own' })\n return []\n }\n const notice = (item: { title: string; text: string }) => aiLayoutIsCopyright(item.title) || aiLayoutIsCopyright(item.text)\n const block = given.items?.some(notice) ? { ...given, items: given.items.filter((item) => !notice(item)) } : given\n if (block !== given) page.settled.push({ at: 'footer', what: 'a copyright line in a list; the footer writes its own' })\n if (FOOTER_LEAVES_OUT.has(block.kind)) {\n page.settled.push({\n at: 'footer',\n what: `a ${block.kind} in the footer; left out`,\n })\n return []\n }\n const pageLinks =\n block.kind === 'list' &&\n (block.items ?? []).some((item) => /^page:/.test(item.to ?? ''))\n if (!pageLinks) return [block]\n if (linksPages || !navItems.length) {\n page.settled.push({ at: 'footer', what: 'a second list of page links; left out' })\n return []\n }\n linksPages = true\n return [{ ...block, items: navItems }]\n })\n const cols = footer?.cols && footer.cols.length >= 2 ? footer.cols : null\n const columns: AiLayoutBlock[][] = cols ? cols.map(() => []) : [[]]\n for (const block of blocks)\n columns[\n cols && block.col !== undefined ? Math.min(block.col, cols.length - 1) : 0\n ].push(block)\n const weights = cols ? [...cols] : [2]\n if (!linksPages && plan.navPages.length) {\n columns.push([\n {\n kind: 'list',\n items: plan.navPages.map((entry) => ({\n title: entry.label,\n text: '',\n to: `page:${entry.id}`,\n })),\n },\n ])\n weights.push(1)\n }\n // A store's account and policies (AGL-3676): under the store heading the\n // design already wrote (\"Our shop\", \"Help\"…), never as a column with no\n // heading beside a heading with nothing under it (AGL-3735); where the\n // design wrote none, a column of their own, headed.\n const storeLinks = plan.storeLinks?.footer ?? []\n if (storeLinks.length) {\n const list: AiLayoutBlock = { kind: 'list', items: storeLinks.map((link) => ({ title: link.label, text: '', to: `page:store:${link.href}` })) }\n const home = aiLayoutFooterStoreHeading(columns, navItems)\n if (home) {\n home.column.splice(home.end, 0, list)\n page.settled.push({ at: 'footer', what: `the store's account and policy links under \"${home.heading}\"` })\n } else {\n columns.push([{ kind: 'heading', text: aiLayoutLabel('customerCare', plan.language) }, list])\n weights.push(1)\n }\n }\n // How to reach the business (AGL-3979): the phone and email it gave, as\n // links that call and write, in a column of their own under its heading,\n // wherever the design's footer did not already show them.\n const contact = page.targets.contact\n const contactItems = contact ? aiLayoutContactItems(contact, aiLayoutContactShown(blocks, contact)) : []\n if (contactItems.length) {\n columns.push([\n { kind: 'heading', text: aiLayoutLabel('contact', plan.language) },\n { kind: 'list', items: contactItems },\n ])\n weights.push(1)\n page.settled.push({ at: 'footer', what: 'the phone and email the business gave, in a column of their own' })\n }\n const filled = columns\n .map((column, position) => ({ column, weight: weights[position] ?? 1 }))\n .filter((entry) => entry.column.length)\n // A footer's columns are top-aligned: each starts at its heading (AGL-3735).\n const top =\n filled.length > 1\n ? compileRow(scope, filled, 'flex-start')\n : filled.length === 1\n ? compileFlow(scope, filled[0].column, 'full')\n : null\n const copyright = tree.add(\n 'muiTypography',\n { children: `© ${name}`, variant: 'body2', component: 'p' },\n scope.band === 'brand' ? null : { color: 'text.secondary' },\n null,\n 'copyright',\n )\n const bottom = tree.add(\n 'muiBox',\n null,\n { pt: 3, borderTop: 1, borderColor: 'divider' },\n [copyright],\n 'footerBottom',\n )\n const stack = tree.add(\n 'muiStack',\n { spacing: '6' },\n null,\n [top, bottom],\n 'footerStack',\n )\n const container = tree.add(\n 'muiContainer',\n { maxWidth: 'lg' },\n { py: { xs: 6, md: 8 } },\n [stack],\n 'footerInner',\n )\n return tree.add(\n 'section',\n {\n element: 'footer',\n ariaLabel: 'Site footer',\n ...(scope.band === 'dark' ? { colorScheme: 'dark' } : {}),\n },\n scope.band === 'soft'\n ? { bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider' }\n : bandSx(scope.band),\n [container],\n 'footer',\n )\n}\n\n/**\n * A source's footer (AGL-4108): its columns, words, profiles and © line, as\n * the source has them, on the quiet band a footer sits on.\n */\nfunction sourceFooter(page: PageScope, source: AiLayoutFrameSource, name: string): string {\n const tree = page.tree\n const drawn = aiLayoutSourceFooter(tree, source.footer as NonNullable<AiLayoutFrameSource['footer']>, { name })\n const stack = tree.add('muiStack', { spacing: '6' }, drawn.sx, [drawn.top, drawn.bottom], 'footerStack')\n const container = tree.add('muiContainer', { maxWidth: 'lg' }, { py: { xs: 6, md: 8 } }, [stack], 'footerInner')\n return tree.add(\n 'section',\n { element: 'footer', ariaLabel: 'Site footer' },\n { bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider' },\n [container],\n 'footer',\n )\n}\n\n/**\n * The header's brand drawn with the site's logo (AGL-4084), as the source's\n * header draws it: the logo alone, named by its alt text, or the logo with\n * the name beside it; either way the link home.\n */\nfunction brandMark(\n tree: AiLayoutTreeBuilder,\n input: { src: string; name: string; alt: string; withName: boolean; homeId: string | null; centered: boolean; grow: boolean },\n): string {\n const image = (alone: boolean) =>\n tree.add(\n 'image',\n {\n src: input.src,\n ...(alone ? { alt: input.alt } : { decorative: true }),\n objectFit: 'contain',\n width: 'auto',\n height: AI_LAYOUT_LOGO_HEIGHT,\n loading: 'eager',\n ...(alone && input.homeId ? { screenId: input.homeId } : {}),\n },\n null,\n null,\n 'logo',\n )\n // Never narrower than the logo (AGL-4108); it grows into the room the\n // navigation leaves only where the navigation does not take it itself.\n const grow = input.centered || !input.grow ? null : { flexGrow: 1 }\n if (!input.withName) {\n return tree.add('muiBox', null, { ...(grow ?? {}), display: 'flex', alignItems: 'center', flexShrink: 0 }, [image(true)], 'brand')\n }\n const words = tree.add('muiTypography', { children: input.name, variant: 'h6', component: 'p' }, { fontWeight: 800, whiteSpace: 'nowrap' }, null, 'brandName')\n const row = tree.add('muiStack', { direction: 'row', spacing: '1.5', alignItems: 'center' }, null, [image(false), words], 'brandRow')\n return input.homeId\n ? tree.add('muiLinkBox', { screenId: input.homeId, ariaLabel: input.name }, { ...(grow ?? {}), textDecoration: 'none', color: 'inherit', flexShrink: 0 }, [row], 'brand')\n : tree.add('muiBox', null, { ...(grow ?? {}), flexShrink: 0 }, [row], 'brand')\n}\n"],"names":["AI_ICON_LIBRARY","AI_LAYOUT_MAX_IMAGES","bandSx","compileFlow","compileRow","destinationProps","aiLayoutContactItems","aiLayoutContactShown","aiLayoutFitText","aiLayoutRepairFrameHollows","AI_LAYOUT_CART_ELEMENT","AI_LAYOUT_MAX_ITEMS","AI_LAYOUT_LABELS_EN","aiLayoutLabel","aiLayoutRenamedLabel","aiLayoutResolveLink","AI_LAYOUT_HEADER_MEASURE","aiLayoutNavBreakpoint","aiLayoutSourceFooter","aiLayoutSourceHeader","AiLayoutTreeBuilder","AI_LAYOUT_LOGO_HEIGHT","AI_LAYOUT_ACCOUNT_LINK","account","AI_LAYOUT_STORE_ANNOUNCEMENT","storeAnnouncement","AI_LAYOUT_STORE_ANNOUNCEMENT_LINK","shopNow","headerLook","band","props","color","sx","boxShadow","bgcolor","aiLayoutIsCopyright","text","test","FOOTER_LEAVES_OUT","Set","frameScope","page","at","centered","index","level","headed","itemsLeft","frame","link","sections","from","formSection","aiCompileLayoutFrame","plan","targets","header","tree","storePages","storeLinks","footer","map","id","href","label","slug","title","siteName","pages","pageId","options","reusableComponents","language","settled","scrollTo","itemIds","images","strong","brand","dark","pageIcon","sparkle","formsPlaced","design","pictures","features","splitAt","quotesOnly","name","blocks","look","scope","navLink","entry","role","interactions","add","children","slice","screenId","renderAs","textDecoration","nodes","navPages","filter","trim","centeredNav","align","length","brandSx","typography","fontWeight","whiteSpace","overflow","textOverflow","minWidth","flexGrow","logo","src","source","alt","replace","brandMark","withName","homeId","grow","variant","component","aspect","Number","isFinite","Math","min","logoHeight","parseInt","brandWidth","round","close","AI_LAYOUT_CLOSE_DRAWER","drawn","onBrand","pagesBreakpoint","nav","menu","ctas","breakpoint","ariaLabel","direction","spacing","alignItems","display","xs","ctaBlock","undefined","find","block","kind","store","shopId","noteBlock","push","what","ctaLabel","ctaResolved","to","repeatsNav","some","ctaTo","cart","ctaProps","cta","sm","flexShrink","accountPath","accountLink","drawer","anchor","flexDirection","gap","p","fullWidth","mt","toggle","ml","middle","justifyContent","row","maxWidth","columnGap","toolbar","disableGutters","minHeight","md","barLook","bar","position","overHero","announcement","said","words","useFlexGap","flexWrap","py","px","slot","sourceFooter","compileFooter","column","prune","rootId","AI_LAYOUT_STORE_FOOTER_HEADING","customerCare","STORE_HEADING","aiLayoutFooterStoreHeading","columns","navItems","candidates","navTo","item","forEach","end","under","site","one","items","has","heading","String","empty","pick","enabled","trigger","event","everyTime","steps","type","asked","closesDark","linksPages","flatMap","given","notice","pageLinks","cols","col","weights","list","home","splice","contact","contactItems","filled","weight","top","copyright","bottom","pt","borderTop","borderColor","stack","container","element","colorScheme","input","image","alone","decorative","objectFit","width","height","loading"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,eAAe,QAAQ,gCAA4B;AAC5D,SACEC,oBAAoB,EACpBC,MAAM,EACNC,WAAW,EACXC,UAAU,EACVC,gBAAgB,QAGX,0BAAsB;AAC7B,SAASC,oBAAoB,EAAEC,oBAAoB,QAAQ,yBAAqB;AAChF,SAASC,eAAe,QAAQ,sBAAkB;AAClD,SAASC,0BAA0B,QAAQ,+BAA2B;AACtE,SAASC,sBAAsB,QAAQ,0BAAsB;AAC7D,SACEC,mBAAmB,QAKd,0BAAsB;AAC7B,SAASC,mBAAmB,EAAEC,aAAa,QAAQ,wBAAoB;AACvE,SACEC,oBAAoB,EACpBC,mBAAmB,QAGd,uBAAmB;AAC1B,SACEC,wBAAwB,EACxBC,qBAAqB,EACrBC,oBAAoB,EACpBC,oBAAoB,QAEf,8BAA0B;AACjC,SAASC,mBAAmB,QAA8B,sBAAkB;AA0F5E,mFAAmF,GACnF,OAAO,MAAMC,wBAAwB,OAAM;AAE3C,kFAAkF,GAClF,OAAO,MAAMC,yBAAyBV,oBAAoBW,OAAO,CAAA;AAEjE,2GAA2G,GAC3G,OAAO,MAAMC,+BAA+BZ,oBAAoBa,iBAAiB,CAAA;AAEjF,2EAA2E,GAC3E,OAAO,MAAMC,oCAAoCd,oBAAoBe,OAAO,CAAA;AAO5E,mDAAmD,GACnD,SAASC,WAAWC,IAAkB;IAIpC,IAAIA,SAAS,SACX,OAAO;QAAEC,OAAO;YAAEC,OAAO;QAAU;QAAGC,IAAI;YAAEC,WAAW;QAAO;IAAE;IAClE,IAAIJ,SAAS,QAAQ;QACnB,OAAO;YACLC,OAAO;gBAAEC,OAAO;YAAU;YAC1BC,IAAI;gBACFC,WAAW;gBACXC,SAAS;gBACTH,OAAO;YACT;QACF;IACF;IACA,uEAAuE;IACvE,2DAA2D;IAC3D,OAAO;QACLD,OAAO;YAAEC,OAAO;QAAU;QAC1BC,IAAI;YAAEE,SAAS;QAAmB;IACpC;AACF;AAEA,+FAA+F,GAC/F,OAAO,SAASC,oBAAoBC,IAAa;IAC/C,OAAO,OAAOA,SAAS,YAAY,mDAAmDC,IAAI,CAACD;AAC7F;AAEA,8FAA8F,GAC9F,MAAME,oBAAwD,IAAIC,IAAI;IACpE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,sFAAsF,GACtF,SAASC,WACPC,IAAe,EACfC,EAAU,EACVb,IAAkB,EAClBc,QAAiB;IAEjB,OAAO;QACLF;QACAG,OAAOF,OAAO,WAAW,IAAI;QAC7BA;QACAb;QACAc;QACAE,OAAO;QACPC,QAAQ;QACRC,WAAWpC;QACXqC,OAAO;QACPC,MAAM;YAAEC,UAAU,EAAE;YAAEC,MAAM,CAAC;YAAGC,aAAa;QAAK;IACpD;AACF;AAEA,2FAA2F,GAC3F,OAAO,SAASC,qBACdL,KAAyE,EACzEM,IAAuB,EACvBC,OAAwB;cAkCTP,eACFQ,cA+CEF;QA9EqBA,kBA6EvBA,kBAAAA,aAEAA,cAE4DA,cAsB1DA,cAGmEA,cAmF9DA;IA/LpB,MAAMG,OAAO,IAAIrC,oBAAoB;IACrC,mFAAmF;IACnF,MAAMsC,aAA6B,UAACJ,mBAAAA,KAAKK,UAAU,qBAAfL,iBAAiBM,MAAM,mBAAI,EAAE,EAAEC,GAAG,CAAC,CAACZ,OAAU,CAAA;YAChFa,IAAI,CAAC,MAAM,EAAEb,KAAKc,IAAI,EAAE;YACxBC,OAAOf,KAAKe,KAAK;YACjBC,MAAMhB,KAAKc,IAAI;YACfA,MAAMd,KAAKc,IAAI;QACjB,CAAA;IACA,MAAMtB,OAAkB;QACtBgB;QACAH,MAAM;YAAEY,OAAOZ,KAAKa,QAAQ;YAAEjB,UAAU,EAAE;QAAC;QAC3CK,SAAS,aAAKA;YAASa,OAAO;mBAAIb,QAAQa,KAAK;mBAAKV;aAAW;YAAEW,QAAQ;;QACzE,0FAA0F;QAC1FC,SAAS;YAAEC,oBAAoB;WAAUjB,KAAKkB,QAAQ,GAAG;YAAEA,UAAUlB,KAAKkB,QAAQ;QAAC,IAAI,CAAC;QACxFC,SAAS,EAAE;QACXC,UAAU,CAAC;QACX,6DAA6D;QAC7DC,SAAS,EAAE;QACX,mFAAmF;QACnFC,QAAQ3E;QACR4E,QAAQ;YAAEC,OAAO;YAAGC,MAAM;QAAE;QAC5B3B,aAAa;QACb4B,UAAUhF,gBAAgBiF,OAAO;QACjCC,aAAa,IAAI3C;QACjB,yDAAyD;QACzD4C,QAAQ;QACRC,UAAU;QACVC,UAAU;QACVC,SAAS,CAAC;QACVC,YAAY,EAAE;IAChB;IACA,MAAMC,OAAOhF,gBAAgB8C,KAAKa,QAAQ,EAAE,WAAWb,KAAKkB,QAAQ,KAAK;IACzE,MAAMhB,UAASR,gBAAAA,MAAMQ,MAAM,YAAZR,gBAAgB;QAAEyC,QAAQ,EAAE;IAAC;IAC5C,MAAM5D,QAAO2B,eAAAA,OAAO3B,IAAI,YAAX2B,eAAe;IAC5B,MAAMkC,OAAO9D,WAAWC;IACxB,MAAM8D,QAAQnD,WACZC,MACA,UACAZ,SAAS,WAAWA,SAAS,SAAS,UAAU,SAChD;IAEF,MAAM+D,UAAU,CACdC,OACAC,MACAC;QAEA,MAAMjC,KAAKL,KAAKuC,GAAG,CACjB,iBACA;YACEC,UACEzF,gBAAgBqF,MAAM7B,KAAK,EAAE,SAASV,KAAKkB,QAAQ,KAAKqB,MAAM7B,KAAK,CAACkC,KAAK,CAAC,GAAG;WAE3EL,MAAM9B,IAAI,GAAG;YAAEA,MAAM8B,MAAM9B,IAAI;QAAC,IAAI;YAAEoC,UAAUN,MAAM/B,EAAE;QAAC;YAC7DsC,UAAU;YACVrE,OAAO;YAET;YAAEsE,gBAAgB;QAAO,GACzB,MACAP;QAEF,IAAIC,cAActC,KAAK6C,KAAK,CAACxC,GAAG,CAACiC,YAAY,GAAGA;QAChD,OAAOjC;IACT;IACA,MAAMM,QAAQd,KAAKiD,QAAQ,CAACC,MAAM,CAAC,CAACX,QAAUA,MAAM7B,KAAK,CAACyC,IAAI;IAC9D,MAAMC,cAAclD,OAAOmD,KAAK,KAAK,YAAYvC,MAAMwC,MAAM,GAAG;IAChE,yEAAyE;IACzE,+EAA+E;IAC/E,2EAA2E;IAC3E,6CAA6C;IAC7C,MAAMC,UAAU;QACdC,YAAY;QACZC,YAAY;QACZV,gBAAgB;QAChBW,YAAY;QACZC,UAAU;QACVC,cAAc;QACdC,UAAU;OACNT,cAAc,CAAC,IAAI;QAAEU,UAAU;IAAE;IAEvC,MAAMC,OAAO/D,EAAAA,cAAAA,KAAKwB,KAAK,sBAAVxB,mBAAAA,YAAY+D,IAAI,qBAAhB/D,iBAAkBgE,GAAG,IAAGhE,KAAKwB,KAAK,CAACuC,IAAI,CAACC,GAAG,GAAG;IAC3D,MAAMC,UAASjE,eAAAA,KAAKiE,MAAM,YAAXjE,eAAe;IAC9B,MAAMkE,MAAM,WAAClE,eAAAA,KAAKwB,KAAK,qBAAVxB,aAAYkE,GAAG,oBAAI,IAAIC,OAAO,CAAC,QAAQ,KAAKhB,IAAI,GAAGP,KAAK,CAAC,GAAG,QAAQV,KAAKU,KAAK,CAAC,GAAG;IAC/F,MAAMpB,QAAQuC,OACVK,UAAUjE,MAAM;QAAE6D,KAAKD;QAAM7B,MAAMA,KAAKU,KAAK,CAAC,GAAG;QAAKsB;QAAKG,UAAUrE,EAAAA,eAAAA,KAAKwB,KAAK,qBAAVxB,aAAYkC,IAAI,MAAK;QAAMoC,QAAQtE,KAAKsE,MAAM;QAAEjF,UAAU+D;QAAamB,MAAM,CAACN;IAAO,KAC1JjE,KAAKsE,MAAM,GACXnE,KAAKuC,GAAG,CACN,iBACA;QACEC,UAAUT,KAAKU,KAAK,CAAC,GAAG;QACxBC,UAAU7C,KAAKsE,MAAM;QACrBxB,UAAU;QACVrE,OAAO;IACT,GACA8E,SACA,MACA,WAEFpD,KAAKuC,GAAG,CACN,iBACA;QAAEC,UAAUT;QAAMsC,SAAS;QAAMC,WAAW;IAAI,GAChDlB,SACA,MACA;IAEN,0EAA0E;IAC1E,MAAMmB,SAAS1E,EAAAA,eAAAA,KAAKwB,KAAK,qBAAVxB,aAAY0E,MAAM,KAAIC,OAAOC,QAAQ,CAAC5E,KAAKwB,KAAK,CAACkD,MAAM,KAAK1E,KAAKwB,KAAK,CAACkD,MAAM,GAAG,IAAIG,KAAKC,GAAG,CAAC9E,KAAKwB,KAAK,CAACkD,MAAM,EAAE,KAAK;IACpI,MAAMK,aAAaJ,OAAOK,QAAQ,CAACjH,uBAAuB;IAC1D,MAAMkH,aAAalB,OACf,AAACW,CAAAA,SAASG,KAAKK,KAAK,CAACR,SAASK,cAAcrH,yBAAyBqG,IAAI,AAAD,IAAM/D,CAAAA,EAAAA,eAAAA,KAAKwB,KAAK,qBAAVxB,aAAYkC,IAAI,IAAGA,KAAKU,KAAK,CAAC,GAAG,IAAIU,MAAM,GAAG,KAAK,KAAK,CAAA,IACtIuB,KAAKC,GAAG,CAAC5C,KAAKoB,MAAM,EAAE,MAAM;IAChC,6DAA6D;IAC7D,MAAM6B,QAAQ;QAACC;KAAuB;IACtC,MAAMC,QAAQpB,SAASpG,qBAAqBsC,MAAM8D,QAAQ;QAAEqB,SAAS/G,SAAS,WAAWA,SAAS;QAAQ4G;QAAOF;IAAW,KAAK;IACjI,4EAA4E;IAC5E,MAAMM,kBAAkB5H,sBAAsB;QAAEsH;QAAYO,KAAK1E,MAAMP,GAAG,CAAC,CAACgC,QAAW,CAAA;gBAAE7B,OAAO6B,MAAM7B,KAAK;gBAAE+E,MAAM;YAAM,CAAA;QAAKC,MAAM,EAAE;IAAC;IACvI,MAAMC,sBAAaN,yBAAAA,MAAOM,UAAU,oBAAIJ;IACxC,MAAMC,MAAMH,QACRA,MAAMG,GAAG,GACT1E,MAAMwC,MAAM,GACVnD,KAAKuC,GAAG,CACN,YACA;QACE+B,WAAW;QACXmB,WAAW;QACXC,WAAW;QACXC,SAAS;QACTC,YAAY;IACd,GACA;QAAEC,SAAS;YAAEC,IAAI;YAAQ,CAACN,WAAW,EAAE;QAAO;QAAGjC,YAAY;IAAS,GACtE5C,MAAMP,GAAG,CAAC,CAACgC,QAAUD,QAAQC,OAAO,aACpC,SAEF;IACN,0EAA0E;IAC1E,gEAAgE;IAChE,MAAM2D,WAAWjC,SAASkC,YAAYjG,OAAOiC,MAAM,CAACiE,IAAI,CAAC,CAACC,QAAUA,MAAMC,IAAI,KAAK;IACnF,sFAAsF;IACtF,MAAMC,QAAQ,CAAC,CAACvG,KAAKwG,MAAM;IAC3B,MAAMC,YAAYF,QAAQrG,OAAOiC,MAAM,CAACiE,IAAI,CAAC,CAACC,QAAUA,MAAMC,IAAI,KAAK,UAAUD,MAAMC,IAAI,KAAK,UAAUD,MAAMC,IAAI,KAAK,UAAUH;IACnI,KAAK,MAAME,SAASnG,OAAOiC,MAAM,CAAE;QACjC,IAAIkE,UAAUH,YAAYG,UAAUI,WAClCtH,KAAKgC,OAAO,CAACuF,IAAI,CAAC;YAChBtH,IAAI;YACJuH,MAAM,CAAC,EAAE,EAAEN,MAAMC,IAAI,CAAC,wBAAwB,CAAC;QACjD;IACJ;IACA,MAAMM,WAAWV,WAAWhJ,gBAAgBgJ,SAASpH,IAAI,EAAE,SAASkB,KAAKkB,QAAQ,IAAI;IACrF,MAAM2F,cACJX,YAAYU,WACRnJ,oBAAoByI,SAASY,EAAE,EAAEF,UAAUvE,MAAM1C,IAAI,EAAER,KAAKc,OAAO,IACnE;IACN,IAAIiG,YAAY,CAACW,aACf1H,KAAKgC,OAAO,CAACuF,IAAI,CAAC;QAChBtH,IAAI;QACJuH,MAAM,CAAC,YAAY,EAAEC,SAAS,6BAA6B,CAAC;IAC9D;IACF,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,sEAAsE;IACtE,MAAMG,aACJF,CAAAA,+BAAAA,YAAaP,IAAI,MAAK,UAAUxF,MAAMkG,IAAI,CAAC,CAACzE,QAAU,CAACA,MAAM9B,IAAI,IAAI8B,MAAM/B,EAAE,KAAKqG,YAAYhE,QAAQ;IACxG,MAAMoE,QAAQJ,eAAeN,SAAUvG,CAAAA,KAAKkH,IAAI,IAAIH,UAAS,IAAK,OAAOF;IACzE,IAAIA,eAAe,CAACI,OAClB9H,KAAKgC,OAAO,CAACuF,IAAI,CAAC;QAChBtH,IAAI;QACJuH,MAAM,CAAC,YAAY,EAAEC,SAAS,yCAAyC,EAAE5G,KAAKkH,IAAI,GAAG,SAAS,aAAa,2BAA2B,CAAC;IACzI;IACF,MAAMC,WAAWF,QACb;QACEtE,UAAUnF,qBAAqBoJ,UAAUK;QACzCzC,SAAS;QACT/F,OAAO4D,MAAM9D,IAAI,KAAK,UAAU,cAAc;OAC3CxB,iBAAiBkK,UAEtB;IACJ,iEAAiE;IACjE,MAAMG,MAAMD,WACRhH,KAAKuC,GAAG,CACN,aACAyE,UACA;QACEnB,SAAS;YAAEC,IAAI;YAAQoB,IAAI;QAAc;QACzC3D,YAAY;QACZ4D,YAAY;IACd,GACA,MACA,SAEF;IACJ,yEAAyE;IACzE,MAAMC,wBAAcvH,oBAAAA,KAAKK,UAAU,qBAAfL,kBAAiB/B,OAAO,oBAAI;IAChD,MAAMuJ,cAAc,CAAChF,MAAcC,cAA0B/D;QAC3D,MAAM8B,KAAKL,KAAKuC,GAAG,CACjB,iBACA;YAAEC,UAAUpF,cAAc,WAAWyC,KAAKkB,QAAQ;YAAGT,MAAM8G;YAAazE,UAAU;YAAQrE,OAAO;QAAU,GAC3G;YAAEsE,gBAAgB;YAAQW,YAAY;WAAahF,KACnD,MACA8D;QAEF,IAAIC,cAActC,KAAK6C,KAAK,CAACxC,GAAG,CAACiC,YAAY,GAAGA;QAChD,OAAOjC;IACT;IACA,2EAA2E;IAC3E,wFAAwF;IACxF,MAAMiH,SAASpC,CAAAA,yBAAAA,MAAOoC,MAAM,CAACnE,MAAM,IAC/BnD,KAAKuC,GAAG,CACN,aACA;QAAEgF,QAAQ;IAAQ,GAClB,MACA;QACEvH,KAAKuC,GAAG,CACN,YACA;YAAE+B,WAAW;YAAOmB,WAAW;QAAO,GACtC;YAAEI,SAAS;YAAQ2B,eAAe;YAAUC,KAAK;YAAGC,GAAG;QAAE,GACzD;eAAIxC,MAAMoC,MAAM;YAAEF,cAAcC,YAAY,eAAerC,SAAS;SAAK,EACzE;KAEH,EACD,YAEF,CAAClB,UAAUnD,MAAMwC,MAAM,GACvBnD,KAAKuC,GAAG,CACN,aACA;QAAEgF,QAAQ;IAAQ,GAClB,MACA;QACEvH,KAAKuC,GAAG,CACN,YACA;YAAE+B,WAAW;YAAOmB,WAAW;QAAO,GACtC;YACEI,SAAS;YACT2B,eAAe;YACfC,KAAK;YACLC,GAAG;YACHrE,YAAY;QACd,GACA;eACK1C,MAAMP,GAAG,CAAC,CAACgC,QAAUD,QAAQC,OAAO,YAAY4C;YACnDoC,cAAcC,YAAY,eAAerC,SAAS;YAClDgC,WACIhH,KAAKuC,GAAG,CACN,aACA,aAAKyE;gBAAUW,WAAW;gBAC1B;gBAAEC,IAAI;YAAE,GACR,MACA,aAEF;SACL,EACD;KAEH,EACD,YAEF;IACJ,MAAMC,SAASP,SACXtH,KAAKuC,GAAG,CACN,mBACA;QAAEkD,WAAW;IAAgB,GAC7B,oEAAoE;IACpE;QAAEI,SAAS;YAAEC,IAAI;YAAe,CAACN,WAAW,EAAE;QAAO;QAAG2B,YAAY;OAAOjC,SAAS,CAACA,MAAMK,IAAI,GAAG;QAAEuC,IAAI;IAAO,IAAI,CAAC,IACpH,MACA,gBAEF;IACJ,MAAMC,SACJ1C,OAAOpC,cACHjD,KAAKuC,GAAG,CACN,UACA,MACA;QAAEoB,UAAU;QAAGkC,SAAS;QAAQmC,gBAAgB;IAAS,GACzD;QAAC3C;KAAI,EACL,aAEFA;IACN,0EAA0E;IAC1E,MAAM0B,OAAOlH,KAAKkH,IAAI,GAClB/G,KAAKuC,GAAG,CAACtF,wBAAwB;QAAEoH,SAAS;IAAS,GAAG;QAAE8C,YAAY;IAAE,GAAG,MAAM,UACjF;IACJ,wEAAwE;IACxE,MAAMrJ,UAAUsJ,cAAcC,YAAY,WAAWrB,WAAW;QAAEH,SAAS;YAAEC,IAAI;YAAQ,CAACN,WAAW,EAAE;QAAc;QAAG2B,YAAY;IAAE,KAAK;IAC3I,6FAA6F;IAC7F,MAAMc,MAAMjI,KAAKuC,GAAG,CAClB,gBACA;QAAE2F,UAAU;IAAK,GACjB;QAAErC,SAAS;QAAQD,YAAY;QAAUuC,WAAW;IAAE,GACtD;QAAC9G;QAAO0G;QAAQ7C,QAAQA,MAAMK,IAAI,GAAG0B;QAAKnJ;QAASiJ;QAAMc;QAAQP;KAAO,EACxE;IAEF,MAAMc,UAAUpI,KAAKuC,GAAG,CACtB,cACA;QAAE8F,gBAAgB;IAAK,GACvB;QAAEC,WAAW;YAAExC,IAAI;YAAIyC,IAAI;QAAG;IAAE,GAChC;QAACN;KAAI,EACL;IAEF,qGAAqG;IACrG,MAAMO,UAAU1E,CAAAA,0BAAAA,OAAQ/D,MAAM,MAAK,SAAS;QAAE1B,OAAO;YAAEC,OAAO;QAAU;QAAGC,IAAI;YAAEE,SAAS;QAAqB;IAAE,IAAIwD;IACrH,MAAMwG,MAAMzI,KAAKuC,GAAG,CAClB,aACA,aACKiG,QAAQnK,KAAK;QAChBqK,UAAU;QACV,mFAAmF;QACnFC,UAAU;QACVrE,WAAW;QACXmB,WAAW;QAEb+C,QAAQjK,EAAE,EACV;QAAC6J;KAAQ,EACT;IAEF,qFAAqF;IACrF,MAAMQ,eACJxC,SAASvG,KAAKkH,IAAI,IAAIlH,KAAKwG,MAAM,GAC7B,AAAC,CAAA;QACC,MAAMwC,OAAO9L,gBAAgBuJ,6BAAAA,UAAW3H,IAAI,EAAE,QAAQkB,KAAKkB,QAAQ;QACnE,IAAIuF,aAAa,CAACuC,MAAM7J,KAAKgC,OAAO,CAACuF,IAAI,CAAC;YAAEtH,IAAI;YAAUuH,MAAM;QAAkE;QAClI,wEAAwE;QACxE,MAAMhH,OAAOQ,KAAKuC,GAAG,CACnB,iBACA;YACEC,UAAUpF,cAAcyL,OAAO,YAAY,qBAAqBhJ,KAAKkB,QAAQ;YAC7E2B,UAAU7C,KAAKwG,MAAM;YACrB1D,UAAU;YACVrE,OAAO;QACT,GACA;YAAEgF,YAAY;QAAI,GAClB,MACA;QAEF,MAAMwF,QAAQD,OACV7I,KAAKuC,GAAG,CAAC,iBAAiB;YAAEC,UAAUqG;YAAMxE,SAAS;YAASC,WAAW;QAAI,GAAG,MAAM,MAAM,sBAC5F;QACJ,OAAOtE,KAAKuC,GAAG,CACb,YACA;YAAEmD,WAAW;YAAOC,SAAS;YAAOqC,gBAAgB;YAAUpC,YAAY;YAAYmD,YAAY;YAAMC,UAAU;QAAO,GACzH;YAAEvK,SAAS;YAAgBH,OAAO;YAAwB+E,YAAY;YAAS4F,IAAI;YAAGC,IAAI;QAAE,GAC5F;YAACJ;YAAOtJ;SAAK,EACb;IAEJ,CAAA,MACA;IACN,wEAAwE;IACxE,4BAA4B;IAC5B,MAAM2J,OAAOnJ,KAAKuC,GAAG,CACnB,cACA;QAAE+B,WAAW;IAAO,GACpB;QAAEX,UAAU;IAAE,GACd,MACA;IAEF,MAAMxD,SAAS2D,CAAAA,0BAAAA,OAAQ3D,MAAM,IAAGiJ,aAAapK,MAAM8E,QAAQ/B,QAAQsH,cAAcrK,MAAMO,MAAMY,MAAM,EAAEN,MAAMkC;IAC3G,yEAAyE;IACzE,yEAAyE;IACzE,IAAI/E,2BAA2BgD,KAAK6C,KAAK,GAAyC;QAChF7D,KAAKgC,OAAO,CAACuF,IAAI,CAAC;YAAEtH,IAAI;YAAUuH,MAAM;QAAoE;IAC9G;IACA,MAAM8C,SAAStJ,KAAKuC,GAAG,CACrB,YACA,MACA;QAAE+F,WAAW;IAAQ,GACrB;QAACM;QAAcH;QAAKU;QAAMhJ;KAAO,EACjC;IAEFH,KAAKuJ,KAAK,CAACD,QAAQ,IAAIxK,IAAI;QAACqK;KAAK;IACjC,MAAMK,SAASxJ,KAAKuC,GAAG,CAAC,OAAO,MAAM,MAAM;QAAC+G;KAAO,EAAE;IACrD,OAAO;QAAEtJ,MAAM;YAAEwJ;YAAQ3G,OAAO7C,KAAK6C,KAAK;QAAC;QAAG7B,SAAShC,KAAKgC,OAAO;IAAC;AACtE;AAEA,8HAA8H,GAC9H,OAAO,MAAMyI,iCAAiCtM,oBAAoBuM,YAAY,CAAA;AAE9E,6EAA6E,GAC7E,MAAMC,gBAAgB;AAEtB;;;;;;;CAOC,GACD,OAAO,SAASC,2BACdC,OAAmC,EACnCC,QAAmC;QAetBC;IAbb,MAAMC,QAAQ,IAAIlL,IAAIgL,SAAS1J,GAAG,CAAC,CAAC6J,OAASA,KAAKtD,EAAE;IACpD,MAAMoD,aAA+F,EAAE;IACvG,KAAK,MAAMT,UAAUO,QAAS;QAC5BP,OAAOY,OAAO,CAAC,CAAChE,OAAOjH;gBAC+BiH;YAApD,IAAIA,MAAMC,IAAI,KAAK,aAAa,CAACwD,cAAc/K,IAAI,EAACsH,cAAAA,MAAMvH,IAAI,YAAVuH,cAAc,KAAK;YACvE,IAAIiE,MAAMlL,KAAK;YACf,MAAOkL,MAAMb,OAAOnG,MAAM,IAAImG,MAAM,CAACa,IAAI,CAAChE,IAAI,KAAK,UAAWgE,OAAO;YACrE,MAAMC,QAAQd,OAAO7G,KAAK,CAACxD,KAAK,GAAGkL;YACnC,MAAME,OAAOD,MAAMvD,IAAI,CAAC,CAACyD;oBAAgCA;uBAAxBA,IAAInE,IAAI,KAAK,UAAU,EAACmE,aAAAA,IAAIC,KAAK,YAATD,aAAa,EAAE,EAAEzD,IAAI,CAAC,CAACoD;wBAAmBA;2BAAVD,MAAMQ,GAAG,EAACP,WAAAA,KAAKtD,EAAE,YAAPsD,WAAW;;;YAC9G,IAAII,MAAM;YACVN,WAAWxD,IAAI,CAAC;gBAAE+C,QAAQA;gBAA2Ba;gBAAKM,SAASC,OAAOxE,MAAMvH,IAAI;gBAAGgM,OAAOP,MAAMjH,MAAM,KAAK;YAAE;QACnH;IACF;IACA,MAAMyH,QAAOb,mBAAAA,WAAW9D,IAAI,CAAC,CAACqE,MAAQA,IAAIK,KAAK,aAAlCZ,mBAAuCA,UAAU,CAAC,EAAE;IACjE,OAAOa,OAAO;QAAEtB,QAAQsB,KAAKtB,MAAM;QAAEa,KAAKS,KAAKT,GAAG;QAAEM,SAASG,KAAKH,OAAO;IAAC,IAAI;AAChF;AAEA,mDAAmD,GACnD,MAAMxF,yBAAyB;IAC7B5E,IAAI;IACJ0B,MAAM;IACN8I,SAAS;IACTC,SAAS;QAAEC,OAAO;QAAgBC,WAAW;IAAK;IAClDC,OAAO;QAAC;YAAEC,MAAM;QAAc;KAAE;AAClC;AAEA;;;;CAIC,GACD,SAAS7B,cACPrK,IAAe,EACfmB,MAA8B,EAC9BN,IAAuB,EACvBkC,IAAY;;QAqEOlC;IAnEnB,MAAMG,OAAOhB,KAAKgB,IAAI;IACtB,MAAMmL,gBAAQhL,0BAAAA,OAAQ/B,IAAI,mBAAI;IAC9B,MAAMA,OAAOyB,KAAKuL,UAAU,IAAKD,CAAAA,UAAU,WAAWA,UAAU,MAAK,IAAK,SAASA;IACnF,IAAI/M,SAAS+M,OAAOnM,KAAKgC,OAAO,CAACuF,IAAI,CAAC;QAAEtH,IAAI;QAAUuH,MAAM,CAAC,EAAE,EAAE2E,MAAM,4CAA4C,CAAC;IAAC;IACrH,MAAMjJ,QAAQnD,WAAWC,MAAM,UAAUZ,MAAM+B,CAAAA,0BAAAA,OAAQ+C,KAAK,MAAK;IACjE,2EAA2E;IAC3E,0EAA0E;IAC1E,4EAA4E;IAC5E,yCAAyC;IACzC,MAAM4G,WAAWjK,KAAKiD,QAAQ,CAAC1C,GAAG,CAAC,CAACgC,QAAW,CAAA;YAC7C3B,OAAO2B,MAAM7B,KAAK;YAClB5B,MAAM;YACNgI,IAAI,CAAC,KAAK,EAAEvE,MAAM/B,EAAE,EAAE;QACxB,CAAA;IACA,IAAIgL,aAAa;IACjB,MAAMrJ,SAAS,UAAC7B,0BAAAA,OAAQ6B,MAAM,oBAAI,EAAE,EAAEsJ,OAAO,CAAC,CAACC;YAmB1CrF;YAXWqF;QAPd,uEAAuE;QACvE,uDAAuD;QACvD,IAAI7M,oBAAoB6M,MAAM5M,IAAI,GAAG;YACnCK,KAAKgC,OAAO,CAACuF,IAAI,CAAC;gBAAEtH,IAAI;gBAAUuH,MAAM;YAA8C;YACtF,OAAO,EAAE;QACX;QACA,MAAMgF,SAAS,CAACvB,OAA0CvL,oBAAoBuL,KAAKxJ,KAAK,KAAK/B,oBAAoBuL,KAAKtL,IAAI;QAC1H,MAAMuH,QAAQqF,EAAAA,eAAAA,MAAMhB,KAAK,qBAAXgB,aAAa1E,IAAI,CAAC2E,WAAU,aAAKD;YAAOhB,OAAOgB,MAAMhB,KAAK,CAACxH,MAAM,CAAC,CAACkH,OAAS,CAACuB,OAAOvB;aAAWsB;QAC7G,IAAIrF,UAAUqF,OAAOvM,KAAKgC,OAAO,CAACuF,IAAI,CAAC;YAAEtH,IAAI;YAAUuH,MAAM;QAAwD;QACrH,IAAI3H,kBAAkB2L,GAAG,CAACtE,MAAMC,IAAI,GAAG;YACrCnH,KAAKgC,OAAO,CAACuF,IAAI,CAAC;gBAChBtH,IAAI;gBACJuH,MAAM,CAAC,EAAE,EAAEN,MAAMC,IAAI,CAAC,wBAAwB,CAAC;YACjD;YACA,OAAO,EAAE;QACX;QACA,MAAMsF,YACJvF,MAAMC,IAAI,KAAK,UACf,EAACD,eAAAA,MAAMqE,KAAK,YAAXrE,eAAe,EAAE,EAAEW,IAAI,CAAC,CAACoD;gBAAuBA;mBAAd,SAASrL,IAAI,EAACqL,WAAAA,KAAKtD,EAAE,YAAPsD,WAAW;;QAC9D,IAAI,CAACwB,WAAW,OAAO;YAACvF;SAAM;QAC9B,IAAImF,cAAc,CAACvB,SAAS3G,MAAM,EAAE;YAClCnE,KAAKgC,OAAO,CAACuF,IAAI,CAAC;gBAAEtH,IAAI;gBAAUuH,MAAM;YAAwC;YAChF,OAAO,EAAE;QACX;QACA6E,aAAa;QACb,OAAO;YAAC,aAAKnF;gBAAOqE,OAAOT;;SAAW;IACxC;IACA,MAAM4B,OAAOvL,CAAAA,0BAAAA,OAAQuL,IAAI,KAAIvL,OAAOuL,IAAI,CAACvI,MAAM,IAAI,IAAIhD,OAAOuL,IAAI,GAAG;IACrE,MAAM7B,UAA6B6B,OAAOA,KAAKtL,GAAG,CAAC,IAAM,EAAE,IAAI;QAAC,EAAE;KAAC;IACnE,KAAK,MAAM8F,SAASlE,OAClB6H,OAAO,CACL6B,QAAQxF,MAAMyF,GAAG,KAAK3F,YAAYtB,KAAKC,GAAG,CAACuB,MAAMyF,GAAG,EAAED,KAAKvI,MAAM,GAAG,KAAK,EAC1E,CAACoD,IAAI,CAACL;IACT,MAAM0F,UAAUF,OAAO;WAAIA;KAAK,GAAG;QAAC;KAAE;IACtC,IAAI,CAACL,cAAcxL,KAAKiD,QAAQ,CAACK,MAAM,EAAE;QACvC0G,QAAQtD,IAAI,CAAC;YACX;gBACEJ,MAAM;gBACNoE,OAAO1K,KAAKiD,QAAQ,CAAC1C,GAAG,CAAC,CAACgC,QAAW,CAAA;wBACnC3B,OAAO2B,MAAM7B,KAAK;wBAClB5B,MAAM;wBACNgI,IAAI,CAAC,KAAK,EAAEvE,MAAM/B,EAAE,EAAE;oBACxB,CAAA;YACF;SACD;QACDuL,QAAQrF,IAAI,CAAC;IACf;IACA,yEAAyE;IACzE,wEAAwE;IACxE,uEAAuE;IACvE,oDAAoD;IACpD,MAAMrG,uBAAaL,mBAAAA,KAAKK,UAAU,qBAAfL,iBAAiBM,MAAM,oBAAI,EAAE;IAChD,IAAID,WAAWiD,MAAM,EAAE;QACrB,MAAM0I,OAAsB;YAAE1F,MAAM;YAAQoE,OAAOrK,WAAWE,GAAG,CAAC,CAACZ,OAAU,CAAA;oBAAEiB,OAAOjB,KAAKe,KAAK;oBAAE5B,MAAM;oBAAIgI,IAAI,CAAC,WAAW,EAAEnH,KAAKc,IAAI,EAAE;gBAAC,CAAA;QAAI;QAC9I,MAAMwL,OAAOlC,2BAA2BC,SAASC;QACjD,IAAIgC,MAAM;YACRA,KAAKxC,MAAM,CAACyC,MAAM,CAACD,KAAK3B,GAAG,EAAE,GAAG0B;YAChC7M,KAAKgC,OAAO,CAACuF,IAAI,CAAC;gBAAEtH,IAAI;gBAAUuH,MAAM,CAAC,4CAA4C,EAAEsF,KAAKrB,OAAO,CAAC,CAAC,CAAC;YAAC;QACzG,OAAO;YACLZ,QAAQtD,IAAI,CAAC;gBAAC;oBAAEJ,MAAM;oBAAWxH,MAAMvB,cAAc,gBAAgByC,KAAKkB,QAAQ;gBAAE;gBAAG8K;aAAK;YAC5FD,QAAQrF,IAAI,CAAC;QACf;IACF;IACA,wEAAwE;IACxE,yEAAyE;IACzE,0DAA0D;IAC1D,MAAMyF,UAAUhN,KAAKc,OAAO,CAACkM,OAAO;IACpC,MAAMC,eAAeD,UAAUnP,qBAAqBmP,SAASlP,qBAAqBkF,QAAQgK,YAAY,EAAE;IACxG,IAAIC,aAAa9I,MAAM,EAAE;QACvB0G,QAAQtD,IAAI,CAAC;YACX;gBAAEJ,MAAM;gBAAWxH,MAAMvB,cAAc,WAAWyC,KAAKkB,QAAQ;YAAE;YACjE;gBAAEoF,MAAM;gBAAQoE,OAAO0B;YAAa;SACrC;QACDL,QAAQrF,IAAI,CAAC;QACbvH,KAAKgC,OAAO,CAACuF,IAAI,CAAC;YAAEtH,IAAI;YAAUuH,MAAM;QAAkE;IAC5G;IACA,MAAM0F,SAASrC,QACZzJ,GAAG,CAAC,CAACkJ,QAAQZ;YAAgCkD;eAAlB;YAAEtC;YAAQ6C,MAAM,GAAEP,oBAAAA,OAAO,CAAClD,SAAS,YAAjBkD,oBAAqB;QAAE;OACpE7I,MAAM,CAAC,CAACX,QAAUA,MAAMkH,MAAM,CAACnG,MAAM;IACxC,6EAA6E;IAC7E,MAAMiJ,MACJF,OAAO/I,MAAM,GAAG,IACZxG,WAAWuF,OAAOgK,QAAQ,gBAC1BA,OAAO/I,MAAM,KAAK,IAChBzG,YAAYwF,OAAOgK,MAAM,CAAC,EAAE,CAAC5C,MAAM,EAAE,UACrC;IACR,MAAM+C,YAAYrM,KAAKuC,GAAG,CACxB,iBACA;QAAEC,UAAU,CAAC,EAAE,EAAET,MAAM;QAAEsC,SAAS;QAASC,WAAW;IAAI,GAC1DpC,MAAM9D,IAAI,KAAK,UAAU,OAAO;QAAEE,OAAO;IAAiB,GAC1D,MACA;IAEF,MAAMgO,SAAStM,KAAKuC,GAAG,CACrB,UACA,MACA;QAAEgK,IAAI;QAAGC,WAAW;QAAGC,aAAa;IAAU,GAC9C;QAACJ;KAAU,EACX;IAEF,MAAMK,QAAQ1M,KAAKuC,GAAG,CACpB,YACA;QAAEoD,SAAS;IAAI,GACf,MACA;QAACyG;QAAKE;KAAO,EACb;IAEF,MAAMK,YAAY3M,KAAKuC,GAAG,CACxB,gBACA;QAAE2F,UAAU;IAAK,GACjB;QAAEe,IAAI;YAAEnD,IAAI;YAAGyC,IAAI;QAAE;IAAE,GACvB;QAACmE;KAAM,EACP;IAEF,OAAO1M,KAAKuC,GAAG,CACb,WACA;QACEqK,SAAS;QACTnH,WAAW;OACPvD,MAAM9D,IAAI,KAAK,SAAS;QAAEyO,aAAa;IAAO,IAAI,CAAC,IAEzD3K,MAAM9D,IAAI,KAAK,SACX;QAAEK,SAAS;QAAoB+N,WAAW;QAAGC,aAAa;IAAU,IACpEhQ,OAAOyF,MAAM9D,IAAI,GACrB;QAACuO;KAAU,EACX;AAEJ;AAEA;;;CAGC,GACD,SAASvD,aAAapK,IAAe,EAAE8E,MAA2B,EAAE/B,IAAY;IAC9E,MAAM/B,OAAOhB,KAAKgB,IAAI;IACtB,MAAMkF,QAAQzH,qBAAqBuC,MAAM8D,OAAO3D,MAAM,EAAgD;QAAE4B;IAAK;IAC7G,MAAM2K,QAAQ1M,KAAKuC,GAAG,CAAC,YAAY;QAAEoD,SAAS;IAAI,GAAGT,MAAM3G,EAAE,EAAE;QAAC2G,MAAMkH,GAAG;QAAElH,MAAMoH,MAAM;KAAC,EAAE;IAC1F,MAAMK,YAAY3M,KAAKuC,GAAG,CAAC,gBAAgB;QAAE2F,UAAU;IAAK,GAAG;QAAEe,IAAI;YAAEnD,IAAI;YAAGyC,IAAI;QAAE;IAAE,GAAG;QAACmE;KAAM,EAAE;IAClG,OAAO1M,KAAKuC,GAAG,CACb,WACA;QAAEqK,SAAS;QAAUnH,WAAW;IAAc,GAC9C;QAAEhH,SAAS;QAAoB+N,WAAW;QAAGC,aAAa;IAAU,GACpE;QAACE;KAAU,EACX;AAEJ;AAEA;;;;CAIC,GACD,SAAS1I,UACPjE,IAAyB,EACzB8M,KAA6H;IAE7H,MAAMC,QAAQ,CAACC,QACbhN,KAAKuC,GAAG,CACN,SACA;YACEsB,KAAKiJ,MAAMjJ,GAAG;WACVmJ,QAAQ;YAAEjJ,KAAK+I,MAAM/I,GAAG;QAAC,IAAI;YAAEkJ,YAAY;QAAK;YACpDC,WAAW;YACXC,OAAO;YACPC,QAAQxP;YACRyP,SAAS;WACLL,SAASF,MAAM3I,MAAM,GAAG;YAAEzB,UAAUoK,MAAM3I,MAAM;QAAC,IAAI,CAAC,IAE5D,MACA,MACA;IAEJ,sEAAsE;IACtE,uEAAuE;IACvE,MAAMC,OAAO0I,MAAM5N,QAAQ,IAAI,CAAC4N,MAAM1I,IAAI,GAAG,OAAO;QAAET,UAAU;IAAE;IAClE,IAAI,CAACmJ,MAAM5I,QAAQ,EAAE;QACnB,OAAOlE,KAAKuC,GAAG,CAAC,UAAU,MAAM,aAAM6B,eAAAA,OAAQ,CAAC;YAAIyB,SAAS;YAAQD,YAAY;YAAUuB,YAAY;YAAK;YAAC4F,MAAM;SAAM,EAAE;IAC5H;IACA,MAAMjE,QAAQ9I,KAAKuC,GAAG,CAAC,iBAAiB;QAAEC,UAAUsK,MAAM/K,IAAI;QAAEsC,SAAS;QAAMC,WAAW;IAAI,GAAG;QAAEhB,YAAY;QAAKC,YAAY;IAAS,GAAG,MAAM;IAClJ,MAAM0E,MAAMjI,KAAKuC,GAAG,CAAC,YAAY;QAAEmD,WAAW;QAAOC,SAAS;QAAOC,YAAY;IAAS,GAAG,MAAM;QAACmH,MAAM;QAAQjE;KAAM,EAAE;IAC1H,OAAOgE,MAAM3I,MAAM,GACfnE,KAAKuC,GAAG,CAAC,cAAc;QAAEG,UAAUoK,MAAM3I,MAAM;QAAEsB,WAAWqH,MAAM/K,IAAI;IAAC,GAAG,aAAMqC,eAAAA,OAAQ,CAAC;QAAIxB,gBAAgB;QAAQtE,OAAO;QAAW6I,YAAY;QAAK;QAACc;KAAI,EAAE,WAC/JjI,KAAKuC,GAAG,CAAC,UAAU,MAAM,aAAM6B,eAAAA,OAAQ,CAAC;QAAI+C,YAAY;QAAK;QAACc;KAAI,EAAE;AAC1E"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-frame.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SX_SCHEME_DARK_KEY } from '@aglyn/aglyn/app-utils/scheme-sx'\nimport type { AiStoreFrameLinks } from '../model/ai-site-store-pages'\nimport { AI_ICON_LIBRARY } from '../runtime/ai-icon-library'\nimport {\n AI_LAYOUT_MAX_IMAGES,\n bandSx,\n compileFlow,\n compileRow,\n destinationProps,\n type PageScope,\n type SectionScope,\n} from './ai-layout-compiler'\nimport { aiLayoutContactItems, aiLayoutContactShown } from './ai-layout-contact'\nimport { aiLayoutFitText } from './ai-layout-copy'\nimport { aiLayoutRepairFrameHollows } from './ai-layout-frame-hollows'\nimport { AI_LAYOUT_CART_ELEMENT } from './ai-layout-listings'\nimport {\n AI_LAYOUT_MAX_ITEMS,\n type AiLayoutBand,\n type AiLayoutBlock,\n type AiLayoutSection,\n type AiLayoutSettlement,\n} from './ai-layout-language'\nimport { AI_LAYOUT_LABELS_EN, aiLayoutLabel } from './ai-layout-labels'\nimport {\n aiLayoutRenamedLabel,\n aiLayoutResolveLink,\n type AiLayoutPage,\n type AiLayoutTargets,\n} from './ai-layout-links'\nimport {\n AI_LAYOUT_HEADER_MEASURE,\n aiLayoutNavBreakpoint,\n aiLayoutSourceFooter,\n aiLayoutSourceHeader,\n type AiLayoutFrameSource,\n} from './ai-layout-frame-source'\nimport { AiLayoutTreeBuilder, type AiLayoutRawTree } from './ai-layout-tree'\n\n/**\n * A site's frame — the header and the footer every page renders between —\n * compiled from the layout language (AGL-3660), the same language a page is\n * designed in.\n *\n * The design is the model's: the header's band and alignment and its one\n * call to action, and the footer's columns and every word in them. What a\n * frame owes the site is the platform's, written here, so it is never wrong\n * and never invented: the site's name as the brand, linking home; its pages\n * as the navigation, a row on a wide screen and the platform's Drawer behind\n * its Menu Button on a phone; the Layout Slot, the page's one main landmark,\n * held tall enough that the footer sits at the bottom of a short page; and\n * the site's pages and name in the footer, where the design gave neither.\n *\n * Every label of the navigation is held to one line, the logo never narrower\n * than itself, and the row shows from the screen width it measures to fit\n * (`aiLayoutNavBreakpoint`), the Menu Button below it (AGL-4108: the 10/29\n * import's seven long titles wrapped from 900 px up and the logo lay over\n * \"Home\" at 1280). A site brought in from elsewhere whose menu the reader\n * found is drawn as its source builds it instead (`plan.source`,\n * `ai-layout-frame-source.ts`): its menus, its buttons, its phone menu and its\n * footer, in place of the site's pages and the design's button and footer.\n */\n\nexport interface AiLayoutFramePlan {\n /** The site's name, which the header and the footer carry as its brand. */\n siteName: string\n /** The site's home page, which the brand links; none where the site has none yet. */\n homeId: string | null\n /** The pages the navigation links, in order. */\n navPages: readonly AiLayoutPage[]\n /**\n * Whether the site's pages close on a dark photo band (AGL-3660,\n * `AiLayoutDesignChoices.coverClose`): a brand or dark footer under it\n * would read as a second loud band, so the footer takes the quiet one.\n */\n closesDark?: boolean\n /**\n * Whether the site sells (AGL-3676): its header carries the store's cart\n * button — the commerce plugin's Cart, which opens the cart in a drawer\n * from every page — beside the navigation.\n */\n cart?: boolean\n /**\n * A selling store's Shop page (AGL-3676), by its id. Its header is a\n * storefront's: the cart beside the navigation and no call-to-action button\n * repeating a link the navigation already has, and a thin announcement bar\n * above it — the line the design gave its header as a note, else one that\n * opens the shop — linking the Shop page.\n */\n shopId?: string | null\n /**\n * A store's own pages (AGL-3676), by path: the header links the account\n * beside the cart, and the footer the account and the store's policies\n * under the site's pages. They are written after the layout, so they are\n * linked by their addresses, as the blog is.\n */\n storeLinks?: AiStoreFrameLinks | null\n /** The site's language (AGL-3760): the frame's own words are in it where `ai-layout-labels.ts` lists it. */\n language?: string\n /**\n * The brand as a site brought in from elsewhere draws it (AGL-4084): its\n * logo alone, its logo with its name, or its name alone, as the source's\n * header shows it. Absent, the name alone.\n */\n brand?: AiLayoutFrameBrand | null\n /**\n * A site brought in from elsewhere whose header the reader found\n * (AGL-4108): its menu with its menus, its buttons with their own\n * addresses, its phone menu and its footer, drawn as the source has them\n * (`ai-layout-frame-source.ts`) in place of the site's pages and the\n * design's button and footer.\n */\n source?: AiLayoutFrameSource | null\n}\n\n/** A header's brand as the source shows it (AGL-4084). */\nexport interface AiLayoutFrameBrand {\n /** The logo, from the site's own media library. */\n logo?: { src: string } | null\n /** The logo a dark-scheme visitor sees, where the frame draws one for each scheme (AGL-4119). */\n logoDark?: { src: string } | null\n /** Whether the footer opens with the logo too (AGL-4119). */\n footer?: boolean\n /** Whether the header prints the name as words, beside the logo or alone. */\n name: boolean\n /** The logo's words for a screen reader, as the source names it (AGL-4108); the site's name where it gave none. */\n alt?: string\n /** The logo's width over its height, which the header row is measured with (AGL-4108). */\n aspect?: number\n}\n\n/** The height a header's logo is drawn at: a Besigner field the owner may change. */\nexport const AI_LAYOUT_LOGO_HEIGHT = '40px'\n\n/** What the header's link to a store's account page says (AGL-3676), in English. */\nexport const AI_LAYOUT_ACCOUNT_LINK = AI_LAYOUT_LABELS_EN.account\n\n/** What a store's announcement bar says where its design gave it no line (AGL-3676): true of every store. */\nexport const AI_LAYOUT_STORE_ANNOUNCEMENT = AI_LAYOUT_LABELS_EN.storeAnnouncement\n\n/** The way into the shop beside the design's own announcement (AGL-3676). */\nexport const AI_LAYOUT_STORE_ANNOUNCEMENT_LINK = AI_LAYOUT_LABELS_EN.shopNow\n\nexport interface AiLayoutCompiledFrame {\n tree: AiLayoutRawTree\n settled: AiLayoutSettlement[]\n}\n\n/** The header's colors by band, as palette roles. */\nfunction headerLook(band: AiLayoutBand): {\n props: Record<string, unknown>\n sx: Record<string, unknown>\n} {\n if (band === 'brand')\n return { props: { color: 'primary' }, sx: { boxShadow: 'none' } }\n if (band === 'dark') {\n return {\n props: { color: 'primary' },\n sx: {\n boxShadow: 'none',\n bgcolor: 'primary.dark',\n color: 'primary.contrastText',\n },\n }\n }\n // A rule, a shadow or nothing under a plain header is the site theme's\n // MuiAppBar style (AGL-3660); the band's color stays here.\n return {\n props: { color: 'inherit' },\n sx: { bgcolor: 'background.paper' },\n }\n}\n\n/** A line that reads as a copyright notice: \"© 2026 …\", \"Copyright …\", \"All rights reserved.\" */\nexport function aiLayoutIsCopyright(text: unknown): boolean {\n return typeof text === 'string' && /^\\s*(?:©|\\(c\\)|copyright\\b)|all rights reserved/i.test(text)\n}\n\n/** What a footer leaves out: a picture slot, and the page sections a footer is no place for. */\nconst FOOTER_LEAVES_OUT: ReadonlySet<AiLayoutBlock['kind']> = new Set([\n 'image',\n 'faq',\n 'quotes',\n 'cards',\n 'steps',\n 'stats',\n 'form',\n 'component',\n])\n\n/** A frame scope: no headings of its own (a layout carries no outline), no pictures. */\nfunction frameScope(\n page: PageScope,\n at: string,\n band: AiLayoutBand,\n centered: boolean,\n): SectionScope {\n return {\n page,\n index: at === 'header' ? 0 : 1,\n at,\n band,\n centered,\n level: 2,\n headed: true,\n itemsLeft: AI_LAYOUT_MAX_ITEMS,\n frame: true,\n link: { sections: [], from: -1, formSection: null },\n }\n}\n\n/** Compiles a site's header and footer, designed in the layout language, into its layout. */\nexport function aiCompileLayoutFrame(\n frame: { header: AiLayoutSection | null; footer: AiLayoutSection | null },\n plan: AiLayoutFramePlan,\n targets: AiLayoutTargets,\n): AiLayoutCompiledFrame {\n const tree = new AiLayoutTreeBuilder('lf')\n // A store's own pages are destinations the footer's list links by path (AGL-3676).\n const storePages: AiLayoutPage[] = (plan.storeLinks?.footer ?? []).map((link) => ({\n id: `store:${link.href}`,\n label: link.label,\n slug: link.href,\n href: link.href,\n }))\n const page: PageScope = {\n tree,\n plan: { title: plan.siteName, sections: [] },\n targets: { ...targets, pages: [...targets.pages, ...storePages], pageId: null },\n // A footer is drawn compact: its lines are lines, never blocks rule 1 would ask to share.\n options: { reusableComponents: true, ...(plan.language ? { language: plan.language } : {}) },\n settled: [],\n scrollTo: {},\n // A frame's lines are its own, never a page section's items.\n itemIds: [],\n // A frame shows no picture slot: a header and a footer are the same on every page.\n images: AI_LAYOUT_MAX_IMAGES,\n strong: { brand: 0, dark: 0 },\n formSection: null,\n pageIcon: AI_ICON_LIBRARY.sparkle,\n formsPlaced: new Set(),\n // A frame is drawn the platform's one way on every site.\n design: null,\n pictures: 0,\n features: 0,\n splitAt: -2,\n quotesOnly: [],\n }\n const name = aiLayoutFitText(plan.siteName, 'heading', plan.language) || 'Home'\n const header = frame.header ?? { blocks: [] }\n const band = header.band ?? 'plain'\n const look = headerLook(band)\n const scope = frameScope(\n page,\n 'header',\n band === 'brand' || band === 'dark' ? 'brand' : 'plain',\n false,\n )\n const navLink = (\n entry: AiLayoutPage,\n role: string,\n interactions?: unknown[],\n ) => {\n const id = tree.add(\n 'muiScreenLink',\n {\n children:\n aiLayoutFitText(entry.label, 'label', plan.language) || entry.label.slice(0, 28),\n // The blog is a path, not a page (AGL-3660).\n ...(entry.href ? { href: entry.href } : { screenId: entry.id }),\n renderAs: 'link',\n color: 'inherit',\n },\n { textDecoration: 'none' },\n null,\n role,\n )\n if (interactions) tree.nodes[id].interactions = interactions\n return id\n }\n const pages = plan.navPages.filter((entry) => entry.label.trim())\n const centeredNav = header.align === 'center' && pages.length > 0\n // The brand takes the room the navigation does not, and gives way before\n // it does: a long name ends in an ellipsis rather than pushing into the links.\n // A logo never gives way: drawn narrower than itself it lay over the first\n // link (the 10/29 header at 1280, AGL-4108).\n const brandSx = {\n typography: 'h6',\n fontWeight: 800,\n textDecoration: 'none',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n minWidth: 0,\n ...(centeredNav ? {} : { flexGrow: 1 }),\n }\n const logo = plan.brand?.logo?.src ? plan.brand.logo.src : null\n const source = plan.source ?? null\n const alt = (plan.brand?.alt ?? '').replace(/\\s+/g, ' ').trim().slice(0, 120) || name.slice(0, 40)\n const brand = logo\n ? brandMark(tree, { src: logo, srcDark: plan.brand?.logoDark?.src ?? null, name: name.slice(0, 40), alt, withName: plan.brand?.name === true, homeId: plan.homeId, centered: centeredNav, grow: !source })\n : plan.homeId\n ? tree.add(\n 'muiScreenLink',\n {\n children: name.slice(0, 40),\n screenId: plan.homeId,\n renderAs: 'link',\n color: 'inherit',\n },\n brandSx,\n null,\n 'brand',\n )\n : tree.add(\n 'muiTypography',\n { children: name, variant: 'h6', component: 'p' },\n brandSx,\n null,\n 'brand',\n )\n // How wide the brand is drawn, which the row is measured with (AGL-4108).\n const aspect = plan.brand?.aspect && Number.isFinite(plan.brand.aspect) && plan.brand.aspect > 0 ? Math.min(plan.brand.aspect, 8) : null\n const logoHeight = Number.parseInt(AI_LAYOUT_LOGO_HEIGHT, 10)\n const brandWidth = logo\n ? (aspect ? Math.round(aspect * logoHeight) : AI_LAYOUT_HEADER_MEASURE.logo) + (plan.brand?.name ? name.slice(0, 40).length * 11 + 12 : 0)\n : Math.min(name.length, 40) * 11\n // The source's own header (AGL-4108), drawn as it builds it.\n const close = [AI_LAYOUT_CLOSE_DRAWER]\n const drawn = source ? aiLayoutSourceHeader(tree, source, { onBrand: band === 'brand' || band === 'dark', close, brandWidth }) : null\n // Every label on one line, and the row only on a screen it fits (AGL-4108).\n const pagesBreakpoint = aiLayoutNavBreakpoint({ brandWidth, nav: pages.map((entry) => ({ label: entry.label, menu: false })), ctas: [] })\n const breakpoint = drawn?.breakpoint ?? pagesBreakpoint\n const nav = drawn\n ? drawn.nav\n : pages.length\n ? tree.add(\n 'muiStack',\n {\n component: 'nav',\n ariaLabel: 'Main',\n direction: 'row',\n spacing: '3',\n alignItems: 'center',\n },\n { display: { xs: 'none', [breakpoint]: 'flex' }, whiteSpace: 'nowrap' },\n pages.map((entry) => navLink(entry, 'navLink')),\n 'nav',\n )\n : null\n // The design's call to action: its first button, where it goes somewhere.\n // A source's header carries its own buttons instead (AGL-4108).\n const ctaBlock = source ? undefined : header.blocks.find((block) => block.kind === 'button')\n // A store's announcement: the first short line the design gave its header (AGL-3676).\n const store = !!plan.shopId\n const noteBlock = store ? header.blocks.find((block) => block.kind === 'note' || block.kind === 'text' || block.kind === 'lede') : undefined\n for (const block of header.blocks) {\n if (block !== ctaBlock && block !== noteBlock)\n page.settled.push({\n at: 'header',\n what: `a ${block.kind} in the header; left out`,\n })\n }\n const ctaLabel = ctaBlock ? aiLayoutFitText(ctaBlock.text, 'label', plan.language) : ''\n const ctaResolved =\n ctaBlock && ctaLabel\n ? aiLayoutResolveLink(ctaBlock.to, ctaLabel, scope.link, page.targets)\n : null\n if (ctaBlock && !ctaResolved)\n page.settled.push({\n at: 'header',\n what: `the button \"${ctaLabel}\" has nowhere to go; left out`,\n })\n // A storefront's header is its navigation and its cart (AGL-3676): the\n // live Willow Wick header's \"Shop candles\" button repeated its nav's Shop.\n // A store's button that only repeats a page the navigation links is left\n // out, and a store that sells carries its cart in that place instead.\n const repeatsNav =\n ctaResolved?.kind === 'page' && pages.some((entry) => !entry.href && entry.id === ctaResolved.screenId)\n const ctaTo = ctaResolved && store && (plan.cart || repeatsNav) ? null : ctaResolved\n if (ctaResolved && !ctaTo)\n page.settled.push({\n at: 'header',\n what: `the button \"${ctaLabel}\" left out: a store's header carries its ${plan.cart ? 'cart' : 'navigation'}, not a button repeating it`,\n })\n const ctaProps = ctaTo\n ? {\n children: aiLayoutRenamedLabel(ctaLabel, ctaTo),\n variant: 'contained',\n color: scope.band === 'brand' ? 'secondary' : 'primary',\n ...destinationProps(ctaTo),\n }\n : null\n // On the smallest phones the call to action moves into the menu.\n const cta = ctaProps\n ? tree.add(\n 'muiButton',\n ctaProps,\n {\n display: { xs: 'none', sm: 'inline-flex' },\n whiteSpace: 'nowrap',\n flexShrink: 0,\n },\n null,\n 'cta',\n )\n : null\n // A store's account, beside its cart and in the phone's menu (AGL-3676).\n const accountPath = plan.storeLinks?.account ?? null\n const accountLink = (role: string, interactions?: unknown[], sx?: Record<string, unknown>) => {\n const id = tree.add(\n 'muiScreenLink',\n { children: aiLayoutLabel('account', plan.language), href: accountPath, renderAs: 'link', color: 'inherit' },\n { textDecoration: 'none', whiteSpace: 'nowrap', ...sx },\n null,\n role,\n )\n if (interactions) tree.nodes[id].interactions = interactions\n return id\n }\n // A phone's menu: the platform's Drawer, opened by its Menu Button; a link\n // followed from it closes it. A source's holds its menus, links and buttons (AGL-4108).\n const drawer = drawn?.drawer.length\n ? tree.add(\n 'muiDrawer',\n { anchor: 'right' },\n null,\n [\n tree.add(\n 'muiStack',\n { component: 'nav', ariaLabel: 'Menu' },\n { display: 'flex', flexDirection: 'column', gap: 3, p: 3 },\n [...drawn.drawer, accountPath ? accountLink('menuAccount', close) : null],\n 'menu',\n ),\n ],\n 'drawer',\n )\n : !source && pages.length\n ? tree.add(\n 'muiDrawer',\n { anchor: 'right' },\n null,\n [\n tree.add(\n 'muiStack',\n { component: 'nav', ariaLabel: 'Menu' },\n {\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n p: 3,\n typography: 'h6',\n },\n [\n ...pages.map((entry) => navLink(entry, 'menuLink', close)),\n accountPath ? accountLink('menuAccount', close) : null,\n ctaProps\n ? tree.add(\n 'muiButton',\n { ...ctaProps, fullWidth: true },\n { mt: 2 },\n null,\n 'menuCta',\n )\n : null,\n ],\n 'menu',\n ),\n ],\n 'drawer',\n )\n : null\n const toggle = drawer\n ? tree.add(\n 'muiDrawerToggle',\n { ariaLabel: 'Open the menu' },\n // Pushed to the end of the row where no button is there to push it.\n { display: { xs: 'inline-flex', [breakpoint]: 'none' }, flexShrink: 0, ...(drawn && !drawn.ctas ? { ml: 'auto' } : {}) },\n null,\n 'menuButton',\n )\n : null\n const middle =\n nav && centeredNav\n ? tree.add(\n 'muiBox',\n null,\n { flexGrow: 1, display: 'flex', justifyContent: 'center' },\n [nav],\n 'navRoom',\n )\n : nav\n // A store's cart, on every page, where a shopper looks for it (AGL-3676).\n const cart = plan.cart\n ? tree.add(AI_LAYOUT_CART_ELEMENT, { variant: 'button' }, { flexShrink: 0 }, null, 'cart')\n : null\n // On a phone the account is in the menu, and the cart stays in the bar.\n const account = accountPath ? accountLink('account', undefined, { display: { xs: 'none', [breakpoint]: 'inline-flex' }, flexShrink: 0 }) : null\n // The row lives in a Container inside the Toolbar Content, which may only sit in an App Bar.\n const row = tree.add(\n 'muiContainer',\n { maxWidth: 'lg' },\n { display: 'flex', alignItems: 'center', columnGap: 3 },\n [brand, middle, drawn ? drawn.ctas : cta, account, cart, toggle, drawer],\n 'headerRow',\n )\n const toolbar = tree.add(\n 'muiToolbar',\n { disableGutters: true },\n { minHeight: { xs: 64, md: 76 } },\n [row],\n 'toolbar',\n )\n // A source's header bar on the ground it sits on (AGL-4108): the page's own, where it is the page's.\n const barLook = source?.header === 'page' ? { props: { color: 'inherit' }, sx: { bgcolor: 'background.default' } } : look\n const bar = tree.add(\n 'muiAppBar',\n {\n ...barLook.props,\n position: 'sticky',\n // Over a page that opens with a photo cover, the bar sits on the photo (AGL-3660).\n overHero: true,\n component: 'header',\n ariaLabel: 'Site header',\n },\n barLook.sx,\n [toolbar],\n 'header',\n )\n // A selling store's announcement bar, above the header, linking its shop (AGL-3676).\n const announcement =\n store && plan.cart && plan.shopId\n ? (() => {\n const said = aiLayoutFitText(noteBlock?.text, 'note', plan.language)\n if (noteBlock && !said) page.settled.push({ at: 'header', what: 'an announcement with no words left; the shop’s own line instead' })\n // The design's line, then the way into the shop; else the way in alone.\n const link = tree.add(\n 'muiScreenLink',\n {\n children: aiLayoutLabel(said ? 'shopNow' : 'storeAnnouncement', plan.language),\n screenId: plan.shopId,\n renderAs: 'link',\n color: 'inherit',\n },\n { fontWeight: 700 },\n null,\n 'announcementLink',\n )\n const words = said\n ? tree.add('muiTypography', { children: said, variant: 'body2', component: 'p' }, null, null, 'announcementText')\n : null\n return tree.add(\n 'muiStack',\n { direction: 'row', spacing: '1.5', justifyContent: 'center', alignItems: 'baseline', useFlexGap: true, flexWrap: 'wrap' },\n { bgcolor: 'primary.main', color: 'primary.contrastText', typography: 'body2', py: 1, px: 2 },\n [words, link],\n 'announcement',\n )\n })()\n : null\n // The page grows into the room the window leaves, so a short page keeps\n // its footer at the bottom.\n const slot = tree.add(\n 'layoutSlot',\n { component: 'main' },\n { flexGrow: 1 },\n null,\n 'slot',\n )\n const footer = source?.footer ? sourceFooter(page, source, name) : compileFooter(page, frame.footer, plan, name)\n // No heading with nothing under it, no column of only a heading, columns\n // top-aligned (AGL-3735): a list under a heading can compile to nothing.\n if (aiLayoutRepairFrameHollows(tree.nodes as unknown as Record<string, unknown>)) {\n page.settled.push({ at: 'footer', what: 'a heading with nothing under it taken out, and its column with it' })\n }\n const column = tree.add(\n 'muiStack',\n null,\n { minHeight: '100vh' },\n [announcement, bar, slot, footer],\n 'frame',\n )\n tree.prune(column, new Set([slot]))\n const rootId = tree.add('div', null, null, [column], 'layout')\n return { tree: { rootId, nodes: tree.nodes }, settled: page.settled }\n}\n\n/** What a store's own column of account and policy links is headed where the footer design gave no store heading (AGL-3735). */\nexport const AI_LAYOUT_STORE_FOOTER_HEADING = AI_LAYOUT_LABELS_EN.customerCare\n\n/** A footer heading a store's account and policies belong under (AGL-3735). */\nconst STORE_HEADING = /\\b(?:shop|store|shopping|help|customer|care|support|service|orders?|account|policies|policy|legal|info|information|shipping|returns)\\b/i\n\n/**\n * The footer heading a store's account and policy links go under\n * (AGL-3735): a heading of the design's that names the store or its help\n * (\"Our shop\", \"Help\", \"Customer care\"), the first with nothing under it\n * before one with words or links of its own. Never the heading over the\n * site's pages, whose list is the site's navigation. `end` is where the\n * links go: the end of what that heading heads.\n */\nexport function aiLayoutFooterStoreHeading(\n columns: readonly AiLayoutBlock[][],\n navItems: readonly { to: string }[],\n): { column: AiLayoutBlock[]; end: number; heading: string } | null {\n const navTo = new Set(navItems.map((item) => item.to))\n const candidates: Array<{ column: AiLayoutBlock[]; end: number; heading: string; empty: boolean }> = []\n for (const column of columns) {\n column.forEach((block, at) => {\n if (block.kind !== 'heading' || !STORE_HEADING.test(block.text ?? '')) return\n let end = at + 1\n while (end < column.length && column[end].kind !== 'heading') end += 1\n const under = column.slice(at + 1, end)\n const site = under.some((one) => one.kind === 'list' && (one.items ?? []).some((item) => navTo.has(item.to ?? '')))\n if (site) return\n candidates.push({ column: column as AiLayoutBlock[], end, heading: String(block.text), empty: under.length === 0 })\n })\n }\n const pick = candidates.find((one) => one.empty) ?? candidates[0]\n return pick ? { column: pick.column, end: pick.end, heading: pick.heading } : null\n}\n\n/** A link followed from the phone menu closes it. */\nconst AI_LAYOUT_CLOSE_DRAWER = {\n id: 'ai-close-menu',\n name: 'Close the menu',\n enabled: true,\n trigger: { event: 'elementClick', everyTime: true },\n steps: [{ type: 'closeDrawer' }],\n}\n\n/**\n * The footer the design describes, with what every footer owes a visitor\n * written by code: the site's pages, where the design links none of them,\n * and the site's name under a rule.\n */\nfunction compileFooter(\n page: PageScope,\n footer: AiLayoutSection | null,\n plan: AiLayoutFramePlan,\n name: string,\n): string {\n const tree = page.tree\n const asked = footer?.band ?? 'soft'\n const band = plan.closesDark && (asked === 'brand' || asked === 'dark') ? 'soft' : asked\n if (band !== asked) page.settled.push({ at: 'footer', what: `a ${asked} footer under a dark closing band drawn soft` })\n const scope = frameScope(page, 'footer', band, footer?.align === 'center')\n // The footer's page links are the site's pages, every one, as the header's\n // are (AGL-3660): a list the model wrote of page links is drawn with them\n // in its place, and a footer with none gets one. The model places the list;\n // it never chooses which pages it holds.\n const navItems = plan.navPages.map((entry) => ({\n title: entry.label,\n text: '',\n to: `page:${entry.id}`,\n }))\n let linksPages = false\n const blocks = (footer?.blocks ?? []).flatMap((given): AiLayoutBlock[] => {\n // The bottom bar carries the frame's one copyright line; a line of the\n // answer's own that reads as one would print it twice.\n if (aiLayoutIsCopyright(given.text)) {\n page.settled.push({ at: 'footer', what: 'a copyright line; the footer writes its own' })\n return []\n }\n const notice = (item: { title: string; text: string }) => aiLayoutIsCopyright(item.title) || aiLayoutIsCopyright(item.text)\n const block = given.items?.some(notice) ? { ...given, items: given.items.filter((item) => !notice(item)) } : given\n if (block !== given) page.settled.push({ at: 'footer', what: 'a copyright line in a list; the footer writes its own' })\n if (FOOTER_LEAVES_OUT.has(block.kind)) {\n page.settled.push({\n at: 'footer',\n what: `a ${block.kind} in the footer; left out`,\n })\n return []\n }\n const pageLinks =\n block.kind === 'list' &&\n (block.items ?? []).some((item) => /^page:/.test(item.to ?? ''))\n if (!pageLinks) return [block]\n if (linksPages || !navItems.length) {\n page.settled.push({ at: 'footer', what: 'a second list of page links; left out' })\n return []\n }\n linksPages = true\n return [{ ...block, items: navItems }]\n })\n const cols = footer?.cols && footer.cols.length >= 2 ? footer.cols : null\n const columns: AiLayoutBlock[][] = cols ? cols.map(() => []) : [[]]\n for (const block of blocks)\n columns[\n cols && block.col !== undefined ? Math.min(block.col, cols.length - 1) : 0\n ].push(block)\n const weights = cols ? [...cols] : [2]\n if (!linksPages && plan.navPages.length) {\n columns.push([\n {\n kind: 'list',\n items: plan.navPages.map((entry) => ({\n title: entry.label,\n text: '',\n to: `page:${entry.id}`,\n })),\n },\n ])\n weights.push(1)\n }\n // A store's account and policies (AGL-3676): under the store heading the\n // design already wrote (\"Our shop\", \"Help\"…), never as a column with no\n // heading beside a heading with nothing under it (AGL-3735); where the\n // design wrote none, a column of their own, headed.\n const storeLinks = plan.storeLinks?.footer ?? []\n if (storeLinks.length) {\n const list: AiLayoutBlock = { kind: 'list', items: storeLinks.map((link) => ({ title: link.label, text: '', to: `page:store:${link.href}` })) }\n const home = aiLayoutFooterStoreHeading(columns, navItems)\n if (home) {\n home.column.splice(home.end, 0, list)\n page.settled.push({ at: 'footer', what: `the store's account and policy links under \"${home.heading}\"` })\n } else {\n columns.push([{ kind: 'heading', text: aiLayoutLabel('customerCare', plan.language) }, list])\n weights.push(1)\n }\n }\n // How to reach the business (AGL-3979): the phone and email it gave, as\n // links that call and write, in a column of their own under its heading,\n // wherever the design's footer did not already show them.\n const contact = page.targets.contact\n const contactItems = contact ? aiLayoutContactItems(contact, aiLayoutContactShown(blocks, contact)) : []\n if (contactItems.length) {\n columns.push([\n { kind: 'heading', text: aiLayoutLabel('contact', plan.language) },\n { kind: 'list', items: contactItems },\n ])\n weights.push(1)\n page.settled.push({ at: 'footer', what: 'the phone and email the business gave, in a column of their own' })\n }\n const filled = columns\n .map((column, position) => ({ column, weight: weights[position] ?? 1 }))\n .filter((entry) => entry.column.length)\n // A footer's columns are top-aligned: each starts at its heading (AGL-3735).\n const top =\n filled.length > 1\n ? compileRow(scope, filled, 'flex-start')\n : filled.length === 1\n ? compileFlow(scope, filled[0].column, 'full')\n : null\n const copyright = tree.add(\n 'muiTypography',\n { children: `© ${name}`, variant: 'body2', component: 'p' },\n scope.band === 'brand' ? null : { color: 'text.secondary' },\n null,\n 'copyright',\n )\n const bottom = tree.add(\n 'muiBox',\n null,\n { pt: 3, borderTop: 1, borderColor: 'divider' },\n [copyright],\n 'footerBottom',\n )\n // The site's own logo, where the header draws it from the site (AGL-4119).\n const footerLogo = plan.brand?.footer && plan.brand.logo?.src\n ? tree.add(\n 'muiBox',\n null,\n null,\n logoPictures(tree, {\n src: plan.brand.logo.src,\n srcDark: plan.brand.logoDark?.src ?? null,\n props: { alt: (plan.brand.alt ?? '').trim() || name.slice(0, 40), objectFit: 'contain', width: 'auto', height: AI_LAYOUT_LOGO_HEIGHT },\n role: 'footerLogo',\n }),\n 'footerLogoBox',\n )\n : null\n const stack = tree.add(\n 'muiStack',\n { spacing: '6' },\n null,\n footerLogo ? [footerLogo, top, bottom] : [top, bottom],\n 'footerStack',\n )\n const container = tree.add(\n 'muiContainer',\n { maxWidth: 'lg' },\n { py: { xs: 6, md: 8 } },\n [stack],\n 'footerInner',\n )\n return tree.add(\n 'section',\n {\n element: 'footer',\n ariaLabel: 'Site footer',\n ...(scope.band === 'dark' ? { colorScheme: 'dark' } : {}),\n },\n scope.band === 'soft'\n ? { bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider' }\n : bandSx(scope.band),\n [container],\n 'footer',\n )\n}\n\n/**\n * A source's footer (AGL-4108): its columns, words, profiles and © line, as\n * the source has them, on the quiet band a footer sits on.\n */\nfunction sourceFooter(page: PageScope, source: AiLayoutFrameSource, name: string): string {\n const tree = page.tree\n const drawn = aiLayoutSourceFooter(tree, source.footer as NonNullable<AiLayoutFrameSource['footer']>, { name })\n const stack = tree.add('muiStack', { spacing: '6' }, drawn.sx, [drawn.top, drawn.bottom], 'footerStack')\n const container = tree.add('muiContainer', { maxWidth: 'lg' }, { py: { xs: 6, md: 8 } }, [stack], 'footerInner')\n return tree.add(\n 'section',\n { element: 'footer', ariaLabel: 'Site footer' },\n { bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider' },\n [container],\n 'footer',\n )\n}\n\n/**\n * A logo as a picture, or as a pair where the site keeps one for dark\n * backgrounds (AGL-4119): the second takes the first's place in the dark\n * scheme, so a visitor sees exactly one.\n */\nfunction logoPictures(\n tree: AiLayoutTreeBuilder,\n input: { src: string; srcDark: string | null; props: Record<string, unknown>; role: string },\n): string[] {\n const light = tree.add(\n 'image',\n { src: input.src, ...input.props },\n input.srcDark ? { [SX_SCHEME_DARK_KEY]: { display: 'none' } } : null,\n null,\n input.role,\n )\n if (!input.srcDark) return [light]\n const { loading: _deferred, ...props } = input.props\n const dark = tree.add(\n 'image',\n { src: input.srcDark, ...props },\n { display: 'none', [SX_SCHEME_DARK_KEY]: { display: 'block' } },\n null,\n `${input.role}Dark`,\n )\n return [light, dark]\n}\n\n/**\n * The header's brand drawn with the site's logo (AGL-4084), as the source's\n * header draws it: the logo alone, named by its alt text, or the logo with\n * the name beside it; either way the link home.\n */\nfunction brandMark(\n tree: AiLayoutTreeBuilder,\n input: { src: string; srcDark: string | null; name: string; alt: string; withName: boolean; homeId: string | null; centered: boolean; grow: boolean },\n): string {\n const image = (alone: boolean, linked: boolean) =>\n logoPictures(tree, {\n src: input.src,\n srcDark: input.srcDark,\n role: 'logo',\n props: {\n ...(alone ? { alt: input.alt } : { decorative: true }),\n objectFit: 'contain',\n width: 'auto',\n height: AI_LAYOUT_LOGO_HEIGHT,\n loading: 'eager',\n ...(linked && input.homeId ? { screenId: input.homeId } : {}),\n },\n })\n // Never narrower than the logo (AGL-4108); it grows into the room the\n // navigation leaves only where the navigation does not take it itself.\n const grow = input.centered || !input.grow ? null : { flexGrow: 1 }\n if (!input.withName) {\n // One link around a pair, so the picture out of sight is no stop in the tab order.\n const homeLink = input.srcDark && input.homeId\n return tree.add(\n homeLink ? 'muiLinkBox' : 'muiBox',\n homeLink ? { screenId: input.homeId } : null,\n { ...(grow ?? {}), display: 'flex', alignItems: 'center', flexShrink: 0 },\n image(true, !homeLink),\n 'brand',\n )\n }\n const words = tree.add('muiTypography', { children: input.name, variant: 'h6', component: 'p' }, { fontWeight: 800, whiteSpace: 'nowrap' }, null, 'brandName')\n const row = tree.add('muiStack', { direction: 'row', spacing: '1.5', alignItems: 'center' }, null, [...image(false, false), words], 'brandRow')\n return input.homeId\n ? tree.add('muiLinkBox', { screenId: input.homeId, ariaLabel: input.name }, { ...(grow ?? {}), textDecoration: 'none', color: 'inherit', flexShrink: 0 }, [row], 'brand')\n : tree.add('muiBox', null, { ...(grow ?? {}), flexShrink: 0 }, [row], 'brand')\n}\n"],"names":["SX_SCHEME_DARK_KEY","AI_ICON_LIBRARY","AI_LAYOUT_MAX_IMAGES","bandSx","compileFlow","compileRow","destinationProps","aiLayoutContactItems","aiLayoutContactShown","aiLayoutFitText","aiLayoutRepairFrameHollows","AI_LAYOUT_CART_ELEMENT","AI_LAYOUT_MAX_ITEMS","AI_LAYOUT_LABELS_EN","aiLayoutLabel","aiLayoutRenamedLabel","aiLayoutResolveLink","AI_LAYOUT_HEADER_MEASURE","aiLayoutNavBreakpoint","aiLayoutSourceFooter","aiLayoutSourceHeader","AiLayoutTreeBuilder","AI_LAYOUT_LOGO_HEIGHT","AI_LAYOUT_ACCOUNT_LINK","account","AI_LAYOUT_STORE_ANNOUNCEMENT","storeAnnouncement","AI_LAYOUT_STORE_ANNOUNCEMENT_LINK","shopNow","headerLook","band","props","color","sx","boxShadow","bgcolor","aiLayoutIsCopyright","text","test","FOOTER_LEAVES_OUT","Set","frameScope","page","at","centered","index","level","headed","itemsLeft","frame","link","sections","from","formSection","aiCompileLayoutFrame","plan","targets","header","tree","storePages","storeLinks","footer","map","id","href","label","slug","title","siteName","pages","pageId","options","reusableComponents","language","settled","scrollTo","itemIds","images","strong","brand","dark","pageIcon","sparkle","formsPlaced","design","pictures","features","splitAt","quotesOnly","name","blocks","look","scope","navLink","entry","role","interactions","add","children","slice","screenId","renderAs","textDecoration","nodes","navPages","filter","trim","centeredNav","align","length","brandSx","typography","fontWeight","whiteSpace","overflow","textOverflow","minWidth","flexGrow","logo","src","source","alt","replace","brandMark","srcDark","logoDark","withName","homeId","grow","variant","component","aspect","Number","isFinite","Math","min","logoHeight","parseInt","brandWidth","round","close","AI_LAYOUT_CLOSE_DRAWER","drawn","onBrand","pagesBreakpoint","nav","menu","ctas","breakpoint","ariaLabel","direction","spacing","alignItems","display","xs","ctaBlock","undefined","find","block","kind","store","shopId","noteBlock","push","what","ctaLabel","ctaResolved","to","repeatsNav","some","ctaTo","cart","ctaProps","cta","sm","flexShrink","accountPath","accountLink","drawer","anchor","flexDirection","gap","p","fullWidth","mt","toggle","ml","middle","justifyContent","row","maxWidth","columnGap","toolbar","disableGutters","minHeight","md","barLook","bar","position","overHero","announcement","said","words","useFlexGap","flexWrap","py","px","slot","sourceFooter","compileFooter","column","prune","rootId","AI_LAYOUT_STORE_FOOTER_HEADING","customerCare","STORE_HEADING","aiLayoutFooterStoreHeading","columns","navItems","candidates","navTo","item","forEach","end","under","site","one","items","has","heading","String","empty","pick","enabled","trigger","event","everyTime","steps","type","asked","closesDark","linksPages","flatMap","given","notice","pageLinks","cols","col","weights","list","home","splice","contact","contactItems","filled","weight","top","copyright","bottom","pt","borderTop","borderColor","footerLogo","logoPictures","objectFit","width","height","stack","container","element","colorScheme","input","light","loading","_deferred","image","alone","linked","decorative","homeLink"],"mappings":"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"}
|
|
@@ -143,6 +143,11 @@ export interface AiLayoutTab {
|
|
|
143
143
|
/** The tab the source shows open. */
|
|
144
144
|
selected?: boolean;
|
|
145
145
|
blocks: AiLayoutBlock[];
|
|
146
|
+
/**
|
|
147
|
+
* The row of columns the source sets in the panel (AGL-4114), as a
|
|
148
|
+
* section's `cols`: relative widths, its blocks placed by `col`.
|
|
149
|
+
*/
|
|
150
|
+
cols?: number[];
|
|
146
151
|
}
|
|
147
152
|
export interface AiLayoutBlock {
|
|
148
153
|
kind: AiLayoutBlockKind | AiLayoutImportBlockKind;
|