@syntrologie/adapt-product 2.34.0 → 2.36.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-NH3CFDTZ.js → chunk-SLHBNATX.js} +1130 -483
  3. package/dist/chunk-SLHBNATX.js.map +7 -0
  4. package/dist/{chunk-FAKCB3BS.js → chunk-Y2QAYCSK.js} +72 -30
  5. package/dist/chunk-Y2QAYCSK.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 +148 -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 +171 -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-Y2QAYCSK.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,334 @@ 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 KIND_SUPERSEDES_ROLE = {
816
+ qa: "faq",
817
+ "peer-feed": "social-proof"
818
+ };
819
+ var DEFAULT_COMMIT_TIMEOUT_MS = 500;
820
+ var NOOP_DISPOSE = () => {
821
+ };
822
+ async function runTakeover(config, ports, opts = {}) {
823
+ if (!ports.hasSignals()) {
824
+ const declaredRoles = new Set(config.hostSections.map((s4) => s4.role));
825
+ void Promise.resolve().then(() => ports.fetchPlan()).then(
826
+ (response2) => ports.renderModules(
827
+ {
828
+ // Dropped on this path (nothing may detach, so the host's own
829
+ // sections all stay attached — rendering an overlap duplicates
830
+ // content, the exact class the spec forbids):
831
+ // 1. host-derived entries (kind:sectionId) — review F2;
832
+ // 2. native kinds superseding a DECLARED host role (two-Q&As
833
+ // bug: our qa next to their attached FAQ).
834
+ order: response2.plan.order.filter((entry) => {
835
+ if (entry.includes(":")) return false;
836
+ const superseded = KIND_SUPERSEDES_ROLE[entry];
837
+ return !(superseded && declaredRoles.has(superseded));
838
+ }),
839
+ suppress: []
840
+ },
841
+ () => {
842
+ }
843
+ )
844
+ ).catch(() => ports.telemetry("takeover.render_failed", { path: "progressive" }));
845
+ return { outcome: "progressive", dispose: NOOP_DISPOSE };
846
+ }
847
+ const commitTimeoutMs = opts.commitTimeoutMs ?? DEFAULT_COMMIT_TIMEOUT_MS;
848
+ const region = ports.region();
849
+ const lift = ports.curtain();
850
+ let timeoutId;
851
+ const timedOut = /* @__PURE__ */ Symbol("timeout");
852
+ const fetchFailed = /* @__PURE__ */ Symbol("fetch-failed");
853
+ const response = await Promise.race([
854
+ ports.fetchPlan().catch(() => fetchFailed),
855
+ new Promise((r) => {
856
+ timeoutId = setTimeout(() => r(timedOut), commitTimeoutMs);
857
+ })
858
+ ]).finally(() => clearTimeout(timeoutId));
859
+ if (response === timedOut || response === fetchFailed) {
860
+ ports.deactivateRoot();
861
+ lift();
862
+ if (response === timedOut) {
863
+ ports.telemetry("takeover.precommit_timeout", { budgetMs: commitTimeoutMs });
864
+ } else {
865
+ ports.telemetry("takeover.plan_fetch_failed", { budgetMs: commitTimeoutMs });
866
+ }
867
+ return { outcome: "aborted-precommit", dispose: NOOP_DISPOSE };
868
+ }
869
+ const plan = response.plan;
870
+ const sectionsById = new Map(config.hostSections.map((s4) => [s4.id, s4]));
871
+ const toSuppress = [];
872
+ let reservedPx = 0;
873
+ for (const id of plan.suppress) {
874
+ const section = sectionsById.get(id);
875
+ if (!section) {
876
+ ports.telemetry("takeover.suppress_undeclared", { sectionId: id });
877
+ continue;
878
+ }
879
+ let el = null;
880
+ try {
881
+ el = ports.findSection(section.anchor);
882
+ } catch {
883
+ }
884
+ if (!el) {
885
+ ports.telemetry("takeover.section_anchor_missing", { sectionId: id });
886
+ continue;
887
+ }
888
+ reservedPx += ports.measureSection(el);
889
+ toSuppress.push({ id, el });
890
+ }
891
+ ports.reserve(reservedPx);
892
+ const handles = /* @__PURE__ */ new Map();
893
+ for (const { id, el } of toSuppress) {
894
+ const handle = detachSection(el);
895
+ if (handle) handles.set(id, handle);
896
+ }
897
+ let disposed = false;
898
+ let guard;
899
+ const dispose = () => {
900
+ if (disposed) return;
901
+ disposed = true;
902
+ guard?.stop();
903
+ for (const handle of handles.values()) handle.restore();
904
+ handles.clear();
905
+ ports.deactivateRoot();
906
+ lift();
907
+ };
908
+ guard = startResurrectionGuard({
909
+ region,
910
+ ignore: (el) => ports.ownsNode(el),
911
+ anchors: new Map(toSuppress.map(({ id }) => [id, sectionsById.get(id).anchor])),
912
+ onResurrected: (sectionId, el) => {
913
+ ports.telemetry("takeover.section_resurrected", { sectionId });
914
+ el.remove();
915
+ },
916
+ onBudgetExhausted: (sectionId, el) => {
917
+ ports.telemetry("takeover.resurrection_budget_exhausted", { sectionId });
918
+ el.remove();
919
+ dispose();
920
+ }
921
+ });
922
+ const onModuleFailed = (suppressedSectionId) => {
923
+ if (!suppressedSectionId) return;
924
+ const handle = handles.get(suppressedSectionId);
925
+ if (!handle) return;
926
+ guard?.unwatch(suppressedSectionId);
927
+ handle.restore();
928
+ handles.delete(suppressedSectionId);
929
+ ports.telemetry("takeover.module_failed_section_restored", {
930
+ sectionId: suppressedSectionId
931
+ });
932
+ };
933
+ void Promise.resolve().then(() => ports.renderModules(plan, onModuleFailed)).catch(() => {
934
+ ports.telemetry("takeover.render_failed", { path: "committed" });
935
+ dispose();
936
+ }).finally(() => ports.releaseReservation());
937
+ lift();
938
+ return { outcome: "committed", dispose };
939
+ }
940
+
941
+ // src/takeover/fetchPlan.ts
942
+ import { z as z2 } from "zod";
943
+ var takeoverPlanResponseSchema = z2.object({
944
+ decisionArchetype: z2.string().min(1),
945
+ plan: takeoverPlanSchema
946
+ }).strict();
947
+ function createTakeoverPlanFetcher(deps) {
948
+ return async () => {
949
+ const resp = await deps.authedFetch("/api/pdp/plan", {
950
+ method: "POST",
951
+ // FROZEN SEAM SHAPE — field set AND order are pinned byte-for-byte by
952
+ // `src/__fixtures__/takeover-plan-request.json`; the runtime-backend PR
953
+ // commits the same fixture. Change both sides together or not at all.
954
+ // Deliberately NO client-scored archetype/decision slugs: the server
955
+ // scores (spec rev 3) — the client sends vocabulary + signals only.
956
+ body: JSON.stringify({
957
+ product_id: deps.productId,
958
+ product_name: deps.productName,
959
+ // Page anatomy: ids + roles only. Anchors are host DOM selectors —
960
+ // client-side facts the server has no business receiving.
961
+ host_sections: deps.config.hostSections.map(({ id, role }) => ({ id, role })),
962
+ decision_archetypes: deps.decisionArchetypes,
963
+ behavior_summary: deps.behaviorSummary,
964
+ signals: deps.signals,
965
+ ingest_snapshot: deps.config.ingestSnapshot,
966
+ // The client's configurable wait (commitTimeoutMs, default 500):
967
+ // the server may classify inline within it (bounded inline classify).
968
+ budget_ms: deps.config.commitTimeoutMs ?? 500
969
+ })
970
+ });
971
+ if (!resp.ok) {
972
+ throw new Error(`takeover plan fetch failed: HTTP ${resp.status}`);
973
+ }
974
+ const data = await resp.json();
975
+ return takeoverPlanResponseSchema.parse(data);
976
+ };
977
+ }
978
+
979
+ // src/takeover/regionCurtain.ts
980
+ var CLASS = "syntro-takeover-curtain";
981
+ var STYLE_ATTR = "data-syntro-takeover-curtain";
982
+ var styleRefs = 0;
983
+ function acquireStyle() {
984
+ styleRefs += 1;
985
+ if (document.head.querySelector(`style[${STYLE_ATTR}]`)) return;
986
+ const styleEl = document.createElement("style");
987
+ styleEl.setAttribute(STYLE_ATTR, "");
988
+ styleEl.textContent = `.${CLASS} { opacity: 0 !important; }`;
989
+ document.head.appendChild(styleEl);
990
+ }
991
+ function releaseStyle() {
992
+ styleRefs = Math.max(0, styleRefs - 1);
993
+ if (styleRefs === 0) {
994
+ document.head.querySelector(`style[${STYLE_ATTR}]`)?.remove();
995
+ }
996
+ }
997
+ function applyRegionCurtain(region, opts = {}) {
998
+ const timeoutMs = opts.timeoutMs ?? 3e3;
999
+ acquireStyle();
1000
+ region.classList.add(CLASS);
1001
+ let lifted = false;
1002
+ const lift = () => {
1003
+ if (lifted) return;
1004
+ lifted = true;
1005
+ clearTimeout(timeoutId);
1006
+ region.classList.remove(CLASS);
1007
+ releaseStyle();
1008
+ };
1009
+ const timeoutId = setTimeout(lift, timeoutMs);
1010
+ return lift;
1011
+ }
1012
+ function applyCurtainToTargets(targets, opts = {}) {
1013
+ const lifts = targets.map((t2) => applyRegionCurtain(t2, opts));
1014
+ return () => {
1015
+ for (const lift of lifts) lift();
1016
+ };
1017
+ }
1018
+
1019
+ // src/takeover/ports.ts
1020
+ function createDomPorts(config, deps) {
1021
+ return {
1022
+ hasSignals: () => deps.signalCount > 0,
1023
+ findSection(anchor) {
1024
+ try {
1025
+ return document.querySelector(anchor);
1026
+ } catch {
1027
+ return null;
1028
+ }
1029
+ },
1030
+ measureSection: (el) => el.getBoundingClientRect().height,
1031
+ reserve(minHeightPx) {
1032
+ if (minHeightPx > 0) deps.root.style.minHeight = `${Math.round(minHeightPx)}px`;
1033
+ },
1034
+ releaseReservation() {
1035
+ deps.root.style.removeProperty("min-height");
1036
+ },
1037
+ region: () => deps.root.parentElement ?? deps.root,
1038
+ ownsNode: (el) => deps.root.contains(el),
1039
+ curtain() {
1040
+ const targets = [deps.root];
1041
+ for (const section of config.hostSections) {
1042
+ try {
1043
+ const el = document.querySelector(section.anchor);
1044
+ if (el) targets.push(el);
1045
+ } catch {
1046
+ }
1047
+ }
1048
+ const failsafe = Math.max(3e3, (config.commitTimeoutMs ?? 500) + 1e3);
1049
+ return applyCurtainToTargets(targets, { timeoutMs: failsafe });
1050
+ },
1051
+ deactivateRoot() {
1052
+ deps.root.replaceChildren();
1053
+ deps.root.style.display = "none";
1054
+ },
1055
+ fetchPlan: deps.fetchPlan,
1056
+ renderModules: deps.renderModules,
1057
+ telemetry: deps.telemetry
1058
+ };
1059
+ }
1060
+ function attachLifecycleDispose(result) {
1061
+ const onHide = () => result.dispose();
1062
+ window.addEventListener("pagehide", onHide, { once: true });
1063
+ return () => window.removeEventListener("pagehide", onHide);
1064
+ }
1065
+
737
1066
  // src/widgets/PdpSectionHeaderLit.ts
738
1067
  import { html, LitElement, nothing } from "lit";
739
1068
  function ensureSectionHeaderStyles() {
@@ -898,11 +1227,298 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-sec
898
1227
  customElements.define("syntro-pdp-section-header", PdpSectionHeaderLit);
899
1228
  }
900
1229
 
