@syntrologie/adapt-product 2.34.0 → 2.35.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.
Files changed (34) hide show
  1. package/dist/cdn.js +2 -2
  2. package/dist/{chunk-FAKCB3BS.js → chunk-AAV4C3P4.js} +67 -30
  3. package/dist/chunk-AAV4C3P4.js.map +7 -0
  4. package/dist/{chunk-NH3CFDTZ.js → chunk-HV6QS4PQ.js} +1115 -483
  5. package/dist/chunk-HV6QS4PQ.js.map +7 -0
  6. package/dist/native/nativeSlotWatcher.d.ts.map +1 -1
  7. package/dist/runtime.d.ts +12 -10
  8. package/dist/runtime.d.ts.map +1 -1
  9. package/dist/runtime.js +6 -2
  10. package/dist/schema-primitives.d.ts +4 -4
  11. package/dist/schema.d.ts +143 -58
  12. package/dist/schema.d.ts.map +1 -1
  13. package/dist/schema.js +9 -1
  14. package/dist/takeover/engine.d.ts +45 -0
  15. package/dist/takeover/engine.d.ts.map +1 -0
  16. package/dist/takeover/fetchPlan.d.ts +61 -0
  17. package/dist/takeover/fetchPlan.d.ts.map +1 -0
  18. package/dist/takeover/ports.d.ts +29 -0
  19. package/dist/takeover/ports.d.ts.map +1 -0
  20. package/dist/takeover/regionCurtain.d.ts +17 -0
  21. package/dist/takeover/regionCurtain.d.ts.map +1 -0
  22. package/dist/takeover/renderModules.d.ts +48 -0
  23. package/dist/takeover/renderModules.d.ts.map +1 -0
  24. package/dist/takeover/resurrectionGuard.d.ts +28 -0
  25. package/dist/takeover/resurrectionGuard.d.ts.map +1 -0
  26. package/dist/takeover/schema.d.ts +163 -0
  27. package/dist/takeover/schema.d.ts.map +1 -0
  28. package/dist/takeover/sectionDetach.d.ts +13 -0
  29. package/dist/takeover/sectionDetach.d.ts.map +1 -0
  30. package/dist/widgets/SyntroPdpLit.d.ts +69 -0
  31. package/dist/widgets/SyntroPdpLit.d.ts.map +1 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-FAKCB3BS.js.map +0 -7
  34. package/dist/chunk-NH3CFDTZ.js.map +0 -7
@@ -9,8 +9,9 @@ import {
9
9
  getProductPlatformAdapter,
10
10
  gridSchema,
11
11
  heroSchema,
12
- recoSchema
13
- } from "./chunk-FAKCB3BS.js";
12
+ recoSchema,
13
+ takeoverPlanSchema
14
+ } from "./chunk-AAV4C3P4.js";
14
15
 
15
16
  // ../../../node_modules/@lit/context/lib/create-context.js