1230
+ // src/widgets/PdpSlotLit.ts
1231
+ import { html as html2, LitElement as LitElement2, nothing as nothing2 } from "lit";
1232
+ function ensureSlotStyles() {
1233
+ if (typeof document === "undefined") return;
1234
+ if (document.getElementById("syntro-pdp-slot-style")) return;
1235
+ const s4 = document.createElement("style");
1236
+ s4.id = "syntro-pdp-slot-style";
1237
+ s4.textContent = SLOT_CSS;
1238
+ document.head.appendChild(s4);
1239
+ }
1240
+ var SLOT_CSS = `
1241
+ .syntro-pdp-slot {
1242
+ --sl-primary: var(--syntro-pdp-primary, hsl(150 32% 38%));
1243
+ --sl-fg: var(--syntro-pdp-fg, hsl(35 15% 92%));
1244
+ --sl-muted: var(--syntro-pdp-muted, hsl(30 8% 55%));
1245
+ --sl-border: var(--syntro-pdp-border, hsl(30 6% 18%));
1246
+ --sl-bg-a: var(--syntro-pdp-card-bg, hsl(25 10% 11%));
1247
+ --sl-bg-b: var(--syntro-pdp-card-bg-b, hsl(25 10% 9%));
1248
+ --sl-display: var(--syntro-pdp-display, inherit);
1249
+
1250
+ position: relative;
1251
+ display: grid;
1252
+ grid-template-areas: 'stack';
1253
+ font-family: var(--syntro-pdp-sans, inherit);
1254
+ }
1255
+ .syntro-pdp-slot > .syntro-pdp-slot-mount,
1256
+ .syntro-pdp-slot > .syntro-pdp-slot-pending,
1257
+ .syntro-pdp-slot > .syntro-pdp-slot-failed {
1258
+ grid-area: stack;
1259
+ }
1260
+
1261
+ .syntro-pdp-slot-mount {
1262
+ min-height: 220px;
1263
+ }
1264
+
1265
+ /* When mutation arrived, hide the pending layer */
1266
+ .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-pending,
1267
+ .syntro-pdp-slot[data-state='failed'] .syntro-pdp-slot-pending {
1268
+ display: none;
1269
+ }
1270
+ .syntro-pdp-slot[data-state='mounted'] .syntro-pdp-slot-failed,
1271
+ .syntro-pdp-slot[data-state='pending'] .syntro-pdp-slot-failed {
1272
+ display: none;
1273
+ }
1274
+
1275
+ /* Pending \u2014 a quietly-animated waiting state. */
1276
+ .syntro-pdp-slot-pending {
1277
+ position: relative;
1278
+ border: 1px dashed var(--sl-border);
1279
+ border-radius: 22px;
1280
+ min-height: 220px;
1281
+ padding: 36px 28px;
1282
+ background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
1283
+ overflow: hidden;
1284
+ display: flex;
1285
+ align-items: center;
1286
+ justify-content: flex-start;
1287
+ }
1288
+ .syntro-pdp-slot-pending-shimmer {
1289
+ position: absolute;
1290
+ inset: 0;
1291
+ background: linear-gradient(
1292
+ 90deg,
1293
+ transparent,
1294
+ color-mix(in srgb, var(--sl-primary) 7%, transparent),
1295
+ transparent
1296
+ );
1297
+ transform: translateX(-100%);
1298
+ animation: syntro-pdp-slot-sweep 1800ms ease-in-out infinite;
1299
+ }
1300
+ .syntro-pdp-slot-pending-row {
1301
+ position: relative;
1302
+ z-index: 1;
1303
+ display: flex;
1304
+ align-items: center;
1305
+ gap: 12px;
1306
+ }
1307
+ .syntro-pdp-slot-pending-dot {
1308
+ flex: 0 0 auto;
1309
+ width: 8px;
1310
+ height: 8px;
1311
+ border-radius: 50%;
1312
+ background: var(--sl-primary);
1313
+ box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
1314
+ animation: syntro-pdp-slot-pulse 1600ms ease-in-out infinite;
1315
+ }
1316
+ .syntro-pdp-slot-pending-label {
1317
+ font-family: var(--sl-display);
1318
+ font-style: italic;
1319
+ font-size: 18px;
1320
+ font-variation-settings: 'SOFT' 70;
1321
+ color: var(--sl-muted);
1322
+ margin: 0;
1323
+ line-height: 1.4;
1324
+ }
1325
+
1326
+ /* Failed \u2014 the planner or sub-agent failed; the host page still works. */
1327
+ .syntro-pdp-slot-failed {
1328
+ border: 1px solid var(--sl-border);
1329
+ border-radius: 22px;
1330
+ min-height: 180px;
1331
+ padding: 24px 28px;
1332
+ background: linear-gradient(180deg, var(--sl-bg-a), var(--sl-bg-b));
1333
+ display: flex;
1334
+ flex-direction: column;
1335
+ justify-content: center;
1336
+ gap: 6px;
1337
+ }
1338
+ .syntro-pdp-slot-failed-title {
1339
+ font-family: var(--sl-display);
1340
+ font-style: italic;
1341
+ font-size: 17px;
1342
+ color: var(--sl-fg);
1343
+ margin: 0;
1344
+ font-variation-settings: 'SOFT' 70;
1345
+ }
1346
+ .syntro-pdp-slot-failed-body {
1347
+ color: var(--sl-muted);
1348
+ font-size: 13.5px;
1349
+ margin: 0;
1350
+ line-height: 1.5;
1351
+ }
1352
+
1353
+ @media (max-width: 640px) {
1354
+ .syntro-pdp-slot-pending,
1355
+ .syntro-pdp-slot-failed {
1356
+ border-radius: 18px;
1357
+ padding: 24px 18px;
1358
+ min-height: 180px;
1359
+ }
1360
+ .syntro-pdp-slot-pending-label {
1361
+ font-size: 15.5px;
1362
+ }
1363
+ }
1364
+
1365
+ @keyframes syntro-pdp-slot-sweep {
1366
+ 0% { transform: translateX(-100%); }
1367
+ 100% { transform: translateX(100%); }
1368
+ }
1369
+ @keyframes syntro-pdp-slot-pulse {
1370
+ 0%, 100% {
1371
+ opacity: 0.6;
1372
+ box-shadow: 0 0 0 6px color-mix(in srgb, var(--sl-primary) 14%, transparent);
1373
+ }
1374
+ 50% {
1375
+ opacity: 1;
1376
+ box-shadow: 0 0 0 8px color-mix(in srgb, var(--sl-primary) 26%, transparent);
1377
+ }
1378
+ }
1379
+ `;
1380
+ var PENDING_COPY = {
1381
+ "trending-news": "Composing this section\u2026",
1382
+ chart: "Drawing the comparison\u2026",
1383
+ qa: "Picking the questions worth answering\u2026",
1384
+ regional: "Locating you in time and place\u2026",
1385
+ "peer-feed": "Finding people like you\u2026"
1386
+ };
1387
+ var PENDING_FALLBACK = "Composing\u2026";
1388
+ var PdpSlotLit = class extends LitElement2 {
1389
+ constructor() {
1390
+ super(...arguments);
1391
+ /** DOM id the host's mutation runtime targets when appending the widget. */
1392
+ this.slotId = "";
1393
+ this.kind = "";
1394
+ this.state = "pending";
1395
+ }
1396
+ createRenderRoot() {
1397
+ return this;
1398
+ }
1399
+ connectedCallback() {
1400
+ super.connectedCallback();
1401
+ ensureSlotStyles();
1402
+ }
1403
+ willUpdate() {
1404
+ this.dataset.state = this.state;
1405
+ }
1406
+ render() {
1407
+ const pendingLabel = PENDING_COPY[this.kind] ?? PENDING_FALLBACK;
1408
+ return html2`
1409
+ <div class="syntro-pdp-slot" data-state=${this.state} data-kind=${this.kind}>
1410
+ <div
1411
+ class="syntro-pdp-slot-mount"
1412
+ id=${this.slotId || nothing2}
1413
+ data-pdp-slot=${this.kind}
1414
+ ></div>
1415
+ <div class="syntro-pdp-slot-pending" aria-hidden=${this.state !== "pending"}>
1416
+ <div class="syntro-pdp-slot-pending-shimmer" aria-hidden="true"></div>
1417
+ <div class="syntro-pdp-slot-pending-row">
1418
+ <span class="syntro-pdp-slot-pending-dot" aria-hidden="true"></span>
1419
+ <p class="syntro-pdp-slot-pending-label">${pendingLabel}</p>
1420
+ </div>
1421
+ </div>
1422
+ <div class="syntro-pdp-slot-failed" aria-hidden=${this.state !== "failed"}>
1423
+ <p class="syntro-pdp-slot-failed-title">
1424
+ Personalized view couldn't load.
1425
+ </p>
1426
+ <p class="syntro-pdp-slot-failed-body">
1427
+ The standard page still has everything you need.
1428
+ </p>
1429
+ </div>
1430
+ </div>
1431
+ `;
1432
+ }
1433
+ };
1434
+ PdpSlotLit.properties = {
1435
+ slotId: { type: String, attribute: "slot-id" },
1436
+ kind: { type: String },
1437
+ state: { type: String, reflect: true }
1438
+ };
1439
+ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-slot")) {
1440
+ customElements.define("syntro-pdp-slot", PdpSlotLit);
1441
+ }
1442
+
1443
+ // src/takeover/renderModules.ts
1444
+ function parsePlanEntry(entry) {
1445
+ const i2 = entry.indexOf(":");
1446
+ if (i2 === -1) return { kind: entry, hostSectionId: null };
1447
+ return { kind: entry.slice(0, i2), hostSectionId: entry.slice(i2 + 1) || null };
1448
+ }
1449
+ function createTakeoverModuleRenderer(deps) {
1450
+ return async (plan, onModuleFailed) => {
1451
+ const decisionArchetype = deps.getDecisionArchetype();
1452
+ const row = deps.getPresetRow(decisionArchetype) ?? {};
1453
+ const bakedWork = [];
1454
+ plan.order.forEach((entry, index) => {
1455
+ const { kind, hostSectionId } = parsePlanEntry(entry);
1456
+ const slotId = `pdp-slot-${kind}`;
1457
+ const preset = row[slotId];
1458
+ const tag = deps.resolveTag(kind, preset?.variant ?? null);
1459
+ if (!tag) {
1460
+ deps.telemetry("takeover.module_kind_unknown", { entry, kind });
1461
+ onModuleFailed(hostSectionId);
1462
+ return;
1463
+ }
1464
+ const envelope = buildPdpPlan([{ slot: slotId, preset }]);
1465
+ const task = envelope.tasks[0];
1466
+ const section = document.createElement("section");
1467
+ section.toggleAttribute("data-syntro-pdp-section", true);
1468
+ section.setAttribute("data-slot", slotId);
1469
+ section.setAttribute("data-syntro-takeover-entry", entry);
1470
+ const header = document.createElement("syntro-pdp-section-header");
1471
+ header.eyebrow = task.header.eyebrow ?? "";
1472
+ header.title = task.header.title ?? "";
1473
+ header.accent = task.header.accent ?? "";
1474
+ header.subtitle = task.header.subtitle ?? "";
1475
+ const inner = document.createElement("div");
1476
+ inner.toggleAttribute("data-syntro-pdp-section-inner", true);
1477
+ const slotEl = document.createElement("syntro-pdp-slot");
1478
+ slotEl.slotId = `syntro-takeover-${index}-${slotId}`;
1479
+ slotEl.kind = kind;
1480
+ slotEl.state = "pending";
1481
+ inner.appendChild(slotEl);
1482
+ section.append(header, inner);
1483
+ deps.root.appendChild(section);
1484
+ const fail = () => {
1485
+ if (hostSectionId) {
1486
+ section.remove();
1487
+ } else {
1488
+ slotEl.state = "failed";
1489
+ }
1490
+ deps.telemetry("takeover.module_failed", { entry, kind });
1491
+ onModuleFailed(hostSectionId);
1492
+ };
1493
+ const mountPayload = async (payload) => {
1494
+ await slotEl.updateComplete;
1495
+ const mount = slotEl.querySelector(".syntro-pdp-slot-mount");
1496
+ if (!mount) {
1497
+ fail();
1498
+ return;
1499
+ }
1500
+ mount.replaceChildren();
1501
+ const widget = document.createElement(tag);
1502
+ widget.data = payload;
1503
+ mount.appendChild(widget);
1504
+ slotEl.state = "mounted";
1505
+ };
1506
+ if (preset) {
1507
+ const data = selectPresetData(preset.kind, preset.data, decisionArchetype);
1508
+ bakedWork.push(mountPayload(data).catch(fail));
1509
+ } else {
1510
+ void deps.requestLiveModule(kind, decisionArchetype).then((payload) => payload ? mountPayload(payload) : fail()).catch(fail);
1511
+ }
1512
+ });
1513
+ await Promise.all(bakedWork);
1514
+ };
1515
+ }
1516
+
901
1517
  // src/widgets/PdpOtherProductsCarouselLit.ts
902
- import { html as html3, LitElement as LitElement3 } from "lit";
1518
+ import { html as html4, LitElement as LitElement4 } from "lit";
903
1519
 
904
1520
  // src/widgets/OtherProductTileLit.ts