16
17
  function n(n2) {
@@ -279,7 +280,7 @@ function selectPresetData(kind, data, decision) {
279
280
  }
280
281
 
281
282
  // src/widgets/SyntroPdpLit.ts
282
- import { html as html5, LitElement as LitElement5, render } from "lit";
283
+ import { html as html6, LitElement as LitElement6, render } from "lit";
283
284
 
284
285
  // src/decision/pdp.ts
285
286
  function createInitialPdpState(generation = 0) {
@@ -734,6 +735,319 @@ async function resolveScoredTemplate(opts) {
734
735
  return { value, decisionValue, setSlots, unsetSlots };
735
736
  }
736
737
 
738
+ // src/takeover/resurrectionGuard.ts
739
+ function startResurrectionGuard(opts) {
740
+ const maxRetries = opts.maxRetries ?? 3;
741
+ const debounceMs = opts.debounceMs ?? 50;
742
+ const watched = new Map(opts.anchors);
743
+ const counts = /* @__PURE__ */ new Map();
744
+ let timer = null;
745
+ let stopped = false;
746
+ const sweep = () => {
747
+ if (stopped) return;
748
+ const present = [];
749
+ for (const [sectionId, selector] of watched) {
750
+ let matches = [];
751
+ try {
752
+ matches = Array.from(opts.region.querySelectorAll(selector));
753
+ } catch {
754
+ continue;
755
+ }
756
+ const el = matches.find((m) => !(opts.ignore?.(m) ?? false));
757
+ if (!el) continue;
758
+ present.push({ sectionId, el, n: (counts.get(sectionId) ?? 0) + 1 });
759
+ }
760
+ const exhausted = present.find((p) => p.n > maxRetries);
761
+ if (exhausted) {
762
+ for (const p of present) p.el.remove();
763
+ opts.onBudgetExhausted(exhausted.sectionId, exhausted.el);
764
+ return;
765
+ }
766
+ for (const { sectionId, el, n: n2 } of present) {
767
+ counts.set(sectionId, n2);
768
+ opts.onResurrected(sectionId, el);
769
+ }
770
+ };
771
+ const observer2 = new MutationObserver(() => {
772
+ if (timer) clearTimeout(timer);
773
+ timer = setTimeout(sweep, debounceMs);
774
+ });
775
+ observer2.observe(opts.region, { childList: true, subtree: true });
776
+ return {
777
+ stop() {
778
+ stopped = true;
779
+ if (timer) clearTimeout(timer);
780
+ observer2.disconnect();
781
+ },
782
+ unwatch(sectionId) {
783
+ watched.delete(sectionId);
784
+ counts.delete(sectionId);
785
+ }
786
+ };
787
+ }
788
+
789
+ // src/takeover/sectionDetach.ts
790
+ var activeDetaches = /* @__PURE__ */ new WeakSet();
791
+ function detachSection(section) {
792
+ if (activeDetaches.has(section)) return null;
793
+ if (!section.parentNode) return null;
794
+ activeDetaches.add(section);
795
+ const anchor = document.createComment("syntro-takeover-section");
796
+ section.before(anchor);
797
+ section.remove();
798
+ let restored = false;
799
+ return {
800
+ section,
801
+ get restored() {
802
+ return restored;
803
+ },
804
+ restore() {
805
+ if (restored) return;
806
+ restored = true;
807
+ if (anchor.parentNode) anchor.after(section);
808
+ anchor.remove();
809
+ activeDetaches.delete(section);
810
+ }
811
+ };
812
+ }
813
+
814
+ // src/takeover/engine.ts
815
+ var DEFAULT_COMMIT_TIMEOUT_MS = 500;
816
+ var NOOP_DISPOSE = () => {
817
+ };
818
+ async function runTakeover(config, ports, opts = {}) {
819
+ if (!ports.hasSignals()) {
820
+ void Promise.resolve().then(() => ports.fetchPlan()).then(
821
+ (response2) => ports.renderModules(
822
+ {
823
+ // Host-derived entries (kind:sectionId) are ALSO dropped here:
824
+ // their source sections stay attached on this path, and rendering
825
+ // our re-presentation next to the attached original duplicates
826
+ // host content — the exact class the spec forbids (review F2).
827
+ order: response2.plan.order.filter((entry) => !entry.includes(":")),
828
+ suppress: []
829
+ },
830
+ () => {
831
+ }
832
+ )
833
+ ).catch(() => ports.telemetry("takeover.render_failed", { path: "progressive" }));
834
+ return { outcome: "progressive", dispose: NOOP_DISPOSE };
835
+ }
836
+ const commitTimeoutMs = opts.commitTimeoutMs ?? DEFAULT_COMMIT_TIMEOUT_MS;
837
+ const region = ports.region();
838
+ const lift = ports.curtain();
839
+ let timeoutId;
840
+ const timedOut = /* @__PURE__ */ Symbol("timeout");
841
+ const fetchFailed = /* @__PURE__ */ Symbol("fetch-failed");
842
+ const response = await Promise.race([
843
+ ports.fetchPlan().catch(() => fetchFailed),
844
+ new Promise((r) => {
845
+ timeoutId = setTimeout(() => r(timedOut), commitTimeoutMs);
846
+ })
847
+ ]).finally(() => clearTimeout(timeoutId));
848
+ if (response === timedOut || response === fetchFailed) {
849
+ ports.deactivateRoot();
850
+ lift();
851
+ if (response === timedOut) {
852
+ ports.telemetry("takeover.precommit_timeout", { budgetMs: commitTimeoutMs });
853
+ } else {
854
+ ports.telemetry("takeover.plan_fetch_failed", { budgetMs: commitTimeoutMs });
855
+ }
856
+ return { outcome: "aborted-precommit", dispose: NOOP_DISPOSE };
857
+ }
858
+ const plan = response.plan;
859
+ const sectionsById = new Map(config.hostSections.map((s4) => [s4.id, s4]));
860
+ const toSuppress = [];
861
+ let reservedPx = 0;
862
+ for (const id of plan.suppress) {
863
+ const section = sectionsById.get(id);
864
+ if (!section) {
865
+ ports.telemetry("takeover.suppress_undeclared", { sectionId: id });
866
+ continue;
867
+ }
868
+ let el = null;
869
+ try {
870
+ el = ports.findSection(section.anchor);
871
+ } catch {
872
+ }
873
+ if (!el) {
874
+ ports.telemetry("takeover.section_anchor_missing", { sectionId: id });
875
+ continue;
876
+ }
877
+ reservedPx += ports.measureSection(el);
878
+ toSuppress.push({ id, el });
879
+ }
880
+ ports.reserve(reservedPx);
881
+ const handles = /* @__PURE__ */ new Map();
882
+ for (const { id, el } of toSuppress) {
883
+ const handle = detachSection(el);
884
+ if (handle) handles.set(id, handle);
885
+ }
886
+ let disposed = false;
887
+ let guard;
888
+ const dispose = () => {
889
+ if (disposed) return;
890
+ disposed = true;
891
+ guard?.stop();
892
+ for (const handle of handles.values()) handle.restore();
893
+ handles.clear();
894
+ ports.deactivateRoot();
895
+ lift();
896
+ };
897
+ guard = startResurrectionGuard({
898
+ region,
899
+ ignore: (el) => ports.ownsNode(el),
900
+ anchors: new Map(toSuppress.map(({ id }) => [id, sectionsById.get(id).anchor])),
901
+ onResurrected: (sectionId, el) => {
902
+ ports.telemetry("takeover.section_resurrected", { sectionId });
903
+ el.remove();
904
+ },
905
+ onBudgetExhausted: (sectionId, el) => {
906
+ ports.telemetry("takeover.resurrection_budget_exhausted", { sectionId });
907
+ el.remove();
908
+ dispose();
909
+ }
910
+ });
911
+ const onModuleFailed = (suppressedSectionId) => {
912
+ if (!suppressedSectionId) return;
913
+ const handle = handles.get(suppressedSectionId);
914
+ if (!handle) return;
915
+ guard?.unwatch(suppressedSectionId);
916
+ handle.restore();
917
+ handles.delete(suppressedSectionId);
918
+ ports.telemetry("takeover.module_failed_section_restored", {
919
+ sectionId: suppressedSectionId
920
+ });
921
+ };
922
+ void Promise.resolve().then(() => ports.renderModules(plan, onModuleFailed)).catch(() => {
923
+ ports.telemetry("takeover.render_failed", { path: "committed" });
924
+ dispose();
925
+ }).finally(() => ports.releaseReservation());
926
+ lift();
927
+ return { outcome: "committed", dispose };
928
+ }
929
+
930
+ // src/takeover/fetchPlan.ts
931
+ import { z as z2 } from "zod";
932
+ var takeoverPlanResponseSchema = z2.object({
933
+ decisionArchetype: z2.string().min(1),
934
+ plan: takeoverPlanSchema
935
+ }).strict();
936
+ function createTakeoverPlanFetcher(deps) {
937
+ return async () => {
938
+ const resp = await deps.authedFetch("/api/pdp/plan", {
939
+ method: "POST",
940
+ // FROZEN SEAM SHAPE — field set AND order are pinned byte-for-byte by
941
+ // `src/__fixtures__/takeover-plan-request.json`; the runtime-backend PR
942
+ // commits the same fixture. Change both sides together or not at all.
943
+ // Deliberately NO client-scored archetype/decision slugs: the server
944
+ // scores (spec rev 3) — the client sends vocabulary + signals only.
945
+ body: JSON.stringify({
946
+ product_id: deps.productId,
947
+ product_name: deps.productName,
948
+ // Page anatomy: ids + roles only. Anchors are host DOM selectors —
949
+ // client-side facts the server has no business receiving.
950
+ host_sections: deps.config.hostSections.map(({ id, role }) => ({ id, role })),
951
+ decision_archetypes: deps.decisionArchetypes,
952
+ behavior_summary: deps.behaviorSummary,
953
+ signals: deps.signals,
954
+ ingest_snapshot: deps.config.ingestSnapshot
955
+ })
956
+ });
957
+ if (!resp.ok) {
958
+ throw new Error(`takeover plan fetch failed: HTTP ${resp.status}`);
959
+ }
960
+ const data = await resp.json();
961
+ return takeoverPlanResponseSchema.parse(data);
962
+ };
963
+ }
964
+
965
+ // src/takeover/regionCurtain.ts
966
+ var CLASS = "syntro-takeover-curtain";
967
+ var STYLE_ATTR = "data-syntro-takeover-curtain";
968
+ var styleRefs = 0;
969
+ function acquireStyle() {
970
+ styleRefs += 1;
971
+ if (document.head.querySelector(`style[${STYLE_ATTR}]`)) return;
972
+ const styleEl = document.createElement("style");
973
+ styleEl.setAttribute(STYLE_ATTR, "");
974
+ styleEl.textContent = `.${CLASS} { opacity: 0 !important; }`;
975
+ document.head.appendChild(styleEl);
976
+ }
977
+ function releaseStyle() {
978
+ styleRefs = Math.max(0, styleRefs - 1);
979
+ if (styleRefs === 0) {
980
+ document.head.querySelector(`style[${STYLE_ATTR}]`)?.remove();
981
+ }
982
+ }
983
+ function applyRegionCurtain(region, opts = {}) {
984
+ const timeoutMs = opts.timeoutMs ?? 3e3;
985
+ acquireStyle();
986
+ region.classList.add(CLASS);
987
+ let lifted = false;
988
+ const lift = () => {
989
+ if (lifted) return;
990
+ lifted = true;
991
+ clearTimeout(timeoutId);
992
+ region.classList.remove(CLASS);
993
+ releaseStyle();
994
+ };
995
+ const timeoutId = setTimeout(lift, timeoutMs);
996
+ return lift;
997
+ }
998
+ function applyCurtainToTargets(targets, opts = {}) {
999
+ const lifts = targets.map((t2) => applyRegionCurtain(t2, opts));
1000
+ return () => {
1001
+ for (const lift of lifts) lift();
1002
+ };
1003
+ }
1004
+
1005
+ // src/takeover/ports.ts
1006
+ function createDomPorts(config, deps) {
1007
+ return {
1008
+ hasSignals: () => deps.signalCount > 0,
1009
+ findSection(anchor) {
1010
+ try {
1011
+ return document.querySelector(anchor);
1012
+ } catch {
1013
+ return null;
1014
+ }
1015
+ },
1016
+ measureSection: (el) => el.getBoundingClientRect().height,
1017
+ reserve(minHeightPx) {
1018
+ if (minHeightPx > 0) deps.root.style.minHeight = `${Math.round(minHeightPx)}px`;
1019
+ },
1020
+ releaseReservation() {
1021
+ deps.root.style.removeProperty("min-height");
1022
+ },
1023
+ region: () => deps.root.parentElement ?? deps.root,
1024
+ ownsNode: (el) => deps.root.contains(el),
1025
+ curtain() {
1026
+ const targets = [deps.root];
1027
+ for (const section of config.hostSections) {
1028
+ try {
1029
+ const el = document.querySelector(section.anchor);
1030
+ if (el) targets.push(el);
1031
+ } catch {
1032
+ }
1033
+ }
1034
+ return applyCurtainToTargets(targets);
1035
+ },
1036
+ deactivateRoot() {
1037
+ deps.root.replaceChildren();
1038
+ deps.root.style.display = "none";
1039
+ },
1040
+ fetchPlan: deps.fetchPlan,
1041
+ renderModules: deps.renderModules,
1042
+ telemetry: deps.telemetry
1043
+ };
1044
+ }
1045
+ function attachLifecycleDispose(result) {
1046
+ const onHide = () => result.dispose();
1047
+ window.addEventListener("pagehide", onHide, { once: true });
1048
+ return () => window.removeEventListener("pagehide", onHide);
1049
+ }
1050
+
737
1051
  // src/widgets/PdpSectionHeaderLit.ts
738
1052
  import { html, LitElement, nothing } from "lit";
739
1053
  function ensureSectionHeaderStyles() {
@@ -898,11 +1212,298 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-sec
898
1212
  customElements.define("syntro-pdp-section-header", PdpSectionHeaderLit);
899
1213
  }
900
1214
 
1215
+ // src/widgets/PdpSlotLit.ts
1216
+ import { html as html2, LitElement as LitElement2, nothing as nothing2 } from "lit";
1217
+ function ensureSlotStyles() {
1218
+ if (typeof document === "undefined") return;
1219
+ if (document.getElementById("syntro-pdp-slot-style")) return;
1220
+ const s4 = document.createElement("style");
1221
+ s4.id = "syntro-pdp-slot-style";
1222
+ s4.textContent = SLOT_CSS;
1223
+ document.head.appendChild(s4);
1224
+ }
1225
+ var SLOT_CSS = `
1226
+ .syntro-pdp-slot {
1227
+ --sl-primary: var(--syntro-pdp-primary, hsl(150 32% 38%));
1228
+ --sl-fg: var(--syntro-pdp-fg, hsl(35 15% 92%));
1229
+ --sl-muted: var(--syntro-pdp-muted, hsl(30 8% 55%));
1230
+ --sl-border: var(--syntro-pdp-border, hsl(30 6% 18%));
1231
+ --sl-bg-a: var(--syntro-pdp-card-bg, hsl(25 10% 11%));
1232
+ --sl-bg-b: var(--syntro-pdp-card-bg-b, hsl(25 10% 9%));
1233
+ --sl-display: var(--syntro-pdp-display, inherit);
1234
+
1235
+ position: relative;
1236
+ display: grid;
1237
+ grid-template-areas: 'stack';
1238
+ font-family: var(--syntro-pdp-sans, inherit);
1239
+ }
1240
+ .syntro-pdp-slot > .syntro-pdp-slot-mount,
1241
+ .syntro-pdp-slot > .syntro-pdp-slot-pending,
1242
+ .syntro-pdp-slot > .syntro-pdp-slot-failed {
1243
+ grid-area: stack;
1244
+ }
1245
+
1246
+ .syntro-pdp-slot-mount {
1247
+ min-height: 220px;
1248
+ }
1249
+
1250
+ /* When mutation arrived, hide the pending layer */
1251
+ .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-pending,
1252
+ .syntro-pdp-slot[data-state='failed'] .syntro-pdp-slot-pending {
1253
+ display: none;
1254
+ }
1255
+ .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-failed,
1256
+ .syntro-pdp-slot[data-state='pending'] .syntro-pdp-slot-failed {
1257
+ display: none;
1258
+ }
1259
+
1260
+ /* Pending \u2014 a quietly-animated waiting state. */
1261
+ .syntro-pdp-slot-pending {
1262
+ position: relative;
1263
+ border: 1px dashed var(--sl-border);
1264
+ border-radius: 22px;
1265
+ min-height: 220px;
1266
+ padding: 36px 28px;
1267
+ background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
1268
+ overflow: hidden;
1269
+ display: flex;
1270
+ align-items: center;
1271
+ justify-content: flex-start;
1272
+ }
1273
+ .syntro-pdp-slot-pending-shimmer {
1274
+ position: absolute;
1275
+ inset: 0;
1276
+ background: linear-gradient(
1277
+ 90deg,
1278
+ transparent,
1279
+ color-mix(in srgb, var(--sl-primary) 7%, transparent),
1280
+ transparent
1281
+ );
1282
+ transform: translateX(-100%);
1283
+ animation: syntro-pdp-slot-sweep 1800ms ease-in-out infinite;
1284
+ }
1285
+ .syntro-pdp-slot-pending-row {
1286
+ position: relative;
1287
+ z-index: 1;
1288
+ display: flex;
1289
+ align-items: center;
1290
+ gap: 12px;
1291
+ }
1292
+ .syntro-pdp-slot-pending-dot {
1293
+ flex: 0 0 auto;
1294
+ width: 8px;
1295
+ height: 8px;
1296
+ border-radius: 50%;
1297
+ background: var(--sl-primary);
1298
+ box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
1299
+ animation: syntro-pdp-slot-pulse 1600ms ease-in-out infinite;
1300
+ }
1301
+ .syntro-pdp-slot-pending-label {
1302
+ font-family: var(--sl-display);
1303
+ font-style: italic;
1304
+ font-size: 18px;
1305
+ font-variation-settings: 'SOFT' 70;
1306
+ color: var(--sl-muted);
1307
+ margin: 0;
1308
+ line-height: 1.4;
1309
+ }
1310
+
1311
+ /* Failed \u2014 the planner or sub-agent failed; the host page still works. */
1312
+ .syntro-pdp-slot-failed {
1313
+ border: 1px solid var(--sl-border);
1314
+ border-radius: 22px;
1315
+ min-height: 180px;
1316
+ padding: 24px 28px;
1317
+ background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
1318
+ display: flex;
1319
+ flex-direction: column;
1320
+ justify-content: center;
1321
+ gap: 6px;
1322
+ }
1323
+ .syntro-pdp-slot-failed-title {
1324
+ font-family: var(--sl-display);
1325
+ font-style: italic;
1326
+ font-size: 17px;
1327
+ color: var(--sl-fg);
1328
+ margin: 0;
1329
+ font-variation-settings: 'SOFT' 70;
1330
+ }
1331
+ .syntro-pdp-slot-failed-body {
1332
+ color: var(--sl-muted);
1333
+ font-size: 13.5px;
1334
+ margin: 0;
1335
+ line-height: 1.5;
1336
+ }
1337
+
1338
+ @media (max-width: 640px) {
1339
+ .syntro-pdp-slot-pending,
1340
+ .syntro-pdp-slot-failed {
1341
+ border-radius: 18px;
1342
+ padding: 24px 18px;
1343
+ min-height: 180px;
1344
+ }
1345
+ .syntro-pdp-slot-pending-label {
1346
+ font-size: 15.5px;
1347
+ }
1348
+ }
1349
+
1350
+ @keyframes syntro-pdp-slot-sweep {
1351
+ 0% { transform: translateX(-100%); }
1352
+ 100% { transform: translateX(100%); }
1353
+ }
1354
+ @keyframes syntro-pdp-slot-pulse {
1355
+ 0%, 100% {
1356
+ opacity: 0.6;
1357
+ box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
1358
+ }
1359
+ 50% {
1360
+ opacity: 1;
1361
+ box-shadow: 0 0 0 8px color-mix(in srgb, var(--sl-primary) 26%, transparent);
1362
+ }
1363
+ }
1364
+ `;
1365
+ var PENDING_COPY = {
1366
+ "trending-news": "Composing this section\u2026",
1367
+ chart: "Drawing the comparison\u2026",
1368
+ qa: "Picking the questions worth answering\u2026",
1369
+ regional: "Locating you in time and place\u2026",
1370
+ "peer-feed": "Finding people like you\u2026"
1371
+ };
1372
+ var PENDING_FALLBACK = "Composing\u2026";
1373
+ var PdpSlotLit = class extends LitElement2 {
1374
+ constructor() {
1375
+ super(...arguments);
1376
+ /** DOM id the host's mutation runtime targets when appending the widget. */
1377
+ this.slotId = "";
1378
+ this.kind = "";
1379
+ this.state = "pending";
1380
+ }
1381
+ createRenderRoot() {
1382
+ return this;
1383
+ }
1384
+ connectedCallback() {
1385
+ super.connectedCallback();
1386
+ ensureSlotStyles();
1387
+ }
1388
+ willUpdate() {
1389
+ this.dataset.state = this.state;
1390
+ }
1391
+ render() {
1392
+ const pendingLabel = PENDING_COPY[this.kind] ?? PENDING_FALLBACK;
1393
+ return html2`
1394
+ <div class="syntro-pdp-slot" data-state=${this.state} data-kind=${this.kind}>
1395
+ <div
1396
+ class="syntro-pdp-slot-mount"
1397
+ id=${this.slotId || nothing2}
1398
+ data-pdp-slot=${this.kind}
1399
+ ></div>
1400
+ <div class="syntro-pdp-slot-pending" aria-hidden=${this.state !== "pending"}>
1401
+ <div class="syntro-pdp-slot-pending-shimmer" aria-hidden="true"></div>
1402
+ <div class="syntro-pdp-slot-pending-row">
1403
+ <span class="syntro-pdp-slot-pending-dot" aria-hidden="true"></span>
1404
+ <p class="syntro-pdp-slot-pending-label">${pendingLabel}</p>
1405
+ </div>
1406
+ </div>
1407
+ <div class="syntro-pdp-slot-failed" aria-hidden=${this.state !== "failed"}>
1408
+ <p class="syntro-pdp-slot-failed-title">
1409
+ Personalized view couldn't load.
1410
+ </p>
1411
+ <p class="syntro-pdp-slot-failed-body">
1412
+ The standard page still has everything you need.
1413
+ </p>
1414
+ </div>
1415
+ </div>
1416
+ `;
1417
+ }
1418
+ };
1419
+ PdpSlotLit.properties = {
1420
+ slotId: { type: String, attribute: "slot-id" },
1421
+ kind: { type: String },
1422
+ state: { type: String, reflect: true }
1423
+ };
1424
+ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-slot")) {
1425
+ customElements.define("syntro-pdp-slot", PdpSlotLit);
1426
+ }
1427
+
1428
+ // src/takeover/renderModules.ts
1429
+ function parsePlanEntry(entry) {
1430
+ const i2 = entry.indexOf(":");
1431
+ if (i2 === -1) return { kind: entry, hostSectionId: null };
1432
+ return { kind: entry.slice(0, i2), hostSectionId: entry.slice(i2 + 1) || null };
1433
+ }
1434
+ function createTakeoverModuleRenderer(deps) {
1435
+ return async (plan, onModuleFailed) => {
1436
+ const decisionArchetype = deps.getDecisionArchetype();
1437
+ const row = deps.getPresetRow(decisionArchetype) ?? {};
1438
+ const bakedWork = [];
1439
+ plan.order.forEach((entry, index) => {
1440
+ const { kind, hostSectionId } = parsePlanEntry(entry);
1441
+ const slotId = `pdp-slot-${kind}`;
1442
+ const preset = row[slotId];
1443
+ const tag = deps.resolveTag(kind, preset?.variant ?? null);
1444
+ if (!tag) {
1445
+ deps.telemetry("takeover.module_kind_unknown", { entry, kind });
1446
+ onModuleFailed(hostSectionId);
1447
+ return;
1448
+ }
1449
+ const envelope = buildPdpPlan([{ slot: slotId, preset }]);
1450
+ const task = envelope.tasks[0];
1451
+ const section = document.createElement("section");
1452
+ section.toggleAttribute("data-syntro-pdp-section", true);
1453
+ section.setAttribute("data-slot", slotId);
1454
+ section.setAttribute("data-syntro-takeover-entry", entry);
1455
+ const header = document.createElement("syntro-pdp-section-header");
1456
+ header.eyebrow = task.header.eyebrow ?? "";
1457
+ header.title = task.header.title ?? "";
1458
+ header.accent = task.header.accent ?? "";
1459
+ header.subtitle = task.header.subtitle ?? "";
1460
+ const inner = document.createElement("div");
1461
+ inner.toggleAttribute("data-syntro-pdp-section-inner", true);
1462
+ const slotEl = document.createElement("syntro-pdp-slot");
1463
+ slotEl.slotId = `syntro-takeover-${index}-${slotId}`;
1464
+ slotEl.kind = kind;
1465
+ slotEl.state = "pending";
1466
+ inner.appendChild(slotEl);
1467
+ section.append(header, inner);
1468
+ deps.root.appendChild(section);
1469
+ const fail = () => {
1470
+ if (hostSectionId) {
1471
+ section.remove();
1472
+ } else {
1473
+ slotEl.state = "failed";
1474
+ }
1475
+ deps.telemetry("takeover.module_failed", { entry, kind });
1476
+ onModuleFailed(hostSectionId);
1477
+ };
1478
+ const mountPayload = async (payload) => {
1479
+ await slotEl.updateComplete;
1480
+ const mount = slotEl.querySelector(".syntro-pdp-slot-mount");
1481
+ if (!mount) {
1482
+ fail();
1483
+ return;
1484
+ }
1485
+ mount.replaceChildren();
1486
+ const widget = document.createElement(tag);
1487
+ widget.data = payload;
1488
+ mount.appendChild(widget);
1489
+ slotEl.state = "mounted";
1490
+ };
1491
+ if (preset) {
1492
+ const data = selectPresetData(preset.kind, preset.data, decisionArchetype);
1493
+ bakedWork.push(mountPayload(data).catch(fail));
1494
+ } else {
1495
+ void deps.requestLiveModule(kind, decisionArchetype).then((payload) => payload ? mountPayload(payload) : fail()).catch(fail);
1496
+ }
1497
+ });
1498
+ await Promise.all(bakedWork);
1499
+ };
1500
+ }
1501
+
901
1502
  // src/widgets/PdpOtherProductsCarouselLit.ts
902
- import { html as html3, LitElement as LitElement3 } from "lit";
1503
+ import { html as html4, LitElement as LitElement4 } from "lit";
903
1504
 
904
1505
  // src/widgets/OtherProductTileLit.ts
905
- import { html as html2, LitElement as LitElement2 } from "lit";
1506
+ import { html as html3, LitElement as LitElement3 } from "lit";
906
1507
  var RELATIONSHIP_LABELS = {
907
1508
  discovery: "Recommended for you",
908
1509
  complement: "Pairs with this",
@@ -1045,7 +1646,7 @@ var OTHER_PRODUCT_TILE_CSS = `
1045
1646
  background: color-mix(in srgb, var(--opt-primary) 10%, transparent);
1046
1647
  }
1047
1648
  `;
1048
- var OtherProductTileLit = class extends LitElement2 {
1649
+ var OtherProductTileLit = class extends LitElement3 {
1049
1650
  constructor() {
1050
1651
  super(...arguments);
1051
1652
  this.tile = null;
@@ -1060,24 +1661,24 @@ var OtherProductTileLit = class extends LitElement2 {
1060
1661
  render() {
1061
1662
  const t2 = this.tile;
1062
1663
  if (!t2) {
1063
- return html2``;
1664
+ return html3``;
1064
1665
  }
1065
1666
  const relationshipLabel = RELATIONSHIP_LABELS[t2.relationship];
1066
1667
  const price = t2.price_cents == null ? "" : `$${(t2.price_cents / 100).toFixed(0)}`;
1067
- return html2`
1668
+ return html3`
1068
1669
  <article class="opt-card" data-relationship="${t2.relationship}">
1069
- ${t2.image_url ? html2`<div class="opt-image">
1670
+ ${t2.image_url ? html3`<div class="opt-image">
1070
1671
  <img src="${t2.image_url}" alt="${t2.name}" loading="lazy" />
1071
1672
  </div>` : null}
1072
1673
  <div class="opt-relationship" data-relationship="${t2.relationship}">
1073
- ${relationshipLabel ? html2`${relationshipLabel}` : null}
1674
+ ${relationshipLabel ? html3`${relationshipLabel}` : null}
1074
1675
  <span class="opt-relationship-type">${t2.relationship}</span>
1075
1676
  </div>
1076
1677
  <h3 class="opt-name">${t2.name}</h3>
1077
- ${t2.tagline ? html2`<p class="opt-tagline">${t2.tagline}</p>` : null}
1078
- ${t2.why_blurb ? html2`<p class="opt-why">${t2.why_blurb}</p>` : null}
1079
- ${t2.evidence_chips.length ? html2`<div class="opt-chips">
1080
- ${t2.evidence_chips.map((c2) => html2`<span class="opt-chip">${c2.display}</span>`)}
1678
+ ${t2.tagline ? html3`<p class="opt-tagline">${t2.tagline}</p>` : null}
1679
+ ${t2.why_blurb ? html3`<p class="opt-why">${t2.why_blurb}</p>` : null}
1680
+ ${t2.evidence_chips.length ? html3`<div class="opt-chips">
1681
+ ${t2.evidence_chips.map((c2) => html3`<span class="opt-chip">${c2.display}</span>`)}
1081
1682
  </div>` : null}
1082
1683
  <div class="opt-footer">
1083
1684
  <span class="opt-price">${price}</span>
@@ -1160,7 +1761,7 @@ syntro-pdp-other-products-carousel {
1160
1761
  }
1161
1762
  }
1162
1763
  `;
1163
- var PdpOtherProductsCarouselLit = class extends LitElement3 {
1764
+ var PdpOtherProductsCarouselLit = class extends LitElement4 {
1164
1765
  constructor() {
1165
1766
  super(...arguments);
1166
1767
  this.data = null;
@@ -1173,12 +1774,12 @@ var PdpOtherProductsCarouselLit = class extends LitElement3 {
1173
1774
  ensureCarouselStyles();
1174
1775
  }
1175
1776
  render() {
1176
- if (!this.data) return html3``;
1177
- return html3`
1777
+ if (!this.data) return html4``;
1778
+ return html4`
1178
1779
  <div class="opc-carousel">
1179
1780
  <div class="carousel" role="list">
1180
1781
  ${this.data.tiles.map(
1181
- (tile) => html3`
1782
+ (tile) => html4`
1182
1783
  <div class="opc-item" role="listitem">
1183
1784
  <syntro-pdp-other-product-tile .tile=${tile}></syntro-pdp-other-product-tile>
1184
1785
  </div>
@@ -1197,7 +1798,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-oth
1197
1798
  }
1198
1799
 
1199
1800
  // src/widgets/PdpOtherProductsGridLit.ts
1200
- import { html as html4, LitElement as LitElement4 } from "lit";
1801
+ import { html as html5, LitElement as LitElement5 } from "lit";
1201
1802
  function ensureGridStyles() {
1202
1803
  if (typeof document === "undefined") return;
1203
1804
  if (document.getElementById("syntro-pdp-other-products-grid-style")) return;
@@ -1226,7 +1827,7 @@ syntro-pdp-other-products-grid {
1226
1827
  }
1227
1828
  }
1228
1829
  `;
1229
- var PdpOtherProductsGridLit = class extends LitElement4 {
1830
+ var PdpOtherProductsGridLit = class extends LitElement5 {
1230
1831
  constructor() {
1231
1832
  super(...arguments);
1232
1833
  this.data = null;
@@ -1239,11 +1840,11 @@ var PdpOtherProductsGridLit = class extends LitElement4 {
1239
1840
  ensureGridStyles();
1240
1841
  }
1241
1842
  render() {
1242
- if (!this.data) return html4``;
1243
- return html4`
1843
+ if (!this.data) return html5``;
1844
+ return html5`
1244
1845
  <div class="grid" role="list">
1245
1846
  ${this.data.tiles.map(
1246
- (tile) => html4`
1847
+ (tile) => html5`
1247
1848
  <syntro-pdp-other-product-tile role="listitem" .tile=${tile}></syntro-pdp-other-product-tile>
1248
1849
  `
1249
1850
  )}
@@ -1750,6 +2351,9 @@ function gatherVisitorSignals() {
1750
2351
  extras: gatherExtras(runtime2, context)
1751
2352
  };
1752
2353
  }
2354
+ function countTakeoverSignals(signals) {
2355
+ return _countSignals(signals.session_metrics) + (signals.chat_excerpt ? 1 : 0);
2356
+ }
1753
2357
  var TEMPLATE_TO_TAG = {
1754
2358
  // trending-news (TrendingNewsVariant)
1755
2359
  "trending-news": "syntro-pdp-trending-news",
@@ -1794,12 +2398,21 @@ function resolveTagForMount(inst) {
1794
2398
  }
1795
2399
  return null;
1796
2400
  }
1797
- var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2401
+ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement6 {
1798
2402
  constructor() {
1799
2403
  super(...arguments);
1800
2404
  this.productId = "";
1801
2405
  this.productName = "";
1802
2406
  this.productBlurb = "";
2407
+ /**
2408
+ * Page-takeover anatomy (FEAT-1785977524), normally delivered through the
2409
+ * widget `props` below. Presence at CONNECT time latches the element into
2410
+ * takeover mode: the engine owns the root and the six-slot compose path
2411
+ * never starts. Setting it after a legacy connect is ignored (warned) —
2412
+ * flipping modes on a live element could leave both paths' DOM behind.
2413
+ */
2414
+ this.takeover = void 0;
2415
+ this._propsValue = void 0;
1803
2416
  /**
1804
2417
  * SDK runtime. Null until the mountable wires it in. We only render
1805
2418
  * the personalized surface once runtimeRef is present AND the
@@ -1840,6 +2453,48 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1840
2453
  */
1841
2454
  this._nativeSlots = /* @__PURE__ */ new Set();
1842
2455
  this._nativeHandles = /* @__PURE__ */ new Map();
2456
+ /**
2457
+ * Takeover mode latch — decided ONCE, at the element's FIRST connect, from
2458
+ * the `takeover` prop, and kept for the element's whole lifetime. While
2459
+ * true, Lit never renders into this element (see shouldUpdate): the engine
2460
+ * renders imperatively and its deactivateRoot() calls replaceChildren() on
2461
+ * this root, which would destroy Lit's child parts. The latch is one-way in
2462
+ * BOTH directions — an element that ever rendered legacy has live Lit parts
2463
+ * (engaging the engine would render next to them, then destroy them), and
2464
+ * an element the engine ever owned has no parts left for Lit to resume.
2465
+ */
2466
+ this._takeoverMode = false;
2467
+ this._takeoverModeLatched = false;
2468
+ /** The single in-flight/settled takeover run for this connected lifetime. */
2469
+ this._takeoverRun = null;
2470
+ /**
2471
+ * Settles when the previous run's dispose has fully completed. A re-run
2472
+ * (reconnect, or a synchronous move between parents) chains on this so a
2473
+ * LATE dispose from the torn-down run can never deactivate the root the
2474
+ * new run is rendering into.
2475
+ */
2476
+ this._takeoverDisposal = Promise.resolve();
2477
+ /** A previous run deactivated the root (display:none + emptied); a re-run
2478
+ * after reconnect must undo that before the engine renders again. */
2479
+ this._takeoverRanBefore = false;
2480
+ this._takeoverLateWarned = false;
2481
+ /**
2482
+ * bfcache re-entry (review F4). pagehide disposes the run
2483
+ * (attachLifecycleDispose) but a bfcache restore does NOT re-fire
2484
+ * connectedCallback — without this listener the restored page would sit on
2485
+ * the native fallback forever. `persisted` is true only for bfcache
2486
+ * restores; the normal-load pageshow is owned by the connect path. Arrow
2487
+ * function per Lit event-handler convention (stable identity for
2488
+ * add/removeEventListener).
2489
+ */
2490
+ this._onTakeoverPageShow = (event) => {
2491
+ if (!event.persisted) return;
2492
+ if (!this._takeoverMode || !this.isConnected) return;
2493
+ const config = this.takeover;
2494
+ if (!config) return;
2495
+ this._teardownTakeover();
2496
+ this._startTakeover(config);
2497
+ };
1843
2498
  /**
1844
2499
  * The scored axes from the current config pass — the SAME values
1845
2500
  * `_fireFromConfig` resolved (sport-archetype preset key + decision archetype).
@@ -1860,6 +2515,23 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1860
2515
  this._dispatchDecision({ type: "dossier-toggled", open });
1861
2516
  };
1862
2517
  }
2518
+ /**
2519
+ * Widget props (the `adaptive-product:pdp` mountable sets `el.props` before
2520
+ * appending). Mapped IMMEDIATELY in the setter — not in willUpdate — so
2521
+ * `takeover` is already on the element when connectedCallback latches the
2522
+ * mode. Absent fields leave the element's current values untouched.
2523
+ */
2524
+ get props() {
2525
+ return this._propsValue;
2526
+ }
2527
+ set props(value) {
2528
+ this._propsValue = value;
2529
+ if (!value) return;
2530
+ if (value.productId) this.productId = value.productId;
2531
+ if (value.productName) this.productName = value.productName;
2532
+ if (value.productBlurb) this.productBlurb = value.productBlurb;
2533
+ if (value.takeover) this.takeover = value.takeover;
2534
+ }
1863
2535
  _dispatchDecision(event) {
1864
2536
  const transition = transitionPdp(this._decisionState, event);
1865
2537
  this._decisionState = transition.state;
@@ -1869,6 +2541,25 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1869
2541
  return this;
1870
2542
  }
1871
2543
  connectedCallback() {
2544
+ if (!this._takeoverModeLatched) {
2545
+ this._takeoverModeLatched = true;
2546
+ this._takeoverMode = Boolean(this.takeover);
2547
+ } else if (!this._takeoverMode && this.takeover && !this._takeoverLateWarned) {
2548
+ this._takeoverLateWarned = true;
2549
+ console.warn(
2550
+ "[syntro-pdp] takeover prop set on an element that already connected on the standard compose path \u2014 ignored (mode is latched per element). Mount a fresh element with `takeover` in its widget props."
2551
+ );
2552
+ }
2553
+ if (this._takeoverMode) {
2554
+ super.connectedCallback();
2555
+ ensureSectionLayoutStyles();
2556
+ if (typeof window !== "undefined") {
2557
+ window.removeEventListener("pageshow", this._onTakeoverPageShow);
2558
+ window.addEventListener("pageshow", this._onTakeoverPageShow);
2559
+ }
2560
+ if (this.takeover) this._startTakeover(this.takeover);
2561
+ return;
2562
+ }
1872
2563
  const reconnecting = this._decisionState.connection === "disconnected";
1873
2564
  super.connectedCallback();
1874
2565
  ensureSectionLayoutStyles();
@@ -1885,6 +2576,14 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1885
2576
  }
1886
2577
  }
1887
2578
  disconnectedCallback() {
2579
+ if (this._takeoverMode) {
2580
+ super.disconnectedCallback();
2581
+ if (typeof window !== "undefined") {
2582
+ window.removeEventListener("pageshow", this._onTakeoverPageShow);
2583
+ }
2584
+ this._teardownTakeover();
2585
+ return;
2586
+ }
1888
2587
  super.disconnectedCallback();
1889
2588
  this._navUnsub?.();
1890
2589
  this._navUnsub = null;
@@ -1892,6 +2591,16 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1892
2591
  this._nativeHandles.clear();
1893
2592
  this._dispatchDecision({ type: "disconnected" });
1894
2593
  }
2594
+ shouldUpdate(changed) {
2595
+ if (this._takeoverMode) return false;
2596
+ if (changed.has("takeover") && this.takeover && !this._takeoverLateWarned) {
2597
+ this._takeoverLateWarned = true;
2598
+ console.warn(
2599
+ "[syntro-pdp] takeover prop set after the element already connected on the standard compose path \u2014 ignored. Provide `takeover` in the widget props before the element connects (or re-mount it)."
2600
+ );
2601
+ }
2602
+ return true;
2603
+ }
1895
2604
  willUpdate(changed) {
1896
2605
  if (changed.has("runtimeRef")) {
1897
2606
  this._syncDecisionRuntime(false);
@@ -2014,6 +2723,135 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2014
2723
  _syncDecisionPortal() {
2015
2724
  this._dispatchDecision({ type: "portal-updated", present: this._whyPortalEl() !== null });
2016
2725
  }
2726
+ // ── Takeover wiring (FEAT-1785977524) ────────────────────────────────────
2727
+ /**
2728
+ * Run the takeover engine with real ports: this element as the root,
2729
+ * `SynOS.authedFetch` as the plan/module transport and the existing slot
2730
+ * machinery as the renderer. Activation is config delivery itself: the
2731
+ * served config either carries `takeover` or it doesn't. Runs at
2732
+ * most once per connected lifetime (`_takeoverRun` latch); disconnect tears
2733
+ * it down and a reconnect re-evaluates fresh.
2734
+ */
2735
+ _startTakeover(config) {
2736
+ if (this._takeoverRun) return;
2737
+ if (!this.productId) {
2738
+ this._track("takeover.missing_product_id", {});
2739
+ console.warn(
2740
+ "[syntro-pdp] takeover requires a product id (widget props / product-id attr) \u2014 skipping takeover, native page untouched."
2741
+ );
2742
+ return;
2743
+ }
2744
+ const synos = _readSynOS();
2745
+ const authedFetch = synos?.authedFetch;
2746
+ const signals = { ...gatherVisitorSignals(), chat_excerpt: readChatExcerpt() };
2747
+ const decisionDescriptions = _readPdpDecisionArchetypes() ?? {};
2748
+ const telemetry2 = (event, props) => this._track(event, props);
2749
+ const scored = { decisionArchetype: "unknown" };
2750
+ const fetchPlan = authedFetch ? createTakeoverPlanFetcher({
2751
+ authedFetch,
2752
+ config,
2753
+ productId: this.productId,
2754
+ productName: this.productName,
2755
+ decisionArchetypes: decisionDescriptions,
2756
+ // No client-side summary exists on the takeover path (the server
2757
+ // scores); the field mirrors /api/pdp/module's for the scorer.
2758
+ behaviorSummary: "",
2759
+ signals
2760
+ }) : null;
2761
+ const run = {
2762
+ disposed: false,
2763
+ detach: null,
2764
+ result: Promise.resolve(null)
2765
+ };
2766
+ const renderModules = createTakeoverModuleRenderer({
2767
+ root: this,
2768
+ getPresetRow: (decisionArchetype) => {
2769
+ const table = _readPdpPresets()?.[this.productId];
2770
+ return table?.[decisionArchetype] ?? table?.unknown;
2771
+ },
2772
+ resolveTag: (kind, variant) => resolveTagForMount({
2773
+ slot: `pdp-slot-${kind}`,
2774
+ kind,
2775
+ variant,
2776
+ header: { eyebrow: "", title: "", accent: null, subtitle: null }
2777
+ }),
2778
+ requestLiveModule: async (kind, decisionArchetype) => {
2779
+ if (!authedFetch) return null;
2780
+ return composeModule(authedFetch, {
2781
+ productName: this.productName,
2782
+ // Guaranteed non-empty: _startTakeover gates on a missing product id.
2783
+ productId: this.productId,
2784
+ kind,
2785
+ variant: null,
2786
+ // The takeover round trip scores only the decision axis (the server
2787
+ // resolves the plan from it); the sport-archetype axis is unscored
2788
+ // on this path, so it is sent as an explicit 'unknown' — never a
2789
+ // silently-invented value.
2790
+ archetype: { slug: "unknown", description: "" },
2791
+ decisionArchetype: decisionArchetype === "unknown" ? null : {
2792
+ slug: decisionArchetype,
2793
+ description: decisionDescriptions[decisionArchetype] ?? ""
2794
+ },
2795
+ behaviorSummary: "",
2796
+ signals
2797
+ });
2798
+ },
2799
+ telemetry: telemetry2,
2800
+ getDecisionArchetype: () => scored.decisionArchetype
2801
+ });
2802
+ const ports = createDomPorts(config, {
2803
+ root: this,
2804
+ signalCount: countTakeoverSignals(signals),
2805
+ fetchPlan: fetchPlan ? async () => {
2806
+ const response = await fetchPlan();
2807
+ scored.decisionArchetype = response.decisionArchetype;
2808
+ return response;
2809
+ } : async () => {
2810
+ throw new Error("SynOS.authedFetch unavailable \u2014 cannot fetch takeover plan");
2811
+ },
2812
+ // Torn-down guard: the progressive path's dispose is a no-op (nothing
2813
+ // was detached), so its BACKGROUND render has no cancellation handle —
2814
+ // this gate is what stops a stale run from appending into a root a
2815
+ // newer run may own by then.
2816
+ renderModules: async (plan, onModuleFailed) => {
2817
+ if (run.disposed) return;
2818
+ return renderModules(plan, onModuleFailed);
2819
+ },
2820
+ telemetry: telemetry2
2821
+ });
2822
+ run.result = this._takeoverDisposal.then(() => {
2823
+ if (run.disposed) return null;
2824
+ if (this._takeoverRanBefore) {
2825
+ this.style.removeProperty("display");
2826
+ this.replaceChildren();
2827
+ }
2828
+ this._takeoverRanBefore = true;
2829
+ return runTakeover(config, ports);
2830
+ }).then((result) => {
2831
+ if (!result) return null;
2832
+ telemetry2("takeover.outcome", { outcome: result.outcome });
2833
+ if (run.disposed) {
2834
+ result.dispose();
2835
+ return result;
2836
+ }
2837
+ run.detach = attachLifecycleDispose(result);
2838
+ return result;
2839
+ }).catch((err) => {
2840
+ telemetry2("takeover.run_failed", { error: String(err).slice(0, 200) });
2841
+ return null;
2842
+ });
2843
+ this._takeoverRun = run;
2844
+ }
2845
+ /** Dispose the current takeover run (idempotent). */
2846
+ _teardownTakeover() {
2847
+ const run = this._takeoverRun;
2848
+ if (!run) return;
2849
+ this._takeoverRun = null;
2850
+ run.disposed = true;
2851
+ run.detach?.();
2852
+ run.detach = null;
2853
+ this._takeoverDisposal = run.result.then((result) => result?.dispose());
2854
+ }
2017
2855
  /**
2018
2856
  * Emit a telemetry event via the runtime's track API.
2019
2857
  * Wrapped in try/catch so a broken telemetry integration never crashes the
@@ -2377,7 +3215,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2377
3215
  if (view.status === "hidden") return "";
2378
3216
  if (view.status === "loading") return this._renderWhyBoxLoading();
2379
3217
  const e2 = view.explanation;
2380
- return html5`
3218
+ return html6`
2381
3219
  <style>
2382
3220
  /* Token bridge: every color resolves from a --syntro-pdp-* var the
2383
3221
  * host (vela pages + SPA) publishes, falling back to a NEUTRAL host
@@ -2464,29 +3302,29 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2464
3302
  Shown in demo mode only — a peek under the hood at the live personalization.
2465
3303
  </div>
2466
3304
  <div data-syntro-pdp-why-archetype>
2467
- Shopping as: <strong>${e2.archetypeLabel}</strong>${e2.archetypeDesc ? html5` — ${e2.archetypeDesc}` : ""}
3305
+ Shopping as: <strong>${e2.archetypeLabel}</strong>${e2.archetypeDesc ? html6` — ${e2.archetypeDesc}` : ""}
2468
3306
  </div>
2469
- ${e2.decisionLabel ? html5`<div data-syntro-pdp-why-archetype>
2470
- What they're weighing: <strong>${e2.decisionLabel}</strong>${e2.decisionDesc ? html5` — “${e2.decisionDesc}”` : ""}
3307
+ ${e2.decisionLabel ? html6`<div data-syntro-pdp-why-archetype>
3308
+ What they're weighing: <strong>${e2.decisionLabel}</strong>${e2.decisionDesc ? html6` — “${e2.decisionDesc}”` : ""}
2471
3309
  </div>` : ""}
2472
- ${e2.summary ? html5`<div data-syntro-pdp-why-summary>"${e2.summary}"</div>` : ""}
3310
+ ${e2.summary ? html6`<div data-syntro-pdp-why-summary>"${e2.summary}"</div>` : ""}
2473
3311
  <div data-syntro-pdp-why-metrics>
2474
3312
  ${e2.metrics.map(
2475
- (m) => html5`<div data-syntro-pdp-why-metric>
3313
+ (m) => html6`<div data-syntro-pdp-why-metric>
2476
3314
  <span data-syntro-pdp-why-metric-value>${m.value}</span>
2477
3315
  <span data-syntro-pdp-why-metric-label>${m.label}</span>
2478
3316
  </div>`
2479
3317
  )}
2480
3318
  </div>
2481
- ${view.dossier.length ? html5`<details data-syntro-pdp-why-dossier ?open=${view.dossierOpen} @toggle=${this._onDossierToggle}>
3319
+ ${view.dossier.length ? html6`<details data-syntro-pdp-why-dossier ?open=${view.dossierOpen} @toggle=${this._onDossierToggle}>
2482
3320
  <summary>What was measured</summary>
2483
3321
  <div data-syntro-pdp-why-dossier-list>
2484
3322
  ${view.dossier.map(
2485
- (m) => html5`<div data-syntro-pdp-why-dossier-row>
3323
+ (m) => html6`<div data-syntro-pdp-why-dossier-row>
2486
3324
  <span data-syntro-pdp-why-dossier-value>${m.value}</span>
2487
3325
  <div data-syntro-pdp-why-dossier-text>
2488
3326
  <span data-syntro-pdp-why-dossier-label>${m.label}</span>
2489
- ${m.hint ? html5`<span data-syntro-pdp-why-dossier-hint>${m.hint}</span>` : ""}
3327
+ ${m.hint ? html6`<span data-syntro-pdp-why-dossier-hint>${m.hint}</span>` : ""}
2490
3328
  </div>
2491
3329
  </div>`
2492
3330
  )}
@@ -2503,7 +3341,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2503
3341
  * so the swap to the filled box is a state change, not a first appearance.
2504
3342
  */
2505
3343
  _renderWhyBoxLoading() {
2506
- return html5`
3344
+ return html6`
2507
3345
  <style>
2508
3346
  [data-syntro-pdp-why] {
2509
3347
  margin: 0; padding: 4px 0;
@@ -2543,18 +3381,18 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2543
3381
  `;
2544
3382
  }
2545
3383
  render() {
2546
- if (this._pageUnresolvable) return html5``;
3384
+ if (this._pageUnresolvable) return html6``;
2547
3385
  if (this._presetsSettled && this._decisionState.stream.status === "idle" && this._decisionState.plan.status === "empty" && !_readPdpPresets()?.[this.productId]) {
2548
- return html5``;
3386
+ return html6``;
2549
3387
  }
2550
3388
  const skeletonStyles = _SyntroPdpLit._skeletonStyles;
2551
3389
  const view = selectPdpView(this._decisionState);
2552
3390
  if (view.layout === "skeleton") {
2553
- return html5`
3391
+ return html6`
2554
3392
  ${skeletonStyles}
2555
3393
  <div data-syntro-pdp-root data-state="pending" data-syntro-pdp-skeleton>
2556
3394
  ${[0, 1, 2].map(
2557
- (i2) => html5`
3395
+ (i2) => html6`
2558
3396
  <section
2559
3397
  data-syntro-pdp-skeleton-section
2560
3398
  style="animation-delay: ${i2 * 0.15}s"
@@ -2571,7 +3409,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2571
3409
  </div>
2572
3410
  `;
2573
3411
  }
2574
- return html5`
3412
+ return html6`
2575
3413
  ${skeletonStyles}
2576
3414
  <div data-syntro-pdp-root data-state=${view.rootState}>
2577
3415
  ${view.whyBox.destination === "inline" ? this._renderWhyBox(view.whyBox) : ""}
@@ -2579,7 +3417,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2579
3417
  if (!slot.visible) return "";
2580
3418
  const task = slot.task;
2581
3419
  if (this._nativeSlots.has(task.slot)) return "";
2582
- return html5`
3420
+ return html6`
2583
3421
  <section data-syntro-pdp-section data-slot=${task.slot}>
2584
3422
  <syntro-pdp-section-header
2585
3423
  .eyebrow=${task.header.eyebrow}
@@ -2603,7 +3441,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2603
3441
  * change) without ever touching the imperatively-managed
2604
3442
  * slot subtree. See adversarial-review failure mode #2.
2605
3443
  */
2606
- slot.showLoading ? html5`<div data-syntro-pdp-slot-shimmer>
3444
+ slot.showLoading ? html6`<div data-syntro-pdp-slot-shimmer>
2607
3445
  <div data-syntro-pdp-skeleton-body></div>
2608
3446
  </div>` : ""}
2609
3447
  </div>
@@ -2619,6 +3457,7 @@ _SyntroPdpLit.properties = {
2619
3457
  productName: { type: String, attribute: "product-name" },
2620
3458
  productBlurb: { type: String, attribute: "product-blurb" },
2621
3459
  runtimeRef: { attribute: false },
3460
+ takeover: { attribute: false },
2622
3461
  _decisionState: { state: true },
2623
3462
  _pageUnresolvable: { state: true },
2624
3463
  _presetsSettled: { state: true }
@@ -2630,7 +3469,7 @@ _SyntroPdpLit.properties = {
2630
3469
  * (see `ensureSectionLayoutStyles`), not here, so they're emitted once
2631
3470
  * per document rather than once per `<syntro-pdp>` instance.
2632
3471
  */
2633
- _SyntroPdpLit._skeletonStyles = html5`
3472
+ _SyntroPdpLit._skeletonStyles = html6`
2634
3473
  <style>
2635
3474
  [data-syntro-pdp-skeleton] {
2636
3475
  display: flex;
@@ -3033,6 +3872,10 @@ async function flush() {
3033
3872
  pending.clear();
3034
3873
  return;
3035
3874
  }
3875
+ if (typeof document !== "undefined" && document.querySelector("syntro-pdp")) {
3876
+ pending.clear();
3877
+ return;
3878
+ }
3036
3879
  const ids = [...pending];
3037
3880
  pending.clear();
3038
3881
  for (const id of ids) await onProductAppeared(id);
@@ -3110,7 +3953,7 @@ function startNativeSlotWatcher() {
3110
3953
  }
3111
3954
 
3112
3955
  // src/widgets/ProductCardLit.ts
3113
- import { html as html7, LitElement as LitElement7, nothing as nothing3 } from "lit";
3956
+ import { html as html8, LitElement as LitElement8, nothing as nothing4 } from "lit";
3114
3957
  import { styleMap } from "lit/directives/style-map.js";
3115
3958
 
3116
3959
  // src/bind/dom-selector.ts
@@ -4138,7 +4981,7 @@ cancel_fn = function() {
4138
4981
  };
4139
4982
 
4140
4983
  // src/widgets/VariantPanelLit.ts
4141
- import { html as html6, LitElement as LitElement6, nothing as nothing2 } from "lit";
4984
+ import { html as html7, LitElement as LitElement7, nothing as nothing3 } from "lit";
4142
4985
  var PANEL_CSS = `
4143
4986
  syntro-variant-panel {
4144
4987
  display: grid;
@@ -4370,7 +5213,7 @@ var PANEL_CSS = `
4370
5213
  .svp-live { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; overflow: hidden; }
4371
5214
  `;
4372
5215
  var _VariantPanelLit_instances, healthProbe_fn;
4373
- var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
5216
+ var _VariantPanelLit = class _VariantPanelLit extends LitElement7 {
4374
5217
  constructor() {
4375
5218
  super();
4376
5219
  __privateAdd(this, _VariantPanelLit_instances);
@@ -4472,7 +5315,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4472
5315
  }
4473
5316
  render() {
4474
5317
  if (this.state === "error") {
4475
- return html6`
5318
+ return html7`
4476
5319
  <div class="svp-error-block" data-error-block>
4477
5320
  <div>Couldn't load options. ${this.error ?? ""}</div>
4478
5321
  <button class="svp-retry-btn" data-retry-button @click=${this._onRetry}>Try again</button>
@@ -4480,7 +5323,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4480
5323
  `;
4481
5324
  }
4482
5325
  if (this.state === "loading" || !this.payload) {
4483
- return html6`
5326
+ return html7`
4484
5327
  <div data-loading-skeleton>
4485
5328
  <div class="svp-skeleton"></div>
4486
5329
  <div class="svp-skeleton"></div>
@@ -4493,26 +5336,26 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4493
5336
  const compareAt = matching?.compare_at_price ?? null;
4494
5337
  const singleVariant = this.payload.attributes.length === 0;
4495
5338
  const heroSrc = this._heroSrc();
4496
- const backBtn = html6`<button
5339
+ const backBtn = html7`<button
4497
5340
  class="svp-back-btn"
4498
5341
  data-back-button
4499
5342
  @click=${this._onBack}
4500
5343
  aria-label="Back"
4501
5344
  >‹ Back</button>`;
4502
- return html6`
5345
+ return html7`
4503
5346
  <div class="svp-image-col" data-image-col>
4504
- ${heroSrc ? html6`<img
5347
+ ${heroSrc ? html7`<img
4505
5348
  class="svp-image"
4506
5349
  data-variant-image
4507
5350
  src=${heroSrc}
4508
5351
  alt=${this.productImage?.alt ?? ""}
4509
5352
  loading="lazy"
4510
- />` : nothing2}
5353
+ />` : nothing3}
4511
5354
  </div>
4512
5355
  <div class="svp-body" data-panel-body>
4513
- ${this.productTitle ? html6`<div class="svp-product-title" data-product-title data-critical-text>${this.productTitle}</div>` : nothing2}
5356
+ ${this.productTitle ? html7`<div class="svp-product-title" data-product-title data-critical-text>${this.productTitle}</div>` : nothing3}
4514
5357
  <div class="svp-attributes-scroll" data-attributes-scroll data-clip-ok>
4515
- ${singleVariant ? html6`<div class="svp-single-variant-note" data-single-variant-note>
5358
+ ${singleVariant ? html7`<div class="svp-single-variant-note" data-single-variant-note>
4516
5359
  Just one option — ready to add.
4517
5360
  </div>` : this.payload.attributes.map((attr) => this._renderAttributeRow(attr))}
4518
5361
  </div>
@@ -4527,23 +5370,23 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4527
5370
  ${// Short label: "Add · $64" (the price commits HERE — the card's
4528
5371
  // front face carries no price; round-3 feedback shortened this
4529
5372
  // so Back fits beside it on the same row).
4530
- ctaPrice != null ? html6`Add ${compareAt ? html6`<span class="svp-compare">$${compareAt.toFixed(2)}</span>` : nothing2}· $${ctaPrice.toFixed(2)}` : html6`Add to cart`}
5373
+ ctaPrice != null ? html7`Add ${compareAt ? html7`<span class="svp-compare">$${compareAt.toFixed(2)}</span>` : nothing3}· $${ctaPrice.toFixed(2)}` : html7`Add to cart`}
4531
5374
  </button>
4532
5375
  ${backBtn}
4533
5376
  </div>
4534
5377
  <div class="svp-live" data-live data-clip-ok aria-live="polite">
4535
- ${this.productTitle ? `Showing options for ${this.productTitle}` : nothing2}
5378
+ ${this.productTitle ? `Showing options for ${this.productTitle}` : nothing3}
4536
5379
  </div>
4537
5380
  </div>
4538
5381
  `;
4539
5382
  }
4540
5383
  _renderAttributeRow(attr) {
4541
5384
  const oosVisible = this._hasAnyOOSForAttribute(attr);
4542
- return html6`
5385
+ return html7`
4543
5386
  <div class="svp-attribute-row" data-attribute-row data-attribute-key=${attr.key}>
4544
5387
  <div class="svp-attribute-label" data-attribute-label id=${`attrlabel-${attr.key}`}>${attr.label}</div>
4545
5388
  ${attr.values.length >= _VariantPanelLit.COLLAPSE_MIN_OPTIONS ? this._renderCollapsedAxis(attr) : attr.kind === "swatch" ? this._renderSwatchRow(attr) : this._renderPillRow(attr)}
4546
- ${oosVisible ? html6`<div class="svp-oos-microcopy" data-out-of-stock-microcopy>Out of stock for one or more options</div>` : nothing2}
5389
+ ${oosVisible ? html7`<div class="svp-oos-microcopy" data-out-of-stock-microcopy>Out of stock for one or more options</div>` : nothing3}
4547
5390
  </div>
4548
5391
  `;
4549
5392
  }
@@ -4552,12 +5395,12 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4552
5395
  }
4553
5396
  _renderPillRow(attr) {
4554
5397
  const segmented = attr.values.length <= _VariantPanelLit.SEGMENTED_MAX_OPTIONS;
4555
- return html6`
4556
- <div class="svp-pill-row" data-segmented=${segmented ? "" : nothing2} data-scroll=${this._isScrollTier(attr) ? "" : nothing2} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
5398
+ return html7`
5399
+ <div class="svp-pill-row" data-segmented=${segmented ? "" : nothing3} data-scroll=${this._isScrollTier(attr) ? "" : nothing3} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
4557
5400
  ${attr.values.map((v) => {
4558
5401
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4559
5402
  const checked = this._selection[attr.key] === v.id;
4560
- return html6`<button
5403
+ return html7`<button
4561
5404
  class="svp-pill"
4562
5405
  data-pill
4563
5406
  data-attribute-key=${attr.key}
@@ -4575,14 +5418,14 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4575
5418
  _renderSwatchRow(attr) {
4576
5419
  const selectedValueId = this._selection[attr.key];
4577
5420
  const selectedLabel = attr.values.find((v) => v.id === selectedValueId)?.label ?? "";
4578
- return html6`
5421
+ return html7`
4579
5422
  <div class="svp-swatch-label">${selectedLabel}</div>
4580
- <div class="svp-swatch-row" data-scroll=${this._isScrollTier(attr) ? "" : nothing2} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
5423
+ <div class="svp-swatch-row" data-scroll=${this._isScrollTier(attr) ? "" : nothing3} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
4581
5424
  ${attr.values.map((v) => {
4582
5425
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4583
5426
  const checked = this._selection[attr.key] === v.id;
4584
5427
  const color = v.swatch?.kind === "color" ? v.swatch.value : "transparent";
4585
- return html6`<button
5428
+ return html7`<button
4586
5429
  class="svp-swatch-pill"
4587
5430
  data-pill
4588
5431
  data-swatch-dot
@@ -4636,8 +5479,8 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4636
5479
  const filter = (this._axisFilter[attr.key] ?? "").trim().toLowerCase();
4637
5480
  const filtered = filter ? attr.values.filter((v) => v.label.toLowerCase().includes(filter)) : attr.values;
4638
5481
  const showFilter = attr.values.length >= _VariantPanelLit.FILTER_MIN_OPTIONS;
4639
- const dot = (v) => v?.swatch?.kind === "color" ? html6`<span class="svp-swatch-dot" style="background-color: ${v.swatch.value}"></span>` : nothing2;
4640
- return html6`
5482
+ const dot = (v) => v?.swatch?.kind === "color" ? html7`<span class="svp-swatch-dot" style="background-color: ${v.swatch.value}"></span>` : nothing3;
5483
+ return html7`
4641
5484
  <div
4642
5485
  class="svp-collapse"
4643
5486
  data-collapsed-axis
@@ -4667,7 +5510,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4667
5510
  <span class="svp-collapse-value">${selected ? selected.label : `Choose ${attr.label.toLowerCase()}`}</span>
4668
5511
  <span class="svp-collapse-caret">${expanded ? "\u25B4" : "\u25BE"}</span>
4669
5512
  </button>
4670
- ${expanded ? html6`
5513
+ ${expanded ? html7`
4671
5514
  <div
4672
5515
  class="svp-collapse-list"
4673
5516
  data-clip-ok
@@ -4675,18 +5518,18 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4675
5518
  role="listbox"
4676
5519
  aria-labelledby=${`attrlabel-${attr.key}`}
4677
5520
  >
4678
- ${showFilter ? html6`<input
5521
+ ${showFilter ? html7`<input
4679
5522
  class="svp-collapse-filter"
4680
5523
  data-collapse-filter
4681
5524
  type="text"
4682
5525
  placeholder=${`Filter ${attr.label.toLowerCase()}\u2026`}
4683
5526
  .value=${this._axisFilter[attr.key] ?? ""}
4684
5527
  @input=${(e2) => this._onAxisFilterInput(attr.key, e2)}
4685
- />` : nothing2}
5528
+ />` : nothing3}
4686
5529
  ${filtered.map((v) => {
4687
5530
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4688
5531
  const isSelected = this._selection[attr.key] === v.id;
4689
- return html6`<button
5532
+ return html7`<button
4690
5533
  class="svp-collapse-option"
4691
5534
  data-collapse-option
4692
5535
  data-value-id=${v.id}
@@ -4697,8 +5540,8 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4697
5540
  @click=${() => this._onCollapsedSelect(attr.key, v.id)}
4698
5541
  >${dot(v)}<span class="svp-collapse-value">${v.label}</span></button>`;
4699
5542
  })}
4700
- ${filtered.length === 0 ? html6`<div class="svp-collapse-empty">No matches</div>` : nothing2}
4701
- </div>` : nothing2}
5543
+ ${filtered.length === 0 ? html7`<div class="svp-collapse-empty">No matches</div>` : nothing3}
5544
+ </div>` : nothing3}
4702
5545
  </div>
4703
5546
  `;
4704
5547
  }
@@ -4823,7 +5666,7 @@ var CARD_FLIP_CSS = `
4823
5666
  }
4824
5667
  `;
4825
5668
  var _effectExecutor, _controller, _unsubDevice, _lastFailureFingerprint, _reportedHealthStates, _healthRaf, _ProductCardLit_instances, scheduleHealthCheck_fn, measureAndReportHealth_fn, cleanupHostResources_fn, dispatchCard_fn, _onFlipAnimationEnd, startBind_fn, readProductObservation_fn, syncDecisionInputsBeforeIntent_fn;
4826
- var ProductCardLit = class extends LitElement7 {
5669
+ var ProductCardLit = class extends LitElement8 {
4827
5670
  constructor() {
4828
5671
  super(...arguments);
4829
5672
  __privateAdd(this, _ProductCardLit_instances);
@@ -4925,9 +5768,9 @@ var ProductCardLit = class extends LitElement7 {
4925
5768
  super.disconnectedCallback();
4926
5769
  }
4927
5770
  render() {
4928
- if (this.validationError || !this.props) return html7``;
5771
+ if (this.validationError || !this.props) return html8``;
4929
5772
  const parsed = cardSchema.safeParse(this.props);
4930
- if (!parsed.success) return html7``;
5773
+ if (!parsed.success) return html8``;
4931
5774
  const density = this._device === "mobile" ? "compact" : parsed.data.density;
4932
5775
  const { product, visibleFacts } = parsed.data;
4933
5776
  const resolved = this.resolved[product.id];
@@ -4954,7 +5797,7 @@ var ProductCardLit = class extends LitElement7 {
4954
5797
  onPrimaryCtaClick,
4955
5798
  !view.primaryCta.disabled
4956
5799
  );
4957
- const backFace = html7`<syntro-variant-panel
5800
+ const backFace = html8`<syntro-variant-panel
4958
5801
  .payload=${view.panel.payload}
4959
5802
  .productTitle=${product.name ?? ""}
4960
5803
  .productImage=${product.image ? { src: product.image.src, alt: product.image.alt } : null}
@@ -4965,27 +5808,27 @@ var ProductCardLit = class extends LitElement7 {
4965
5808
  @variant-panel-retry=${this._onVariantRetry}
4966
5809
  @variant-panel-selection-change=${this._onVariantSelectionChange}
4967
5810
  ></syntro-variant-panel>
4968
- ${view.addError ? html7`<div data-add-to-cart-error>${view.addError}</div>` : nothing3}`;
5811
+ ${view.addError ? html8`<div data-add-to-cart-error>${view.addError}</div>` : nothing4}`;
4969
5812
  const backView = view.face === "back" && view.flipAnimating ? (
4970
5813
  // Mid-flip: both faces coexist inside a preserve-3d container. The
4971
5814
  // front turns away (inert + aria-hidden) while the back turns in.
4972
- html7`<div data-card-flip @animationend=${__privateGet(this, _onFlipAnimationEnd)}>
5815
+ html8`<div data-card-flip @animationend=${__privateGet(this, _onFlipAnimationEnd)}>
4973
5816
  <div data-face="front" aria-hidden="true" inert>${frontContent}</div>
4974
5817
  <div data-face="back">${backFace}</div>
4975
5818
  </div>`
4976
5819
  ) : view.face === "back" ? (
4977
5820
  // Settled back: flat, untransformed — no flip container, no perspective.
4978
- html7`<div data-face="back">${backFace}</div>`
4979
- ) : html7`<div data-face="front">
5821
+ html8`<div data-face="back">${backFace}</div>`
5822
+ ) : html8`<div data-face="front">
4980
5823
  ${frontContent}
4981
- ${view.addError ? html7`<div data-add-to-cart-error>${view.addError}</div>` : nothing3}
5824
+ ${view.addError ? html8`<div data-add-to-cart-error>${view.addError}</div>` : nothing4}
4982
5825
  </div>`;
4983
- return html7`
5826
+ return html8`
4984
5827
  <article
4985
5828
  class="sc-product-card"
4986
5829
  data-active-face=${view.face}
4987
5830
  data-density=${density}
4988
- data-labels=${product.labels ? JSON.stringify(product.labels) : nothing3}
5831
+ data-labels=${product.labels ? JSON.stringify(product.labels) : nothing4}
4989
5832
  style=${styleMap(articleStyles)}
4990
5833
  >
4991
5834
  ${backView}
@@ -5515,7 +6358,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5515
6358
  maxWidth: "100%",
5516
6359
  flexShrink: "1"
5517
6360
  };
5518
- const ctaRow = html7`<div class="sc-product-card__ctas" style=${styleMap(ctasStyles)}>
6361
+ const ctaRow = html8`<div class="sc-product-card__ctas" style=${styleMap(ctasStyles)}>
5519
6362
  ${ctas.map((c2, i2) => {
5520
6363
  const disabled2 = c2.actionId === "add_to_cart" && !commerceAvailable;
5521
6364
  const ctaStyles = {
@@ -5523,13 +6366,13 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5523
6366
  ...disabled2 ? { opacity: "0.5", "pointer-events": "none", cursor: "not-allowed" } : {}
5524
6367
  };
5525
6368
  const ctaLabel = c2.label;
5526
- return html7`<a
6369
+ return html8`<a
5527
6370
  class="sc-product-card__cta"
5528
6371
  data-product-cta=${i2 === 0 ? "primary" : "secondary"}
5529
6372
  data-critical-text
5530
6373
  data-variant=${c2.variant}
5531
- data-disabled=${disabled2 ? "true" : nothing3}
5532
- aria-disabled=${disabled2 ? "true" : nothing3}
6374
+ data-disabled=${disabled2 ? "true" : nothing4}
6375
+ aria-disabled=${disabled2 ? "true" : nothing4}
5533
6376
  href=${c2.actionId === "add_to_cart" ? "#" : c2.href ?? "#"}
5534
6377
  target=${c2.target}
5535
6378
  rel=${c2.target === "_blank" ? "noopener noreferrer" : ""}
@@ -5546,7 +6389,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5546
6389
  >`;
5547
6390
  })}
5548
6391
  </div>`;
5549
- const ratingOverlay = overlay && product.rating && isVisible("rating") ? html7`<div
6392
+ const ratingOverlay = overlay && product.rating && isVisible("rating") ? html8`<div
5550
6393
  class="sc-product-card__rating sc-product-card__rating--overlay"
5551
6394
  data-product-rating
5552
6395
  data-rating-value=${product.rating.value}
@@ -5561,20 +6404,20 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5561
6404
  style=${styleMap({ opacity: "0.8", marginLeft: "0.15rem", display: "var(--sc-card-rating-count-display, inline)" })}
5562
6405
  >(${product.rating.count.toLocaleString()})</span
5563
6406
  >
5564
- </div>` : nothing3;
5565
- const priceOverlay = overlay && isVisible("price") && (product.price || product.salePrice) ? html7`<div
6407
+ </div>` : nothing4;
6408
+ const priceOverlay = overlay && isVisible("price") && (product.price || product.salePrice) ? html8`<div
5566
6409
  class="sc-product-card__price sc-product-card__price--overlay"
5567
6410
  data-product-price
5568
6411
  style=${styleMap(overlayPriceStyles)}
5569
6412
  >
5570
6413
  <span
5571
6414
  class="sc-product-card__amount"
5572
- data-product-price-sale=${hasSalePrice ? "true" : nothing3}
6415
+ data-product-price-sale=${hasSalePrice ? "true" : nothing4}
5573
6416
  data-critical-text
5574
6417
  >${activePriceText}</span
5575
6418
  >
5576
- </div>` : nothing3;
5577
- const mediaBlock = overlay ? html7`<div class="sc-product-card__media" style=${styleMap(mediaWrapperStyles)}>
6419
+ </div>` : nothing4;
6420
+ const mediaBlock = overlay ? html8`<div class="sc-product-card__media" style=${styleMap(mediaWrapperStyles)}>
5578
6421
  <img
5579
6422
  class="sc-product-card__image"
5580
6423
  data-product-image
@@ -5585,7 +6428,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5585
6428
  style=${styleMap(overlayImgStyles)}
5586
6429
  />
5587
6430
  ${ratingOverlay}${priceOverlay}
5588
- </div>` : html7`<img
6431
+ </div>` : html8`<img
5589
6432
  class="sc-product-card__image"
5590
6433
  data-product-image
5591
6434
  src=${imgSrc}
@@ -5594,7 +6437,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5594
6437
  @error=${onImageError}
5595
6438
  style=${styleMap(imageStyles)}
5596
6439
  />`;
5597
- return html7`
6440
+ return html8`
5598
6441
  <div class="sc-product-card__grid" data-product-card-grid style=${styleMap(rootGridStyles)}>
5599
6442
  ${mediaBlock}
5600
6443
  <div class="sc-product-card__content" style=${styleMap(contentColStyles)}>
@@ -5658,7 +6501,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5658
6501
  // the product page reachable.
5659
6502
  (() => {
5660
6503
  const navCta = ctas.find((c2) => c2.href);
5661
- return navCta?.href ? html7`<a
6504
+ return navCta?.href ? html8`<a
5662
6505
  data-product-name-link
5663
6506
  href=${navCta.href}
5664
6507
  target=${navCta.target ?? "_self"}
@@ -5668,7 +6511,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5668
6511
  })()}</h3>
5669
6512
  ${// On compact the rating renders as an image OVERLAY pill (item 2),
5670
6513
  // so it is omitted from the header identity row here.
5671
- !overlay && product.rating && isVisible("rating") ? html7`<div
6514
+ !overlay && product.rating && isVisible("rating") ? html8`<div
5672
6515
  class="sc-product-card__rating"
5673
6516
  data-product-rating
5674
6517
  data-rating-value=${product.rating.value}
@@ -5683,9 +6526,9 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5683
6526
  <span class="sc-product-card__rating-stars" style="color: #f5a623;">★</span>
5684
6527
  <span style=${styleMap({ marginLeft: "0.2rem", fontWeight: "600" })}>${product.rating.value}</span>
5685
6528
  <span class="sc-product-card__rating-count" style=${styleMap({ opacity: "0.65", marginLeft: "0.2rem", display: "var(--sc-card-rating-count-display, inline)" })}>(${product.rating.count.toLocaleString()})</span>
5686
- </div>` : nothing3}
6529
+ </div>` : nothing4}
5687
6530
  </div>
5688
- ${(product.tagline || product.framing) && isVisible("tagline") ? html7`<p
6531
+ ${(product.tagline || product.framing) && isVisible("tagline") ? html8`<p
5689
6532
  class="sc-product-card__tagline"
5690
6533
  data-product-tagline
5691
6534
  style=${styleMap({
@@ -5719,7 +6562,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5719
6562
  minWidth: "0",
5720
6563
  overflowWrap: "anywhere"
5721
6564
  })}
5722
- >${product.tagline || product.framing}</p>` : nothing3}
6565
+ >${product.tagline || product.framing}</p>` : nothing4}
5723
6566
  </header>
5724
6567
  <div
5725
6568
  class="sc-product-card__body"
@@ -5733,36 +6576,36 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5733
6576
  >
5734
6577
  ${factOrder.map((key) => {
5735
6578
  if (key === "price") {
5736
- if (overlay) return nothing3;
5737
- if (!isVisible("price") || !product.price && !product.salePrice) return nothing3;
5738
- return html7`<div
6579
+ if (overlay) return nothing4;
6580
+ if (!isVisible("price") || !product.price && !product.salePrice) return nothing4;
6581
+ return html8`<div
5739
6582
  class="sc-product-card__price"
5740
6583
  data-product-price
5741
6584
  style=${styleMap(priceBlockStyles)}
5742
6585
  >
5743
- ${hasSalePrice && product.price ? html7`<span
6586
+ ${hasSalePrice && product.price ? html8`<span
5744
6587
  class="sc-product-card__amount-original"
5745
6588
  data-product-price-original
5746
6589
  style=${styleMap(priceOriginalStyles)}
5747
6590
  >${product.price.amount}</span
5748
- >` : nothing3}
6591
+ >` : nothing4}
5749
6592
  <span
5750
6593
  class="sc-product-card__amount"
5751
- data-product-price-sale=${hasSalePrice ? "true" : nothing3}
6594
+ data-product-price-sale=${hasSalePrice ? "true" : nothing4}
5752
6595
  data-critical-text
5753
6596
  style=${styleMap(priceSaleStyles)}
5754
6597
  >${activePriceText}</span
5755
6598
  >
5756
- ${activeCadence ? html7`<span
6599
+ ${activeCadence ? html8`<span
5757
6600
  class="sc-product-card__cadence"
5758
6601
  style=${styleMap(priceCadenceStyles)}
5759
6602
  >${activeCadence}</span
5760
- >` : nothing3}
6603
+ >` : nothing4}
5761
6604
  </div>`;
5762
6605
  }
5763
6606
  if (key === "availability") {
5764
- if (!isVisible("availability") || !product.availability) return nothing3;
5765
- return html7`<span
6607
+ if (!isVisible("availability") || !product.availability) return nothing4;
6608
+ return html8`<span
5766
6609
  class="sc-product-card__availability"
5767
6610
  data-product-availability
5768
6611
  data-availability=${product.availability}
@@ -5771,8 +6614,8 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5771
6614
  >`;
5772
6615
  }
5773
6616
  if (key === "badge") {
5774
- if (!isVisible("badge") || !product.badge) return nothing3;
5775
- return html7`<span
6617
+ if (!isVisible("badge") || !product.badge) return nothing4;
6618
+ return html8`<span
5776
6619
  class="sc-product-card__badge"
5777
6620
  data-product-badge
5778
6621
  data-tone=${product.badge.tone}
@@ -5788,12 +6631,12 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5788
6631
  >`;
5789
6632
  }
5790
6633
  if (key === "specs") {
5791
- if (!isVisible("specs") || specGroups.length === 0) return nothing3;
6634
+ if (!isVisible("specs") || specGroups.length === 0) return nothing4;
5792
6635
  if (density === "compact") {
5793
6636
  const allRows = specGroups.flatMap((g) => g.rows);
5794
6637
  const highlights = allRows.slice(0, 4);
5795
- if (highlights.length === 0) return nothing3;
5796
- return html7`<div
6638
+ if (highlights.length === 0) return nothing4;
6639
+ return html8`<div
5797
6640
  class="sc-product-card__specs"
5798
6641
  data-density="compact"
5799
6642
  data-clip-ok
@@ -5803,7 +6646,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5803
6646
  style=${styleMap(specChipRowStyles)}
5804
6647
  >
5805
6648
  ${highlights.map(
5806
- (r) => html7`<span
6649
+ (r) => html8`<span
5807
6650
  data-spec-chip
5808
6651
  style=${styleMap(specChipStyles)}
5809
6652
  ><span style="font-weight: 600;">${r.name}</span
@@ -5812,9 +6655,9 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5812
6655
  )}
5813
6656
  </div>`;
5814
6657
  }
5815
- return html7`<div class="sc-product-card__specs" style=${styleMap(specsContainerStyles)}>
6658
+ return html8`<div class="sc-product-card__specs" style=${styleMap(specsContainerStyles)}>
5816
6659
  ${specGroups.map(
5817
- (g) => html7`<section
6660
+ (g) => html8`<section
5818
6661
  class="sc-product-card__spec-section"
5819
6662
  data-spec-section=${g.section}
5820
6663
  style=${styleMap(specGroupStyles)}
@@ -5832,7 +6675,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5832
6675
  style=${styleMap(specRowsStyles)}
5833
6676
  >
5834
6677
  ${g.rows.map(
5835
- (r) => html7`<li
6678
+ (r) => html8`<li
5836
6679
  data-spec-row
5837
6680
  data-spec-chip
5838
6681
  data-attribute-emphasis=${r.emphasis ? "true" : "false"}
@@ -5857,12 +6700,12 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5857
6700
  style=${styleMap(specValueStyles)}
5858
6701
  >${r.value}</span
5859
6702
  >
5860
- ${r.unit ? html7`<span
6703
+ ${r.unit ? html8`<span
5861
6704
  class="sc-product-card__spec-unit"
5862
6705
  data-spec-unit
5863
6706
  style="opacity: 0.72;"
5864
6707
  >${r.unit}</span
5865
- >` : nothing3}
6708
+ >` : nothing4}
5866
6709
  </li>`
5867
6710
  )}
5868
6711
  </ul>
@@ -5871,8 +6714,8 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5871
6714
  </div>`;
5872
6715
  }
5873
6716
  if (key === "framing") {
5874
- if (!isVisible("framing") || !showFraming) return nothing3;
5875
- return html7`<p
6717
+ if (!isVisible("framing") || !showFraming) return nothing4;
6718
+ return html8`<p
5876
6719
  class="sc-product-card__framing"
5877
6720
  style=${styleMap({
5878
6721
  margin: "0",
@@ -5885,7 +6728,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5885
6728
  .innerHTML=${sanitizeHtml(product.framing ?? "")}
5886
6729
  ></p>`;
5887
6730
  }
5888
- return nothing3;
6731
+ return nothing4;
5889
6732
  })}
5890
6733
  </div>
5891
6734
  </div>
@@ -5895,11 +6738,11 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5895
6738
  }
5896
6739
  function renderProductCard(product, density, resolved, visibleFacts) {
5897
6740
  const articleStyles = _buildArticleStyles(density);
5898
- return html7`
6741
+ return html8`
5899
6742
  <article
5900
6743
  class="sc-product-card"
5901
6744
  data-density=${density}
5902
- data-labels=${product.labels ? JSON.stringify(product.labels) : nothing3}
6745
+ data-labels=${product.labels ? JSON.stringify(product.labels) : nothing4}
5903
6746
  style=${styleMap(articleStyles)}
5904
6747
  >
5905
6748
  ${renderProductCardInner(product, density, resolved, visibleFacts, product.ctas, void 0)}
@@ -5913,9 +6756,9 @@ function onImageError(e2) {
5913
6756
  }
5914
6757
 
5915
6758
  // src/widgets/ProductComparisonLit.ts
5916
- import { html as html8, LitElement as LitElement8, nothing as nothing4 } from "lit";
6759
+ import { html as html9, LitElement as LitElement9, nothing as nothing5 } from "lit";
5917
6760
  var _controller2, _parsed, _ProductComparisonLit_instances, healthProbe_fn2, _scrollListenerEl, _onBodyScroll, syncScrollCue_fn, startBind_fn2, renderDiveDeeper_fn, onDiveDeeper_fn, visibleRows_fn, rowComplete_fn, maxFields_fn, synthesizeRows_fn, renderMatrix_fn;
5918
- var ProductComparisonLit = class extends LitElement8 {
6761
+ var ProductComparisonLit = class extends LitElement9 {
5919
6762
  constructor() {
5920
6763
  super();
5921
6764
  __privateAdd(this, _ProductComparisonLit_instances);
@@ -5957,7 +6800,7 @@ var ProductComparisonLit = class extends LitElement8 {
5957
6800
  __privateGet(this, _controller2)?.destroy();
5958
6801
  }
5959
6802
  render() {
5960
- if (this.validationError || !__privateGet(this, _parsed)) return html8``;
6803
+ if (this.validationError || !__privateGet(this, _parsed)) return html9``;
5961
6804
  const parsed = __privateGet(this, _parsed);
5962
6805
  const bodyStyle = (
5963
6806
  // touch-action:pan-y is REQUIRED for the deck swipe-to-cycle to work over a
@@ -5971,7 +6814,7 @@ var ProductComparisonLit = class extends LitElement8 {
5971
6814
  // rows and hands horizontal drags back to the deck's swipe handler.
5972
6815
  "flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;touch-action:pan-y;scrollbar-width:none;-ms-overflow-style:none;overscroll-behavior:contain;" + (this.scrollFade ? "mask-image:linear-gradient(to bottom,#000 calc(100% - 18px),transparent);-webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 18px),transparent);" : "")
5973
6816
  );
5974
- return html8`
6817
+ return html9`
5975
6818
  <section
5976
6819
  class="sc-product-comparison"
5977
6820
  style="display:flex;flex-direction:column;flex:1 1 auto;padding:2px var(--sc-comparison-inset,12px) var(--sc-comparison-inset,12px);box-sizing:border-box;max-width:100%;min-width:0;min-height:0;max-height:100%;overflow:hidden;"
@@ -6006,11 +6849,11 @@ var ProductComparisonLit = class extends LitElement8 {
6006
6849
  }
6007
6850
  }
6008
6851
  </style>
6009
- ${parsed.heading ? html8`<h2
6852
+ ${parsed.heading ? html9`<h2
6010
6853
  class="sc-product-comparison__heading"
6011
6854
  data-comparison-heading
6012
6855
  style="flex:0 0 auto;margin:0 0 4px;font:600 14px/1.3 var(--sc-font-family,inherit);color:var(--sc-tile-title-color,inherit);min-width:0;overflow-wrap:break-word;"
6013
- >${parsed.heading}</h2>` : nothing4}
6856
+ >${parsed.heading}</h2>` : nothing5}
6014
6857
  <div
6015
6858
  class="sc-product-comparison__scroll-wrap"
6016
6859
  style="position:relative;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;"
@@ -6031,7 +6874,7 @@ var ProductComparisonLit = class extends LitElement8 {
6031
6874
  // it's in-theme; pointer-events:none so it never blocks scroll/taps;
6032
6875
  // gated on scrollFade (content below the current scroll) so it hides
6033
6876
  // at the end. Bounce is dropped under prefers-reduced-motion (style).
6034
- this.scrollFade ? html8`<span class="sc-product-comparison__scroll-cue" aria-hidden="true"></span>` : nothing4}
6877
+ this.scrollFade ? html9`<span class="sc-product-comparison__scroll-cue" aria-hidden="true"></span>` : nothing5}
6035
6878
  </div>
6036
6879
  ${__privateMethod(this, _ProductComparisonLit_instances, renderDiveDeeper_fn).call(this, parsed)}
6037
6880
  </section>
@@ -6116,9 +6959,9 @@ startBind_fn2 = function() {
6116
6959
  * chat-bar mountable turns it into a user turn.
6117
6960
  */
6118
6961
  renderDiveDeeper_fn = function(parsed) {
6119
- if (parsed.products.length < 2) return nothing4;
6962
+ if (parsed.products.length < 2) return nothing5;
6120
6963
  const chipStyle = "flex:0 0 auto;align-self:flex-end;margin-top:6px;padding:4px 10px;border-radius:9999px;border:1px solid var(--sc-color-border,rgba(0,0,0,0.14));background:transparent;cursor:pointer;font:600 12px/1.2 var(--sc-font-family,inherit);color:var(--sc-color-primary,#3d8a5e);white-space:nowrap;";
6121
- return html8`<button
6964
+ return html9`<button
6122
6965
  type="button"
6123
6966
  class="sc-product-comparison__dive-deeper"
6124
6967
  data-dive-deeper
@@ -6197,7 +7040,7 @@ renderMatrix_fn = function(products, rows) {
6197
7040
  const colHeadStyle = "display:block;padding:6px 3px;text-align:left;font-weight:600;min-width:0;";
6198
7041
  const labelStyle = "padding:8px 4px 8px 2px;font-weight:600;font-size:0.75rem;opacity:0.75;border-top:1px solid var(--sc-tile-border-color,rgba(0,0,0,0.08));align-self:stretch;min-width:0;overflow-wrap:break-word;hyphens:auto;";
6199
7042
  const cellStyle = "padding:8px 6px;border-top:1px solid var(--sc-tile-border-color,rgba(0,0,0,0.08));align-self:stretch;min-width:0;overflow-wrap:anywhere;";
6200
- return html8`
7043
+ return html9`
6201
7044
  <div
6202
7045
  class="sc-product-comparison__matrix"
6203
7046
  data-comparison-matrix
@@ -6231,7 +7074,7 @@ renderMatrix_fn = function(products, rows) {
6231
7074
  const showRatingPill = !compactHeaders && p.rating;
6232
7075
  const nameOverlayStyle = compactHeaders ? "display:block;font-weight:600;font-size:0.66rem;line-height:1.2;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.55);white-space:normal;overflow-wrap:break-word;min-width:0;" : "display:block;font-weight:600;font-size:0.76rem;line-height:1.25;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.55);white-space:normal;overflow-wrap:break-word;min-width:0;";
6233
7076
  const mediaStyle = "position:relative;display:block;width:100%;aspect-ratio:var(--sc-comparison-image-aspect, 19 / 10);border-radius:10px;overflow:hidden;background:#e5e7eb;text-decoration:none;";
6234
- const cardInner = html8`
7077
+ const cardInner = html9`
6235
7078
  <img
6236
7079
  class="sc-product-comparison__thumb"
6237
7080
  src=${imgSrc}
@@ -6240,33 +7083,33 @@ renderMatrix_fn = function(products, rows) {
6240
7083
  style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;"
6241
7084
  />
6242
7085
  <span aria-hidden="true" style="position:absolute;inset:auto 0 0 0;height:62%;background:linear-gradient(transparent,rgba(0,0,0,.62));"></span>
6243
- ${showRatingPill && p.rating ? html8`<span
7086
+ ${showRatingPill && p.rating ? html9`<span
6244
7087
  class="sc-product-comparison__rating-pill"
6245
7088
  data-product-rating
6246
7089
  data-rating-value=${p.rating.value}
6247
7090
  aria-label=${`${p.rating.value} out of ${p.rating.max ?? 5}, ${p.rating.count} reviews`}
6248
7091
  style=${`${pillBase}left:4px;`}
6249
7092
  ><span style="color:#f5a623;">★</span><span style="margin-left:0.12rem;">${p.rating.value}</span></span
6250
- >` : nothing4}
6251
- ${priceText ? html8`<span
7093
+ >` : nothing5}
7094
+ ${priceText ? html9`<span
6252
7095
  class="sc-product-comparison__price"
6253
7096
  data-critical-text
6254
7097
  style=${`${pillBase}right:4px;`}
6255
7098
  >${priceText}</span
6256
- >` : nothing4}
7099
+ >` : nothing5}
6257
7100
  <span
6258
7101
  class="sc-product-comparison__name"
6259
7102
  data-critical-text
6260
7103
  style=${`position:absolute;left:8px;right:8px;bottom:6px;${nameOverlayStyle}`}
6261
7104
  >${p.name}</span
6262
7105
  >`;
6263
- return html8`<div
7106
+ return html9`<div
6264
7107
  class="sc-product-comparison__matrix-col"
6265
7108
  role="columnheader"
6266
7109
  data-product-id=${p.id}
6267
7110
  style=${colHeadStyle}
6268
7111
  >
6269
- ${pdpHref ? html8`<a
7112
+ ${pdpHref ? html9`<a
6270
7113
  class="sc-product-comparison__media"
6271
7114
  data-comparison-media
6272
7115
  data-product-cta="primary"
@@ -6277,19 +7120,19 @@ renderMatrix_fn = function(products, rows) {
6277
7120
  data-action-id=${navCta?.actionId ?? ""}
6278
7121
  data-variant=${navCta?.variant ?? ""}
6279
7122
  style=${mediaStyle}
6280
- >${cardInner}</a>` : html8`<div class="sc-product-comparison__media" data-comparison-media style=${mediaStyle}>${cardInner}</div>`}
7123
+ >${cardInner}</a>` : html9`<div class="sc-product-comparison__media" data-comparison-media style=${mediaStyle}>${cardInner}</div>`}
6281
7124
  </div>`;
6282
7125
  })}
6283
7126
  </div>
6284
7127
  ${rows.map((row) => {
6285
7128
  const cells = [row.valueA, row.valueB, row.valueC, row.valueD];
6286
- return html8`
7129
+ return html9`
6287
7130
  <div role="row" style="display:contents;">
6288
7131
  <span class="sc-product-comparison__matrix-label" role="rowheader" style=${labelStyle}
6289
7132
  >${row.label}</span
6290
7133
  >
6291
7134
  ${products.map(
6292
- (_p, i2) => html8`<span class="sc-product-comparison__matrix-cell" role="cell" style=${cellStyle}
7135
+ (_p, i2) => html9`<span class="sc-product-comparison__matrix-cell" role="cell" style=${cellStyle}
6293
7136
  >${cells[i2] ?? "\u2014"}</span
6294
7137
  >`
6295
7138
  )}
@@ -6307,9 +7150,9 @@ ProductComparisonLit.properties = {
6307
7150
  };
6308
7151
 
6309
7152
  // src/widgets/ProductGridLit.ts
6310
- import { html as html9, LitElement as LitElement9, nothing as nothing5 } from "lit";
7153
+ import { html as html10, LitElement as LitElement10, nothing as nothing6 } from "lit";
6311
7154
  var _controller3, _ProductGridLit_instances, startBind_fn3;
6312
- var ProductGridLit = class extends LitElement9 {
7155
+ var ProductGridLit = class extends LitElement10 {
6313
7156
  constructor() {
6314
7157
  super(...arguments);
6315
7158
  __privateAdd(this, _ProductGridLit_instances);
@@ -6335,20 +7178,20 @@ var ProductGridLit = class extends LitElement9 {
6335
7178
  __privateGet(this, _controller3)?.destroy();
6336
7179
  }
6337
7180
  render() {
6338
- if (this.validationError || !this.props) return html9``;
7181
+ if (this.validationError || !this.props) return html10``;
6339
7182
  const parsed = gridSchema.safeParse(this.props);
6340
- if (!parsed.success) return html9``;
7183
+ if (!parsed.success) return html10``;
6341
7184
  const { products, desktopColumns, heading } = parsed.data;
6342
- return html9`
7185
+ return html10`
6343
7186
  <section class="sc-product-grid">
6344
- ${heading ? html9`<h2 data-grid-heading class="sc-product-grid__heading">${heading}</h2>` : nothing5}
7187
+ ${heading ? html10`<h2 data-grid-heading class="sc-product-grid__heading">${heading}</h2>` : nothing6}
6345
7188
  <div
6346
7189
  data-grid-root
6347
7190
  class="sc-product-grid__cells"
6348
7191
  style=${`--sc-product-grid-cols:${desktopColumns}`}
6349
7192
  >
6350
7193
  ${products.map(
6351
- (p) => html9`<div data-grid-cell class="sc-product-grid__cell">
7194
+ (p) => html10`<div data-grid-cell class="sc-product-grid__cell">
6352
7195
  ${renderProductCard(p, "standard", this.resolved[p.id])}
6353
7196
  </div>`
6354
7197
  )}
@@ -6389,9 +7232,9 @@ ProductGridLit.properties = {
6389
7232
  };
6390
7233
 
6391
7234
  // src/widgets/ProductHeroLit.ts
6392
- import { html as html10, LitElement as LitElement10, nothing as nothing6 } from "lit";
7235
+ import { html as html11, LitElement as LitElement11, nothing as nothing7 } from "lit";
6393
7236
  var _controller4, _ProductHeroLit_instances, startBind_fn4;
6394
- var ProductHeroLit = class extends LitElement10 {
7237
+ var ProductHeroLit = class extends LitElement11 {
6395
7238
  constructor() {
6396
7239
  super(...arguments);
6397
7240
  __privateAdd(this, _ProductHeroLit_instances);
@@ -6417,9 +7260,9 @@ var ProductHeroLit = class extends LitElement10 {
6417
7260
  __privateGet(this, _controller4)?.destroy();
6418
7261
  }
6419
7262
  render() {
6420
- if (this.validationError || !this.props) return html10``;
7263
+ if (this.validationError || !this.props) return html11``;
6421
7264
  const parsed = heroSchema.safeParse(this.props);
6422
- if (!parsed.success) return html10``;
7265
+ if (!parsed.success) return html11``;
6423
7266
  const { product, layout, longCopy } = parsed.data;
6424
7267
  const resolved = this.resolved[product.id];
6425
7268
  const imgSrc = resolved?.image ?? product.image.src;
@@ -6428,7 +7271,7 @@ var ProductHeroLit = class extends LitElement10 {
6428
7271
  const sectionStyles = isTopLayout ? "display:block;" : `display:flex;flex-direction:${layout === "image-right" ? "row-reverse" : "row"};gap:1rem;align-items:flex-start;`;
6429
7272
  const imageStyles = isTopLayout ? "width:100%;max-height:160px;object-fit:cover;border-radius:8px;display:block;margin-bottom:0.75rem;" : "width:128px;height:128px;object-fit:cover;border-radius:8px;flex-shrink:0;";
6430
7273
  const contentStyles = isTopLayout ? "" : "flex:1;min-width:0;";
6431
- return html10`
7274
+ return html11`
6432
7275
  <section class="sc-product-hero" data-hero-layout=${layout} style=${sectionStyles}>
6433
7276
  <img
6434
7277
  class="sc-product-hero__image"
@@ -6439,18 +7282,18 @@ var ProductHeroLit = class extends LitElement10 {
6439
7282
  />
6440
7283
  <div class="sc-product-hero__content" style=${contentStyles}>
6441
7284
  <h2 class="sc-product-hero__name">${product.name}</h2>
6442
- ${product.tagline ? html10`<p class="sc-product-hero__tagline">${product.tagline}</p>` : nothing6}
6443
- ${product.price ? html10`<p class="sc-product-hero__price">
6444
- ${priceText}${product.price.cadence ? html10` <small>${product.price.cadence}</small>` : nothing6}
6445
- </p>` : nothing6}
6446
- ${longCopy ? html10`<div
7285
+ ${product.tagline ? html11`<p class="sc-product-hero__tagline">${product.tagline}</p>` : nothing7}
7286
+ ${product.price ? html11`<p class="sc-product-hero__price">
7287
+ ${priceText}${product.price.cadence ? html11` <small>${product.price.cadence}</small>` : nothing7}
7288
+ </p>` : nothing7}
7289
+ ${longCopy ? html11`<div
6447
7290
  data-hero-longcopy
6448
7291
  class="sc-product-hero__longcopy"
6449
7292
  .innerHTML=${sanitizeHtml(longCopy)}
6450
- ></div>` : nothing6}
7293
+ ></div>` : nothing7}
6451
7294
  <div class="sc-product-hero__ctas">
6452
7295
  ${product.ctas.map(
6453
- (c2, i2) => html10`<a
7296
+ (c2, i2) => html11`<a
6454
7297
  class="sc-product-hero__cta"
6455
7298
  data-product-cta=${i2 === 0 ? "primary" : "secondary"}
6456
7299
  data-variant=${c2.variant}
@@ -6498,10 +7341,10 @@ ProductHeroLit.properties = {
6498
7341
  };
6499
7342
 
6500
7343
  // src/widgets/ProductRecoCarouselLit.ts
6501
- import { html as html11, LitElement as LitElement11, nothing as nothing7 } from "lit";
7344
+ import { html as html12, LitElement as LitElement12, nothing as nothing8 } from "lit";
6502
7345
  import { styleMap as styleMap2 } from "lit/directives/style-map.js";
6503
7346
  var _ProductRecoCarouselLit_instances, healthProbe_fn3;
6504
- var ProductRecoCarouselLit = class extends LitElement11 {
7347
+ var ProductRecoCarouselLit = class extends LitElement12 {
6505
7348
  constructor() {
6506
7349
  super();
6507
7350
  __privateAdd(this, _ProductRecoCarouselLit_instances);
@@ -6520,20 +7363,20 @@ var ProductRecoCarouselLit = class extends LitElement11 {
6520
7363
  }
6521
7364
  render() {
6522
7365
  const items = this._parsed?.items ?? [];
6523
- if (items.length === 0) return html11``;
6524
- return html11`
7366
+ if (items.length === 0) return html12``;
7367
+ return html12`
6525
7368
  <section class="sc-reco" style="box-sizing:border-box;display:flex;flex-direction:column;height:100%;padding:2px var(--sc-reco-inset,12px) var(--sc-reco-inset,12px);">
6526
7369
  <div class="sc-reco__carousel" role="list" style="display:flex;align-items:stretch;gap:8px;flex:1 1 auto;min-height:0;overflow-x:auto;scroll-snap-type:x mandatory;">
6527
7370
  ${items.map(
6528
- (it) => html11`
7371
+ (it) => html12`
6529
7372
  <div role="listitem" style="display:contents;">
6530
7373
  <a data-reco-item data-product-cta="primary" href=${it.pdp_href}
6531
7374
  style=${styleMap2({ position: "relative", flex: "0 0 auto", aspectRatio: "4 / 5", minHeight: "var(--sc-reco-item-min-h, 162px)", maxHeight: "var(--sc-reco-item-max-h, 340px)", borderRadius: "12px", overflow: "hidden", scrollSnapAlign: "start", textDecoration: "none", display: "block", background: "#e5e7eb" })}>
6532
- ${it.image_url ? html11`<img src=${it.image_url} alt=${it.hook ?? "Recommended product"} loading="lazy" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;">` : nothing7}
7375
+ ${it.image_url ? html12`<img src=${it.image_url} alt=${it.hook ?? "Recommended product"} loading="lazy" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;">` : nothing8}
6533
7376
  <span style="position:absolute;inset:auto 0 0 0;height:60%;background:linear-gradient(transparent,rgba(0,0,0,.62));"></span>
6534
7377
  <span style="position:absolute;left:8px;right:8px;bottom:8px;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.5);">
6535
- ${it.price ? html11`<span style="display:block;font-weight:700;font-size:0.9rem;">${it.price}</span>` : nothing7}
6536
- ${it.hook ? html11`<span style="display:block;font-size:0.72rem;line-height:1.2;opacity:.95;">${it.hook}</span>` : nothing7}
7378
+ ${it.price ? html12`<span style="display:block;font-weight:700;font-size:0.9rem;">${it.price}</span>` : nothing8}
7379
+ ${it.hook ? html12`<span style="display:block;font-size:0.72rem;line-height:1.2;opacity:.95;">${it.hook}</span>` : nothing8}
6537
7380
  </span>
6538
7381
  </a>
6539
7382
  </div>`
@@ -6568,7 +7411,7 @@ if (!customElements.get("syntro-product-reco-carousel"))
6568
7411
  customElements.define("syntro-product-reco-carousel", ProductRecoCarouselLit);
6569
7412
 
6570
7413
  // src/widgets/PdpTrendingNewsLit.ts
6571
- import { html as html12, LitElement as LitElement12 } from "lit";
7414
+ import { html as html13, LitElement as LitElement13 } from "lit";
6572
7415
 
6573
7416
  // src/widgets/entrance.ts
6574
7417
  function armEntranceSettle(onSettle, container, settleMs, fastPath = false) {
@@ -6915,7 +7758,7 @@ var TRENDING_NEWS_CSS = `
6915
7758
  }
6916
7759
  }
6917
7760
  `;
6918
- var PdpTrendingNewsLit = class extends LitElement12 {
7761
+ var PdpTrendingNewsLit = class extends LitElement13 {
6919
7762
  constructor() {
6920
7763
  super(...arguments);
6921
7764
  this.data = void 0;
@@ -6951,7 +7794,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6951
7794
  }
6952
7795
  render() {
6953
7796
  if (!this.data) {
6954
- return html12`<div data-skeleton class="pdp-trending-news-skeleton">
7797
+ return html13`<div data-skeleton class="pdp-trending-news-skeleton">
6955
7798
  <div class="pdp-skeleton-bar" style="width:60%"></div>
6956
7799
  <div class="pdp-skeleton-bar" style="width:90%"></div>
6957
7800
  <div class="pdp-skeleton-bar" style="width:80%"></div>
@@ -6961,7 +7804,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6961
7804
  const items = this.data.items;
6962
7805
  const featured = items[0];
6963
7806
  const rest = items.slice(1);
6964
- return html12`
7807
+ return html13`
6965
7808
  <section
6966
7809
  class="${this._entering ? "pdp-trending-news is-entering" : "pdp-trending-news"}"
6967
7810
  aria-label="Trending news"
@@ -6978,7 +7821,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6978
7821
  <p class="pdp-tn-blurb">${featured.blurb}</p>
6979
7822
  </article>
6980
7823
  ${rest.map(
6981
- (item) => html12`
7824
+ (item) => html13`
6982
7825
  <article class="pdp-tn-card">
6983
7826
  <div class="pdp-tn-meta">
6984
7827
  <span class="pdp-tn-dot" aria-hidden="true"></span>
@@ -7000,8 +7843,8 @@ PdpTrendingNewsLit.properties = {
7000
7843
  _entering: { state: true }
7001
7844
  };
7002
7845
  function renderHeadlineLink(item) {
7003
- if (!item.url) return html12`${item.headline}`;
7004
- return html12`<a
7846
+ if (!item.url) return html13`${item.headline}`;
7847
+ return html13`<a
7005
7848
  class="pdp-tn-headline-link"
7006
7849
  href=${item.url}
7007
7850
  target="_blank"
@@ -7014,7 +7857,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7014
7857
  }
7015
7858
 
7016
7859
  // src/widgets/PdpTrendingNewsMagazineLit.ts
7017
- import { html as html13, LitElement as LitElement13 } from "lit";
7860
+ import { html as html14, LitElement as LitElement14 } from "lit";
7018
7861
  function ensureMagazineStyles() {
7019
7862
  if (typeof document === "undefined") return;
7020
7863
  if (document.getElementById("syntro-pdp-trending-news-magazine-style")) return;
@@ -7194,7 +8037,7 @@ var MAGAZINE_CSS = `
7194
8037
  }
7195
8038
  }
7196
8039
  `;
7197
- var PdpTrendingNewsMagazineLit = class extends LitElement13 {
8040
+ var PdpTrendingNewsMagazineLit = class extends LitElement14 {
7198
8041
  constructor() {
7199
8042
  super(...arguments);
7200
8043
  this.data = void 0;
@@ -7208,13 +8051,13 @@ var PdpTrendingNewsMagazineLit = class extends LitElement13 {
7208
8051
  }
7209
8052
  render() {
7210
8053
  if (!this.data) {
7211
- return html13`<div aria-busy="true" class="pdp-tn-mag" style="opacity:0.5;">…</div>`;
8054
+ return html14`<div aria-busy="true" class="pdp-tn-mag" style="opacity:0.5;">…</div>`;
7212
8055
  }
7213
8056
  const items = this.data.items;
7214
8057
  const [lead, ...rest] = items;
7215
- return html13`
8058
+ return html14`
7216
8059
  <section class="pdp-tn-mag" aria-label="Trending news">
7217
- ${lead ? html13`<article class="pdp-tn-mag__lead">
8060
+ ${lead ? html14`<article class="pdp-tn-mag__lead">
7218
8061
  <div class="pdp-tn-mag__meta">
7219
8062
  <span class="pdp-tn-mag__meta-source">${lead.source}</span>
7220
8063
  · ${lead.published_relative}
@@ -7223,7 +8066,7 @@ var PdpTrendingNewsMagazineLit = class extends LitElement13 {
7223
8066
  <p class="pdp-tn-mag__blurb">${lead.blurb}</p>
7224
8067
  </article>` : ""}
7225
8068
  ${rest.map(
7226
- (it) => html13`<article class="pdp-tn-mag__item">
8069
+ (it) => html14`<article class="pdp-tn-mag__item">
7227
8070
  <div class="pdp-tn-mag__meta">
7228
8071
  <span class="pdp-tn-mag__meta-source">${it.source}</span>
7229
8072
  · ${it.published_relative}
@@ -7240,8 +8083,8 @@ PdpTrendingNewsMagazineLit.properties = {
7240
8083
  data: { attribute: false }
7241
8084
  };
7242
8085
  function renderHeadlineLink2(item) {
7243
- if (!item.url) return html13`${item.headline}`;
7244
- return html13`<a
8086
+ if (!item.url) return html14`${item.headline}`;
8087
+ return html14`<a
7245
8088
  class="pdp-tn-mag__headline-link"
7246
8089
  href=${item.url}
7247
8090
  target="_blank"
@@ -7254,7 +8097,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7254
8097
  }
7255
8098
 
7256
8099
  // src/widgets/PdpTrendingNewsHeroLit.ts
7257
- import { html as html14, LitElement as LitElement14 } from "lit";
8100
+ import { html as html15, LitElement as LitElement15 } from "lit";
7258
8101
  function ensureHeroStyles() {
7259
8102
  if (typeof document === "undefined") return;
7260
8103
  if (document.getElementById("syntro-pdp-trending-news-hero-style")) return;
@@ -7445,7 +8288,7 @@ var HERO_CSS = `
7445
8288
  }
7446
8289
  }
7447
8290
  `;
7448
- var PdpTrendingNewsHeroLit = class extends LitElement14 {
8291
+ var PdpTrendingNewsHeroLit = class extends LitElement15 {
7449
8292
  constructor() {
7450
8293
  super(...arguments);
7451
8294
  this.data = void 0;
@@ -7459,11 +8302,11 @@ var PdpTrendingNewsHeroLit = class extends LitElement14 {
7459
8302
  }
7460
8303
  render() {
7461
8304
  if (!this.data) {
7462
- return html14`<div aria-busy="true" class="pdp-tn-hero" style="opacity:0.5;">…</div>`;
8305
+ return html15`<div aria-busy="true" class="pdp-tn-hero" style="opacity:0.5;">…</div>`;
7463
8306
  }
7464
8307
  const [lead, ...rest] = this.data.items;
7465
- if (!lead) return html14``;
7466
- return html14`
8308
+ if (!lead) return html15``;
8309
+ return html15`
7467
8310
  <section class="pdp-tn-hero" aria-label="Trending news">
7468
8311
  <article class="pdp-tn-hero__panel">
7469
8312
  <blockquote class="pdp-tn-hero__quote">${lead.blurb}</blockquote>
@@ -7474,9 +8317,9 @@ var PdpTrendingNewsHeroLit = class extends LitElement14 {
7474
8317
  </footer>
7475
8318
  <p class="pdp-tn-hero__headline">${renderHeadlineLink3(lead)}</p>
7476
8319
  </article>
7477
- ${rest.length ? html14`<div class="pdp-tn-hero__followon">
8320
+ ${rest.length ? html15`<div class="pdp-tn-hero__followon">
7478
8321
  ${rest.map(
7479
- (it) => html14`<div class="pdp-tn-hero__row">
8322
+ (it) => html15`<div class="pdp-tn-hero__row">
7480
8323
  <p class="pdp-tn-hero__row-headline">${renderHeadlineLink3(it)}</p>
7481
8324
  <span class="pdp-tn-hero__row-meta">${it.source}</span>
7482
8325
  </div>`
@@ -7490,8 +8333,8 @@ PdpTrendingNewsHeroLit.properties = {
7490
8333
  data: { attribute: false }
7491
8334
  };
7492
8335
  function renderHeadlineLink3(item) {
7493
- if (!item.url) return html14`${item.headline}`;
7494
- return html14`<a
8336
+ if (!item.url) return html15`${item.headline}`;
8337
+ return html15`<a
7495
8338
  class="pdp-tn-hero__headline-link"
7496
8339
  href=${item.url}
7497
8340
  target="_blank"
@@ -7504,7 +8347,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7504
8347
  }
7505
8348
 
7506
8349
  // src/widgets/PdpPeerFeedMasonryLit.ts
7507
- import { html as html15, LitElement as LitElement15 } from "lit";
8350
+ import { html as html16, LitElement as LitElement16 } from "lit";
7508
8351
  function ensureMasonryStyles() {
7509
8352
  if (typeof document === "undefined") return;
7510
8353
  if (document.getElementById("syntro-pdp-peer-feed-masonry-style")) return;
@@ -7648,7 +8491,7 @@ function personaHue(s4) {
7648
8491
  for (let i2 = 0; i2 < s4.length; i2++) h = h * 31 + s4.charCodeAt(i2) | 0;
7649
8492
  return Math.abs(h) % 360;
7650
8493
  }
7651
- var PdpPeerFeedMasonryLit = class extends LitElement15 {
8494
+ var PdpPeerFeedMasonryLit = class extends LitElement16 {
7652
8495
  constructor() {
7653
8496
  super(...arguments);
7654
8497
  this.data = void 0;
@@ -7662,13 +8505,13 @@ var PdpPeerFeedMasonryLit = class extends LitElement15 {
7662
8505
  }
7663
8506
  render() {
7664
8507
  if (!this.data) {
7665
- return html15`<div aria-busy="true" class="pdp-pf-mas" style="opacity:0.5;">…</div>`;
8508
+ return html16`<div aria-busy="true" class="pdp-pf-mas" style="opacity:0.5;">…</div>`;
7666
8509
  }
7667
- return html15`
8510
+ return html16`
7668
8511
  <section class="pdp-pf-mas" aria-label="Peer voices">
7669
8512
  <div class="pdp-pf-mas__grid">
7670
8513
  ${this.data.peers.map(
7671
- (p) => html15`<article
8514
+ (p) => html16`<article
7672
8515
  class="pdp-pf-mas__card"
7673
8516
  style=${`--pf-avatar-hue: ${personaHue(p.persona)};`}
7674
8517
  >
@@ -7696,7 +8539,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-pee
7696
8539
  }
7697
8540
 
7698
8541
  // src/widgets/PdpPeerFeedCarouselLit.ts
7699
- import { html as html16, LitElement as LitElement16, svg } from "lit";
8542
+ import { html as html17, LitElement as LitElement17, svg } from "lit";
7700
8543
  function ensureCarouselStyles2() {
7701
8544
  if (typeof document === "undefined") return;
7702
8545
  if (document.getElementById("syntro-pdp-peer-feed-carousel-style")) return;
@@ -7912,7 +8755,7 @@ function renderGlyph(kind) {
7912
8755
  <path d="M30 6 L34 26 L54 30 L34 34 L30 54 L26 34 L6 30 L26 26 Z" stroke="currentColor" stroke-width="1.6" fill="none" stroke-linejoin="round"/>
7913
8756
  </svg>`;
7914
8757
  }
7915
- var PdpPeerFeedCarouselLit = class extends LitElement16 {
8758
+ var PdpPeerFeedCarouselLit = class extends LitElement17 {
7916
8759
  constructor() {
7917
8760
  super(...arguments);
7918
8761
  this.data = void 0;
@@ -7926,15 +8769,15 @@ var PdpPeerFeedCarouselLit = class extends LitElement16 {
7926
8769
  }
7927
8770
  render() {
7928
8771
  if (!this.data) {
7929
- return html16`<div aria-busy="true" class="pdp-pf-car" style="opacity:0.5;">…</div>`;
8772
+ return html17`<div aria-busy="true" class="pdp-pf-car" style="opacity:0.5;">…</div>`;
7930
8773
  }
7931
- return html16`
8774
+ return html17`
7932
8775
  <section class="pdp-pf-car" aria-label="Peer voices">
7933
8776
  <div class="pdp-pf-car__track">
7934
8777
  ${this.data.peers.map((p) => {
7935
8778
  const kind = glyphFor(p.persona);
7936
8779
  const hue = glyphHue(p.persona);
7937
- return html16`<article class="pdp-pf-car__card" style=${`--pf-glyph-hue: ${hue};`}>
8780
+ return html17`<article class="pdp-pf-car__card" style=${`--pf-glyph-hue: ${hue};`}>
7938
8781
  <span class="pdp-pf-car__glyph" aria-hidden="true">${renderGlyph(kind)}</span>
7939
8782
  <span class="pdp-pf-car__persona">${p.persona}</span>
7940
8783
  <blockquote class="pdp-pf-car__quote">${p.quote}</blockquote>
@@ -7959,7 +8802,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-pee
7959
8802
  }
7960
8803
 
7961
8804
  // src/widgets/PdpChartLit.ts
7962
- import { html as html17, LitElement as LitElement17, nothing as nothing8, svg as svg2 } from "lit";
8805
+ import { html as html18, LitElement as LitElement18, nothing as nothing9, svg as svg2 } from "lit";
7963
8806
  function formatNum(v) {
7964
8807
  if (v === void 0 || !Number.isFinite(v)) return "\u2014";
7965
8808
  if (Number.isInteger(v)) return v.toLocaleString("en-US");
@@ -8582,7 +9425,7 @@ function colorVar(seriesIdx) {
8582
9425
  return `var(--pc-color-${seriesIdx % PALETTE_SIZE})`;
8583
9426
  }
8584
9427
  var _PdpChartLit_instances, renderLegend_fn, renderTable_fn, renderBars_fn, renderLine_fn;
8585
- var PdpChartLit = class extends LitElement17 {
9428
+ var PdpChartLit = class extends LitElement18 {
8586
9429
  constructor() {
8587
9430
  super(...arguments);
8588
9431
  __privateAdd(this, _PdpChartLit_instances);
@@ -8618,7 +9461,7 @@ var PdpChartLit = class extends LitElement17 {
8618
9461
  }
8619
9462
  render() {
8620
9463
  if (!this.data) {
8621
- return html17`<div data-skeleton class="pdp-chart-skeleton">
9464
+ return html18`<div data-skeleton class="pdp-chart-skeleton">
8622
9465
  <div class="pdp-skeleton-bar" style="width:50%"></div>
8623
9466
  <div class="pdp-skeleton-rect" style="height:200px"></div>
8624
9467
  </div>`;
@@ -8627,7 +9470,7 @@ var PdpChartLit = class extends LitElement17 {
8627
9470
  const allSeriesOnePoint = this.data.series.every((s4) => s4.points.length <= 1);
8628
9471
  const effectiveKind = isTable ? "table" : this.data.viz_kind === "line" && !allSeriesOnePoint ? "line" : "bar";
8629
9472
  const isMultiSeries = this.data.series.length > 1;
8630
- return html17`
9473
+ return html18`
8631
9474
  <section
8632
9475
  class="${this._entering ? "pdp-chart pdp-chart-frame is-entering" : "pdp-chart pdp-chart-frame"}"
8633
9476
  aria-label="${this.data.title}"
@@ -8638,11 +9481,11 @@ var PdpChartLit = class extends LitElement17 {
8638
9481
  </div>
8639
9482
  <h3 class="pdp-chart-title">${this.data.title}</h3>
8640
9483
 
8641
- ${effectiveKind === "table" ? __privateMethod(this, _PdpChartLit_instances, renderTable_fn).call(this) : nothing8}
8642
- ${effectiveKind === "bar" ? __privateMethod(this, _PdpChartLit_instances, renderBars_fn).call(this) : nothing8}
8643
- ${effectiveKind === "line" ? __privateMethod(this, _PdpChartLit_instances, renderLine_fn).call(this) : nothing8}
8644
- ${effectiveKind !== "table" && isMultiSeries ? __privateMethod(this, _PdpChartLit_instances, renderLegend_fn).call(this) : nothing8}
8645
- ${this.data.rationale ? html17`<p class="pdp-chart-rationale">${this.data.rationale}</p>` : nothing8}
9484
+ ${effectiveKind === "table" ? __privateMethod(this, _PdpChartLit_instances, renderTable_fn).call(this) : nothing9}
9485
+ ${effectiveKind === "bar" ? __privateMethod(this, _PdpChartLit_instances, renderBars_fn).call(this) : nothing9}
9486
+ ${effectiveKind === "line" ? __privateMethod(this, _PdpChartLit_instances, renderLine_fn).call(this) : nothing9}
9487
+ ${effectiveKind !== "table" && isMultiSeries ? __privateMethod(this, _PdpChartLit_instances, renderLegend_fn).call(this) : nothing9}
9488
+ ${this.data.rationale ? html18`<p class="pdp-chart-rationale">${this.data.rationale}</p>` : nothing9}
8646
9489
  </section>
8647
9490
  `;
8648
9491
  }
@@ -8650,10 +9493,10 @@ var PdpChartLit = class extends LitElement17 {
8650
9493
  _PdpChartLit_instances = new WeakSet();
8651
9494
  renderLegend_fn = function() {
8652
9495
  const data = this.data;
8653
- return html17`
9496
+ return html18`
8654
9497
  <ol class="pdp-chart-legend" aria-label="Legend">
8655
9498
  ${data.series.map(
8656
- (s4, idx) => html17`
9499
+ (s4, idx) => html18`
8657
9500
  <li class="pdp-chart-legend-item">
8658
9501
  <span
8659
9502
  class="pdp-chart-legend-swatch"
@@ -8669,22 +9512,22 @@ renderLegend_fn = function() {
8669
9512
  };
8670
9513
  renderTable_fn = function() {
8671
9514
  const matrix = buildComparisonMatrix(this.data);
8672
- return html17`
9515
+ return html18`
8673
9516
  <div class="pdp-chart-table-wrap">
8674
9517
  <table class="pdp-chart-table">
8675
9518
  <thead>
8676
9519
  <tr>
8677
9520
  <th></th>
8678
- ${matrix.colLabels.map((label) => html17`<th>${label}</th>`)}
9521
+ ${matrix.colLabels.map((label) => html18`<th>${label}</th>`)}
8679
9522
  </tr>
8680
9523
  </thead>
8681
9524
  <tbody>
8682
9525
  ${matrix.rowLabels.map(
8683
- (row, rowIdx) => html17`
9526
+ (row, rowIdx) => html18`
8684
9527
  <tr class=${rowIdx === matrix.winningRow ? "is-winning" : ""}>
8685
9528
  <td>${row}</td>
8686
9529
  ${matrix.cells[rowIdx].map(
8687
- (cell) => html17`<td class="pdp-chart-numeric-cell">${formatNum(cell)}</td>`
9530
+ (cell) => html18`<td class="pdp-chart-numeric-cell">${formatNum(cell)}</td>`
8688
9531
  )}
8689
9532
  </tr>
8690
9533
  `
@@ -8699,7 +9542,7 @@ renderBars_fn = function() {
8699
9542
  const { buckets, yMax } = buildBarBuckets(data);
8700
9543
  const ticks = niceTicks(yMax);
8701
9544
  const scaleMax = Math.max(yMax, ticks[ticks.length - 1]);
8702
- return html17`
9545
+ return html18`
8703
9546
  <div
8704
9547
  class="pdp-chart-bars"
8705
9548
  role="figure"
@@ -8708,7 +9551,7 @@ renderBars_fn = function() {
8708
9551
  >
8709
9552
  <div class="pdp-chart-yaxis" aria-hidden="true">
8710
9553
  ${ticks.map(
8711
- (t2) => html17`
9554
+ (t2) => html18`
8712
9555
  <span
8713
9556
  class="pdp-chart-yaxis-tick"
8714
9557
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8720,7 +9563,7 @@ renderBars_fn = function() {
8720
9563
  </div>
8721
9564
  <div class="pdp-chart-bars-area">
8722
9565
  ${ticks.map(
8723
- (t2) => html17`
9566
+ (t2) => html18`
8724
9567
  <div
8725
9568
  class="pdp-chart-bars-gridline"
8726
9569
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8730,11 +9573,11 @@ renderBars_fn = function() {
8730
9573
  )}
8731
9574
  <div class="pdp-chart-bars-baseline" aria-hidden="true"></div>
8732
9575
  ${buckets.map(
8733
- (bucket, bIdx) => html17`
9576
+ (bucket, bIdx) => html18`
8734
9577
  <div class="pdp-chart-bars-bucket">
8735
9578
  <div class="pdp-chart-bars-stack">
8736
9579
  ${bucket.bars.map(
8737
- (bar, barIdxInBucket) => html17`
9580
+ (bar, barIdxInBucket) => html18`
8738
9581
  <div
8739
9582
  class="pdp-chart-bar"
8740
9583
  style="
@@ -8745,9 +9588,9 @@ renderBars_fn = function() {
8745
9588
  role="img"
8746
9589
  aria-label="${bucket.label} — ${bar.seriesName}: ${formatNum(bar.value)}"
8747
9590
  >
8748
- ${bucket.bars.length === 1 ? html17`<span class="pdp-chart-bar-value"
9591
+ ${bucket.bars.length === 1 ? html18`<span class="pdp-chart-bar-value"
8749
9592
  >${formatNum(bar.value)}</span
8750
- >` : nothing8}
9593
+ >` : nothing9}
8751
9594
  </div>
8752
9595
  `
8753
9596
  )}
@@ -8765,7 +9608,7 @@ renderLine_fn = function() {
8765
9608
  const { series, xLabels, yMax } = buildLinePaths(data);
8766
9609
  const ticks = niceTicks(yMax);
8767
9610
  const scaleMax = Math.max(yMax, ticks[ticks.length - 1]);
8768
- return html17`
9611
+ return html18`
8769
9612
  <div
8770
9613
  class="pdp-chart-line"
8771
9614
  role="figure"
@@ -8775,7 +9618,7 @@ renderLine_fn = function() {
8775
9618
  >
8776
9619
  <div class="pdp-chart-line-yaxis" aria-hidden="true">
8777
9620
  ${ticks.map(
8778
- (t2) => html17`
9621
+ (t2) => html18`
8779
9622
  <span
8780
9623
  class="pdp-chart-yaxis-tick"
8781
9624
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8824,7 +9667,7 @@ renderLine_fn = function() {
8824
9667
  style="--col-count:${xLabels.length}"
8825
9668
  aria-hidden="true"
8826
9669
  >
8827
- ${xLabels.map((label) => html17`<span>${label}</span>`)}
9670
+ ${xLabels.map((label) => html18`<span>${label}</span>`)}
8828
9671
  </div>
8829
9672
  `;
8830
9673
  };
@@ -8837,7 +9680,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
8837
9680
  }
8838
9681
 
8839
9682
  // src/widgets/PdpChartBarStackedLit.ts
8840
- import { html as html18, LitElement as LitElement18 } from "lit";
9683
+ import { html as html19, LitElement as LitElement19 } from "lit";
8841
9684
  function ensureStyles() {
8842
9685
  if (typeof document === "undefined") return;
8843
9686
  if (document.getElementById("syntro-pdp-chart-bar-style")) return;
@@ -8925,7 +9768,7 @@ var CSS = `
8925
9768
  }
8926
9769
  `;
8927
9770
  var PALETTE = ["hsl(150 32% 50%)", "hsl(40 75% 60%)", "hsl(208 50% 55%)", "hsl(320 38% 60%)"];
8928
- var PdpChartBarStackedLit = class extends LitElement18 {
9771
+ var PdpChartBarStackedLit = class extends LitElement19 {
8929
9772
  constructor() {
8930
9773
  super(...arguments);
8931
9774
  this.data = void 0;
@@ -8938,16 +9781,16 @@ var PdpChartBarStackedLit = class extends LitElement18 {
8938
9781
  ensureStyles();
8939
9782
  }
8940
9783
  render() {
8941
- if (!this.data) return html18`<div class="pdp-chart-bar" style="opacity:0.5;">…</div>`;
9784
+ if (!this.data) return html19`<div class="pdp-chart-bar" style="opacity:0.5;">…</div>`;
8942
9785
  const { title, series } = this.data;
8943
9786
  const allX = Array.from(new Set(series.flatMap((s4) => s4.points.map((p) => p.x))));
8944
9787
  const max = Math.max(...series.flatMap((s4) => s4.points.map((p) => p.y)), 1);
8945
- return html18`
9788
+ return html19`
8946
9789
  <section class="pdp-chart-bar" aria-label=${title}>
8947
9790
  <h3 class="pdp-chart-bar__title">${title}</h3>
8948
- ${series.length > 1 ? html18`<div class="pdp-chart-bar__legend">
9791
+ ${series.length > 1 ? html19`<div class="pdp-chart-bar__legend">
8949
9792
  ${series.map(
8950
- (s4, i2) => html18`<span
9793
+ (s4, i2) => html19`<span
8951
9794
  ><span
8952
9795
  class="pdp-chart-bar__legend-dot"
8953
9796
  style=${`background: ${PALETTE[i2 % PALETTE.length]};`}
@@ -8957,14 +9800,14 @@ var PdpChartBarStackedLit = class extends LitElement18 {
8957
9800
  )}
8958
9801
  </div>` : ""}
8959
9802
  ${allX.map(
8960
- (x) => html18`<div class="pdp-chart-bar__row">
9803
+ (x) => html19`<div class="pdp-chart-bar__row">
8961
9804
  <div class="pdp-chart-bar__row-label">${x}</div>
8962
9805
  <div class="pdp-chart-bar__row-bars">
8963
9806
  ${series.map((s4, i2) => {
8964
9807
  const point = s4.points.find((p) => p.x === x);
8965
9808
  if (!point) return "";
8966
9809
  const pct = point.y / max * 100;
8967
- return html18`<div class="pdp-chart-bar__bar-track">
9810
+ return html19`<div class="pdp-chart-bar__bar-track">
8968
9811
  <div
8969
9812
  class="pdp-chart-bar__bar-fill"
8970
9813
  style=${`width: ${pct.toFixed(1)}%; background: ${PALETTE[i2 % PALETTE.length]};`}
@@ -8987,7 +9830,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
8987
9830
  }
8988
9831
 
8989
9832
  // src/widgets/PdpChartMetricPullLit.ts
8990
- import { html as html19, LitElement as LitElement19, svg as svg3 } from "lit";
9833
+ import { html as html20, LitElement as LitElement20, svg as svg3 } from "lit";
8991
9834
  function ensureStyles2() {
8992
9835
  if (typeof document === "undefined") return;
8993
9836
  if (document.getElementById("syntro-pdp-chart-metric-style")) return;
@@ -9099,7 +9942,7 @@ function buildSparkline(points) {
9099
9942
  const peakIndex = points.reduce((best, p, i2) => p.y > points[best].y ? i2 : best, 0);
9100
9943
  return { linePath: line, areaPath: area, peakIndex };
9101
9944
  }
9102
- var PdpChartMetricPullLit = class extends LitElement19 {
9945
+ var PdpChartMetricPullLit = class extends LitElement20 {
9103
9946
  constructor() {
9104
9947
  super(...arguments);
9105
9948
  this.data = void 0;
@@ -9112,10 +9955,10 @@ var PdpChartMetricPullLit = class extends LitElement19 {
9112
9955
  ensureStyles2();
9113
9956
  }
9114
9957
  render() {
9115
- if (!this.data) return html19`<div class="pdp-chart-met" style="opacity:0.5;">…</div>`;
9958
+ if (!this.data) return html20`<div class="pdp-chart-met" style="opacity:0.5;">…</div>`;
9116
9959
  const { title, series } = this.data;
9117
9960
  const first = series[0];
9118
- if (!first || first.points.length === 0) return html19``;
9961
+ if (!first || first.points.length === 0) return html20``;
9119
9962
  const points = first.points;
9120
9963
  const peak = points.reduce((b, p) => p.y > b.y ? p : b, points[0]);
9121
9964
  const mean = points.reduce((s4, p) => s4 + p.y, 0) / points.length;
@@ -9128,7 +9971,7 @@ var PdpChartMetricPullLit = class extends LitElement19 {
9128
9971
  const max = Math.max(...points.map((p) => p.y));
9129
9972
  const range = max - min || 1;
9130
9973
  const py = h - 4 - (peak.y - min) / range * (h - 8);
9131
- return html19`
9974
+ return html20`
9132
9975
  <section class="pdp-chart-met" aria-label=${title}>
9133
9976
  <div class="pdp-chart-met__metric">
9134
9977
  <span class="pdp-chart-met__big">${peak.y}</span>
@@ -9160,7 +10003,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
9160
10003
  }
9161
10004
 
9162
10005
  // src/widgets/PdpQaAccordionLit.ts
9163
- import { html as html20, LitElement as LitElement20 } from "lit";
10006
+ import { html as html21, LitElement as LitElement21 } from "lit";
9164
10007
  function ensureStyles3() {
9165
10008
  if (typeof document === "undefined") return;
9166
10009
  if (document.getElementById("syntro-pdp-qa-accordion-style")) return;
@@ -9242,7 +10085,7 @@ var CSS3 = `
9242
10085
  max-width: 56ch;
9243
10086
  }
9244
10087
  `;
9245
- var PdpQaAccordionLit = class extends LitElement20 {
10088
+ var PdpQaAccordionLit = class extends LitElement21 {
9246
10089
  constructor() {
9247
10090
  super(...arguments);
9248
10091
  this.data = void 0;
@@ -9255,11 +10098,11 @@ var PdpQaAccordionLit = class extends LitElement20 {
9255
10098
  ensureStyles3();
9256
10099
  }
9257
10100
  render() {
9258
- if (!this.data) return html20`<div class="pdp-qa-acc" style="opacity:0.5;">…</div>`;
9259
- return html20`
10101
+ if (!this.data) return html21`<div class="pdp-qa-acc" style="opacity:0.5;">…</div>`;
10102
+ return html21`
9260
10103
  <section class="pdp-qa-acc" aria-label="Frequently asked questions">
9261
10104
  ${this.data.items.map(
9262
- (it) => html20`<details class="pdp-qa-acc__item">
10105
+ (it) => html21`<details class="pdp-qa-acc__item">
9263
10106
  <summary>
9264
10107
  <span class="pdp-qa-acc__chev" aria-hidden="true"></span>
9265
10108
  <span>${it.question}</span>
@@ -9279,7 +10122,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-qa-
9279
10122
  }
9280
10123
 
9281
10124
  // src/widgets/PdpQaSideBySideLit.ts
9282
- import { html as html21, LitElement as LitElement21 } from "lit";
10125
+ import { html as html22, LitElement as LitElement22 } from "lit";
9283
10126
  function ensureStyles4() {
9284
10127
  if (typeof document === "undefined") return;
9285
10128
  if (document.getElementById("syntro-pdp-qa-side-style")) return;
@@ -9353,7 +10196,7 @@ var CSS4 = `
9353
10196
  margin: 0;
9354
10197
  }
9355
10198
  `;
9356
- var PdpQaSideBySideLit = class extends LitElement21 {
10199
+ var PdpQaSideBySideLit = class extends LitElement22 {
9357
10200
  constructor() {
9358
10201
  super(...arguments);
9359
10202
  this.data = void 0;
@@ -9366,11 +10209,11 @@ var PdpQaSideBySideLit = class extends LitElement21 {
9366
10209
  ensureStyles4();
9367
10210
  }
9368
10211
  render() {
9369
- if (!this.data) return html21`<div class="pdp-qa-side" style="opacity:0.5;">…</div>`;
9370
- return html21`
10212
+ if (!this.data) return html22`<div class="pdp-qa-side" style="opacity:0.5;">…</div>`;
10213
+ return html22`
9371
10214
  <section class="pdp-qa-side" aria-label="Q&A">
9372
10215
  ${this.data.items.map(
9373
- (it) => html21`<div class="pdp-qa-side__item">
10216
+ (it) => html22`<div class="pdp-qa-side__item">
9374
10217
  <h4 class="pdp-qa-side__q">${it.question}</h4>
9375
10218
  <p class="pdp-qa-side__a">${it.answer}</p>
9376
10219
  </div>`
@@ -9387,7 +10230,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-qa-
9387
10230
  }
9388
10231
 
9389
10232
  // src/widgets/PdpRegionalFullBleedLit.ts
9390
- import { html as html22, LitElement as LitElement22 } from "lit";
10233
+ import { html as html23, LitElement as LitElement23 } from "lit";
9391
10234
  function ensureStyles5() {
9392
10235
  if (typeof document === "undefined") return;
9393
10236
  if (document.getElementById("syntro-pdp-regional-fullbleed-style")) return;
@@ -9478,7 +10321,7 @@ var CSS5 = `
9478
10321
  font-style: italic;
9479
10322
  }
9480
10323
  `;
9481
- var PdpRegionalFullBleedLit = class extends LitElement22 {
10324
+ var PdpRegionalFullBleedLit = class extends LitElement23 {
9482
10325
  constructor() {
9483
10326
  super(...arguments);
9484
10327
  this.data = void 0;
@@ -9491,9 +10334,9 @@ var PdpRegionalFullBleedLit = class extends LitElement22 {
9491
10334
  ensureStyles5();
9492
10335
  }
9493
10336
  render() {
9494
- if (!this.data) return html22`<div class="pdp-reg-fb" style="opacity:0.5;">…</div>`;
10337
+ if (!this.data) return html23`<div class="pdp-reg-fb" style="opacity:0.5;">…</div>`;
9495
10338
  const d = this.data;
9496
- return html22`
10339
+ return html23`
9497
10340
  <section class="pdp-reg-fb" aria-label="Where you are">
9498
10341
  <article class="pdp-reg-fb__panel">
9499
10342
  <svg class="pdp-reg-fb__glyph" viewBox="0 0 56 56" aria-hidden="true">
@@ -9536,7 +10379,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-reg
9536
10379
  }
9537
10380
 
9538
10381
  // src/widgets/PdpRegionalInlineNoteLit.ts
9539
- import { html as html23, LitElement as LitElement23 } from "lit";
10382
+ import { html as html24, LitElement as LitElement24 } from "lit";
9540
10383
  function ensureStyles6() {
9541
10384
  if (typeof document === "undefined") return;
9542
10385
  if (document.getElementById("syntro-pdp-regional-inline-style")) return;
@@ -9597,7 +10440,7 @@ var CSS6 = `
9597
10440
  font-style: italic;
9598
10441
  }
9599
10442
  `;
9600
- var PdpRegionalInlineNoteLit = class extends LitElement23 {
10443
+ var PdpRegionalInlineNoteLit = class extends LitElement24 {
9601
10444
  constructor() {
9602
10445
  super(...arguments);
9603
10446
  this.data = void 0;
@@ -9610,9 +10453,9 @@ var PdpRegionalInlineNoteLit = class extends LitElement23 {
9610
10453
  ensureStyles6();
9611
10454
  }
9612
10455
  render() {
9613
- if (!this.data) return html23`<div class="pdp-reg-in" style="opacity:0.5;">…</div>`;
10456
+ if (!this.data) return html24`<div class="pdp-reg-in" style="opacity:0.5;">…</div>`;
9614
10457
  const d = this.data;
9615
- return html23`
10458
+ return html24`
9616
10459
  <aside class="pdp-reg-in" aria-label="Regional note">
9617
10460
  <svg class="pdp-reg-in__icon" viewBox="0 0 22 22" aria-hidden="true">
9618
10461
  <circle cx="11" cy="11" r="9" fill="none" stroke="currentColor" stroke-width="1.6"/>
@@ -9640,8 +10483,8 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-reg
9640
10483
  }
9641
10484
 
9642
10485
  // src/widgets/PdpSlotPlaceholderLit.ts
9643
- import { html as html24, LitElement as LitElement24 } from "lit";
9644
- var PdpSlotPlaceholderLit = class extends LitElement24 {
10486
+ import { html as html25, LitElement as LitElement25 } from "lit";
10487
+ var PdpSlotPlaceholderLit = class extends LitElement25 {
9645
10488
  constructor() {
9646
10489
  super(...arguments);
9647
10490
  this.label = "More personalized content coming soon";
@@ -9650,7 +10493,7 @@ var PdpSlotPlaceholderLit = class extends LitElement24 {
9650
10493
  return this;
9651
10494
  }
9652
10495
  render() {
9653
- return html24`
10496
+ return html25`
9654
10497
  <div class="pdp-slot-placeholder" data-placeholder>
9655
10498
  <p>${this.label}</p>
9656
10499
  <small>Ask in chat to explore this product further.</small>
@@ -9666,7 +10509,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-slo
9666
10509
  }
9667
10510
 
9668
10511
  // src/widgets/PdpRibbonLit.ts
9669
- import { html as html25, LitElement as LitElement25, nothing as nothing9 } from "lit";
10512
+ import { html as html26, LitElement as LitElement26, nothing as nothing10 } from "lit";
9670
10513
  function ensureRibbonStyles() {
9671
10514
  if (typeof document === "undefined") return;
9672
10515
  if (document.getElementById("syntro-pdp-ribbon-style")) return;
@@ -9795,7 +10638,7 @@ var RIBBON_CSS = `
9795
10638
  100% { transform: translateX(110%); }
9796
10639
  }
9797
10640
  `;
9798
- var PdpRibbonLit = class extends LitElement25 {
10641
+ var PdpRibbonLit = class extends LitElement26 {
9799
10642
  constructor() {
9800
10643
  super(...arguments);
9801
10644
  this.topic = "";
@@ -9833,7 +10676,7 @@ var PdpRibbonLit = class extends LitElement25 {
9833
10676
  }
9834
10677
  render() {
9835
10678
  const cls = this._entering ? "syntro-pdp-ribbon is-entering" : "syntro-pdp-ribbon";
9836
- return html25`
10679
+ return html26`
9837
10680
  <div class="${cls}" role="status" aria-live="polite">
9838
10681
  <span class="syntro-pdp-ribbon-sweep" aria-hidden="true"></span>
9839
10682
  <svg
@@ -9853,7 +10696,7 @@ var PdpRibbonLit = class extends LitElement25 {
9853
10696
  </svg>
9854
10697
  <p class="syntro-pdp-ribbon-copy">
9855
10698
  Tailored to your conversation about
9856
- ${this.topic ? html25` <span class="syntro-pdp-ribbon-topic">${this.topic}</span>.` : nothing9}
10699
+ ${this.topic ? html26` <span class="syntro-pdp-ribbon-topic">${this.topic}</span>.` : nothing10}
9857
10700
  <span class="syntro-pdp-ribbon-trail"> ${this.subtitle}</span>
9858
10701
  </p>
9859
10702
  </div>
@@ -9869,219 +10712,6 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-rib
9869
10712
  customElements.define("syntro-pdp-ribbon", PdpRibbonLit);
9870
10713
  }
9871
10714
 
9872
- // src/widgets/PdpSlotLit.ts
9873
- import { html as html26, LitElement as LitElement26, nothing as nothing10 } from "lit";
9874
- function ensureSlotStyles() {
9875
- if (typeof document === "undefined") return;
9876
- if (document.getElementById("syntro-pdp-slot-style")) return;
9877
- const s4 = document.createElement("style");
9878
- s4.id = "syntro-pdp-slot-style";
9879
- s4.textContent = SLOT_CSS;
9880
- document.head.appendChild(s4);
9881
- }
9882
- var SLOT_CSS = `
9883
- .syntro-pdp-slot {
9884
- --sl-primary: var(--syntro-pdp-primary, hsl(150 32% 38%));
9885
- --sl-fg: var(--syntro-pdp-fg, hsl(35 15% 92%));
9886
- --sl-muted: var(--syntro-pdp-muted, hsl(30 8% 55%));
9887
- --sl-border: var(--syntro-pdp-border, hsl(30 6% 18%));
9888
- --sl-bg-a: var(--syntro-pdp-card-bg, hsl(25 10% 11%));
9889
- --sl-bg-b: var(--syntro-pdp-card-bg-b, hsl(25 10% 9%));
9890
- --sl-display: var(--syntro-pdp-display, inherit);
9891
-
9892
- position: relative;
9893
- display: grid;
9894
- grid-template-areas: 'stack';
9895
- font-family: var(--syntro-pdp-sans, inherit);
9896
- }
9897
- .syntro-pdp-slot > .syntro-pdp-slot-mount,
9898
- .syntro-pdp-slot > .syntro-pdp-slot-pending,
9899
- .syntro-pdp-slot > .syntro-pdp-slot-failed {
9900
- grid-area: stack;
9901
- }
9902
-
9903
- .syntro-pdp-slot-mount {
9904
- min-height: 220px;
9905
- }
9906
-
9907
- /* When mutation arrived, hide the pending layer */
9908
- .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-pending,
9909
- .syntro-pdp-slot[data-state='failed'] .syntro-pdp-slot-pending {
9910
- display: none;
9911
- }
9912
- .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-failed,
9913
- .syntro-pdp-slot[data-state='pending'] .syntro-pdp-slot-failed {
9914
- display: none;
9915
- }
9916
-
9917
- /* Pending \u2014 a quietly-animated waiting state. */
9918
- .syntro-pdp-slot-pending {
9919
- position: relative;
9920
- border: 1px dashed var(--sl-border);
9921
- border-radius: 22px;
9922
- min-height: 220px;
9923
- padding: 36px 28px;
9924
- background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
9925
- overflow: hidden;
9926
- display: flex;
9927
- align-items: center;
9928
- justify-content: flex-start;
9929
- }
9930
- .syntro-pdp-slot-pending-shimmer {
9931
- position: absolute;
9932
- inset: 0;
9933
- background: linear-gradient(
9934
- 90deg,
9935
- transparent,
9936
- color-mix(in srgb, var(--sl-primary) 7%, transparent),
9937
- transparent
9938
- );
9939
- transform: translateX(-100%);
9940
- animation: syntro-pdp-slot-sweep 1800ms ease-in-out infinite;
9941
- }
9942
- .syntro-pdp-slot-pending-row {
9943
- position: relative;
9944
- z-index: 1;
9945
- display: flex;
9946
- align-items: center;
9947
- gap: 12px;
9948
- }
9949
- .syntro-pdp-slot-pending-dot {
9950
- flex: 0 0 auto;
9951
- width: 8px;
9952
- height: 8px;
9953
- border-radius: 50%;
9954
- background: var(--sl-primary);
9955
- box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
9956
- animation: syntro-pdp-slot-pulse 1600ms ease-in-out infinite;
9957
- }
9958
- .syntro-pdp-slot-pending-label {
9959
- font-family: var(--sl-display);
9960
- font-style: italic;
9961
- font-size: 18px;
9962
- font-variation-settings: 'SOFT' 70;
9963
- color: var(--sl-muted);
9964
- margin: 0;
9965
- line-height: 1.4;
9966
- }
9967
-
9968
- /* Failed \u2014 the planner or sub-agent failed; the host page still works. */
9969
- .syntro-pdp-slot-failed {
9970
- border: 1px solid var(--sl-border);
9971
- border-radius: 22px;
9972
- min-height: 180px;
9973
- padding: 24px 28px;
9974
- background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
9975
- display: flex;
9976
- flex-direction: column;
9977
- justify-content: center;
9978
- gap: 6px;
9979
- }
9980
- .syntro-pdp-slot-failed-title {
9981
- font-family: var(--sl-display);
9982
- font-style: italic;
9983
- font-size: 17px;
9984
- color: var(--sl-fg);
9985
- margin: 0;
9986
- font-variation-settings: 'SOFT' 70;
9987
- }
9988
- .syntro-pdp-slot-failed-body {
9989
- color: var(--sl-muted);
9990
- font-size: 13.5px;
9991
- margin: 0;
9992
- line-height: 1.5;
9993
- }
9994
-
9995
- @media (max-width: 640px) {
9996
- .syntro-pdp-slot-pending,
9997
- .syntro-pdp-slot-failed {
9998
- border-radius: 18px;
9999
- padding: 24px 18px;
10000
- min-height: 180px;
10001
- }
10002
- .syntro-pdp-slot-pending-label {
10003
- font-size: 15.5px;
10004
- }
10005
- }
10006
-
10007
- @keyframes syntro-pdp-slot-sweep {
10008
- 0% { transform: translateX(-100%); }
10009
- 100% { transform: translateX(100%); }
10010
- }
10011
- @keyframes syntro-pdp-slot-pulse {
10012
- 0%, 100% {
10013
- opacity: 0.6;
10014
- box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
10015
- }
10016
- 50% {
10017
- opacity: 1;
10018
- box-shadow: 0 0 0 8px color-mix(in srgb, var(--sl-primary) 26%, transparent);
10019
- }
10020
- }
10021
- `;
10022
- var PENDING_COPY = {
10023
- "trending-news": "Composing this section\u2026",
10024
- chart: "Drawing the comparison\u2026",
10025
- qa: "Picking the questions worth answering\u2026",
10026
- regional: "Locating you in time and place\u2026",
10027
- "peer-feed": "Finding people like you\u2026"
10028
- };
10029
- var PENDING_FALLBACK = "Composing\u2026";
10030
- var PdpSlotLit = class extends LitElement26 {
10031
- constructor() {
10032
- super(...arguments);
10033
- /** DOM id the host's mutation runtime targets when appending the widget. */
10034
- this.slotId = "";
10035
- this.kind = "";
10036
- this.state = "pending";
10037
- }
10038
- createRenderRoot() {
10039
- return this;
10040
- }
10041
- connectedCallback() {
10042
- super.connectedCallback();
10043
- ensureSlotStyles();
10044
- }
10045
- willUpdate() {
10046
- this.dataset.state = this.state;
10047
- }
10048
- render() {
10049
- const pendingLabel = PENDING_COPY[this.kind] ?? PENDING_FALLBACK;
10050
- return html26`
10051
- <div class="syntro-pdp-slot" data-state=${this.state} data-kind=${this.kind}>
10052
- <div
10053
- class="syntro-pdp-slot-mount"
10054
- id=${this.slotId || nothing10}
10055
- data-pdp-slot=${this.kind}
10056
- ></div>
10057
- <div class="syntro-pdp-slot-pending" aria-hidden=${this.state !== "pending"}>
10058
- <div class="syntro-pdp-slot-pending-shimmer" aria-hidden="true"></div>
10059
- <div class="syntro-pdp-slot-pending-row">
10060
- <span class="syntro-pdp-slot-pending-dot" aria-hidden="true"></span>
10061
- <p class="syntro-pdp-slot-pending-label">${pendingLabel}</p>
10062
- </div>
10063
- </div>
10064
- <div class="syntro-pdp-slot-failed" aria-hidden=${this.state !== "failed"}>
10065
- <p class="syntro-pdp-slot-failed-title">
10066
- Personalized view couldn't load.
10067
- </p>
10068
- <p class="syntro-pdp-slot-failed-body">
10069
- The standard page still has everything you need.
10070
- </p>
10071
- </div>
10072
- </div>
10073
- `;
10074
- }
10075
- };
10076
- PdpSlotLit.properties = {
10077
- slotId: { type: String, attribute: "slot-id" },
10078
- kind: { type: String },
10079
- state: { type: String, reflect: true }
10080
- };
10081
- if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-slot")) {
10082
- customElements.define("syntro-pdp-slot", PdpSlotLit);
10083
- }
10084
-
10085
10715
  // src/widgets/PdpQaLit.ts
10086
10716
  import { html as html27, LitElement as LitElement27, nothing as nothing11 } from "lit";
10087
10717
  function ensureQaStyles() {
@@ -11050,6 +11680,8 @@ var runtime = {
11050
11680
  var runtime_default = runtime;
11051
11681
 
11052
11682
  export {
11683
+ detachSection,
11684
+ runTakeover,
11053
11685
  _testing,
11054
11686
  onActivate,
11055
11687
  ProductCardMountable,
@@ -11089,4 +11721,4 @@ export {
11089
11721
  * SPDX-License-Identifier: BSD-3-Clause
11090
11722
  *)
11091
11723
  */
11092
- //# sourceMappingURL=chunk-NH3CFDTZ.js.map
11724
+ //# sourceMappingURL=chunk-HV6QS4PQ.js.map