905
- import { html as html2, LitElement as LitElement2 } from "lit";
1521
+ import { html as html3, LitElement as LitElement3 } from "lit";
906
1522
  var RELATIONSHIP_LABELS = {
907
1523
  discovery: "Recommended for you",
908
1524
  complement: "Pairs with this",
@@ -1045,7 +1661,7 @@ var OTHER_PRODUCT_TILE_CSS = `
1045
1661
  background: color-mix(in srgb, var(--opt-primary) 10%, transparent);
1046
1662
  }
1047
1663
  `;
1048
- var OtherProductTileLit = class extends LitElement2 {
1664
+ var OtherProductTileLit = class extends LitElement3 {
1049
1665
  constructor() {
1050
1666
  super(...arguments);
1051
1667
  this.tile = null;
@@ -1060,24 +1676,24 @@ var OtherProductTileLit = class extends LitElement2 {
1060
1676
  render() {
1061
1677
  const t2 = this.tile;
1062
1678
  if (!t2) {
1063
- return html2``;
1679
+ return html3``;
1064
1680
  }
1065
1681
  const relationshipLabel = RELATIONSHIP_LABELS[t2.relationship];
1066
1682
  const price = t2.price_cents == null ? "" : `$${(t2.price_cents / 100).toFixed(0)}`;
1067
- return html2`
1683
+ return html3`
1068
1684
  <article class="opt-card" data-relationship="${t2.relationship}">
1069
- ${t2.image_url ? html2`<div class="opt-image">
1685
+ ${t2.image_url ? html3`<div class="opt-image">
1070
1686
  <img src="${t2.image_url}" alt="${t2.name}" loading="lazy" />
1071
1687
  </div>` : null}
1072
1688
  <div class="opt-relationship" data-relationship="${t2.relationship}">
1073
- ${relationshipLabel ? html2`${relationshipLabel}` : null}
1689
+ ${relationshipLabel ? html3`${relationshipLabel}` : null}
1074
1690
  <span class="opt-relationship-type">${t2.relationship}</span>
1075
1691
  </div>
1076
1692
  <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>`)}
1693
+ ${t2.tagline ? html3`<p class="opt-tagline">${t2.tagline}</p>` : null}
1694
+ ${t2.why_blurb ? html3`<p class="opt-why">${t2.why_blurb}</p>` : null}
1695
+ ${t2.evidence_chips.length ? html3`<div class="opt-chips">
1696
+ ${t2.evidence_chips.map((c2) => html3`<span class="opt-chip">${c2.display}</span>`)}
1081
1697
  </div>` : null}
1082
1698
  <div class="opt-footer">
1083
1699
  <span class="opt-price">${price}</span>
@@ -1160,7 +1776,7 @@ syntro-pdp-other-products-carousel {
1160
1776
  }
1161
1777
  }
1162
1778
  `;
1163
- var PdpOtherProductsCarouselLit = class extends LitElement3 {
1779
+ var PdpOtherProductsCarouselLit = class extends LitElement4 {
1164
1780
  constructor() {
1165
1781
  super(...arguments);
1166
1782
  this.data = null;
@@ -1173,12 +1789,12 @@ var PdpOtherProductsCarouselLit = class extends LitElement3 {
1173
1789
  ensureCarouselStyles();
1174
1790
  }
1175
1791
  render() {
1176
- if (!this.data) return html3``;
1177
- return html3`
1792
+ if (!this.data) return html4``;
1793
+ return html4`
1178
1794
  <div class="opc-carousel">
1179
1795
  <div class="carousel" role="list">
1180
1796
  ${this.data.tiles.map(
1181
- (tile) => html3`
1797
+ (tile) => html4`
1182
1798
  <div class="opc-item" role="listitem">
1183
1799
  <syntro-pdp-other-product-tile .tile=${tile}></syntro-pdp-other-product-tile>
1184
1800
  </div>
@@ -1197,7 +1813,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-oth
1197
1813
  }
1198
1814
 
1199
1815
  // src/widgets/PdpOtherProductsGridLit.ts
1200
- import { html as html4, LitElement as LitElement4 } from "lit";
1816
+ import { html as html5, LitElement as LitElement5 } from "lit";
1201
1817
  function ensureGridStyles() {
1202
1818
  if (typeof document === "undefined") return;
1203
1819
  if (document.getElementById("syntro-pdp-other-products-grid-style")) return;
@@ -1226,7 +1842,7 @@ syntro-pdp-other-products-grid {
1226
1842
  }
1227
1843
  }
1228
1844
  `;
1229
- var PdpOtherProductsGridLit = class extends LitElement4 {
1845
+ var PdpOtherProductsGridLit = class extends LitElement5 {
1230
1846
  constructor() {
1231
1847
  super(...arguments);
1232
1848
  this.data = null;
@@ -1239,11 +1855,11 @@ var PdpOtherProductsGridLit = class extends LitElement4 {
1239
1855
  ensureGridStyles();
1240
1856
  }
1241
1857
  render() {
1242
- if (!this.data) return html4``;
1243
- return html4`
1858
+ if (!this.data) return html5``;
1859
+ return html5`
1244
1860
  <div class="grid" role="list">
1245
1861
  ${this.data.tiles.map(
1246
- (tile) => html4`
1862
+ (tile) => html5`
1247
1863
  <syntro-pdp-other-product-tile role="listitem" .tile=${tile}></syntro-pdp-other-product-tile>
1248
1864
  `
1249
1865
  )}
@@ -1750,6 +2366,9 @@ function gatherVisitorSignals() {
1750
2366
  extras: gatherExtras(runtime2, context)
1751
2367
  };
1752
2368
  }
2369
+ function countTakeoverSignals(signals) {
2370
+ return _countSignals(signals.session_metrics) + (signals.chat_excerpt ? 1 : 0);
2371
+ }
1753
2372
  var TEMPLATE_TO_TAG = {
1754
2373
  // trending-news (TrendingNewsVariant)
1755
2374
  "trending-news": "syntro-pdp-trending-news",
@@ -1794,12 +2413,21 @@ function resolveTagForMount(inst) {
1794
2413
  }
1795
2414
  return null;
1796
2415
  }
1797
- var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2416
+ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement6 {
1798
2417
  constructor() {
1799
2418
  super(...arguments);
1800
2419
  this.productId = "";
1801
2420
  this.productName = "";
1802
2421
  this.productBlurb = "";
2422
+ /**
2423
+ * Page-takeover anatomy (FEAT-1785977524), normally delivered through the
2424
+ * widget `props` below. Presence at CONNECT time latches the element into
2425
+ * takeover mode: the engine owns the root and the six-slot compose path
2426
+ * never starts. Setting it after a legacy connect is ignored (warned) —
2427
+ * flipping modes on a live element could leave both paths' DOM behind.
2428
+ */
2429
+ this.takeover = void 0;
2430
+ this._propsValue = void 0;
1803
2431
  /**
1804
2432
  * SDK runtime. Null until the mountable wires it in. We only render
1805
2433
  * the personalized surface once runtimeRef is present AND the
@@ -1840,6 +2468,48 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1840
2468
  */
1841
2469
  this._nativeSlots = /* @__PURE__ */ new Set();
1842
2470
  this._nativeHandles = /* @__PURE__ */ new Map();
2471
+ /**
2472
+ * Takeover mode latch — decided ONCE, at the element's FIRST connect, from
2473
+ * the `takeover` prop, and kept for the element's whole lifetime. While
2474
+ * true, Lit never renders into this element (see shouldUpdate): the engine
2475
+ * renders imperatively and its deactivateRoot() calls replaceChildren() on
2476
+ * this root, which would destroy Lit's child parts. The latch is one-way in
2477
+ * BOTH directions — an element that ever rendered legacy has live Lit parts
2478
+ * (engaging the engine would render next to them, then destroy them), and
2479
+ * an element the engine ever owned has no parts left for Lit to resume.
2480
+ */
2481
+ this._takeoverMode = false;
2482
+ this._takeoverModeLatched = false;
2483
+ /** The single in-flight/settled takeover run for this connected lifetime. */
2484
+ this._takeoverRun = null;
2485
+ /**
2486
+ * Settles when the previous run's dispose has fully completed. A re-run
2487
+ * (reconnect, or a synchronous move between parents) chains on this so a
2488
+ * LATE dispose from the torn-down run can never deactivate the root the
2489
+ * new run is rendering into.
2490
+ */
2491
+ this._takeoverDisposal = Promise.resolve();
2492
+ /** A previous run deactivated the root (display:none + emptied); a re-run
2493
+ * after reconnect must undo that before the engine renders again. */
2494
+ this._takeoverRanBefore = false;
2495
+ this._takeoverLateWarned = false;
2496
+ /**
2497
+ * bfcache re-entry (review F4). pagehide disposes the run
2498
+ * (attachLifecycleDispose) but a bfcache restore does NOT re-fire
2499
+ * connectedCallback — without this listener the restored page would sit on
2500
+ * the native fallback forever. `persisted` is true only for bfcache
2501
+ * restores; the normal-load pageshow is owned by the connect path. Arrow
2502
+ * function per Lit event-handler convention (stable identity for
2503
+ * add/removeEventListener).
2504
+ */
2505
+ this._onTakeoverPageShow = (event) => {
2506
+ if (!event.persisted) return;
2507
+ if (!this._takeoverMode || !this.isConnected) return;
2508
+ const config = this.takeover;
2509
+ if (!config) return;
2510
+ this._teardownTakeover();
2511
+ this._startTakeover(config);
2512
+ };
1843
2513
  /**
1844
2514
  * The scored axes from the current config pass — the SAME values
1845
2515
  * `_fireFromConfig` resolved (sport-archetype preset key + decision archetype).
@@ -1860,6 +2530,23 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1860
2530
  this._dispatchDecision({ type: "dossier-toggled", open });
1861
2531
  };
1862
2532
  }
2533
+ /**
2534
+ * Widget props (the `adaptive-product:pdp` mountable sets `el.props` before
2535
+ * appending). Mapped IMMEDIATELY in the setter — not in willUpdate — so
2536
+ * `takeover` is already on the element when connectedCallback latches the
2537
+ * mode. Absent fields leave the element's current values untouched.
2538
+ */
2539
+ get props() {
2540
+ return this._propsValue;
2541
+ }
2542
+ set props(value) {
2543
+ this._propsValue = value;
2544
+ if (!value) return;
2545
+ if (value.productId) this.productId = value.productId;
2546
+ if (value.productName) this.productName = value.productName;
2547
+ if (value.productBlurb) this.productBlurb = value.productBlurb;
2548
+ if (value.takeover) this.takeover = value.takeover;
2549
+ }
1863
2550
  _dispatchDecision(event) {
1864
2551
  const transition = transitionPdp(this._decisionState, event);
1865
2552
  this._decisionState = transition.state;
@@ -1869,6 +2556,25 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1869
2556
  return this;
1870
2557
  }
1871
2558
  connectedCallback() {
2559
+ if (!this._takeoverModeLatched) {
2560
+ this._takeoverModeLatched = true;
2561
+ this._takeoverMode = Boolean(this.takeover);
2562
+ } else if (!this._takeoverMode && this.takeover && !this._takeoverLateWarned) {
2563
+ this._takeoverLateWarned = true;
2564
+ console.warn(
2565
+ "[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."
2566
+ );
2567
+ }
2568
+ if (this._takeoverMode) {
2569
+ super.connectedCallback();
2570
+ ensureSectionLayoutStyles();
2571
+ if (typeof window !== "undefined") {
2572
+ window.removeEventListener("pageshow", this._onTakeoverPageShow);
2573
+ window.addEventListener("pageshow", this._onTakeoverPageShow);
2574
+ }
2575
+ if (this.takeover) this._startTakeover(this.takeover);
2576
+ return;
2577
+ }
1872
2578
  const reconnecting = this._decisionState.connection === "disconnected";
1873
2579
  super.connectedCallback();
1874
2580
  ensureSectionLayoutStyles();
@@ -1885,6 +2591,14 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1885
2591
  }
1886
2592
  }
1887
2593
  disconnectedCallback() {
2594
+ if (this._takeoverMode) {
2595
+ super.disconnectedCallback();
2596
+ if (typeof window !== "undefined") {
2597
+ window.removeEventListener("pageshow", this._onTakeoverPageShow);
2598
+ }
2599
+ this._teardownTakeover();
2600
+ return;
2601
+ }
1888
2602
  super.disconnectedCallback();
1889
2603
  this._navUnsub?.();
1890
2604
  this._navUnsub = null;
@@ -1892,6 +2606,16 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
1892
2606
  this._nativeHandles.clear();
1893
2607
  this._dispatchDecision({ type: "disconnected" });
1894
2608
  }
2609
+ shouldUpdate(changed) {
2610
+ if (this._takeoverMode) return false;
2611
+ if (changed.has("takeover") && this.takeover && !this._takeoverLateWarned) {
2612
+ this._takeoverLateWarned = true;
2613
+ console.warn(
2614
+ "[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)."
2615
+ );
2616
+ }
2617
+ return true;
2618
+ }
1895
2619
  willUpdate(changed) {
1896
2620
  if (changed.has("runtimeRef")) {
1897
2621
  this._syncDecisionRuntime(false);
@@ -2014,6 +2738,135 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2014
2738
  _syncDecisionPortal() {
2015
2739
  this._dispatchDecision({ type: "portal-updated", present: this._whyPortalEl() !== null });
2016
2740
  }
2741
+ // ── Takeover wiring (FEAT-1785977524) ────────────────────────────────────
2742
+ /**
2743
+ * Run the takeover engine with real ports: this element as the root,
2744
+ * `SynOS.authedFetch` as the plan/module transport and the existing slot
2745
+ * machinery as the renderer. Activation is config delivery itself: the
2746
+ * served config either carries `takeover` or it doesn't. Runs at
2747
+ * most once per connected lifetime (`_takeoverRun` latch); disconnect tears
2748
+ * it down and a reconnect re-evaluates fresh.
2749
+ */
2750
+ _startTakeover(config) {
2751
+ if (this._takeoverRun) return;
2752
+ if (!this.productId) {
2753
+ this._track("takeover.missing_product_id", {});
2754
+ console.warn(
2755
+ "[syntro-pdp] takeover requires a product id (widget props / product-id attr) \u2014 skipping takeover, native page untouched."
2756
+ );
2757
+ return;
2758
+ }
2759
+ const synos = _readSynOS();
2760
+ const authedFetch = synos?.authedFetch;
2761
+ const signals = { ...gatherVisitorSignals(), chat_excerpt: readChatExcerpt() };
2762
+ const decisionDescriptions = _readPdpDecisionArchetypes() ?? {};
2763
+ const telemetry2 = (event, props) => this._track(event, props);
2764
+ const scored = { decisionArchetype: "unknown" };
2765
+ const fetchPlan = authedFetch ? createTakeoverPlanFetcher({
2766
+ authedFetch,
2767
+ config,
2768
+ productId: this.productId,
2769
+ productName: this.productName,
2770
+ decisionArchetypes: decisionDescriptions,
2771
+ // No client-side summary exists on the takeover path (the server
2772
+ // scores); the field mirrors /api/pdp/module's for the scorer.
2773
+ behaviorSummary: "",
2774
+ signals
2775
+ }) : null;
2776
+ const run = {
2777
+ disposed: false,
2778
+ detach: null,
2779
+ result: Promise.resolve(null)
2780
+ };
2781
+ const renderModules = createTakeoverModuleRenderer({
2782
+ root: this,
2783
+ getPresetRow: (decisionArchetype) => {
2784
+ const table = _readPdpPresets()?.[this.productId];
2785
+ return table?.[decisionArchetype] ?? table?.unknown;
2786
+ },
2787
+ resolveTag: (kind, variant) => resolveTagForMount({
2788
+ slot: `pdp-slot-${kind}`,
2789
+ kind,
2790
+ variant,
2791
+ header: { eyebrow: "", title: "", accent: null, subtitle: null }
2792
+ }),
2793
+ requestLiveModule: async (kind, decisionArchetype) => {
2794
+ if (!authedFetch) return null;
2795
+ return composeModule(authedFetch, {
2796
+ productName: this.productName,
2797
+ // Guaranteed non-empty: _startTakeover gates on a missing product id.
2798
+ productId: this.productId,
2799
+ kind,
2800
+ variant: null,
2801
+ // The takeover round trip scores only the decision axis (the server
2802
+ // resolves the plan from it); the sport-archetype axis is unscored
2803
+ // on this path, so it is sent as an explicit 'unknown' — never a
2804
+ // silently-invented value.
2805
+ archetype: { slug: "unknown", description: "" },
2806
+ decisionArchetype: decisionArchetype === "unknown" ? null : {
2807
+ slug: decisionArchetype,
2808
+ description: decisionDescriptions[decisionArchetype] ?? ""
2809
+ },
2810
+ behaviorSummary: "",
2811
+ signals
2812
+ });
2813
+ },
2814
+ telemetry: telemetry2,
2815
+ getDecisionArchetype: () => scored.decisionArchetype
2816
+ });
2817
+ const ports = createDomPorts(config, {
2818
+ root: this,
2819
+ signalCount: countTakeoverSignals(signals),
2820
+ fetchPlan: fetchPlan ? async () => {
2821
+ const response = await fetchPlan();
2822
+ scored.decisionArchetype = response.decisionArchetype;
2823
+ return response;
2824
+ } : async () => {
2825
+ throw new Error("SynOS.authedFetch unavailable \u2014 cannot fetch takeover plan");
2826
+ },
2827
+ // Torn-down guard: the progressive path's dispose is a no-op (nothing
2828
+ // was detached), so its BACKGROUND render has no cancellation handle —
2829
+ // this gate is what stops a stale run from appending into a root a
2830
+ // newer run may own by then.
2831
+ renderModules: async (plan, onModuleFailed) => {
2832
+ if (run.disposed) return;
2833
+ return renderModules(plan, onModuleFailed);
2834
+ },
2835
+ telemetry: telemetry2
2836
+ });
2837
+ run.result = this._takeoverDisposal.then(() => {
2838
+ if (run.disposed) return null;
2839
+ if (this._takeoverRanBefore) {
2840
+ this.style.removeProperty("display");
2841
+ this.replaceChildren();
2842
+ }
2843
+ this._takeoverRanBefore = true;
2844
+ return runTakeover(config, ports, { commitTimeoutMs: config.commitTimeoutMs });
2845
+ }).then((result) => {
2846
+ if (!result) return null;
2847
+ telemetry2("takeover.outcome", { outcome: result.outcome });
2848
+ if (run.disposed) {
2849
+ result.dispose();
2850
+ return result;
2851
+ }
2852
+ run.detach = attachLifecycleDispose(result);
2853
+ return result;
2854
+ }).catch((err) => {
2855
+ telemetry2("takeover.run_failed", { error: String(err).slice(0, 200) });
2856
+ return null;
2857
+ });
2858
+ this._takeoverRun = run;
2859
+ }
2860
+ /** Dispose the current takeover run (idempotent). */
2861
+ _teardownTakeover() {
2862
+ const run = this._takeoverRun;
2863
+ if (!run) return;
2864
+ this._takeoverRun = null;
2865
+ run.disposed = true;
2866
+ run.detach?.();
2867
+ run.detach = null;
2868
+ this._takeoverDisposal = run.result.then((result) => result?.dispose());
2869
+ }
2017
2870
  /**
2018
2871
  * Emit a telemetry event via the runtime's track API.
2019
2872
  * Wrapped in try/catch so a broken telemetry integration never crashes the
@@ -2377,7 +3230,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2377
3230
  if (view.status === "hidden") return "";
2378
3231
  if (view.status === "loading") return this._renderWhyBoxLoading();
2379
3232
  const e2 = view.explanation;
2380
- return html5`
3233
+ return html6`
2381
3234
  <style>
2382
3235
  /* Token bridge: every color resolves from a --syntro-pdp-* var the
2383
3236
  * host (vela pages + SPA) publishes, falling back to a NEUTRAL host
@@ -2464,29 +3317,29 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2464
3317
  Shown in demo mode only — a peek under the hood at the live personalization.
2465
3318
  </div>
2466
3319
  <div data-syntro-pdp-why-archetype>
2467
- Shopping as: <strong>${e2.archetypeLabel}</strong>${e2.archetypeDesc ? html5` — ${e2.archetypeDesc}` : ""}
3320
+ Shopping as: <strong>${e2.archetypeLabel}</strong>${e2.archetypeDesc ? html6` — ${e2.archetypeDesc}` : ""}
2468
3321
  </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}”` : ""}
3322
+ ${e2.decisionLabel ? html6`<div data-syntro-pdp-why-archetype>
3323
+ What they're weighing: <strong>${e2.decisionLabel}</strong>${e2.decisionDesc ? html6` — “${e2.decisionDesc}”` : ""}
2471
3324
  </div>` : ""}
2472
- ${e2.summary ? html5`<div data-syntro-pdp-why-summary>"${e2.summary}"</div>` : ""}
3325
+ ${e2.summary ? html6`<div data-syntro-pdp-why-summary>"${e2.summary}"</div>` : ""}
2473
3326
  <div data-syntro-pdp-why-metrics>
2474
3327
  ${e2.metrics.map(
2475
- (m) => html5`<div data-syntro-pdp-why-metric>
3328
+ (m) => html6`<div data-syntro-pdp-why-metric>
2476
3329
  <span data-syntro-pdp-why-metric-value>${m.value}</span>
2477
3330
  <span data-syntro-pdp-why-metric-label>${m.label}</span>
2478
3331
  </div>`
2479
3332
  )}
2480
3333
  </div>
2481
- ${view.dossier.length ? html5`<details data-syntro-pdp-why-dossier ?open=${view.dossierOpen} @toggle=${this._onDossierToggle}>
3334
+ ${view.dossier.length ? html6`<details data-syntro-pdp-why-dossier ?open=${view.dossierOpen} @toggle=${this._onDossierToggle}>
2482
3335
  <summary>What was measured</summary>
2483
3336
  <div data-syntro-pdp-why-dossier-list>
2484
3337
  ${view.dossier.map(
2485
- (m) => html5`<div data-syntro-pdp-why-dossier-row>
3338
+ (m) => html6`<div data-syntro-pdp-why-dossier-row>
2486
3339
  <span data-syntro-pdp-why-dossier-value>${m.value}</span>
2487
3340
  <div data-syntro-pdp-why-dossier-text>
2488
3341
  <span data-syntro-pdp-why-dossier-label>${m.label}</span>
2489
- ${m.hint ? html5`<span data-syntro-pdp-why-dossier-hint>${m.hint}</span>` : ""}
3342
+ ${m.hint ? html6`<span data-syntro-pdp-why-dossier-hint>${m.hint}</span>` : ""}
2490
3343
  </div>
2491
3344
  </div>`
2492
3345
  )}
@@ -2503,7 +3356,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2503
3356
  * so the swap to the filled box is a state change, not a first appearance.
2504
3357
  */
2505
3358
  _renderWhyBoxLoading() {
2506
- return html5`
3359
+ return html6`
2507
3360
  <style>
2508
3361
  [data-syntro-pdp-why] {
2509
3362
  margin: 0; padding: 4px 0;
@@ -2543,18 +3396,18 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2543
3396
  `;
2544
3397
  }
2545
3398
  render() {
2546
- if (this._pageUnresolvable) return html5``;
3399
+ if (this._pageUnresolvable) return html6``;
2547
3400
  if (this._presetsSettled && this._decisionState.stream.status === "idle" && this._decisionState.plan.status === "empty" && !_readPdpPresets()?.[this.productId]) {
2548
- return html5``;
3401
+ return html6``;
2549
3402
  }
2550
3403
  const skeletonStyles = _SyntroPdpLit._skeletonStyles;
2551
3404
  const view = selectPdpView(this._decisionState);
2552
3405
  if (view.layout === "skeleton") {
2553
- return html5`
3406
+ return html6`
2554
3407
  ${skeletonStyles}
2555
3408
  <div data-syntro-pdp-root data-state="pending" data-syntro-pdp-skeleton>
2556
3409
  ${[0, 1, 2].map(
2557
- (i2) => html5`
3410
+ (i2) => html6`
2558
3411
  <section
2559
3412
  data-syntro-pdp-skeleton-section
2560
3413
  style="animation-delay: ${i2 * 0.15}s"
@@ -2571,7 +3424,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2571
3424
  </div>
2572
3425
  `;
2573
3426
  }
2574
- return html5`
3427
+ return html6`
2575
3428
  ${skeletonStyles}
2576
3429
  <div data-syntro-pdp-root data-state=${view.rootState}>
2577
3430
  ${view.whyBox.destination === "inline" ? this._renderWhyBox(view.whyBox) : ""}
@@ -2579,7 +3432,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2579
3432
  if (!slot.visible) return "";
2580
3433
  const task = slot.task;
2581
3434
  if (this._nativeSlots.has(task.slot)) return "";
2582
- return html5`
3435
+ return html6`
2583
3436
  <section data-syntro-pdp-section data-slot=${task.slot}>
2584
3437
  <syntro-pdp-section-header
2585
3438
  .eyebrow=${task.header.eyebrow}
@@ -2603,7 +3456,7 @@ var _SyntroPdpLit = class _SyntroPdpLit extends LitElement5 {
2603
3456
  * change) without ever touching the imperatively-managed
2604
3457
  * slot subtree. See adversarial-review failure mode #2.
2605
3458
  */
2606
- slot.showLoading ? html5`<div data-syntro-pdp-slot-shimmer>
3459
+ slot.showLoading ? html6`<div data-syntro-pdp-slot-shimmer>
2607
3460
  <div data-syntro-pdp-skeleton-body></div>
2608
3461
  </div>` : ""}
2609
3462
  </div>
@@ -2619,6 +3472,7 @@ _SyntroPdpLit.properties = {
2619
3472
  productName: { type: String, attribute: "product-name" },
2620
3473
  productBlurb: { type: String, attribute: "product-blurb" },
2621
3474
  runtimeRef: { attribute: false },
3475
+ takeover: { attribute: false },
2622
3476
  _decisionState: { state: true },
2623
3477
  _pageUnresolvable: { state: true },
2624
3478
  _presetsSettled: { state: true }
@@ -2630,7 +3484,7 @@ _SyntroPdpLit.properties = {
2630
3484
  * (see `ensureSectionLayoutStyles`), not here, so they're emitted once
2631
3485
  * per document rather than once per `<syntro-pdp>` instance.
2632
3486
  */
2633
- _SyntroPdpLit._skeletonStyles = html5`
3487
+ _SyntroPdpLit._skeletonStyles = html6`
2634
3488
  <style>
2635
3489
  [data-syntro-pdp-skeleton] {
2636
3490
  display: flex;
@@ -3033,6 +3887,10 @@ async function flush() {
3033
3887
  pending.clear();
3034
3888
  return;
3035
3889
  }
3890
+ if (typeof document !== "undefined" && document.querySelector("syntro-pdp")) {
3891
+ pending.clear();
3892
+ return;
3893
+ }
3036
3894
  const ids = [...pending];
3037
3895
  pending.clear();
3038
3896
  for (const id of ids) await onProductAppeared(id);
@@ -3110,7 +3968,7 @@ function startNativeSlotWatcher() {
3110
3968
  }
3111
3969
 
3112
3970
  // src/widgets/ProductCardLit.ts
3113
- import { html as html7, LitElement as LitElement7, nothing as nothing3 } from "lit";
3971
+ import { html as html8, LitElement as LitElement8, nothing as nothing4 } from "lit";
3114
3972
  import { styleMap } from "lit/directives/style-map.js";
3115
3973
 
3116
3974
  // src/bind/dom-selector.ts
@@ -4138,7 +4996,7 @@ cancel_fn = function() {
4138
4996
  };
4139
4997
 
4140
4998
  // src/widgets/VariantPanelLit.ts
4141
- import { html as html6, LitElement as LitElement6, nothing as nothing2 } from "lit";
4999
+ import { html as html7, LitElement as LitElement7, nothing as nothing3 } from "lit";
4142
5000
  var PANEL_CSS = `
4143
5001
  syntro-variant-panel {
4144
5002
  display: grid;
@@ -4370,7 +5228,7 @@ var PANEL_CSS = `
4370
5228
  .svp-live { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; overflow: hidden; }
4371
5229
  `;
4372
5230
  var _VariantPanelLit_instances, healthProbe_fn;
4373
- var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
5231
+ var _VariantPanelLit = class _VariantPanelLit extends LitElement7 {
4374
5232
  constructor() {
4375
5233
  super();
4376
5234
  __privateAdd(this, _VariantPanelLit_instances);
@@ -4472,7 +5330,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4472
5330
  }
4473
5331
  render() {
4474
5332
  if (this.state === "error") {
4475
- return html6`
5333
+ return html7`
4476
5334
  <div class="svp-error-block" data-error-block>
4477
5335
  <div>Couldn't load options. ${this.error ?? ""}</div>
4478
5336
  <button class="svp-retry-btn" data-retry-button @click=${this._onRetry}>Try again</button>
@@ -4480,7 +5338,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4480
5338
  `;
4481
5339
  }
4482
5340
  if (this.state === "loading" || !this.payload) {
4483
- return html6`
5341
+ return html7`
4484
5342
  <div data-loading-skeleton>
4485
5343
  <div class="svp-skeleton"></div>
4486
5344
  <div class="svp-skeleton"></div>
@@ -4493,26 +5351,26 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4493
5351
  const compareAt = matching?.compare_at_price ?? null;
4494
5352
  const singleVariant = this.payload.attributes.length === 0;
4495
5353
  const heroSrc = this._heroSrc();
4496
- const backBtn = html6`<button
5354
+ const backBtn = html7`<button
4497
5355
  class="svp-back-btn"
4498
5356
  data-back-button
4499
5357
  @click=${this._onBack}
4500
5358
  aria-label="Back"
4501
5359
  >‹ Back</button>`;
4502
- return html6`
5360
+ return html7`
4503
5361
  <div class="svp-image-col" data-image-col>
4504
- ${heroSrc ? html6`<img
5362
+ ${heroSrc ? html7`<img
4505
5363
  class="svp-image"
4506
5364
  data-variant-image
4507
5365
  src=${heroSrc}
4508
5366
  alt=${this.productImage?.alt ?? ""}
4509
5367
  loading="lazy"
4510
- />` : nothing2}
5368
+ />` : nothing3}
4511
5369
  </div>
4512
5370
  <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}
5371
+ ${this.productTitle ? html7`<div class="svp-product-title" data-product-title data-critical-text>${this.productTitle}</div>` : nothing3}
4514
5372
  <div class="svp-attributes-scroll" data-attributes-scroll data-clip-ok>
4515
- ${singleVariant ? html6`<div class="svp-single-variant-note" data-single-variant-note>
5373
+ ${singleVariant ? html7`<div class="svp-single-variant-note" data-single-variant-note>
4516
5374
  Just one option — ready to add.
4517
5375
  </div>` : this.payload.attributes.map((attr) => this._renderAttributeRow(attr))}
4518
5376
  </div>
@@ -4527,23 +5385,23 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4527
5385
  ${// Short label: "Add · $64" (the price commits HERE — the card's
4528
5386
  // front face carries no price; round-3 feedback shortened this
4529
5387
  // 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`}
5388
+ ctaPrice != null ? html7`Add ${compareAt ? html7`<span class="svp-compare">$${compareAt.toFixed(2)}</span>` : nothing3}· $${ctaPrice.toFixed(2)}` : html7`Add to cart`}
4531
5389
  </button>
4532
5390
  ${backBtn}
4533
5391
  </div>
4534
5392
  <div class="svp-live" data-live data-clip-ok aria-live="polite">
4535
- ${this.productTitle ? `Showing options for ${this.productTitle}` : nothing2}
5393
+ ${this.productTitle ? `Showing options for ${this.productTitle}` : nothing3}
4536
5394
  </div>
4537
5395
  </div>
4538
5396
  `;
4539
5397
  }
4540
5398
  _renderAttributeRow(attr) {
4541
5399
  const oosVisible = this._hasAnyOOSForAttribute(attr);
4542
- return html6`
5400
+ return html7`
4543
5401
  <div class="svp-attribute-row" data-attribute-row data-attribute-key=${attr.key}>
4544
5402
  <div class="svp-attribute-label" data-attribute-label id=${`attrlabel-${attr.key}`}>${attr.label}</div>
4545
5403
  ${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}
5404
+ ${oosVisible ? html7`<div class="svp-oos-microcopy" data-out-of-stock-microcopy>Out of stock for one or more options</div>` : nothing3}
4547
5405
  </div>
4548
5406
  `;
4549
5407
  }
@@ -4552,12 +5410,12 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4552
5410
  }
4553
5411
  _renderPillRow(attr) {
4554
5412
  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}`}>
5413
+ return html7`
5414
+ <div class="svp-pill-row" data-segmented=${segmented ? "" : nothing3} data-scroll=${this._isScrollTier(attr) ? "" : nothing3} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
4557
5415
  ${attr.values.map((v) => {
4558
5416
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4559
5417
  const checked = this._selection[attr.key] === v.id;
4560
- return html6`<button
5418
+ return html7`<button
4561
5419
  class="svp-pill"
4562
5420
  data-pill
4563
5421
  data-attribute-key=${attr.key}
@@ -4575,14 +5433,14 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4575
5433
  _renderSwatchRow(attr) {
4576
5434
  const selectedValueId = this._selection[attr.key];
4577
5435
  const selectedLabel = attr.values.find((v) => v.id === selectedValueId)?.label ?? "";
4578
- return html6`
5436
+ return html7`
4579
5437
  <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}`}>
5438
+ <div class="svp-swatch-row" data-scroll=${this._isScrollTier(attr) ? "" : nothing3} role="radiogroup" aria-labelledby=${`attrlabel-${attr.key}`}>
4581
5439
  ${attr.values.map((v) => {
4582
5440
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4583
5441
  const checked = this._selection[attr.key] === v.id;
4584
5442
  const color = v.swatch?.kind === "color" ? v.swatch.value : "transparent";
4585
- return html6`<button
5443
+ return html7`<button
4586
5444
  class="svp-swatch-pill"
4587
5445
  data-pill
4588
5446
  data-swatch-dot
@@ -4636,8 +5494,8 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4636
5494
  const filter = (this._axisFilter[attr.key] ?? "").trim().toLowerCase();
4637
5495
  const filtered = filter ? attr.values.filter((v) => v.label.toLowerCase().includes(filter)) : attr.values;
4638
5496
  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`
5497
+ const dot = (v) => v?.swatch?.kind === "color" ? html7`<span class="svp-swatch-dot" style="background-color: ${v.swatch.value}"></span>` : nothing3;
5498
+ return html7`
4641
5499
  <div
4642
5500
  class="svp-collapse"
4643
5501
  data-collapsed-axis
@@ -4667,7 +5525,7 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4667
5525
  <span class="svp-collapse-value">${selected ? selected.label : `Choose ${attr.label.toLowerCase()}`}</span>
4668
5526
  <span class="svp-collapse-caret">${expanded ? "\u25B4" : "\u25BE"}</span>
4669
5527
  </button>
4670
- ${expanded ? html6`
5528
+ ${expanded ? html7`
4671
5529
  <div
4672
5530
  class="svp-collapse-list"
4673
5531
  data-clip-ok
@@ -4675,18 +5533,18 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4675
5533
  role="listbox"
4676
5534
  aria-labelledby=${`attrlabel-${attr.key}`}
4677
5535
  >
4678
- ${showFilter ? html6`<input
5536
+ ${showFilter ? html7`<input
4679
5537
  class="svp-collapse-filter"
4680
5538
  data-collapse-filter
4681
5539
  type="text"
4682
5540
  placeholder=${`Filter ${attr.label.toLowerCase()}\u2026`}
4683
5541
  .value=${this._axisFilter[attr.key] ?? ""}
4684
5542
  @input=${(e2) => this._onAxisFilterInput(attr.key, e2)}
4685
- />` : nothing2}
5543
+ />` : nothing3}
4686
5544
  ${filtered.map((v) => {
4687
5545
  const disabled2 = this._isValueDisabled(attr.key, v.id);
4688
5546
  const isSelected = this._selection[attr.key] === v.id;
4689
- return html6`<button
5547
+ return html7`<button
4690
5548
  class="svp-collapse-option"
4691
5549
  data-collapse-option
4692
5550
  data-value-id=${v.id}
@@ -4697,8 +5555,8 @@ var _VariantPanelLit = class _VariantPanelLit extends LitElement6 {
4697
5555
  @click=${() => this._onCollapsedSelect(attr.key, v.id)}
4698
5556
  >${dot(v)}<span class="svp-collapse-value">${v.label}</span></button>`;
4699
5557
  })}
4700
- ${filtered.length === 0 ? html6`<div class="svp-collapse-empty">No matches</div>` : nothing2}
4701
- </div>` : nothing2}
5558
+ ${filtered.length === 0 ? html7`<div class="svp-collapse-empty">No matches</div>` : nothing3}
5559
+ </div>` : nothing3}
4702
5560
  </div>
4703
5561
  `;
4704
5562
  }
@@ -4823,7 +5681,7 @@ var CARD_FLIP_CSS = `
4823
5681
  }
4824
5682
  `;
4825
5683
  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 {
5684
+ var ProductCardLit = class extends LitElement8 {
4827
5685
  constructor() {
4828
5686
  super(...arguments);
4829
5687
  __privateAdd(this, _ProductCardLit_instances);
@@ -4925,9 +5783,9 @@ var ProductCardLit = class extends LitElement7 {
4925
5783
  super.disconnectedCallback();
4926
5784
  }
4927
5785
  render() {
4928
- if (this.validationError || !this.props) return html7``;
5786
+ if (this.validationError || !this.props) return html8``;
4929
5787
  const parsed = cardSchema.safeParse(this.props);
4930
- if (!parsed.success) return html7``;
5788
+ if (!parsed.success) return html8``;
4931
5789
  const density = this._device === "mobile" ? "compact" : parsed.data.density;
4932
5790
  const { product, visibleFacts } = parsed.data;
4933
5791
  const resolved = this.resolved[product.id];
@@ -4954,7 +5812,7 @@ var ProductCardLit = class extends LitElement7 {
4954
5812
  onPrimaryCtaClick,
4955
5813
  !view.primaryCta.disabled
4956
5814
  );
4957
- const backFace = html7`<syntro-variant-panel
5815
+ const backFace = html8`<syntro-variant-panel
4958
5816
  .payload=${view.panel.payload}
4959
5817
  .productTitle=${product.name ?? ""}
4960
5818
  .productImage=${product.image ? { src: product.image.src, alt: product.image.alt } : null}
@@ -4965,27 +5823,27 @@ var ProductCardLit = class extends LitElement7 {
4965
5823
  @variant-panel-retry=${this._onVariantRetry}
4966
5824
  @variant-panel-selection-change=${this._onVariantSelectionChange}
4967
5825
  ></syntro-variant-panel>
4968
- ${view.addError ? html7`<div data-add-to-cart-error>${view.addError}</div>` : nothing3}`;
5826
+ ${view.addError ? html8`<div data-add-to-cart-error>${view.addError}</div>` : nothing4}`;
4969
5827
  const backView = view.face === "back" && view.flipAnimating ? (
4970
5828
  // Mid-flip: both faces coexist inside a preserve-3d container. The
4971
5829
  // front turns away (inert + aria-hidden) while the back turns in.
4972
- html7`<div data-card-flip @animationend=${__privateGet(this, _onFlipAnimationEnd)}>
5830
+ html8`<div data-card-flip @animationend=${__privateGet(this, _onFlipAnimationEnd)}>
4973
5831
  <div data-face="front" aria-hidden="true" inert>${frontContent}</div>
4974
5832
  <div data-face="back">${backFace}</div>
4975
5833
  </div>`
4976
5834
  ) : view.face === "back" ? (
4977
5835
  // Settled back: flat, untransformed — no flip container, no perspective.
4978
- html7`<div data-face="back">${backFace}</div>`
4979
- ) : html7`<div data-face="front">
5836
+ html8`<div data-face="back">${backFace}</div>`
5837
+ ) : html8`<div data-face="front">
4980
5838
  ${frontContent}
4981
- ${view.addError ? html7`<div data-add-to-cart-error>${view.addError}</div>` : nothing3}
5839
+ ${view.addError ? html8`<div data-add-to-cart-error>${view.addError}</div>` : nothing4}
4982
5840
  </div>`;
4983
- return html7`
5841
+ return html8`
4984
5842
  <article
4985
5843
  class="sc-product-card"
4986
5844
  data-active-face=${view.face}
4987
5845
  data-density=${density}
4988
- data-labels=${product.labels ? JSON.stringify(product.labels) : nothing3}
5846
+ data-labels=${product.labels ? JSON.stringify(product.labels) : nothing4}
4989
5847
  style=${styleMap(articleStyles)}
4990
5848
  >
4991
5849
  ${backView}
@@ -5515,7 +6373,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5515
6373
  maxWidth: "100%",
5516
6374
  flexShrink: "1"
5517
6375
  };
5518
- const ctaRow = html7`<div class="sc-product-card__ctas" style=${styleMap(ctasStyles)}>
6376
+ const ctaRow = html8`<div class="sc-product-card__ctas" style=${styleMap(ctasStyles)}>
5519
6377
  ${ctas.map((c2, i2) => {
5520
6378
  const disabled2 = c2.actionId === "add_to_cart" && !commerceAvailable;
5521
6379
  const ctaStyles = {
@@ -5523,13 +6381,13 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5523
6381
  ...disabled2 ? { opacity: "0.5", "pointer-events": "none", cursor: "not-allowed" } : {}
5524
6382
  };
5525
6383
  const ctaLabel = c2.label;
5526
- return html7`<a
6384
+ return html8`<a
5527
6385
  class="sc-product-card__cta"
5528
6386
  data-product-cta=${i2 === 0 ? "primary" : "secondary"}
5529
6387
  data-critical-text
5530
6388
  data-variant=${c2.variant}
5531
- data-disabled=${disabled2 ? "true" : nothing3}
5532
- aria-disabled=${disabled2 ? "true" : nothing3}
6389
+ data-disabled=${disabled2 ? "true" : nothing4}
6390
+ aria-disabled=${disabled2 ? "true" : nothing4}
5533
6391
  href=${c2.actionId === "add_to_cart" ? "#" : c2.href ?? "#"}
5534
6392
  target=${c2.target}
5535
6393
  rel=${c2.target === "_blank" ? "noopener noreferrer" : ""}
@@ -5546,7 +6404,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5546
6404
  >`;
5547
6405
  })}
5548
6406
  </div>`;
5549
- const ratingOverlay = overlay && product.rating && isVisible("rating") ? html7`<div
6407
+ const ratingOverlay = overlay && product.rating && isVisible("rating") ? html8`<div
5550
6408
  class="sc-product-card__rating sc-product-card__rating--overlay"
5551
6409
  data-product-rating
5552
6410
  data-rating-value=${product.rating.value}
@@ -5561,20 +6419,20 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5561
6419
  style=${styleMap({ opacity: "0.8", marginLeft: "0.15rem", display: "var(--sc-card-rating-count-display, inline)" })}
5562
6420
  >(${product.rating.count.toLocaleString()})</span
5563
6421
  >
5564
- </div>` : nothing3;
5565
- const priceOverlay = overlay && isVisible("price") && (product.price || product.salePrice) ? html7`<div
6422
+ </div>` : nothing4;
6423
+ const priceOverlay = overlay && isVisible("price") && (product.price || product.salePrice) ? html8`<div
5566
6424
  class="sc-product-card__price sc-product-card__price--overlay"
5567
6425
  data-product-price
5568
6426
  style=${styleMap(overlayPriceStyles)}
5569
6427
  >
5570
6428
  <span
5571
6429
  class="sc-product-card__amount"
5572
- data-product-price-sale=${hasSalePrice ? "true" : nothing3}
6430
+ data-product-price-sale=${hasSalePrice ? "true" : nothing4}
5573
6431
  data-critical-text
5574
6432
  >${activePriceText}</span
5575
6433
  >
5576
- </div>` : nothing3;
5577
- const mediaBlock = overlay ? html7`<div class="sc-product-card__media" style=${styleMap(mediaWrapperStyles)}>
6434
+ </div>` : nothing4;
6435
+ const mediaBlock = overlay ? html8`<div class="sc-product-card__media" style=${styleMap(mediaWrapperStyles)}>
5578
6436
  <img
5579
6437
  class="sc-product-card__image"
5580
6438
  data-product-image
@@ -5585,7 +6443,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5585
6443
  style=${styleMap(overlayImgStyles)}
5586
6444
  />
5587
6445
  ${ratingOverlay}${priceOverlay}
5588
- </div>` : html7`<img
6446
+ </div>` : html8`<img
5589
6447
  class="sc-product-card__image"
5590
6448
  data-product-image
5591
6449
  src=${imgSrc}
@@ -5594,7 +6452,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5594
6452
  @error=${onImageError}
5595
6453
  style=${styleMap(imageStyles)}
5596
6454
  />`;
5597
- return html7`
6455
+ return html8`
5598
6456
  <div class="sc-product-card__grid" data-product-card-grid style=${styleMap(rootGridStyles)}>
5599
6457
  ${mediaBlock}
5600
6458
  <div class="sc-product-card__content" style=${styleMap(contentColStyles)}>
@@ -5658,7 +6516,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5658
6516
  // the product page reachable.
5659
6517
  (() => {
5660
6518
  const navCta = ctas.find((c2) => c2.href);
5661
- return navCta?.href ? html7`<a
6519
+ return navCta?.href ? html8`<a
5662
6520
  data-product-name-link
5663
6521
  href=${navCta.href}
5664
6522
  target=${navCta.target ?? "_self"}
@@ -5668,7 +6526,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5668
6526
  })()}</h3>
5669
6527
  ${// On compact the rating renders as an image OVERLAY pill (item 2),
5670
6528
  // so it is omitted from the header identity row here.
5671
- !overlay && product.rating && isVisible("rating") ? html7`<div
6529
+ !overlay && product.rating && isVisible("rating") ? html8`<div
5672
6530
  class="sc-product-card__rating"
5673
6531
  data-product-rating
5674
6532
  data-rating-value=${product.rating.value}
@@ -5683,9 +6541,9 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5683
6541
  <span class="sc-product-card__rating-stars" style="color: #f5a623;">★</span>
5684
6542
  <span style=${styleMap({ marginLeft: "0.2rem", fontWeight: "600" })}>${product.rating.value}</span>
5685
6543
  <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}
6544
+ </div>` : nothing4}
5687
6545
  </div>
5688
- ${(product.tagline || product.framing) && isVisible("tagline") ? html7`<p
6546
+ ${(product.tagline || product.framing) && isVisible("tagline") ? html8`<p
5689
6547
  class="sc-product-card__tagline"
5690
6548
  data-product-tagline
5691
6549
  style=${styleMap({
@@ -5719,7 +6577,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5719
6577
  minWidth: "0",
5720
6578
  overflowWrap: "anywhere"
5721
6579
  })}
5722
- >${product.tagline || product.framing}</p>` : nothing3}
6580
+ >${product.tagline || product.framing}</p>` : nothing4}
5723
6581
  </header>
5724
6582
  <div
5725
6583
  class="sc-product-card__body"
@@ -5733,36 +6591,36 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5733
6591
  >
5734
6592
  ${factOrder.map((key) => {
5735
6593
  if (key === "price") {
5736
- if (overlay) return nothing3;
5737
- if (!isVisible("price") || !product.price && !product.salePrice) return nothing3;
5738
- return html7`<div
6594
+ if (overlay) return nothing4;
6595
+ if (!isVisible("price") || !product.price && !product.salePrice) return nothing4;
6596
+ return html8`<div
5739
6597
  class="sc-product-card__price"
5740
6598
  data-product-price
5741
6599
  style=${styleMap(priceBlockStyles)}
5742
6600
  >
5743
- ${hasSalePrice && product.price ? html7`<span
6601
+ ${hasSalePrice && product.price ? html8`<span
5744
6602
  class="sc-product-card__amount-original"
5745
6603
  data-product-price-original
5746
6604
  style=${styleMap(priceOriginalStyles)}
5747
6605
  >${product.price.amount}</span
5748
- >` : nothing3}
6606
+ >` : nothing4}
5749
6607
  <span
5750
6608
  class="sc-product-card__amount"
5751
- data-product-price-sale=${hasSalePrice ? "true" : nothing3}
6609
+ data-product-price-sale=${hasSalePrice ? "true" : nothing4}
5752
6610
  data-critical-text
5753
6611
  style=${styleMap(priceSaleStyles)}
5754
6612
  >${activePriceText}</span
5755
6613
  >
5756
- ${activeCadence ? html7`<span
6614
+ ${activeCadence ? html8`<span
5757
6615
  class="sc-product-card__cadence"
5758
6616
  style=${styleMap(priceCadenceStyles)}
5759
6617
  >${activeCadence}</span
5760
- >` : nothing3}
6618
+ >` : nothing4}
5761
6619
  </div>`;
5762
6620
  }
5763
6621
  if (key === "availability") {
5764
- if (!isVisible("availability") || !product.availability) return nothing3;
5765
- return html7`<span
6622
+ if (!isVisible("availability") || !product.availability) return nothing4;
6623
+ return html8`<span
5766
6624
  class="sc-product-card__availability"
5767
6625
  data-product-availability
5768
6626
  data-availability=${product.availability}
@@ -5771,8 +6629,8 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5771
6629
  >`;
5772
6630
  }
5773
6631
  if (key === "badge") {
5774
- if (!isVisible("badge") || !product.badge) return nothing3;
5775
- return html7`<span
6632
+ if (!isVisible("badge") || !product.badge) return nothing4;
6633
+ return html8`<span
5776
6634
  class="sc-product-card__badge"
5777
6635
  data-product-badge
5778
6636
  data-tone=${product.badge.tone}
@@ -5788,12 +6646,12 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5788
6646
  >`;
5789
6647
  }
5790
6648
  if (key === "specs") {
5791
- if (!isVisible("specs") || specGroups.length === 0) return nothing3;
6649
+ if (!isVisible("specs") || specGroups.length === 0) return nothing4;
5792
6650
  if (density === "compact") {
5793
6651
  const allRows = specGroups.flatMap((g) => g.rows);
5794
6652
  const highlights = allRows.slice(0, 4);
5795
- if (highlights.length === 0) return nothing3;
5796
- return html7`<div
6653
+ if (highlights.length === 0) return nothing4;
6654
+ return html8`<div
5797
6655
  class="sc-product-card__specs"
5798
6656
  data-density="compact"
5799
6657
  data-clip-ok
@@ -5803,7 +6661,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5803
6661
  style=${styleMap(specChipRowStyles)}
5804
6662
  >
5805
6663
  ${highlights.map(
5806
- (r) => html7`<span
6664
+ (r) => html8`<span
5807
6665
  data-spec-chip
5808
6666
  style=${styleMap(specChipStyles)}
5809
6667
  ><span style="font-weight: 600;">${r.name}</span
@@ -5812,9 +6670,9 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5812
6670
  )}
5813
6671
  </div>`;
5814
6672
  }
5815
- return html7`<div class="sc-product-card__specs" style=${styleMap(specsContainerStyles)}>
6673
+ return html8`<div class="sc-product-card__specs" style=${styleMap(specsContainerStyles)}>
5816
6674
  ${specGroups.map(
5817
- (g) => html7`<section
6675
+ (g) => html8`<section
5818
6676
  class="sc-product-card__spec-section"
5819
6677
  data-spec-section=${g.section}
5820
6678
  style=${styleMap(specGroupStyles)}
@@ -5832,7 +6690,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5832
6690
  style=${styleMap(specRowsStyles)}
5833
6691
  >
5834
6692
  ${g.rows.map(
5835
- (r) => html7`<li
6693
+ (r) => html8`<li
5836
6694
  data-spec-row
5837
6695
  data-spec-chip
5838
6696
  data-attribute-emphasis=${r.emphasis ? "true" : "false"}
@@ -5857,12 +6715,12 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5857
6715
  style=${styleMap(specValueStyles)}
5858
6716
  >${r.value}</span
5859
6717
  >
5860
- ${r.unit ? html7`<span
6718
+ ${r.unit ? html8`<span
5861
6719
  class="sc-product-card__spec-unit"
5862
6720
  data-spec-unit
5863
6721
  style="opacity: 0.72;"
5864
6722
  >${r.unit}</span
5865
- >` : nothing3}
6723
+ >` : nothing4}
5866
6724
  </li>`
5867
6725
  )}
5868
6726
  </ul>
@@ -5871,8 +6729,8 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5871
6729
  </div>`;
5872
6730
  }
5873
6731
  if (key === "framing") {
5874
- if (!isVisible("framing") || !showFraming) return nothing3;
5875
- return html7`<p
6732
+ if (!isVisible("framing") || !showFraming) return nothing4;
6733
+ return html8`<p
5876
6734
  class="sc-product-card__framing"
5877
6735
  style=${styleMap({
5878
6736
  margin: "0",
@@ -5885,7 +6743,7 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5885
6743
  .innerHTML=${sanitizeHtml(product.framing ?? "")}
5886
6744
  ></p>`;
5887
6745
  }
5888
- return nothing3;
6746
+ return nothing4;
5889
6747
  })}
5890
6748
  </div>
5891
6749
  </div>
@@ -5895,11 +6753,11 @@ function renderProductCardInner(product, density, resolved, visibleFacts, ctas,
5895
6753
  }
5896
6754
  function renderProductCard(product, density, resolved, visibleFacts) {
5897
6755
  const articleStyles = _buildArticleStyles(density);
5898
- return html7`
6756
+ return html8`
5899
6757
  <article
5900
6758
  class="sc-product-card"
5901
6759
  data-density=${density}
5902
- data-labels=${product.labels ? JSON.stringify(product.labels) : nothing3}
6760
+ data-labels=${product.labels ? JSON.stringify(product.labels) : nothing4}
5903
6761
  style=${styleMap(articleStyles)}
5904
6762
  >
5905
6763
  ${renderProductCardInner(product, density, resolved, visibleFacts, product.ctas, void 0)}
@@ -5913,9 +6771,9 @@ function onImageError(e2) {
5913
6771
  }
5914
6772
 
5915
6773
  // src/widgets/ProductComparisonLit.ts
5916
- import { html as html8, LitElement as LitElement8, nothing as nothing4 } from "lit";
6774
+ import { html as html9, LitElement as LitElement9, nothing as nothing5 } from "lit";
5917
6775
  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 {
6776
+ var ProductComparisonLit = class extends LitElement9 {
5919
6777
  constructor() {
5920
6778
  super();
5921
6779
  __privateAdd(this, _ProductComparisonLit_instances);
@@ -5957,7 +6815,7 @@ var ProductComparisonLit = class extends LitElement8 {
5957
6815
  __privateGet(this, _controller2)?.destroy();
5958
6816
  }
5959
6817
  render() {
5960
- if (this.validationError || !__privateGet(this, _parsed)) return html8``;
6818
+ if (this.validationError || !__privateGet(this, _parsed)) return html9``;
5961
6819
  const parsed = __privateGet(this, _parsed);
5962
6820
  const bodyStyle = (
5963
6821
  // touch-action:pan-y is REQUIRED for the deck swipe-to-cycle to work over a
@@ -5971,7 +6829,7 @@ var ProductComparisonLit = class extends LitElement8 {
5971
6829
  // rows and hands horizontal drags back to the deck's swipe handler.
5972
6830
  "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
6831
  );
5974
- return html8`
6832
+ return html9`
5975
6833
  <section
5976
6834
  class="sc-product-comparison"
5977
6835
  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 +6864,11 @@ var ProductComparisonLit = class extends LitElement8 {
6006
6864
  }
6007
6865
  }
6008
6866
  </style>
6009
- ${parsed.heading ? html8`<h2
6867
+ ${parsed.heading ? html9`<h2
6010
6868
  class="sc-product-comparison__heading"
6011
6869
  data-comparison-heading
6012
6870
  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}
6871
+ >${parsed.heading}</h2>` : nothing5}
6014
6872
  <div
6015
6873
  class="sc-product-comparison__scroll-wrap"
6016
6874
  style="position:relative;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;"
@@ -6031,7 +6889,7 @@ var ProductComparisonLit = class extends LitElement8 {
6031
6889
  // it's in-theme; pointer-events:none so it never blocks scroll/taps;
6032
6890
  // gated on scrollFade (content below the current scroll) so it hides
6033
6891
  // 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}
6892
+ this.scrollFade ? html9`<span class="sc-product-comparison__scroll-cue" aria-hidden="true"></span>` : nothing5}
6035
6893
  </div>
6036
6894
  ${__privateMethod(this, _ProductComparisonLit_instances, renderDiveDeeper_fn).call(this, parsed)}
6037
6895
  </section>
@@ -6116,9 +6974,9 @@ startBind_fn2 = function() {
6116
6974
  * chat-bar mountable turns it into a user turn.
6117
6975
  */
6118
6976
  renderDiveDeeper_fn = function(parsed) {
6119
- if (parsed.products.length < 2) return nothing4;
6977
+ if (parsed.products.length < 2) return nothing5;
6120
6978
  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
6979
+ return html9`<button
6122
6980
  type="button"
6123
6981
  class="sc-product-comparison__dive-deeper"
6124
6982
  data-dive-deeper
@@ -6197,7 +7055,7 @@ renderMatrix_fn = function(products, rows) {
6197
7055
  const colHeadStyle = "display:block;padding:6px 3px;text-align:left;font-weight:600;min-width:0;";
6198
7056
  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
7057
  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`
7058
+ return html9`
6201
7059
  <div
6202
7060
  class="sc-product-comparison__matrix"
6203
7061
  data-comparison-matrix
@@ -6231,7 +7089,7 @@ renderMatrix_fn = function(products, rows) {
6231
7089
  const showRatingPill = !compactHeaders && p.rating;
6232
7090
  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
7091
  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`
7092
+ const cardInner = html9`
6235
7093
  <img
6236
7094
  class="sc-product-comparison__thumb"
6237
7095
  src=${imgSrc}
@@ -6240,33 +7098,33 @@ renderMatrix_fn = function(products, rows) {
6240
7098
  style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;"
6241
7099
  />
6242
7100
  <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
7101
+ ${showRatingPill && p.rating ? html9`<span
6244
7102
  class="sc-product-comparison__rating-pill"
6245
7103
  data-product-rating
6246
7104
  data-rating-value=${p.rating.value}
6247
7105
  aria-label=${`${p.rating.value} out of ${p.rating.max ?? 5}, ${p.rating.count} reviews`}
6248
7106
  style=${`${pillBase}left:4px;`}
6249
7107
  ><span style="color:#f5a623;">★</span><span style="margin-left:0.12rem;">${p.rating.value}</span></span
6250
- >` : nothing4}
6251
- ${priceText ? html8`<span
7108
+ >` : nothing5}
7109
+ ${priceText ? html9`<span
6252
7110
  class="sc-product-comparison__price"
6253
7111
  data-critical-text
6254
7112
  style=${`${pillBase}right:4px;`}
6255
7113
  >${priceText}</span
6256
- >` : nothing4}
7114
+ >` : nothing5}
6257
7115
  <span
6258
7116
  class="sc-product-comparison__name"
6259
7117
  data-critical-text
6260
7118
  style=${`position:absolute;left:8px;right:8px;bottom:6px;${nameOverlayStyle}`}
6261
7119
  >${p.name}</span
6262
7120
  >`;
6263
- return html8`<div
7121
+ return html9`<div
6264
7122
  class="sc-product-comparison__matrix-col"
6265
7123
  role="columnheader"
6266
7124
  data-product-id=${p.id}
6267
7125
  style=${colHeadStyle}
6268
7126
  >
6269
- ${pdpHref ? html8`<a
7127
+ ${pdpHref ? html9`<a
6270
7128
  class="sc-product-comparison__media"
6271
7129
  data-comparison-media
6272
7130
  data-product-cta="primary"
@@ -6277,19 +7135,19 @@ renderMatrix_fn = function(products, rows) {
6277
7135
  data-action-id=${navCta?.actionId ?? ""}
6278
7136
  data-variant=${navCta?.variant ?? ""}
6279
7137
  style=${mediaStyle}
6280
- >${cardInner}</a>` : html8`<div class="sc-product-comparison__media" data-comparison-media style=${mediaStyle}>${cardInner}</div>`}
7138
+ >${cardInner}</a>` : html9`<div class="sc-product-comparison__media" data-comparison-media style=${mediaStyle}>${cardInner}</div>`}
6281
7139
  </div>`;
6282
7140
  })}
6283
7141
  </div>
6284
7142
  ${rows.map((row) => {
6285
7143
  const cells = [row.valueA, row.valueB, row.valueC, row.valueD];
6286
- return html8`
7144
+ return html9`
6287
7145
  <div role="row" style="display:contents;">
6288
7146
  <span class="sc-product-comparison__matrix-label" role="rowheader" style=${labelStyle}
6289
7147
  >${row.label}</span
6290
7148
  >
6291
7149
  ${products.map(
6292
- (_p, i2) => html8`<span class="sc-product-comparison__matrix-cell" role="cell" style=${cellStyle}
7150
+ (_p, i2) => html9`<span class="sc-product-comparison__matrix-cell" role="cell" style=${cellStyle}
6293
7151
  >${cells[i2] ?? "\u2014"}</span
6294
7152
  >`
6295
7153
  )}
@@ -6307,9 +7165,9 @@ ProductComparisonLit.properties = {
6307
7165
  };
6308
7166
 
6309
7167
  // src/widgets/ProductGridLit.ts
6310
- import { html as html9, LitElement as LitElement9, nothing as nothing5 } from "lit";
7168
+ import { html as html10, LitElement as LitElement10, nothing as nothing6 } from "lit";
6311
7169
  var _controller3, _ProductGridLit_instances, startBind_fn3;
6312
- var ProductGridLit = class extends LitElement9 {
7170
+ var ProductGridLit = class extends LitElement10 {
6313
7171
  constructor() {
6314
7172
  super(...arguments);
6315
7173
  __privateAdd(this, _ProductGridLit_instances);
@@ -6335,20 +7193,20 @@ var ProductGridLit = class extends LitElement9 {
6335
7193
  __privateGet(this, _controller3)?.destroy();
6336
7194
  }
6337
7195
  render() {
6338
- if (this.validationError || !this.props) return html9``;
7196
+ if (this.validationError || !this.props) return html10``;
6339
7197
  const parsed = gridSchema.safeParse(this.props);
6340
- if (!parsed.success) return html9``;
7198
+ if (!parsed.success) return html10``;
6341
7199
  const { products, desktopColumns, heading } = parsed.data;
6342
- return html9`
7200
+ return html10`
6343
7201
  <section class="sc-product-grid">
6344
- ${heading ? html9`<h2 data-grid-heading class="sc-product-grid__heading">${heading}</h2>` : nothing5}
7202
+ ${heading ? html10`<h2 data-grid-heading class="sc-product-grid__heading">${heading}</h2>` : nothing6}
6345
7203
  <div
6346
7204
  data-grid-root
6347
7205
  class="sc-product-grid__cells"
6348
7206
  style=${`--sc-product-grid-cols:${desktopColumns}`}
6349
7207
  >
6350
7208
  ${products.map(
6351
- (p) => html9`<div data-grid-cell class="sc-product-grid__cell">
7209
+ (p) => html10`<div data-grid-cell class="sc-product-grid__cell">
6352
7210
  ${renderProductCard(p, "standard", this.resolved[p.id])}
6353
7211
  </div>`
6354
7212
  )}
@@ -6389,9 +7247,9 @@ ProductGridLit.properties = {
6389
7247
  };
6390
7248
 
6391
7249
  // src/widgets/ProductHeroLit.ts
6392
- import { html as html10, LitElement as LitElement10, nothing as nothing6 } from "lit";
7250
+ import { html as html11, LitElement as LitElement11, nothing as nothing7 } from "lit";
6393
7251
  var _controller4, _ProductHeroLit_instances, startBind_fn4;
6394
- var ProductHeroLit = class extends LitElement10 {
7252
+ var ProductHeroLit = class extends LitElement11 {
6395
7253
  constructor() {
6396
7254
  super(...arguments);
6397
7255
  __privateAdd(this, _ProductHeroLit_instances);
@@ -6417,9 +7275,9 @@ var ProductHeroLit = class extends LitElement10 {
6417
7275
  __privateGet(this, _controller4)?.destroy();
6418
7276
  }
6419
7277
  render() {
6420
- if (this.validationError || !this.props) return html10``;
7278
+ if (this.validationError || !this.props) return html11``;
6421
7279
  const parsed = heroSchema.safeParse(this.props);
6422
- if (!parsed.success) return html10``;
7280
+ if (!parsed.success) return html11``;
6423
7281
  const { product, layout, longCopy } = parsed.data;
6424
7282
  const resolved = this.resolved[product.id];
6425
7283
  const imgSrc = resolved?.image ?? product.image.src;
@@ -6428,7 +7286,7 @@ var ProductHeroLit = class extends LitElement10 {
6428
7286
  const sectionStyles = isTopLayout ? "display:block;" : `display:flex;flex-direction:${layout === "image-right" ? "row-reverse" : "row"};gap:1rem;align-items:flex-start;`;
6429
7287
  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
7288
  const contentStyles = isTopLayout ? "" : "flex:1;min-width:0;";
6431
- return html10`
7289
+ return html11`
6432
7290
  <section class="sc-product-hero" data-hero-layout=${layout} style=${sectionStyles}>
6433
7291
  <img
6434
7292
  class="sc-product-hero__image"
@@ -6439,18 +7297,18 @@ var ProductHeroLit = class extends LitElement10 {
6439
7297
  />
6440
7298
  <div class="sc-product-hero__content" style=${contentStyles}>
6441
7299
  <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
7300
+ ${product.tagline ? html11`<p class="sc-product-hero__tagline">${product.tagline}</p>` : nothing7}
7301
+ ${product.price ? html11`<p class="sc-product-hero__price">
7302
+ ${priceText}${product.price.cadence ? html11` <small>${product.price.cadence}</small>` : nothing7}
7303
+ </p>` : nothing7}
7304
+ ${longCopy ? html11`<div
6447
7305
  data-hero-longcopy
6448
7306
  class="sc-product-hero__longcopy"
6449
7307
  .innerHTML=${sanitizeHtml(longCopy)}
6450
- ></div>` : nothing6}
7308
+ ></div>` : nothing7}
6451
7309
  <div class="sc-product-hero__ctas">
6452
7310
  ${product.ctas.map(
6453
- (c2, i2) => html10`<a
7311
+ (c2, i2) => html11`<a
6454
7312
  class="sc-product-hero__cta"
6455
7313
  data-product-cta=${i2 === 0 ? "primary" : "secondary"}
6456
7314
  data-variant=${c2.variant}
@@ -6498,10 +7356,10 @@ ProductHeroLit.properties = {
6498
7356
  };
6499
7357
 
6500
7358
  // src/widgets/ProductRecoCarouselLit.ts
6501
- import { html as html11, LitElement as LitElement11, nothing as nothing7 } from "lit";
7359
+ import { html as html12, LitElement as LitElement12, nothing as nothing8 } from "lit";
6502
7360
  import { styleMap as styleMap2 } from "lit/directives/style-map.js";
6503
7361
  var _ProductRecoCarouselLit_instances, healthProbe_fn3;
6504
- var ProductRecoCarouselLit = class extends LitElement11 {
7362
+ var ProductRecoCarouselLit = class extends LitElement12 {
6505
7363
  constructor() {
6506
7364
  super();
6507
7365
  __privateAdd(this, _ProductRecoCarouselLit_instances);
@@ -6520,20 +7378,20 @@ var ProductRecoCarouselLit = class extends LitElement11 {
6520
7378
  }
6521
7379
  render() {
6522
7380
  const items = this._parsed?.items ?? [];
6523
- if (items.length === 0) return html11``;
6524
- return html11`
7381
+ if (items.length === 0) return html12``;
7382
+ return html12`
6525
7383
  <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
7384
  <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
7385
  ${items.map(
6528
- (it) => html11`
7386
+ (it) => html12`
6529
7387
  <div role="listitem" style="display:contents;">
6530
7388
  <a data-reco-item data-product-cta="primary" href=${it.pdp_href}
6531
7389
  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}
7390
+ ${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
7391
  <span style="position:absolute;inset:auto 0 0 0;height:60%;background:linear-gradient(transparent,rgba(0,0,0,.62));"></span>
6534
7392
  <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}
7393
+ ${it.price ? html12`<span style="display:block;font-weight:700;font-size:0.9rem;">${it.price}</span>` : nothing8}
7394
+ ${it.hook ? html12`<span style="display:block;font-size:0.72rem;line-height:1.2;opacity:.95;">${it.hook}</span>` : nothing8}
6537
7395
  </span>
6538
7396
  </a>
6539
7397
  </div>`
@@ -6568,7 +7426,7 @@ if (!customElements.get("syntro-product-reco-carousel"))
6568
7426
  customElements.define("syntro-product-reco-carousel", ProductRecoCarouselLit);
6569
7427
 
6570
7428
  // src/widgets/PdpTrendingNewsLit.ts
6571
- import { html as html12, LitElement as LitElement12 } from "lit";
7429
+ import { html as html13, LitElement as LitElement13 } from "lit";
6572
7430
 
6573
7431
  // src/widgets/entrance.ts
6574
7432
  function armEntranceSettle(onSettle, container, settleMs, fastPath = false) {
@@ -6915,7 +7773,7 @@ var TRENDING_NEWS_CSS = `
6915
7773
  }
6916
7774
  }
6917
7775
  `;
6918
- var PdpTrendingNewsLit = class extends LitElement12 {
7776
+ var PdpTrendingNewsLit = class extends LitElement13 {
6919
7777
  constructor() {
6920
7778
  super(...arguments);
6921
7779
  this.data = void 0;
@@ -6951,7 +7809,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6951
7809
  }
6952
7810
  render() {
6953
7811
  if (!this.data) {
6954
- return html12`<div data-skeleton class="pdp-trending-news-skeleton">
7812
+ return html13`<div data-skeleton class="pdp-trending-news-skeleton">
6955
7813
  <div class="pdp-skeleton-bar" style="width:60%"></div>
6956
7814
  <div class="pdp-skeleton-bar" style="width:90%"></div>
6957
7815
  <div class="pdp-skeleton-bar" style="width:80%"></div>
@@ -6961,7 +7819,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6961
7819
  const items = this.data.items;
6962
7820
  const featured = items[0];
6963
7821
  const rest = items.slice(1);
6964
- return html12`
7822
+ return html13`
6965
7823
  <section
6966
7824
  class="${this._entering ? "pdp-trending-news is-entering" : "pdp-trending-news"}"
6967
7825
  aria-label="Trending news"
@@ -6978,7 +7836,7 @@ var PdpTrendingNewsLit = class extends LitElement12 {
6978
7836
  <p class="pdp-tn-blurb">${featured.blurb}</p>
6979
7837
  </article>
6980
7838
  ${rest.map(
6981
- (item) => html12`
7839
+ (item) => html13`
6982
7840
  <article class="pdp-tn-card">
6983
7841
  <div class="pdp-tn-meta">
6984
7842
  <span class="pdp-tn-dot" aria-hidden="true"></span>
@@ -7000,8 +7858,8 @@ PdpTrendingNewsLit.properties = {
7000
7858
  _entering: { state: true }
7001
7859
  };
7002
7860
  function renderHeadlineLink(item) {
7003
- if (!item.url) return html12`${item.headline}`;
7004
- return html12`<a
7861
+ if (!item.url) return html13`${item.headline}`;
7862
+ return html13`<a
7005
7863
  class="pdp-tn-headline-link"
7006
7864
  href=${item.url}
7007
7865
  target="_blank"
@@ -7014,7 +7872,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7014
7872
  }
7015
7873
 
7016
7874
  // src/widgets/PdpTrendingNewsMagazineLit.ts
7017
- import { html as html13, LitElement as LitElement13 } from "lit";
7875
+ import { html as html14, LitElement as LitElement14 } from "lit";
7018
7876
  function ensureMagazineStyles() {
7019
7877
  if (typeof document === "undefined") return;
7020
7878
  if (document.getElementById("syntro-pdp-trending-news-magazine-style")) return;
@@ -7194,7 +8052,7 @@ var MAGAZINE_CSS = `
7194
8052
  }
7195
8053
  }
7196
8054
  `;
7197
- var PdpTrendingNewsMagazineLit = class extends LitElement13 {
8055
+ var PdpTrendingNewsMagazineLit = class extends LitElement14 {
7198
8056
  constructor() {
7199
8057
  super(...arguments);
7200
8058
  this.data = void 0;
@@ -7208,13 +8066,13 @@ var PdpTrendingNewsMagazineLit = class extends LitElement13 {
7208
8066
  }
7209
8067
  render() {
7210
8068
  if (!this.data) {
7211
- return html13`<div aria-busy="true" class="pdp-tn-mag" style="opacity:0.5;">…</div>`;
8069
+ return html14`<div aria-busy="true" class="pdp-tn-mag" style="opacity:0.5;">…</div>`;
7212
8070
  }
7213
8071
  const items = this.data.items;
7214
8072
  const [lead, ...rest] = items;
7215
- return html13`
8073
+ return html14`
7216
8074
  <section class="pdp-tn-mag" aria-label="Trending news">
7217
- ${lead ? html13`<article class="pdp-tn-mag__lead">
8075
+ ${lead ? html14`<article class="pdp-tn-mag__lead">
7218
8076
  <div class="pdp-tn-mag__meta">
7219
8077
  <span class="pdp-tn-mag__meta-source">${lead.source}</span>
7220
8078
  · ${lead.published_relative}
@@ -7223,7 +8081,7 @@ var PdpTrendingNewsMagazineLit = class extends LitElement13 {
7223
8081
  <p class="pdp-tn-mag__blurb">${lead.blurb}</p>
7224
8082
  </article>` : ""}
7225
8083
  ${rest.map(
7226
- (it) => html13`<article class="pdp-tn-mag__item">
8084
+ (it) => html14`<article class="pdp-tn-mag__item">
7227
8085
  <div class="pdp-tn-mag__meta">
7228
8086
  <span class="pdp-tn-mag__meta-source">${it.source}</span>
7229
8087
  · ${it.published_relative}
@@ -7240,8 +8098,8 @@ PdpTrendingNewsMagazineLit.properties = {
7240
8098
  data: { attribute: false }
7241
8099
  };
7242
8100
  function renderHeadlineLink2(item) {
7243
- if (!item.url) return html13`${item.headline}`;
7244
- return html13`<a
8101
+ if (!item.url) return html14`${item.headline}`;
8102
+ return html14`<a
7245
8103
  class="pdp-tn-mag__headline-link"
7246
8104
  href=${item.url}
7247
8105
  target="_blank"
@@ -7254,7 +8112,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7254
8112
  }
7255
8113
 
7256
8114
  // src/widgets/PdpTrendingNewsHeroLit.ts
7257
- import { html as html14, LitElement as LitElement14 } from "lit";
8115
+ import { html as html15, LitElement as LitElement15 } from "lit";
7258
8116
  function ensureHeroStyles() {
7259
8117
  if (typeof document === "undefined") return;
7260
8118
  if (document.getElementById("syntro-pdp-trending-news-hero-style")) return;
@@ -7445,7 +8303,7 @@ var HERO_CSS = `
7445
8303
  }
7446
8304
  }
7447
8305
  `;
7448
- var PdpTrendingNewsHeroLit = class extends LitElement14 {
8306
+ var PdpTrendingNewsHeroLit = class extends LitElement15 {
7449
8307
  constructor() {
7450
8308
  super(...arguments);
7451
8309
  this.data = void 0;
@@ -7459,11 +8317,11 @@ var PdpTrendingNewsHeroLit = class extends LitElement14 {
7459
8317
  }
7460
8318
  render() {
7461
8319
  if (!this.data) {
7462
- return html14`<div aria-busy="true" class="pdp-tn-hero" style="opacity:0.5;">…</div>`;
8320
+ return html15`<div aria-busy="true" class="pdp-tn-hero" style="opacity:0.5;">…</div>`;
7463
8321
  }
7464
8322
  const [lead, ...rest] = this.data.items;
7465
- if (!lead) return html14``;
7466
- return html14`
8323
+ if (!lead) return html15``;
8324
+ return html15`
7467
8325
  <section class="pdp-tn-hero" aria-label="Trending news">
7468
8326
  <article class="pdp-tn-hero__panel">
7469
8327
  <blockquote class="pdp-tn-hero__quote">${lead.blurb}</blockquote>
@@ -7474,9 +8332,9 @@ var PdpTrendingNewsHeroLit = class extends LitElement14 {
7474
8332
  </footer>
7475
8333
  <p class="pdp-tn-hero__headline">${renderHeadlineLink3(lead)}</p>
7476
8334
  </article>
7477
- ${rest.length ? html14`<div class="pdp-tn-hero__followon">
8335
+ ${rest.length ? html15`<div class="pdp-tn-hero__followon">
7478
8336
  ${rest.map(
7479
- (it) => html14`<div class="pdp-tn-hero__row">
8337
+ (it) => html15`<div class="pdp-tn-hero__row">
7480
8338
  <p class="pdp-tn-hero__row-headline">${renderHeadlineLink3(it)}</p>
7481
8339
  <span class="pdp-tn-hero__row-meta">${it.source}</span>
7482
8340
  </div>`
@@ -7490,8 +8348,8 @@ PdpTrendingNewsHeroLit.properties = {
7490
8348
  data: { attribute: false }
7491
8349
  };
7492
8350
  function renderHeadlineLink3(item) {
7493
- if (!item.url) return html14`${item.headline}`;
7494
- return html14`<a
8351
+ if (!item.url) return html15`${item.headline}`;
8352
+ return html15`<a
7495
8353
  class="pdp-tn-hero__headline-link"
7496
8354
  href=${item.url}
7497
8355
  target="_blank"
@@ -7504,7 +8362,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-tre
7504
8362
  }
7505
8363
 
7506
8364
  // src/widgets/PdpPeerFeedMasonryLit.ts
7507
- import { html as html15, LitElement as LitElement15 } from "lit";
8365
+ import { html as html16, LitElement as LitElement16 } from "lit";
7508
8366
  function ensureMasonryStyles() {
7509
8367
  if (typeof document === "undefined") return;
7510
8368
  if (document.getElementById("syntro-pdp-peer-feed-masonry-style")) return;
@@ -7648,7 +8506,7 @@ function personaHue(s4) {
7648
8506
  for (let i2 = 0; i2 < s4.length; i2++) h = h * 31 + s4.charCodeAt(i2) | 0;
7649
8507
  return Math.abs(h) % 360;
7650
8508
  }
7651
- var PdpPeerFeedMasonryLit = class extends LitElement15 {
8509
+ var PdpPeerFeedMasonryLit = class extends LitElement16 {
7652
8510
  constructor() {
7653
8511
  super(...arguments);
7654
8512
  this.data = void 0;
@@ -7662,13 +8520,13 @@ var PdpPeerFeedMasonryLit = class extends LitElement15 {
7662
8520
  }
7663
8521
  render() {
7664
8522
  if (!this.data) {
7665
- return html15`<div aria-busy="true" class="pdp-pf-mas" style="opacity:0.5;">…</div>`;
8523
+ return html16`<div aria-busy="true" class="pdp-pf-mas" style="opacity:0.5;">…</div>`;
7666
8524
  }
7667
- return html15`
8525
+ return html16`
7668
8526
  <section class="pdp-pf-mas" aria-label="Peer voices">
7669
8527
  <div class="pdp-pf-mas__grid">
7670
8528
  ${this.data.peers.map(
7671
- (p) => html15`<article
8529
+ (p) => html16`<article
7672
8530
  class="pdp-pf-mas__card"
7673
8531
  style=${`--pf-avatar-hue: ${personaHue(p.persona)};`}
7674
8532
  >
@@ -7696,7 +8554,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-pee
7696
8554
  }
7697
8555
 
7698
8556
  // src/widgets/PdpPeerFeedCarouselLit.ts
7699
- import { html as html16, LitElement as LitElement16, svg } from "lit";
8557
+ import { html as html17, LitElement as LitElement17, svg } from "lit";
7700
8558
  function ensureCarouselStyles2() {
7701
8559
  if (typeof document === "undefined") return;
7702
8560
  if (document.getElementById("syntro-pdp-peer-feed-carousel-style")) return;
@@ -7912,7 +8770,7 @@ function renderGlyph(kind) {
7912
8770
  <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
8771
  </svg>`;
7914
8772
  }
7915
- var PdpPeerFeedCarouselLit = class extends LitElement16 {
8773
+ var PdpPeerFeedCarouselLit = class extends LitElement17 {
7916
8774
  constructor() {
7917
8775
  super(...arguments);
7918
8776
  this.data = void 0;
@@ -7926,15 +8784,15 @@ var PdpPeerFeedCarouselLit = class extends LitElement16 {
7926
8784
  }
7927
8785
  render() {
7928
8786
  if (!this.data) {
7929
- return html16`<div aria-busy="true" class="pdp-pf-car" style="opacity:0.5;">…</div>`;
8787
+ return html17`<div aria-busy="true" class="pdp-pf-car" style="opacity:0.5;">…</div>`;
7930
8788
  }
7931
- return html16`
8789
+ return html17`
7932
8790
  <section class="pdp-pf-car" aria-label="Peer voices">
7933
8791
  <div class="pdp-pf-car__track">
7934
8792
  ${this.data.peers.map((p) => {
7935
8793
  const kind = glyphFor(p.persona);
7936
8794
  const hue = glyphHue(p.persona);
7937
- return html16`<article class="pdp-pf-car__card" style=${`--pf-glyph-hue: ${hue};`}>
8795
+ return html17`<article class="pdp-pf-car__card" style=${`--pf-glyph-hue: ${hue};`}>
7938
8796
  <span class="pdp-pf-car__glyph" aria-hidden="true">${renderGlyph(kind)}</span>
7939
8797
  <span class="pdp-pf-car__persona">${p.persona}</span>
7940
8798
  <blockquote class="pdp-pf-car__quote">${p.quote}</blockquote>
@@ -7959,7 +8817,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-pee
7959
8817
  }
7960
8818
 
7961
8819
  // src/widgets/PdpChartLit.ts
7962
- import { html as html17, LitElement as LitElement17, nothing as nothing8, svg as svg2 } from "lit";
8820
+ import { html as html18, LitElement as LitElement18, nothing as nothing9, svg as svg2 } from "lit";
7963
8821
  function formatNum(v) {
7964
8822
  if (v === void 0 || !Number.isFinite(v)) return "\u2014";
7965
8823
  if (Number.isInteger(v)) return v.toLocaleString("en-US");
@@ -8582,7 +9440,7 @@ function colorVar(seriesIdx) {
8582
9440
  return `var(--pc-color-${seriesIdx % PALETTE_SIZE})`;
8583
9441
  }
8584
9442
  var _PdpChartLit_instances, renderLegend_fn, renderTable_fn, renderBars_fn, renderLine_fn;
8585
- var PdpChartLit = class extends LitElement17 {
9443
+ var PdpChartLit = class extends LitElement18 {
8586
9444
  constructor() {
8587
9445
  super(...arguments);
8588
9446
  __privateAdd(this, _PdpChartLit_instances);
@@ -8618,7 +9476,7 @@ var PdpChartLit = class extends LitElement17 {
8618
9476
  }
8619
9477
  render() {
8620
9478
  if (!this.data) {
8621
- return html17`<div data-skeleton class="pdp-chart-skeleton">
9479
+ return html18`<div data-skeleton class="pdp-chart-skeleton">
8622
9480
  <div class="pdp-skeleton-bar" style="width:50%"></div>
8623
9481
  <div class="pdp-skeleton-rect" style="height:200px"></div>
8624
9482
  </div>`;
@@ -8627,7 +9485,7 @@ var PdpChartLit = class extends LitElement17 {
8627
9485
  const allSeriesOnePoint = this.data.series.every((s4) => s4.points.length <= 1);
8628
9486
  const effectiveKind = isTable ? "table" : this.data.viz_kind === "line" && !allSeriesOnePoint ? "line" : "bar";
8629
9487
  const isMultiSeries = this.data.series.length > 1;
8630
- return html17`
9488
+ return html18`
8631
9489
  <section
8632
9490
  class="${this._entering ? "pdp-chart pdp-chart-frame is-entering" : "pdp-chart pdp-chart-frame"}"
8633
9491
  aria-label="${this.data.title}"
@@ -8638,11 +9496,11 @@ var PdpChartLit = class extends LitElement17 {
8638
9496
  </div>
8639
9497
  <h3 class="pdp-chart-title">${this.data.title}</h3>
8640
9498
 
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}
9499
+ ${effectiveKind === "table" ? __privateMethod(this, _PdpChartLit_instances, renderTable_fn).call(this) : nothing9}
9500
+ ${effectiveKind === "bar" ? __privateMethod(this, _PdpChartLit_instances, renderBars_fn).call(this) : nothing9}
9501
+ ${effectiveKind === "line" ? __privateMethod(this, _PdpChartLit_instances, renderLine_fn).call(this) : nothing9}
9502
+ ${effectiveKind !== "table" && isMultiSeries ? __privateMethod(this, _PdpChartLit_instances, renderLegend_fn).call(this) : nothing9}
9503
+ ${this.data.rationale ? html18`<p class="pdp-chart-rationale">${this.data.rationale}</p>` : nothing9}
8646
9504
  </section>
8647
9505
  `;
8648
9506
  }
@@ -8650,10 +9508,10 @@ var PdpChartLit = class extends LitElement17 {
8650
9508
  _PdpChartLit_instances = new WeakSet();
8651
9509
  renderLegend_fn = function() {
8652
9510
  const data = this.data;
8653
- return html17`
9511
+ return html18`
8654
9512
  <ol class="pdp-chart-legend" aria-label="Legend">
8655
9513
  ${data.series.map(
8656
- (s4, idx) => html17`
9514
+ (s4, idx) => html18`
8657
9515
  <li class="pdp-chart-legend-item">
8658
9516
  <span
8659
9517
  class="pdp-chart-legend-swatch"
@@ -8669,22 +9527,22 @@ renderLegend_fn = function() {
8669
9527
  };
8670
9528
  renderTable_fn = function() {
8671
9529
  const matrix = buildComparisonMatrix(this.data);
8672
- return html17`
9530
+ return html18`
8673
9531
  <div class="pdp-chart-table-wrap">
8674
9532
  <table class="pdp-chart-table">
8675
9533
  <thead>
8676
9534
  <tr>
8677
9535
  <th></th>
8678
- ${matrix.colLabels.map((label) => html17`<th>${label}</th>`)}
9536
+ ${matrix.colLabels.map((label) => html18`<th>${label}</th>`)}
8679
9537
  </tr>
8680
9538
  </thead>
8681
9539
  <tbody>
8682
9540
  ${matrix.rowLabels.map(
8683
- (row, rowIdx) => html17`
9541
+ (row, rowIdx) => html18`
8684
9542
  <tr class=${rowIdx === matrix.winningRow ? "is-winning" : ""}>
8685
9543
  <td>${row}</td>
8686
9544
  ${matrix.cells[rowIdx].map(
8687
- (cell) => html17`<td class="pdp-chart-numeric-cell">${formatNum(cell)}</td>`
9545
+ (cell) => html18`<td class="pdp-chart-numeric-cell">${formatNum(cell)}</td>`
8688
9546
  )}
8689
9547
  </tr>
8690
9548
  `
@@ -8699,7 +9557,7 @@ renderBars_fn = function() {
8699
9557
  const { buckets, yMax } = buildBarBuckets(data);
8700
9558
  const ticks = niceTicks(yMax);
8701
9559
  const scaleMax = Math.max(yMax, ticks[ticks.length - 1]);
8702
- return html17`
9560
+ return html18`
8703
9561
  <div
8704
9562
  class="pdp-chart-bars"
8705
9563
  role="figure"
@@ -8708,7 +9566,7 @@ renderBars_fn = function() {
8708
9566
  >
8709
9567
  <div class="pdp-chart-yaxis" aria-hidden="true">
8710
9568
  ${ticks.map(
8711
- (t2) => html17`
9569
+ (t2) => html18`
8712
9570
  <span
8713
9571
  class="pdp-chart-yaxis-tick"
8714
9572
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8720,7 +9578,7 @@ renderBars_fn = function() {
8720
9578
  </div>
8721
9579
  <div class="pdp-chart-bars-area">
8722
9580
  ${ticks.map(
8723
- (t2) => html17`
9581
+ (t2) => html18`
8724
9582
  <div
8725
9583
  class="pdp-chart-bars-gridline"
8726
9584
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8730,11 +9588,11 @@ renderBars_fn = function() {
8730
9588
  )}
8731
9589
  <div class="pdp-chart-bars-baseline" aria-hidden="true"></div>
8732
9590
  ${buckets.map(
8733
- (bucket, bIdx) => html17`
9591
+ (bucket, bIdx) => html18`
8734
9592
  <div class="pdp-chart-bars-bucket">
8735
9593
  <div class="pdp-chart-bars-stack">
8736
9594
  ${bucket.bars.map(
8737
- (bar, barIdxInBucket) => html17`
9595
+ (bar, barIdxInBucket) => html18`
8738
9596
  <div
8739
9597
  class="pdp-chart-bar"
8740
9598
  style="
@@ -8745,9 +9603,9 @@ renderBars_fn = function() {
8745
9603
  role="img"
8746
9604
  aria-label="${bucket.label} — ${bar.seriesName}: ${formatNum(bar.value)}"
8747
9605
  >
8748
- ${bucket.bars.length === 1 ? html17`<span class="pdp-chart-bar-value"
9606
+ ${bucket.bars.length === 1 ? html18`<span class="pdp-chart-bar-value"
8749
9607
  >${formatNum(bar.value)}</span
8750
- >` : nothing8}
9608
+ >` : nothing9}
8751
9609
  </div>
8752
9610
  `
8753
9611
  )}
@@ -8765,7 +9623,7 @@ renderLine_fn = function() {
8765
9623
  const { series, xLabels, yMax } = buildLinePaths(data);
8766
9624
  const ticks = niceTicks(yMax);
8767
9625
  const scaleMax = Math.max(yMax, ticks[ticks.length - 1]);
8768
- return html17`
9626
+ return html18`
8769
9627
  <div
8770
9628
  class="pdp-chart-line"
8771
9629
  role="figure"
@@ -8775,7 +9633,7 @@ renderLine_fn = function() {
8775
9633
  >
8776
9634
  <div class="pdp-chart-line-yaxis" aria-hidden="true">
8777
9635
  ${ticks.map(
8778
- (t2) => html17`
9636
+ (t2) => html18`
8779
9637
  <span
8780
9638
  class="pdp-chart-yaxis-tick"
8781
9639
  style="bottom:${t2 / scaleMax * 100}%"
@@ -8824,7 +9682,7 @@ renderLine_fn = function() {
8824
9682
  style="--col-count:${xLabels.length}"
8825
9683
  aria-hidden="true"
8826
9684
  >
8827
- ${xLabels.map((label) => html17`<span>${label}</span>`)}
9685
+ ${xLabels.map((label) => html18`<span>${label}</span>`)}
8828
9686
  </div>
8829
9687
  `;
8830
9688
  };
@@ -8837,7 +9695,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
8837
9695
  }
8838
9696
 
8839
9697
  // src/widgets/PdpChartBarStackedLit.ts
8840
- import { html as html18, LitElement as LitElement18 } from "lit";
9698
+ import { html as html19, LitElement as LitElement19 } from "lit";
8841
9699
  function ensureStyles() {
8842
9700
  if (typeof document === "undefined") return;
8843
9701
  if (document.getElementById("syntro-pdp-chart-bar-style")) return;
@@ -8925,7 +9783,7 @@ var CSS = `
8925
9783
  }
8926
9784
  `;
8927
9785
  var PALETTE = ["hsl(150 32% 50%)", "hsl(40 75% 60%)", "hsl(208 50% 55%)", "hsl(320 38% 60%)"];
8928
- var PdpChartBarStackedLit = class extends LitElement18 {
9786
+ var PdpChartBarStackedLit = class extends LitElement19 {
8929
9787
  constructor() {
8930
9788
  super(...arguments);
8931
9789
  this.data = void 0;
@@ -8938,16 +9796,16 @@ var PdpChartBarStackedLit = class extends LitElement18 {
8938
9796
  ensureStyles();
8939
9797
  }
8940
9798
  render() {
8941
- if (!this.data) return html18`<div class="pdp-chart-bar" style="opacity:0.5;">…</div>`;
9799
+ if (!this.data) return html19`<div class="pdp-chart-bar" style="opacity:0.5;">…</div>`;
8942
9800
  const { title, series } = this.data;
8943
9801
  const allX = Array.from(new Set(series.flatMap((s4) => s4.points.map((p) => p.x))));
8944
9802
  const max = Math.max(...series.flatMap((s4) => s4.points.map((p) => p.y)), 1);
8945
- return html18`
9803
+ return html19`
8946
9804
  <section class="pdp-chart-bar" aria-label=${title}>
8947
9805
  <h3 class="pdp-chart-bar__title">${title}</h3>
8948
- ${series.length > 1 ? html18`<div class="pdp-chart-bar__legend">
9806
+ ${series.length > 1 ? html19`<div class="pdp-chart-bar__legend">
8949
9807
  ${series.map(
8950
- (s4, i2) => html18`<span
9808
+ (s4, i2) => html19`<span
8951
9809
  ><span
8952
9810
  class="pdp-chart-bar__legend-dot"
8953
9811
  style=${`background: ${PALETTE[i2 % PALETTE.length]};`}
@@ -8957,14 +9815,14 @@ var PdpChartBarStackedLit = class extends LitElement18 {
8957
9815
  )}
8958
9816
  </div>` : ""}
8959
9817
  ${allX.map(
8960
- (x) => html18`<div class="pdp-chart-bar__row">
9818
+ (x) => html19`<div class="pdp-chart-bar__row">
8961
9819
  <div class="pdp-chart-bar__row-label">${x}</div>
8962
9820
  <div class="pdp-chart-bar__row-bars">
8963
9821
  ${series.map((s4, i2) => {
8964
9822
  const point = s4.points.find((p) => p.x === x);
8965
9823
  if (!point) return "";
8966
9824
  const pct = point.y / max * 100;
8967
- return html18`<div class="pdp-chart-bar__bar-track">
9825
+ return html19`<div class="pdp-chart-bar__bar-track">
8968
9826
  <div
8969
9827
  class="pdp-chart-bar__bar-fill"
8970
9828
  style=${`width: ${pct.toFixed(1)}%; background: ${PALETTE[i2 % PALETTE.length]};`}
@@ -8987,7 +9845,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
8987
9845
  }
8988
9846
 
8989
9847
  // src/widgets/PdpChartMetricPullLit.ts
8990
- import { html as html19, LitElement as LitElement19, svg as svg3 } from "lit";
9848
+ import { html as html20, LitElement as LitElement20, svg as svg3 } from "lit";
8991
9849
  function ensureStyles2() {
8992
9850
  if (typeof document === "undefined") return;
8993
9851
  if (document.getElementById("syntro-pdp-chart-metric-style")) return;
@@ -9099,7 +9957,7 @@ function buildSparkline(points) {
9099
9957
  const peakIndex = points.reduce((best, p, i2) => p.y > points[best].y ? i2 : best, 0);
9100
9958
  return { linePath: line, areaPath: area, peakIndex };
9101
9959
  }
9102
- var PdpChartMetricPullLit = class extends LitElement19 {
9960
+ var PdpChartMetricPullLit = class extends LitElement20 {
9103
9961
  constructor() {
9104
9962
  super(...arguments);
9105
9963
  this.data = void 0;
@@ -9112,10 +9970,10 @@ var PdpChartMetricPullLit = class extends LitElement19 {
9112
9970
  ensureStyles2();
9113
9971
  }
9114
9972
  render() {
9115
- if (!this.data) return html19`<div class="pdp-chart-met" style="opacity:0.5;">…</div>`;
9973
+ if (!this.data) return html20`<div class="pdp-chart-met" style="opacity:0.5;">…</div>`;
9116
9974
  const { title, series } = this.data;
9117
9975
  const first = series[0];
9118
- if (!first || first.points.length === 0) return html19``;
9976
+ if (!first || first.points.length === 0) return html20``;
9119
9977
  const points = first.points;
9120
9978
  const peak = points.reduce((b, p) => p.y > b.y ? p : b, points[0]);
9121
9979
  const mean = points.reduce((s4, p) => s4 + p.y, 0) / points.length;
@@ -9128,7 +9986,7 @@ var PdpChartMetricPullLit = class extends LitElement19 {
9128
9986
  const max = Math.max(...points.map((p) => p.y));
9129
9987
  const range = max - min || 1;
9130
9988
  const py = h - 4 - (peak.y - min) / range * (h - 8);
9131
- return html19`
9989
+ return html20`
9132
9990
  <section class="pdp-chart-met" aria-label=${title}>
9133
9991
  <div class="pdp-chart-met__metric">
9134
9992
  <span class="pdp-chart-met__big">${peak.y}</span>
@@ -9160,7 +10018,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-cha
9160
10018
  }
9161
10019
 
9162
10020
  // src/widgets/PdpQaAccordionLit.ts
9163
- import { html as html20, LitElement as LitElement20 } from "lit";
10021
+ import { html as html21, LitElement as LitElement21 } from "lit";
9164
10022
  function ensureStyles3() {
9165
10023
  if (typeof document === "undefined") return;
9166
10024
  if (document.getElementById("syntro-pdp-qa-accordion-style")) return;
@@ -9242,7 +10100,7 @@ var CSS3 = `
9242
10100
  max-width: 56ch;
9243
10101
  }
9244
10102
  `;
9245
- var PdpQaAccordionLit = class extends LitElement20 {
10103
+ var PdpQaAccordionLit = class extends LitElement21 {
9246
10104
  constructor() {
9247
10105
  super(...arguments);
9248
10106
  this.data = void 0;
@@ -9255,11 +10113,11 @@ var PdpQaAccordionLit = class extends LitElement20 {
9255
10113
  ensureStyles3();
9256
10114
  }
9257
10115
  render() {
9258
- if (!this.data) return html20`<div class="pdp-qa-acc" style="opacity:0.5;">…</div>`;
9259
- return html20`
10116
+ if (!this.data) return html21`<div class="pdp-qa-acc" style="opacity:0.5;">…</div>`;
10117
+ return html21`
9260
10118
  <section class="pdp-qa-acc" aria-label="Frequently asked questions">
9261
10119
  ${this.data.items.map(
9262
- (it) => html20`<details class="pdp-qa-acc__item">
10120
+ (it) => html21`<details class="pdp-qa-acc__item">
9263
10121
  <summary>
9264
10122
  <span class="pdp-qa-acc__chev" aria-hidden="true"></span>
9265
10123
  <span>${it.question}</span>
@@ -9279,7 +10137,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-qa-
9279
10137
  }
9280
10138
 
9281
10139
  // src/widgets/PdpQaSideBySideLit.ts
9282
- import { html as html21, LitElement as LitElement21 } from "lit";
10140
+ import { html as html22, LitElement as LitElement22 } from "lit";
9283
10141
  function ensureStyles4() {
9284
10142
  if (typeof document === "undefined") return;
9285
10143
  if (document.getElementById("syntro-pdp-qa-side-style")) return;
@@ -9353,7 +10211,7 @@ var CSS4 = `
9353
10211
  margin: 0;
9354
10212
  }
9355
10213
  `;
9356
- var PdpQaSideBySideLit = class extends LitElement21 {
10214
+ var PdpQaSideBySideLit = class extends LitElement22 {
9357
10215
  constructor() {
9358
10216
  super(...arguments);
9359
10217
  this.data = void 0;
@@ -9366,11 +10224,11 @@ var PdpQaSideBySideLit = class extends LitElement21 {
9366
10224
  ensureStyles4();
9367
10225
  }
9368
10226
  render() {
9369
- if (!this.data) return html21`<div class="pdp-qa-side" style="opacity:0.5;">…</div>`;
9370
- return html21`
10227
+ if (!this.data) return html22`<div class="pdp-qa-side" style="opacity:0.5;">…</div>`;
10228
+ return html22`
9371
10229
  <section class="pdp-qa-side" aria-label="Q&A">
9372
10230
  ${this.data.items.map(
9373
- (it) => html21`<div class="pdp-qa-side__item">
10231
+ (it) => html22`<div class="pdp-qa-side__item">
9374
10232
  <h4 class="pdp-qa-side__q">${it.question}</h4>
9375
10233
  <p class="pdp-qa-side__a">${it.answer}</p>
9376
10234
  </div>`
@@ -9387,7 +10245,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-qa-
9387
10245
  }
9388
10246
 
9389
10247
  // src/widgets/PdpRegionalFullBleedLit.ts
9390
- import { html as html22, LitElement as LitElement22 } from "lit";
10248
+ import { html as html23, LitElement as LitElement23 } from "lit";
9391
10249
  function ensureStyles5() {
9392
10250
  if (typeof document === "undefined") return;
9393
10251
  if (document.getElementById("syntro-pdp-regional-fullbleed-style")) return;
@@ -9478,7 +10336,7 @@ var CSS5 = `
9478
10336
  font-style: italic;
9479
10337
  }
9480
10338
  `;
9481
- var PdpRegionalFullBleedLit = class extends LitElement22 {
10339
+ var PdpRegionalFullBleedLit = class extends LitElement23 {
9482
10340
  constructor() {
9483
10341
  super(...arguments);
9484
10342
  this.data = void 0;
@@ -9491,9 +10349,9 @@ var PdpRegionalFullBleedLit = class extends LitElement22 {
9491
10349
  ensureStyles5();
9492
10350
  }
9493
10351
  render() {
9494
- if (!this.data) return html22`<div class="pdp-reg-fb" style="opacity:0.5;">…</div>`;
10352
+ if (!this.data) return html23`<div class="pdp-reg-fb" style="opacity:0.5;">…</div>`;
9495
10353
  const d = this.data;
9496
- return html22`
10354
+ return html23`
9497
10355
  <section class="pdp-reg-fb" aria-label="Where you are">
9498
10356
  <article class="pdp-reg-fb__panel">
9499
10357
  <svg class="pdp-reg-fb__glyph" viewBox="0 0 56 56" aria-hidden="true">
@@ -9536,7 +10394,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-reg
9536
10394
  }
9537
10395
 
9538
10396
  // src/widgets/PdpRegionalInlineNoteLit.ts
9539
- import { html as html23, LitElement as LitElement23 } from "lit";
10397
+ import { html as html24, LitElement as LitElement24 } from "lit";
9540
10398
  function ensureStyles6() {
9541
10399
  if (typeof document === "undefined") return;
9542
10400
  if (document.getElementById("syntro-pdp-regional-inline-style")) return;
@@ -9597,7 +10455,7 @@ var CSS6 = `
9597
10455
  font-style: italic;
9598
10456
  }
9599
10457
  `;
9600
- var PdpRegionalInlineNoteLit = class extends LitElement23 {
10458
+ var PdpRegionalInlineNoteLit = class extends LitElement24 {
9601
10459
  constructor() {
9602
10460
  super(...arguments);
9603
10461
  this.data = void 0;
@@ -9610,9 +10468,9 @@ var PdpRegionalInlineNoteLit = class extends LitElement23 {
9610
10468
  ensureStyles6();
9611
10469
  }
9612
10470
  render() {
9613
- if (!this.data) return html23`<div class="pdp-reg-in" style="opacity:0.5;">…</div>`;
10471
+ if (!this.data) return html24`<div class="pdp-reg-in" style="opacity:0.5;">…</div>`;
9614
10472
  const d = this.data;
9615
- return html23`
10473
+ return html24`
9616
10474
  <aside class="pdp-reg-in" aria-label="Regional note">
9617
10475
  <svg class="pdp-reg-in__icon" viewBox="0 0 22 22" aria-hidden="true">
9618
10476
  <circle cx="11" cy="11" r="9" fill="none" stroke="currentColor" stroke-width="1.6"/>
@@ -9640,8 +10498,8 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-reg
9640
10498
  }
9641
10499
 
9642
10500
  // src/widgets/PdpSlotPlaceholderLit.ts
9643
- import { html as html24, LitElement as LitElement24 } from "lit";
9644
- var PdpSlotPlaceholderLit = class extends LitElement24 {
10501
+ import { html as html25, LitElement as LitElement25 } from "lit";
10502
+ var PdpSlotPlaceholderLit = class extends LitElement25 {
9645
10503
  constructor() {
9646
10504
  super(...arguments);
9647
10505
  this.label = "More personalized content coming soon";
@@ -9650,7 +10508,7 @@ var PdpSlotPlaceholderLit = class extends LitElement24 {
9650
10508
  return this;
9651
10509
  }
9652
10510
  render() {
9653
- return html24`
10511
+ return html25`
9654
10512
  <div class="pdp-slot-placeholder" data-placeholder>
9655
10513
  <p>${this.label}</p>
9656
10514
  <small>Ask in chat to explore this product further.</small>
@@ -9666,7 +10524,7 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-slo
9666
10524
  }
9667
10525
 
9668
10526
  // src/widgets/PdpRibbonLit.ts
9669
- import { html as html25, LitElement as LitElement25, nothing as nothing9 } from "lit";
10527
+ import { html as html26, LitElement as LitElement26, nothing as nothing10 } from "lit";
9670
10528
  function ensureRibbonStyles() {
9671
10529
  if (typeof document === "undefined") return;
9672
10530
  if (document.getElementById("syntro-pdp-ribbon-style")) return;
@@ -9795,7 +10653,7 @@ var RIBBON_CSS = `
9795
10653
  100% { transform: translateX(110%); }
9796
10654
  }
9797
10655
  `;
9798
- var PdpRibbonLit = class extends LitElement25 {
10656
+ var PdpRibbonLit = class extends LitElement26 {
9799
10657
  constructor() {
9800
10658
  super(...arguments);
9801
10659
  this.topic = "";
@@ -9833,7 +10691,7 @@ var PdpRibbonLit = class extends LitElement25 {
9833
10691
  }
9834
10692
  render() {
9835
10693
  const cls = this._entering ? "syntro-pdp-ribbon is-entering" : "syntro-pdp-ribbon";
9836
- return html25`
10694
+ return html26`
9837
10695
  <div class="${cls}" role="status" aria-live="polite">
9838
10696
  <span class="syntro-pdp-ribbon-sweep" aria-hidden="true"></span>
9839
10697
  <svg
@@ -9853,7 +10711,7 @@ var PdpRibbonLit = class extends LitElement25 {
9853
10711
  </svg>
9854
10712
  <p class="syntro-pdp-ribbon-copy">
9855
10713
  Tailored to your conversation about
9856
- ${this.topic ? html25` <span class="syntro-pdp-ribbon-topic">${this.topic}</span>.` : nothing9}
10714
+ ${this.topic ? html26` <span class="syntro-pdp-ribbon-topic">${this.topic}</span>.` : nothing10}
9857
10715
  <span class="syntro-pdp-ribbon-trail"> ${this.subtitle}</span>
9858
10716
  </p>
9859
10717
  </div>
@@ -9869,219 +10727,6 @@ if (typeof customElements !== "undefined" && !customElements.get("syntro-pdp-rib
9869
10727
  customElements.define("syntro-pdp-ribbon", PdpRibbonLit);
9870
10728
  }
9871
10729
 
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
10730
  // src/widgets/PdpQaLit.ts
10086
10731
  import { html as html27, LitElement as LitElement27, nothing as nothing11 } from "lit";
10087
10732
  function ensureQaStyles() {
@@ -11050,6 +11695,8 @@ var runtime = {
11050
11695
  var runtime_default = runtime;
11051
11696
 
11052
11697
  export {
11698
+ detachSection,
11699
+ runTakeover,
11053
11700
  _testing,
11054
11701
  onActivate,
11055
11702
  ProductCardMountable,
@@ -11089,4 +11736,4 @@ export {
11089
11736
  * SPDX-License-Identifier: BSD-3-Clause
11090
11737
  *)
11091
11738
  */
11092
- //# sourceMappingURL=chunk-NH3CFDTZ.js.map
11739
+ //# sourceMappingURL=chunk-SLHBNATX.js.map