dsh-ptc-plus 0.4.3 → 0.4.10

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 (66) hide show
  1. package/README.en.md +15 -3
  2. package/README.md +15 -3
  3. package/client.js +1157 -533
  4. package/cordis.patch.yml +12 -2
  5. package/docs/README.md +2 -0
  6. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +60 -4
  7. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +5 -1
  8. package/docs/adr/0019-plugin-settings-and-kill-switch.md +14 -3
  9. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
  10. package/docs/adr/0023-global-user-bindings.md +1 -1
  11. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +82 -18
  12. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +3 -3
  13. package/docs/adr/0032-own-session-log-facts-in-a-host-only-projection.md +27 -0
  14. package/docs/adr/0033-gate-client-visual-usability-in-a-browser.md +23 -0
  15. package/docs/architecture.md +6 -4
  16. package/docs/binding-review-placement-design.md +29 -21
  17. package/docs/client-ui.md +20 -8
  18. package/docs/client-visual-contract.md +48 -0
  19. package/docs/durability-design.md +12 -0
  20. package/docs/installation.md +48 -9
  21. package/docs/publishing.md +4 -4
  22. package/docs/release-notes.md +109 -0
  23. package/docs/runtime-reference.md +8 -2
  24. package/docs/user-bindings.en.md +2 -2
  25. package/docs/user-bindings.md +3 -3
  26. package/docs/verification-optimization-work.md +26 -0
  27. package/docs/verification.md +7 -1
  28. package/index.js +28 -7
  29. package/internal/compiler-platform.js +5 -3
  30. package/internal/compiler-service.js +2 -9
  31. package/internal/cordis-tools-owner.js +75 -16
  32. package/internal/direct-surface-owner.js +333 -7
  33. package/internal/edit-transport-owner.js +8 -5
  34. package/internal/execution-provider-owner.js +157 -0
  35. package/internal/execution-seam-compat.js +69 -113
  36. package/internal/isolated-worker.js +12 -8
  37. package/internal/recovery-tips.js +50 -21
  38. package/internal/rejected-cell-editor.js +11 -21
  39. package/internal/runtime-bridge-owner.js +88 -57
  40. package/internal/runtime-contexts.js +13 -13
  41. package/internal/session-events.js +40 -4
  42. package/internal/session-journal-recovery.js +678 -181
  43. package/internal/session-log-view.js +189 -43
  44. package/internal/session-runtime.js +58 -10
  45. package/internal/settings-compat.js +12 -2
  46. package/internal/user-bindings-owner.js +6 -5
  47. package/locale/en.json +6 -0
  48. package/locale/zh.json +6 -0
  49. package/package.json +18 -13
  50. package/src/client-authoring-view.js +222 -141
  51. package/src/client-binding-review.js +2 -0
  52. package/src/client-code-editor.js +6 -0
  53. package/src/client-copy.js +10 -0
  54. package/src/client-feature-gates.js +12 -5
  55. package/src/client-host-compat.js +23 -2
  56. package/src/client-primitives.js +249 -0
  57. package/src/client-repl-view.js +3 -3
  58. package/src/client-settings-view.js +2 -29
  59. package/src/client-styles.js +92 -33
  60. package/src/client-tool-view.js +8 -3
  61. package/src/client-workbench.js +9 -7
  62. package/src/client.js +72 -46
  63. package/assets/ptc-plus-bindings-en.png +0 -0
  64. package/assets/ptc-plus-bindings-zh.png +0 -0
  65. package/assets/ptc-plus-repair-en.png +0 -0
  66. package/assets/ptc-plus-repair-zh.png +0 -0
@@ -1,9 +1,14 @@
1
1
  const CLIENT_STYLE_ID = 'ptc-plus-client-style'
2
2
  const CLIENT_CSS = `
3
- .ptcPlusBindingDockAnchor{position:relative;flex:none;block-size:0;min-width:0;width:min(calc(100% - 32px),44rem);margin-inline:auto}
4
- .ptcPlusBindingDock{position:absolute;inset-inline:0;bottom:var(--ptc-plus-review-offset,8px);box-sizing:border-box;min-width:0;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:14px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c);box-shadow:0 8px 32px rgba(0,0,0,.14),0 2px 6px rgba(0,0,0,.06);max-block-size:var(--ptc-plus-review-height,80dvh);overflow:auto;overscroll-behavior:contain}
5
- .ptcPlusBindingDockHead{display:flex;flex:none;align-items:center;gap:4px;min-width:0;padding:0 10px 0 0}.ptcPlusBindingDockToggle{appearance:none;display:flex;flex:1;align-items:center;gap:10px;min-width:0;min-height:54px;padding:10px 12px;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.ptcPlusBindingDockToggle:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusBindingDockToggle:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-3px}.ptcPlusBindingDockSymbol{display:grid;place-items:center;flex:none;width:30px;height:30px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-secondary,#52565d);font:600 13px ui-monospace,monospace}.ptcPlusBindingDockHeading{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;font-size:13px;line-height:18px}.ptcPlusBindingDockHeading strong,.ptcPlusBindingDockHeading>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ptcPlusBindingDockHeading>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusBindingDockChevron{display:flex;flex:none;transform:rotate(180deg);transition:transform .16s ease}.ptcPlusBindingDockToggle[aria-expanded=true] .ptcPlusBindingDockChevron{transform:rotate(0deg)}
6
- .ptcPlusBindingDockBody{flex:none;min-width:0;max-block-size:min(32dvh,20rem,var(--ptc-plus-review-space,100dvh));overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDock[data-scroll=panel] .ptcPlusBindingDockBody{max-block-size:none;overflow:visible;scrollbar-gutter:auto}.ptcPlusBindingDockBody:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}.ptcPlusBindingDockBody .ptcPlusAuthoringDraft{border:0;padding:12px 14px;background:transparent;gap:10px}.ptcPlusBindingDockBody .ptcPlusBindingCommandSource,.ptcPlusBindingDockBody .ptcPlusBindingCommandCode{max-height:none;margin:0}.ptcPlusBindingDockBody pre{font-size:12px;line-height:19px}.ptcPlusBindingDockBody .ptcPlusBindingMeta{font:11px/17px ui-monospace,monospace;overflow-wrap:anywhere}.ptcPlusBindingDockActions{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:6px;padding:10px 12px;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDockActions>button{min-width:0;white-space:normal}.ptcPlusBindingDockDiscard{margin-inline-end:auto}.ptcPlusBindingDock .ptcPlusMessage{margin:0;font-size:12px;line-height:19px}.ptcPlusBindingDock>.ptcPlusMessage{padding:8px 12px}.ptcPlusComposerBindingAnchor{display:inline-flex;min-width:1px;min-height:1px}.ptcPlusComposerBindingAnchor .ptcPlusAuthorButton{position:relative}.ptcPlusDraftBadge{position:absolute;top:-2px;right:-3px;display:grid;place-items:center;box-sizing:border-box;min-width:14px;height:14px;padding-inline:3px;border:1.5px solid var(--dsw-alias-bg-base,#fff);border-radius:8px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font:600 9px/1 system-ui,sans-serif;pointer-events:none}.ptcPlusDraftBadge[data-attention=true]{background:var(--dsw-alias-state-warning-primary,#a15c00)}.ptcPlusDraftMenuItem{display:flex;min-width:0;max-width:240px;flex-direction:column;gap:3px;white-space:normal;overflow-wrap:anywhere}.ptcPlusDraftMenuItem strong{font-size:12px;font-weight:600}.ptcPlusDraftMenuItem>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusComposerBindingAnchor[data-text=true] .ptcPlusAuthorButtonShell{width:auto}
3
+ .ptcPlusTool,.ptcPlusComposerBindingAnchor{--ptc-plus-warning-label:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 65%,var(--dsw-alias-label-primary,#18191c))}.ptcPlusTool{font-family:inherit;font-size:13px;line-height:18px}.ptcPlusTool .ptcPlusToolRow{box-sizing:border-box;height:auto;min-height:24px;align-items:flex-start;padding-block:3px}.ptcPlusToolDisclosureContent{min-width:0;flex:1}.ptcPlusTool .ptcPlusToolDisclosureLayout{min-width:0;align-items:flex-start}.ptcPlusTool .ptcPlusToolTitle,.ptcPlusTool .ptcPlusToolSummary,.ptcPlusTool .ptcPlusToolSummaryLine,.ptcPlusTool .ptcPlusToolState,.ptcPlusTool .ptcPlusToolDescription,.ptcPlusTool .ptcPlusToolSep{font-size:13px;line-height:18px}.ptcPlusTool .ptcPlusToolTitle{flex:none;margin-inline-end:6px}.ptcPlusTool .ptcPlusToolState{flex:none;white-space:nowrap}.ptcPlusTool .ptcPlusToolSep{display:inline-block;min-width:6px}.ptcPlusToolSummary{display:flex;min-width:0;align-items:baseline}.ptcPlusToolSummaryLine{display:flex;min-width:0;align-items:baseline;overflow:hidden}.ptcPlusToolDescription{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ptcPlusToolSummary .ptcPlusToolDescription{flex:1}.ptcPlusToolPreview{display:flex;flex:1;min-width:0;flex-direction:column;gap:4px;margin-inline-start:6px}.ptcPlusToolPreview .ptcPlusToolSummaryLine{display:block}.ptcPlusToolPreview .ptcPlusToolDescription{display:inline;white-space:normal;overflow-wrap:anywhere}.ptcPlusToolPreview .ptcPlusFeatures{margin:0}
4
+ .ptcPlusBindingMenuContent{font-family:inherit;font-size:13px;line-height:18px;display:flex;flex-direction:column;min-width:0;min-height:0;width:100%;max-block-size:min(440px,60dvh,var(--ptc-plus-menu-space,100dvh));overflow:hidden}.ptcPlusBindingMenuScroll{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.ptcPlusMenuGroupChevron{display:block;align-self:center;width:14px;height:14px;flex:none;margin-inline-end:6px}.ptcPlusMenuGroupChevron[data-expanded=true]{transform:rotate(90deg)}.ptcPlusOwnedMenuRow{appearance:none;box-sizing:border-box;display:flex;align-items:center;width:100%;min-width:0;min-height:38px;padding:8px 10px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer}.ptcPlusOwnedMenuRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusOwnedMenuRow:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}.ptcPlusOwnedMenuRow:disabled{opacity:.5;cursor:default}.ptcPlusOwnedMenuSeparator{margin:6px 0;border-top:1px solid var(--dsw-alias-border-l2)}
5
+ .ptcPlusBindingDockAnchor{position:relative;flex:none;min-width:0;block-size:0;width:min(calc(100% - 32px),44rem);margin-inline:auto}
6
+ .ptcPlusBindingPreviewLayer{position:fixed;z-index:40;block-size:min(440px,45dvh,var(--ptc-plus-review-space,100dvh));display:flex;align-items:flex-end;pointer-events:none;font-family:inherit;font-size:13px;line-height:18px}.ptcPlusBindingPreviewLayer[data-available=false]{visibility:hidden;pointer-events:none}.ptcPlusBindingDock{position:relative;font-family:inherit;font-size:13px;line-height:18px;box-sizing:border-box;min-width:0;display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:14px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c);box-shadow:0 8px 32px rgba(0,0,0,.14),0 2px 6px rgba(0,0,0,.06);width:100%;max-block-size:100%;pointer-events:auto;overflow:hidden;overscroll-behavior:contain}
7
+ .ptcPlusBindingDockHead{display:flex;flex:none;align-items:center;gap:4px;min-width:0;padding:0 10px 0 0}.ptcPlusBindingDockControls{display:flex;flex:none;align-items:center;gap:12px}.ptcPlusBindingDockToggle{box-sizing:border-box;appearance:none;display:flex;flex:1;align-items:center;gap:10px;min-width:0;min-height:54px;padding:10px 12px;border:0;background:transparent;color:inherit;text-align:start;font:inherit;cursor:pointer}.ptcPlusBindingDockToggle:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusBindingDockToggle:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-3px}.ptcPlusBindingDockSymbol{display:grid;place-items:center;flex:none;width:30px;height:30px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-secondary,#52565d);font:600 13px ui-monospace,monospace}.ptcPlusBindingDockHeading{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;font-size:13px;line-height:18px}.ptcPlusBindingDockHeading strong,.ptcPlusBindingDockHeading>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ptcPlusBindingDockHeading>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusBindingDockChevron{display:flex;flex:none;transform:rotate(180deg);transition:transform .16s ease}.ptcPlusBindingDockToggle[aria-expanded=true] .ptcPlusBindingDockChevron{transform:rotate(0deg)}
8
+ .ptcPlusBindingDockBody{box-sizing:border-box;flex:1 1 auto;min-width:0;min-block-size:41px;max-block-size:20rem;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDockBody:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}.ptcPlusBindingDockBody .ptcPlusAuthoringDraft{border:0;padding:12px 14px;background:transparent;gap:10px}.ptcPlusBindingDockBody .ptcPlusBindingCommandSource,.ptcPlusBindingDockBody .ptcPlusBindingCommandCode{max-height:none;margin:0}.ptcPlusBindingDockBody pre{font-size:12px;line-height:19px}.ptcPlusBindingDockBody .ptcPlusBindingMeta{font:11px/17px ui-monospace,monospace;overflow-wrap:anywhere}.ptcPlusBindingDockActions{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:6px;padding:10px 12px;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusBindingDockActions>button{width:auto;min-width:0;white-space:normal}.ptcPlusBindingDockDiscard{margin-inline-end:auto}.ptcPlusBindingDock .ptcPlusMessage{margin:0;font-size:12px;line-height:19px}.ptcPlusBindingDockBody>.ptcPlusMessage{padding:8px 12px;overflow-wrap:anywhere}.ptcPlusBindingDock[data-compact=true]>.ptcPlusBindingDockBody,.ptcPlusBindingDock[data-compact=true]>.ptcPlusBindingDockActions{position:absolute;inset-inline:0;visibility:hidden;pointer-events:none}.ptcPlusComposerBindingAnchor{display:inline-flex;min-width:1px;min-height:1px}.ptcPlusComposerBindingAnchor .ptcPlusAuthorButton{position:relative}.ptcPlusDraftBadge{position:absolute;top:-2px;right:-3px;display:grid;place-items:center;box-sizing:border-box;min-width:14px;height:14px;padding-inline:3px;border:1.5px solid var(--dsw-alias-bg-base,#fff);border-radius:8px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font:600 9px/1 system-ui,sans-serif;pointer-events:none}.ptcPlusDraftBadge[data-attention=true]{background:var(--ptc-plus-warning-label);color:var(--dsw-alias-bg-base,#fff)}.ptcPlusDraftMenuItem{display:flex;min-width:0;max-width:240px;flex-direction:column;gap:3px;white-space:normal;overflow-wrap:anywhere}.ptcPlusDraftMenuItem strong{font-size:12px;font-weight:600}.ptcPlusDraftMenuItem>span{font-size:11px;color:var(--dsw-alias-label-secondary,#52565d)}.ptcPlusComposerBindingAnchor[data-text=true] .ptcPlusAuthorButtonShell{width:auto}
9
+ .ptcPlusBindingReviewModal.ptcPlusBindingReviewModal{box-sizing:border-box;display:flex;flex-direction:column;width:min(1200px,calc(100vw - 48px));max-width:100%;height:min(900px,88dvh);max-height:100%;min-height:0;padding:0;gap:0;border-radius:14px;overflow:hidden}.ptcPlusBindingReviewModal .ptcPlusBindingDock{position:relative;inset:auto;flex:1;min-height:0;max-block-size:none;border:0;border-radius:0;box-shadow:none;overflow:hidden}.ptcPlusBindingReviewModal .ptcPlusBindingDockToggle{cursor:default;padding:16px 20px}.ptcPlusBindingReviewModal .ptcPlusBindingDockToggle:hover{background:transparent}.ptcPlusBindingReviewModal .ptcPlusBindingDockBody{min-block-size:0;max-block-size:none}.ptcPlusBindingReviewModal .ptcPlusAuthoringDraft{padding:18px 20px;gap:14px}.ptcPlusBindingReviewModal .ptcPlusBindingDockBody pre{font-size:13px;line-height:21px}.ptcPlusBindingReviewModal .ptcPlusBindingDockActions{padding:12px 20px}.ptcPlusBindingReviewModal .ptcPlusBindingDockHead{padding-inline-end:16px}
10
+ @media(max-height:400px){.ptcPlusBindingReviewModal.ptcPlusBindingReviewModal{height:calc(100dvh - 24px)}.ptcPlusBindingReviewModal .ptcPlusBindingDockToggle{padding-block:8px}.ptcPlusBindingReviewModal .ptcPlusBindingDockActions{padding-block:6px}}
11
+ @media(max-width:560px){.ptcPlusBindingDockAnchor{width:calc(100% - 16px)}.ptcPlusBindingReviewModal.ptcPlusBindingReviewModal{width:calc(100vw - 48px);height:calc(100dvh - 24px)}.ptcPlusBindingReviewModal .ptcPlusBindingDockToggle{padding:12px}.ptcPlusBindingReviewModal .ptcPlusBindingDockHead{padding-inline-end:8px}.ptcPlusBindingReviewModal .ptcPlusAuthoringDraft{padding:12px}.ptcPlusBindingReviewModal .ptcPlusBindingDockActions{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);padding:10px 12px}.ptcPlusBindingReviewModal .ptcPlusBindingDockDiscard{grid-column:1/-1;justify-self:start}}
7
12
  .ptcPlusBindingCommand .ptcPlusMessage{margin:0}.ptcPlusBindingSourceDetails{min-width:0}.ptcPlusBindingSourceDetails>summary{cursor:pointer;font-size:12px;line-height:20px}.ptcPlusBindingItem>button,.ptcPlusGlobalItem>button{align-self:center}.ptcPlusAuthoringDraft>strong{font-size:13px;line-height:20px;overflow-wrap:anywhere}.ptcPlusBindingCommand .ptcPlusBindingCommandState{max-width:100%;box-sizing:border-box;white-space:normal}.ptcPlusBindingCommand .ptcPlusAuthoringDraft{min-width:0;padding:0;border:0;border-radius:0;background:transparent}
8
13
  .ptcPlusCard{list-style:none;border:0.5px solid var(--dsw-alias-border-l4);border-radius:16px;background:var(--dsw-alias-bg-layer-3);overflow:hidden;transition:border-color .16s ease,background-color .16s ease}
9
14
  .ptcPlusCard:hover{border-color:var(--dsw-alias-label-dimmed)}
@@ -12,6 +17,7 @@ const CLIENT_CSS = `
12
17
  .ptcPlusHeader{appearance:none;width:100%;display:flex;align-items:center;gap:12px;padding:14px 16px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer;border-radius:12px}
13
18
  .ptcPlusHeader:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
14
19
  .ptcPlusButton:focus-visible,.ptcPlusInput:focus-visible,.ptcPlusSelect:focus-visible,.ptcPlusTextarea:focus-visible,.ptcPlusBindingSelect:focus-visible,.ptcPlusReplBindingTrigger:focus-visible,.ptcPlusReplInspect:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}
20
+ .ptcPlusBindingSelect:disabled,.ptcPlusSelect:disabled,.ptcPlusTextarea:disabled{cursor:not-allowed;opacity:.4}
15
21
  .ptcPlusHeadText{display:flex;flex:1;min-width:0;flex-direction:column;align-items:flex-start;gap:3px}.ptcPlusName{font-size:15px;font-weight:600;line-height:1.4}.ptcPlusDescription{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;overflow-wrap:anywhere}.ptcPlusStatus{display:inline-flex;align-items:center;flex:none;padding:1px 8px;border-radius:999px;corner-shape:round;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:500;line-height:17px;white-space:nowrap}.ptcPlusStatus[data-enabled=true]{color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-tertiary)}.ptcPlusStatus[data-enabled=false]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-module-platform)}
16
22
  .ptcPlusChevron{display:flex;color:var(--dsw-alias-label-tertiary);transition:transform .18s ease}.ptcPlusChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusBody{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s ease}.ptcPlusBody[data-open=true]{grid-template-rows:1fr}.ptcPlusBodyInner{min-height:0;overflow:hidden}.ptcPlusFields{margin:0 16px;padding:8px 0 12px;border-top:0.5px solid var(--dsw-alias-border-l2)}
17
23
  .ptcPlusGroup+.ptcPlusGroup{margin-top:20px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle{margin:0;padding:8px 0;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:600;letter-spacing:0;line-height:20px}.ptcPlusRow{display:flex;align-items:center;gap:12px;min-height:48px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle+.ptcPlusRow{border-top:0}.ptcPlusMain{flex:1;min-width:0}.ptcPlusLabel{font-size:13px;font-weight:500;line-height:1.5}.ptcPlusDetail,.ptcPlusMessage{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow-wrap:anywhere}.ptcPlusInput{box-sizing:border-box;min-width:72px;width:140px;height:34px;padding:0 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5}.ptcPlusInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ptcPlusCheck{width:18px;height:18px;accent-color:var(--dsw-alias-brand-primary)}
@@ -19,37 +25,43 @@ const CLIENT_CSS = `
19
25
  .ptcPlusSettingAction{padding:4px 0 12px}
20
26
  .ptcPlusSettingsModal.ptcPlusSettingsModal{width:min(760px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 40px);border-radius:8px}.ptcPlusSettingsDialogContent{min-height:0;overflow:auto;overscroll-behavior:contain}.ptcPlusSettingsDialog{min-width:0}.ptcPlusSettingsDialog .ptcPlusFields{margin:0;padding:0 0 12px;border-top:0}
21
27
  .ptcPlusDanger{color:var(--dsw-alias-state-error-primary)}
22
- .ptcPlusActiveShell{display:inline-flex;align-items:center}.ptcPlusActive{appearance:none;display:inline-flex;height:24px;align-items:center;gap:5px;padding:0 8px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 32%,transparent);border-radius:6px;background:var(--dsw-alias-state-success-tertiary,#e7f7ef);color:var(--dsw-alias-state-success-primary,#16794f);cursor:help;font-family:inherit;font-size:12px;font-weight:600;line-height:18px;white-space:nowrap;transition:background-color .14s ease,border-color .14s ease}.ptcPlusActive:hover,.ptcPlusActive[aria-expanded=true]{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 48%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 16%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusActive:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary,#16794f);outline-offset:2px}.ptcPlusReplPopover{position:fixed;z-index:2147483000;inset:auto;display:none;box-sizing:border-box;margin:0;padding:0;border:0;overflow:visible;background:transparent;color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusReplPopover:popover-open,.ptcPlusReplPopover[data-open=true]{display:block}.ptcPlusReplPopover::backdrop{background:transparent}.ptcPlusReplCard{display:flex;max-height:inherit;overflow:hidden;flex-direction:column;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 22%,var(--dsw-alias-border-l2,rgba(0,0,0,.1)));border-top:3px solid var(--dsw-alias-state-success-primary,#16794f);border-radius:8px;background:var(--dsw-alias-bg-layer-3,#fff);box-shadow:0 14px 36px rgba(16,24,40,.2),0 3px 10px rgba(16,24,40,.1);color:var(--dsw-alias-label-primary,#18191c);white-space:normal}.ptcPlusReplHead{display:grid;flex:none;grid-template-columns:auto minmax(0,1fr);align-items:center;column-gap:8px;padding:11px 13px 10px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 7%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusReplStatusDot{grid-row:1/3;width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#16794f);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 14%,transparent)}.ptcPlusReplTitle,.ptcPlusReplSummary{display:block;min-width:0}.ptcPlusReplTitle{font-size:13px;font-weight:600;line-height:19px}.ptcPlusReplSummary{min-height:16px;overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:16px}.ptcPlusReplList{min-height:0;margin:0;padding:5px 0;overflow:auto;overscroll-behavior:contain;list-style:none;scrollbar-gutter:stable}.ptcPlusReplBinding{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px 10px;padding:7px 12px}.ptcPlusReplBinding:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusReplIdentity{display:flex;min-width:0;align-items:center;gap:7px}.ptcPlusReplName{min-width:0;overflow:hidden;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplKind{flex:none;padding:1px 6px;border:1px solid color-mix(in srgb,currentColor 22%,transparent);border-radius:999px;background:color-mix(in srgb,currentColor 10%,transparent);font-size:10px;font-weight:600;line-height:15px}.ptcPlusReplKind[data-kind=variable]{color:var(--dsw-alias-interactive-primary,#315fbd)}.ptcPlusReplKind[data-kind=function]{color:#7651b5}.ptcPlusReplKind[data-kind=class]{color:var(--dsw-alias-state-warning-primary,#946200)}.ptcPlusReplKind[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplInspect{grid-column:2;grid-row:1/3;display:inline-flex;align-items:center;gap:4px;padding:3px 5px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font:500 11px/17px inherit;white-space:nowrap}.ptcPlusReplInspect:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusReplInspect:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}.ptcPlusReplDefinition{grid-column:1/-1;min-width:0;margin-top:4px;padding:8px;border-left:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03))}.ptcPlusReplLocation{display:block;margin-bottom:5px;color:var(--dsw-alias-label-tertiary,#74777d);font-size:10px;line-height:15px}.ptcPlusReplCode{max-height:180px;margin:0;overflow:auto;color:inherit;font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusReplEmpty,.ptcPlusReplMore{display:block;color:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusReplEmpty{padding:18px 13px;font-size:12px;line-height:18px}.ptcPlusReplMore{padding:8px 13px;border-top:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03));font-size:11px;line-height:17px}
23
- .ptcPlusReplTabs{display:flex;flex:none;padding:6px 8px 0;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}.ptcPlusReplTab{flex:1;padding:5px 6px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font-family:inherit;font-size:11px;font-weight:600;line-height:17px}.ptcPlusReplTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-interactive-primary,#4d6bfe);color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusGlobalPane{display:flex;min-height:0;flex-direction:column;gap:8px;padding:8px 12px}.ptcPlusGlobalList{min-height:0;margin:0 -12px -8px;padding:5px 0;overflow:auto;list-style:none}.ptcPlusGlobalItem{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 10px;padding:7px 12px;border-radius:8px}.ptcPlusGlobalItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusGlobalItem .ptcPlusGlobalSource,.ptcPlusGlobalItem .ptcPlusReplEmpty{grid-column:1/-1}.ptcPlusAuthoringDraft{display:flex;flex-direction:column;gap:6px;padding:10px 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusGlobalSource{max-height:180px;margin:6px 0 0;padding:8px 10px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:8px;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
24
- .ptcPlusReplList{max-height:min(52vh,480px)}.ptcPlusReplBinding{grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;content-visibility:auto;contain-intrinsic-size:36px;cursor:pointer;transition:background-color .16s ease}.ptcPlusReplBinding:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-2px}.ptcPlusReplBinding[data-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplName{grid-column:1}.ptcPlusReplName[data-kind=variable]{color:var(--dsw-alias-interactive-primary,#315fbd)}.ptcPlusReplName[data-kind=function]{color:#7651b5}.ptcPlusReplName[data-kind=class]{color:var(--dsw-alias-state-warning-primary,#946200)}.ptcPlusReplName[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1}.ptcPlusReplChevron{grid-column:2;grid-row:1/3;display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#74777d);transition:transform .2s ease}.ptcPlusReplChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusReplDefinitionWrap{grid-column:1/-1;display:grid;grid-template-rows:0fr;min-width:0;transition:grid-template-rows .24s cubic-bezier(.2,.7,.2,1)}.ptcPlusReplDefinitionWrap[data-open=true]{grid-template-rows:1fr}.ptcPlusReplDefinitionInner{min-height:0;overflow:hidden}
25
- .ptcPlusTool{display:flex;min-width:0;flex-direction:column}.ptcPlusToolPreview{display:flex;min-width:0;flex:1 1 auto;flex-direction:row;align-items:center;overflow:hidden;margin-left:7px}.ptcPlusToolPreview .ptcPlusFeatures{flex:0 1 auto;flex-wrap:nowrap;overflow:hidden;margin:0 0 0 7px}.ptcPlusToolSummaryLine{box-sizing:border-box;display:flex;min-width:0;min-height:20px;flex:1 1 auto;align-items:center;gap:7px;padding:0;color:inherit;line-height:20px}.ptcPlusToolSummary{box-sizing:border-box;display:flex;min-width:0;min-height:32px;align-items:center;gap:7px;padding:0;color:inherit;line-height:20px}.ptcPlusToolSummary[data-expandable=true]{cursor:pointer}.ptcPlusToolSummary[data-expandable=true]:hover .ptcPlusToolTitle{color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusToolSummary:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:2px}.ptcPlusToolLeading{display:flex;width:16px;height:20px;flex:none;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusToolChevron{transition:transform .16s ease}.ptcPlusToolChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusToolTitle{display:flex;height:20px;flex:none;align-items:center;font-size:13px;font-weight:500;line-height:20px}.ptcPlusToolState{display:flex;height:20px;flex:none;align-items:center;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:20px}.ptcPlusToolSummaryLine[data-state=running] .ptcPlusToolState,.ptcPlusToolSummary[data-state=running] .ptcPlusToolState{color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusToolSummaryLine[data-state=error] .ptcPlusToolState,.ptcPlusToolSummary[data-state=error] .ptcPlusToolState{color:var(--dsw-alias-state-danger-primary,#c43d3d)}.ptcPlusToolSummaryLine[data-state=stopped] .ptcPlusToolState,.ptcPlusToolSummary[data-state=stopped] .ptcPlusToolState{color:var(--dsw-alias-state-warning-primary,#a15c00)}.ptcPlusToolSep{width:3px;height:3px;flex:none;border-radius:50%;background:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusToolDescription{display:flex;min-width:0;min-height:20px;flex:1 1 auto;align-items:center;overflow:hidden;color:var(--dsw-alias-label-secondary,#52565d);font-size:13px;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.ptcPlusToolPreview .ptcPlusFeature{flex:none;max-width:180px;white-space:nowrap}.ptcPlusToolPreview .ptcPlusFeatureDetail{max-width:120px}.ptcPlusToolSummaryLine[data-state=error] .ptcPlusToolDescription,.ptcPlusToolSummary[data-state=error] .ptcPlusToolDescription{color:var(--dsw-alias-state-danger-primary,#c43d3d)}.ptcPlusToolSummaryLine[data-state=stopped] .ptcPlusToolDescription,.ptcPlusToolSummary[data-state=stopped] .ptcPlusToolDescription{color:var(--dsw-alias-state-warning-primary,#a15c00)}
26
- .ptcPlusFeatures{display:flex;min-width:0;flex-wrap:wrap;gap:3px 14px;margin:0 0 5px 23px}.ptcPlusFeature{display:inline-flex;min-width:0;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px}.ptcPlusFeature::before{width:4px;height:4px;flex:none;border-radius:50%;background:var(--dsw-alias-interactive-primary,#4d6bfe);content:''}.ptcPlusFeatureName{font-weight:500}.ptcPlusFeatureDetail{min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}
28
+ .ptcPlusActiveShell{display:inline-flex;align-items:center}.ptcPlusActive{appearance:none;display:inline-flex;height:24px;align-items:center;gap:5px;padding:0 8px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 32%,transparent);border-radius:6px;background:var(--dsw-alias-state-success-tertiary,#e7f7ef);color:var(--dsw-alias-state-success-primary,#16794f);cursor:help;font-family:inherit;font-size:12px;font-weight:600;line-height:18px;white-space:nowrap;transition:background-color .14s ease,border-color .14s ease}.ptcPlusActive:hover,.ptcPlusActive[aria-expanded=true]{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 48%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 16%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusActive:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary,#16794f);outline-offset:2px}.ptcPlusReplPopover{position:fixed;z-index:2147483000;inset:auto;display:none;box-sizing:border-box;margin:0;padding:0;border:0;overflow:visible;background:transparent;color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusReplPopover:popover-open,.ptcPlusReplPopover[data-open=true]{display:block}.ptcPlusReplPopover::backdrop{background:transparent}.ptcPlusReplCard{display:flex;max-height:inherit;overflow:hidden;flex-direction:column;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 22%,var(--dsw-alias-border-l2,rgba(0,0,0,.1)));border-top:3px solid var(--dsw-alias-state-success-primary,#16794f);border-radius:8px;background:var(--dsw-alias-bg-layer-3,#fff);box-shadow:0 14px 36px rgba(16,24,40,.2),0 3px 10px rgba(16,24,40,.1);color:var(--dsw-alias-label-primary,#18191c);white-space:normal}.ptcPlusReplHead{display:grid;flex:none;grid-template-columns:auto minmax(0,1fr);align-items:center;column-gap:8px;padding:11px 13px 10px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 7%,var(--dsw-alias-bg-layer-3,#fff))}.ptcPlusReplStatusDot{grid-row:1/3;width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-state-success-primary,#16794f);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-state-success-primary,#16794f) 14%,transparent)}.ptcPlusReplTitle,.ptcPlusReplSummary{display:block;min-width:0}.ptcPlusReplTitle{font-size:13px;font-weight:600;line-height:19px}.ptcPlusReplSummary{min-height:16px;overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:16px}.ptcPlusReplList{min-height:0;margin:0;padding:5px 0;overflow:auto;overscroll-behavior:contain;list-style:none;scrollbar-gutter:stable}.ptcPlusReplBinding{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px 10px;padding:7px 12px}.ptcPlusReplBinding:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusReplIdentity{display:flex;min-width:0;align-items:center;gap:7px}.ptcPlusReplName{min-width:0;overflow:hidden;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplKind{flex:none;padding:1px 6px;border:1px solid color-mix(in srgb,currentColor 22%,transparent);border-radius:999px;background:color-mix(in srgb,currentColor 10%,transparent);font-size:10px;font-weight:600;line-height:15px}.ptcPlusReplKind[data-kind=variable]{color:var(--dsw-alias-state-business-primary,#315fbd)}.ptcPlusReplKind[data-kind=function]{color:#7651b5}.ptcPlusReplKind[data-kind=class]{color:var(--dsw-alias-state-warn-primary,#946200)}.ptcPlusReplKind[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.ptcPlusReplInspect{grid-column:2;grid-row:1/3;display:inline-flex;align-items:center;gap:4px;padding:3px 5px;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font:500 11px/17px inherit;white-space:nowrap}.ptcPlusReplInspect:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusReplInspect:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:1px}.ptcPlusReplDefinition{grid-column:1/-1;min-width:0;margin-top:4px;padding:8px;border-left:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03))}.ptcPlusReplLocation{display:block;margin-bottom:5px;color:var(--dsw-alias-label-tertiary,#74777d);font-size:10px;line-height:15px}.ptcPlusReplCode{max-height:180px;margin:0;overflow:auto;color:inherit;font:11px/16px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusReplEmpty,.ptcPlusReplMore{display:block;color:var(--dsw-alias-label-tertiary,#74777d)}.ptcPlusReplEmpty{padding:18px 13px;font-size:12px;line-height:18px}.ptcPlusReplMore{padding:8px 13px;border-top:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03));font-size:11px;line-height:17px}
29
+ .ptcPlusReplTabs{display:flex;flex:none;padding:6px 8px 0;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}.ptcPlusReplTab{flex:1;padding:5px 6px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;font-family:inherit;font-size:11px;font-weight:600;line-height:17px}.ptcPlusReplTab[aria-selected=true]{border-bottom-color:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-label-primary,#18191c)}.ptcPlusGlobalPane{display:flex;min-height:0;flex-direction:column;gap:8px;padding:8px 12px}.ptcPlusGlobalList{min-height:0;margin:0 -12px -8px;padding:5px 0;overflow:auto;list-style:none}.ptcPlusGlobalItem{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 10px;padding:7px 12px;border-radius:8px}.ptcPlusGlobalItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusGlobalItem .ptcPlusGlobalSource,.ptcPlusGlobalItem .ptcPlusReplEmpty{grid-column:1/-1}.ptcPlusAuthoringDraft{display:flex;flex-direction:column;gap:6px;padding:10px 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusGlobalSource{max-height:180px;margin:6px 0 0;padding:8px 10px;overflow:auto;background:var(--dsw-alias-markdown-code-block);border-radius:8px;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
30
+ .ptcPlusReplList{max-height:min(52vh,480px)}.ptcPlusReplBinding{grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;content-visibility:auto;contain-intrinsic-size:36px;cursor:pointer;transition:background-color .16s ease}.ptcPlusReplBinding:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}.ptcPlusReplBinding[data-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplName{grid-column:1}.ptcPlusReplName[data-kind=variable]{color:var(--dsw-alias-state-business-primary,#315fbd)}.ptcPlusReplName[data-kind=function]{color:#7651b5}.ptcPlusReplName[data-kind=class]{color:var(--dsw-alias-state-warn-primary,#946200)}.ptcPlusReplName[data-kind=import]{color:#14766f}.ptcPlusReplPreview{grid-column:1}.ptcPlusReplChevron{grid-column:2;grid-row:1/3;display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary,#74777d);transition:transform .2s ease}.ptcPlusReplChevron[data-open=true]{transform:rotate(180deg)}.ptcPlusReplDefinitionWrap{grid-column:1/-1;display:grid;grid-template-rows:0fr;min-width:0;transition:grid-template-rows .24s cubic-bezier(.2,.7,.2,1)}.ptcPlusReplDefinitionWrap[data-open=true]{grid-template-rows:1fr}.ptcPlusReplDefinitionInner{min-height:0;overflow:hidden}
31
+ .ptcPlusDraftBadge[data-attention=true]{background:var(--dsw-alias-bg-base,#fff);color:var(--ptc-plus-warning-label)}
32
+ .ptcPlusToolSummary+.ptcPlusFeatures{margin-top:4px}.ptcPlusFeatures{display:flex;min-width:0;flex-wrap:wrap;gap:3px 14px;margin:0 0 5px 23px}.ptcPlusFeature{display:inline-flex;min-width:0;max-width:100%;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px}.ptcPlusFeature::before{width:4px;height:4px;flex:none;border-radius:50%;background:var(--dsw-alias-state-business-primary,#4d6bfe);content:''}.ptcPlusFeatureName{min-width:0;font-weight:500;overflow-wrap:anywhere}.ptcPlusFeatureDetail{min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary,#74777d);font-family:ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}
27
33
  .ptcPlusToolBody{margin:4px 0 8px 23px;border-left:2px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.03))}.ptcPlusToolSection{display:flex;min-width:0;flex-direction:column;gap:4px;padding:9px 11px}.ptcPlusToolSection+.ptcPlusToolSection{border-top:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}.ptcPlusToolSectionLabel{color:var(--dsw-alias-label-tertiary,#74777d);font-size:10px;font-weight:600;line-height:16px;text-transform:uppercase}.ptcPlusToolCode{max-height:320px;margin:0;overflow:auto;color:inherit;font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusIoCard{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.1));border-radius:12px;background:var(--dsw-alias-markdown-code-block,rgba(38,49,72,.06));overflow:hidden}.ptcPlusIoText{max-height:320px;margin:0;padding:12px 16px;overflow:auto;color:var(--dsw-alias-label-secondary,#52565d);font:12px/18px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusIoText[data-error]{color:var(--dsw-alias-state-error-primary,#c43d3d)}.ptcPlusInspect{display:inline-flex;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:999px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer;opacity:0;font-size:11px;line-height:16px;transition:opacity .1s ease;display:inline-flex}.ptcPlusTool:hover .ptcPlusInspect,.ptcPlusInspect:focus-visible{opacity:1}.ptcPlusInspect:hover{background:var(--dsw-alias-interactive-bg-hover-solid,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#18191c)}
28
- .ptcPlusAuthorButtonShell{display:inline-flex;width:28px;height:28px;flex:none;align-items:center;justify-content:center}.ptcPlusAuthorButton{appearance:none;display:inline-flex;box-sizing:border-box;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer}.ptcPlusAuthorButton:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusAuthorButton:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}.ptcPlusAuthorButtonShell[data-text=true]{width:auto}.ptcPlusAuthorButtonLabel{padding:0 4px;font-size:12px;line-height:18px;font-weight:500}.ptcPlusComposerNotice{max-width:160px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px;overflow-wrap:anywhere}.ptcPlusButton>svg{flex:none;margin-right:5px;vertical-align:-2px}
34
+ .ptcPlusAuthorButtonShell{display:inline-flex;width:28px;height:28px;flex:none;align-items:center;justify-content:center}.ptcPlusAuthorButton{appearance:none;display:inline-flex;box-sizing:border-box;width:28px;height:28px;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#52565d);cursor:pointer}.ptcPlusAuthorButton:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusAuthorButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:1px}.ptcPlusAuthorButtonShell[data-text=true]{width:auto}.ptcPlusAuthorButtonLabel{padding:0 4px;font-size:12px;line-height:18px;font-weight:500}.ptcPlusComposerNotice{max-width:160px;color:var(--dsw-alias-label-secondary,#52565d);font-size:11px;line-height:17px;overflow-wrap:anywhere}.ptcPlusButton>svg{flex:none;margin-right:5px;vertical-align:-2px}
29
35
  @media(max-width:760px){.ptcPlusBindingsGrid{grid-template-columns:1fr}.ptcPlusBindingFields{grid-template-columns:1fr}.ptcPlusBindingField[data-wide=true]{grid-column:auto}.ptcPlusBindingSourceGrid{grid-template-columns:1fr}.ptcPlusBindingDebugBody{grid-template-columns:1fr}.ptcPlusBindingDebugBody .ptcPlusButton{width:100%}.ptcPlusBindingDebugWarning{grid-column:1}}
30
36
  @media(max-width:560px){.ptcPlusHeader{padding:12px}.ptcPlusFields{margin:0 12px}.ptcPlusSettingsModal.ptcPlusSettingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusSettingsDialog .ptcPlusFields{margin:0}.ptcPlusRow{align-items:flex-start;flex-direction:column;gap:6px;padding:10px 0}.ptcPlusInput{width:100%}.ptcPlusFooter,.ptcPlusBindingsHead{align-items:stretch;flex-direction:column}.ptcPlusButton{width:100%}.ptcPlusFeatures,.ptcPlusToolBody{margin-left:0}.ptcPlusToolSummary .ptcPlusToolDescription{white-space:normal;overflow-wrap:anywhere}}
31
37
  @media(prefers-reduced-motion:reduce){.ptcPlusHeader,.ptcPlusChevron,.ptcPlusBody,.ptcPlusButton,.ptcPlusActive,.ptcPlusToolChevron,.ptcPlusReplChevron,.ptcPlusReplDefinitionWrap,.ptcPlusInspect,.ptcPlusBindingDockChevron{transition:none}}
32
38
  /* The summary button owns disclosure; definition content is a separate grid item. */
33
- .ptcPlusReplBinding{padding:0;cursor:default}.ptcPlusReplBindingTrigger{appearance:none;display:grid;width:100%;grid-column:1/-1;grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer;font:inherit;transition:background-color .16s ease}.ptcPlusReplBindingTrigger:hover,.ptcPlusReplBindingTrigger[aria-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplBindingTrigger:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-2px}
39
+ .ptcPlusReplBinding{padding:0;cursor:default}.ptcPlusReplBindingTrigger{appearance:none;display:grid;width:100%;grid-column:1/-1;grid-template-columns:minmax(0,1fr) 24px;gap:3px 8px;min-height:36px;padding:5px 12px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer;font:inherit;transition:background-color .16s ease}.ptcPlusReplBindingTrigger:hover,.ptcPlusReplBindingTrigger[aria-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 5%,transparent)}.ptcPlusReplBindingTrigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}
34
40
  /* High-contrast TypeScript-like token colors adapt to the active text theme. */
35
- .ptcPlusReplCard .ptcPlusReplName[data-kind=variable]{color:color-mix(in srgb,#005cc5 78%,var(--dsw-alias-label-primary,#18191c))}
36
- .ptcPlusReplCard .ptcPlusReplName[data-kind=function]{color:color-mix(in srgb,#795e26 78%,var(--dsw-alias-label-primary,#18191c))}
37
- .ptcPlusReplCard .ptcPlusReplName[data-kind=class]{color:color-mix(in srgb,#267f99 78%,var(--dsw-alias-label-primary,#18191c))}
38
- .ptcPlusReplCard .ptcPlusReplName[data-kind=import]{color:color-mix(in srgb,#af00db 78%,var(--dsw-alias-label-primary,#18191c))}
41
+ .ptcPlusReplCard .ptcPlusReplName[data-kind=variable]{color:color-mix(in srgb,#005cc5 55%,var(--dsw-alias-label-primary,#18191c))}
42
+ .ptcPlusReplCard .ptcPlusReplName[data-kind=function]{color:color-mix(in srgb,#795e26 55%,var(--dsw-alias-label-primary,#18191c))}
43
+ .ptcPlusReplCard .ptcPlusReplName[data-kind=class]{color:color-mix(in srgb,#267f99 55%,var(--dsw-alias-label-primary,#18191c))}
44
+ .ptcPlusReplCard .ptcPlusReplName[data-kind=import]{color:color-mix(in srgb,#af00db 55%,var(--dsw-alias-label-primary,#18191c))}
39
45
  /* Keep the session-header action on the same compact 32px rhythm as DSH chrome. */
40
46
  .ptcPlusActiveShell{display:inline-flex;height:28px;align-items:center;justify-content:center;line-height:0;vertical-align:middle}.ptcPlusActive{box-sizing:border-box;height:28px;justify-content:center;gap:6px;padding:0 6px;border:0;background:transparent;font-family:inherit;font-size:13px;font-weight:500;line-height:18px}.ptcPlusActive::before{width:6px;height:6px;flex:none;border-radius:50%;background:currentColor;box-shadow:0 0 0 2px color-mix(in srgb,currentColor 18%,transparent);content:''}.ptcPlusActive:hover,.ptcPlusActive[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusActiveLabel{display:inline-flex;height:18px;align-items:center;line-height:18px}
41
47
  @media(max-width:560px){.ptcPlusActiveShell{display:none}}
42
48
  /* The compatibility probe never paints: it exists so the entry can read whether
43
49
  the installed Menu mounted the region it was given. */
44
50
  .ptcPlusMenuProbe{display:none}
45
- /* The pinned carrier is a Client-owned label cell: the host already draws the
46
- hairline above it, and the cell's own type must not leak into the grid. The
47
- compound selector is load-bearing: the base .ptcPlusMenuActions rule is
48
- declared later in this sheet, so an equal-specificity override loses and the
49
- grid would draw a second hairline under the host's. */
50
- .ptcPlusMenuActions.ptcPlusMenuActionsPinned{margin-top:0;border-top:0;font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary)}
51
- [role=menu]:has(.ptcPlusBindingMenuAction,.ptcPlusDraftMenuItem){width:min(320px,calc(100vw - 24px));min-width:0;max-height:min(440px,60dvh,var(--ptc-plus-menu-space,100dvh));border-radius:12px}.ptcPlusBindingQuickRow{display:flex;min-width:0;flex-direction:column;gap:3px;white-space:normal}.ptcPlusBindingQuickName{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px}.ptcPlusBindingQuickName strong{min-width:0;overflow:hidden;text-overflow:ellipsis;font-weight:500;white-space:nowrap}.ptcPlusBindingQuickState{flex:none;min-width:5em;text-align:end;font-size:11px;color:var(--dsw-alias-label-tertiary)}.ptcPlusBindingQuickRow[data-enabled=true] .ptcPlusBindingQuickState{color:var(--dsw-alias-state-success-primary)}.ptcPlusBindingQuickPurpose{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px}.ptcPlusBindingMenuAction{font-size:13px}
52
- .ptcPlusMenuActions{margin-top:6px;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusMenuAuthoring{padding:8px 4px}.ptcPlusMenuGroupLabel{padding:0 4px 6px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.ptcPlusMenuActionGrid,.ptcPlusMenuUtilities{display:flex;gap:6px;min-width:0}.ptcPlusMenuUtilities{padding:6px 4px}.ptcPlusMenuAuthoring+.ptcPlusMenuUtilities{border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusMenuButton{appearance:none;display:flex;flex:1;align-items:center;justify-content:center;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:7px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;text-align:center;cursor:pointer}.ptcPlusMenuButton:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusMenuButton:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:-2px}.ptcPlusMenuButton .ptcPlusBindingMenuAction{white-space:normal;overflow-wrap:anywhere;line-height:18px}.ptcPlusMenuUtilities .ptcPlusMenuButton{border-color:transparent;color:var(--dsw-alias-label-secondary)}.ptcPlusMenuUtilities .ptcPlusBindingMenuAction{font-size:12px}
51
+ .ptcPlusBindingMenu{display:flex;flex-direction:column;overflow:hidden;width:min(320px,calc(100vw - 24px));min-width:0;max-height:min(440px,60dvh);border-radius:12px}.ptcPlusBindingQuickRow{display:flex;flex:1;min-width:0;flex-direction:column;gap:3px;white-space:normal}.ptcPlusBindingQuickName{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px}.ptcPlusBindingQuickName strong{min-width:0;overflow:hidden;text-overflow:ellipsis;font-weight:500;white-space:nowrap}.ptcPlusBindingQuickState{flex:none;min-width:5em;text-align:end;font-size:11px;color:var(--dsw-alias-label-tertiary)}.ptcPlusBindingQuickRow[data-enabled=true] .ptcPlusBindingQuickState{color:var(--dsw-alias-state-success-primary)}.ptcPlusBindingQuickPurpose{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:12px}.ptcPlusBindingMenuAction{font-size:13px}
52
+ .ptcPlusMenuActions{flex:none;margin-top:0;border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusMenuAuthoring{padding:6px 4px}.ptcPlusMenuGroupLabel{padding:0 4px 4px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.ptcPlusMenuActionGrid,.ptcPlusMenuUtilities{display:flex;gap:6px;min-width:0}.ptcPlusMenuUtilities{padding:4px}.ptcPlusMenuAuthoring+.ptcPlusMenuUtilities{border-top:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1))}.ptcPlusMenuButton{box-sizing:border-box;appearance:none;display:flex;flex:1;align-items:center;justify-content:center;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:7px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;text-align:center;cursor:pointer}.ptcPlusMenuButton:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}.ptcPlusMenuButton:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}.ptcPlusMenuButton .ptcPlusBindingMenuAction{white-space:normal;overflow-wrap:anywhere;line-height:18px}.ptcPlusMenuUtilities .ptcPlusMenuButton{border-color:transparent;color:var(--dsw-alias-label-secondary)}.ptcPlusMenuUtilities .ptcPlusBindingMenuAction{font-size:12px}
53
+ @media(max-height:440px){.ptcPlusMenuAuthoring .ptcPlusMenuGroupLabel{display:none}.ptcPlusMenuAuthoring{padding-block:4px}.ptcPlusMenuButton{min-height:30px;padding:4px}}
54
+ .ptcPlusBindingMenu.ptcPlusFallbackMenuList{overflow:hidden}
55
+ /* Fallbacks used only when the installed generation ships no Menu or Modal. */
56
+ .ptcPlusFallbackMenu{display:inline-flex}.ptcPlusFallbackMenuList{position:fixed;z-index:60;box-sizing:border-box;min-width:min(220px,calc(100vw - 24px));max-width:min(320px,calc(100vw - 24px));overflow:auto;overscroll-behavior:contain;padding:6px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:12px;background:var(--dsw-alias-bg-layer-3,#fff);color:var(--dsw-alias-label-primary,#18191c);box-shadow:0 8px 32px rgba(0,0,0,.14)}
57
+ .ptcPlusFallbackMenuItem{display:flex;box-sizing:border-box;width:100%;align-items:center;gap:6px;padding:8px 10px;border:0;border-radius:8px;background:transparent;color:inherit;font:inherit;font-size:13px;text-align:start;cursor:pointer}
58
+ .ptcPlusFallbackMenuItem:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}
59
+ .ptcPlusFallbackMenuItem:disabled{opacity:.5;cursor:not-allowed}
60
+ .ptcPlusFallbackMenuLabel{padding:6px 10px 2px;color:var(--dsw-alias-label-tertiary,#74777d);font-size:11px;line-height:16px}
61
+ .ptcPlusFallbackMenuSeparator{height:1px;margin:4px 6px;background:var(--dsw-alias-border-l3,rgba(0,0,0,.1))}
62
+ .ptcPlusFallbackModalBackdrop{position:fixed;inset:0;z-index:50;display:grid;place-items:center;background:rgba(16,24,40,.35)}
63
+ .ptcPlusFallbackModal{box-sizing:border-box;width:min(760px,calc(100vw - 32px));max-height:calc(100dvh - 40px);overflow:auto;padding:16px 18px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.1));border-radius:8px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c)}
64
+ .ptcPlusFallbackModalHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.ptcPlusFallbackModalHead h2{margin:0;font-size:17px;line-height:24px}
53
65
 
54
66
  `
55
67
 
@@ -72,10 +84,10 @@ const REPL_CONSOLE_CSS = `
72
84
  .ptcPlusObservationGrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:24px}.ptcPlusObservationCatalog{min-width:0}
73
85
  .ptcPlusObservationFilters{display:flex;gap:10px;align-items:center;margin-bottom:8px}.ptcPlusObservationFilters>.ptcPlusSelect{width:120px;height:32px;flex:none;font-size:12px}
74
86
  .ptcPlusSearch{display:flex;align-items:center;gap:8px;box-sizing:border-box;min-width:0;flex:1;height:32px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-tertiary)}
75
- .ptcPlusSearch>svg{flex:none}.ptcPlusSearch input{min-width:0;width:100%;height:100%;padding:0;border:0;outline:none;background:transparent;color:var(--dsw-alias-label-primary);font:12px/20px inherit}.ptcPlusSearch:focus-within{outline:2px solid var(--dsw-alias-interactive-primary,#4d6bfe);outline-offset:1px}
87
+ .ptcPlusSearch>svg{flex:none}.ptcPlusSearch input{min-width:0;width:100%;height:100%;padding:0;border:0;outline:none;background:transparent;color:var(--dsw-alias-label-primary);font:12px/20px inherit}.ptcPlusSearch:focus-within{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:1px}
76
88
  .ptcPlusObservations{height:256px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:6px}
77
89
  .ptcPlusObservationTable{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0;font-size:12px;text-align:left}.ptcPlusObservationTable th{position:sticky;top:0;z-index:1;height:32px;padding:0 10px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-tertiary);font-weight:500;border-bottom:1px solid var(--dsw-alias-border-l2)}
78
- .ptcPlusObservationTable th:first-child{width:34%}.ptcPlusObservationTable th:nth-child(2){width:16%}.ptcPlusObservationTable th:nth-child(3){width:72px}.ptcPlusObservationTable td{height:34px;padding:0 10px;border-bottom:1px solid var(--dsw-alias-border-l2);overflow:hidden}.ptcPlusObservationTable tr:last-child td{border-bottom:0}.ptcPlusObservationTable tbody tr{cursor:pointer}.ptcPlusObservationTable tbody tr:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusObservationTable tr[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 7%,transparent)}
90
+ .ptcPlusObservationTable th:first-child{width:34%}.ptcPlusObservationTable th:nth-child(2){width:16%}.ptcPlusObservationTable th:nth-child(3){width:72px}.ptcPlusObservationTable td{height:34px;padding:0 10px;border-bottom:1px solid var(--dsw-alias-border-l2);overflow:hidden}.ptcPlusObservationTable tr:last-child td{border-bottom:0}.ptcPlusObservationTable tbody tr{cursor:pointer}.ptcPlusObservationTable tbody tr:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusObservationTable tr[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 7%,transparent)}
79
91
  .ptcPlusObservationSelect{display:block;width:100%;min-width:0;height:34px;padding:0;border:0;background:transparent;color:inherit;cursor:pointer;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationKind{color:var(--dsw-alias-label-tertiary);white-space:nowrap}
80
92
  .ptcPlusObservationValue{display:flex;min-width:0;align-items:center;gap:6px}.ptcPlusObservationValue code{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:11px/18px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationState{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px}.ptcPlusObservationValue .ptcPlusObservationState{flex:none}.ptcPlusObservationEmpty{padding:12px}
81
93
  .ptcPlusBindingInspector{box-sizing:border-box;min-width:0;max-height:296px;overflow:auto;padding-left:24px;border-left:1px solid var(--dsw-alias-border-l2)}
@@ -83,35 +95,82 @@ const REPL_CONSOLE_CSS = `
83
95
  .ptcPlusObservationLabel{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:12px 0 6px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}
84
96
  .ptcPlusObservationCode{max-height:184px;margin:0;overflow:auto;border-radius:6px;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusObservationPreview{margin:0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;white-space:pre-wrap;overflow-wrap:anywhere;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusObservationUnavailable{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px}
85
97
  .ptcPlusBindingsSurface{min-width:0;container-type:inline-size}.ptcPlusBindingsSurface .ptcPlusBindings{margin:0;padding:0;border:0}.ptcPlusBindingsSurface .ptcPlusBindingsGrid{grid-template-columns:220px minmax(0,1fr);gap:20px;margin-top:12px}.ptcPlusBindingsSurface .ptcPlusBindingsTitle{font-size:15px;line-height:22px}
86
- .ptcPlusBindingPane{min-width:0}.ptcPlusBindingPane>.ptcPlusSearch{flex:none;margin-bottom:2px}.ptcPlusBindingsSurface .ptcPlusBindingsHead{flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px}.ptcPlusBindingsSurface .ptcPlusBindingList{max-height:350px;overflow:auto;gap:0;padding:0;border:0;border-radius:0;background:transparent}.ptcPlusBindingsSurface .ptcPlusBindingItem{min-height:52px;padding:8px;border-radius:4px;box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingsSurface .ptcPlusBindingItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-interactive-primary,#4d6bfe) 7%,transparent)}
98
+ .ptcPlusBindingPane{min-width:0}.ptcPlusBindingPane>.ptcPlusSearch{flex:none;margin-bottom:2px}.ptcPlusBindingsSurface .ptcPlusBindingsHead{flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px}.ptcPlusBindingsSurface .ptcPlusBindingList{max-height:350px;overflow:auto;gap:0;padding:0;border:0;border-radius:0;background:transparent}.ptcPlusBindingsSurface .ptcPlusBindingItem{min-height:52px;padding:8px;border-radius:4px;box-sizing:border-box;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingsSurface .ptcPlusBindingItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 7%,transparent)}
87
99
  .ptcPlusBindingsSurface .ptcPlusBindingName{font-size:12px;font-weight:500;white-space:normal;overflow-wrap:anywhere}.ptcPlusBindingsSurface .ptcPlusBindingMeta{font-size:11px;line-height:16px}.ptcPlusBindingsSurface .ptcPlusBindingEditor{border:0;border-radius:0;background:transparent;overflow:visible}
88
- .ptcPlusBindingSwitch{appearance:none;position:relative;align-self:center;flex:none;width:30px;height:18px;padding:2px;border:0;border-radius:9px;background:var(--dsw-alias-label-dimmed,#a5a7ad);cursor:pointer}.ptcPlusBindingSwitch span{display:block;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0002;transition:transform .15s ease}.ptcPlusBindingSwitch[aria-checked=true]{background:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusBindingSwitch[aria-checked=true] span{transform:translateX(12px)}.ptcPlusBindingSwitch:disabled{cursor:not-allowed;opacity:.5}
100
+ .ptcPlusBindingSwitch{appearance:none;position:relative;align-self:center;flex:none;width:30px;height:18px;padding:2px;border:0;border-radius:9px;background:var(--dsw-alias-label-dimmed,#a5a7ad);cursor:pointer}.ptcPlusBindingSwitch span{display:block;width:14px;height:14px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0002;transition:transform .15s ease}.ptcPlusBindingSwitch[aria-checked=true]{background:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusBindingSwitch[aria-checked=true] span{transform:translateX(12px)}.ptcPlusBindingSwitch:disabled{cursor:not-allowed;opacity:.5}
89
101
  .ptcPlusEditorHead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;min-height:32px;margin-bottom:8px}.ptcPlusEditorFile{min-width:0;overflow-wrap:anywhere;font:600 13px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusBindingLifecycle{gap:6px}
90
102
  .ptcPlusIconButton{display:inline-flex;align-items:center;justify-content:center;flex:none;box-sizing:border-box;width:30px;height:30px;padding:0;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}.ptcPlusIconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusIconButton[data-kind=danger]:hover{color:var(--dsw-alias-state-error-primary)}.ptcPlusIconButton:disabled{opacity:.4;cursor:not-allowed}
91
- .ptcPlusCodeEditor{min-width:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;--ptc-code-keyword:color-mix(in srgb,#a13d96 75%,var(--dsw-alias-label-primary));--ptc-code-string:color-mix(in srgb,#af643c 75%,var(--dsw-alias-label-primary));--ptc-code-number:color-mix(in srgb,#477ac2 75%,var(--dsw-alias-label-primary));--ptc-code-type:color-mix(in srgb,#258579 75%,var(--dsw-alias-label-primary));--ptc-code-function:color-mix(in srgb,#825bbe 75%,var(--dsw-alias-label-primary))}.ptcPlusCodeEditor:focus-within{border-color:var(--dsw-alias-interactive-primary,#4d6bfe)}.ptcPlusCodeEditor .cm-editor{height:336px}.ptcPlusCodeEditor .cm-scroller{min-height:0}.ptcPlusCodeEditor .cm-line{overflow-wrap:anywhere}
103
+ .ptcPlusCodeEditor{min-width:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;--ptc-code-keyword:color-mix(in srgb,#a13d96 75%,var(--dsw-alias-label-primary));--ptc-code-string:color-mix(in srgb,#af643c 75%,var(--dsw-alias-label-primary));--ptc-code-number:color-mix(in srgb,#477ac2 75%,var(--dsw-alias-label-primary));--ptc-code-type:color-mix(in srgb,#258579 75%,var(--dsw-alias-label-primary));--ptc-code-function:color-mix(in srgb,#825bbe 75%,var(--dsw-alias-label-primary))}.ptcPlusCodeEditor:focus-within{border-color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCodeEditor .cm-editor{height:336px}.ptcPlusCodeEditor .cm-scroller{min-height:0}.ptcPlusCodeEditor .cm-line{overflow-wrap:anywhere}
92
104
  .ptcPlusBindingsSurface .ptcPlusBindingSection{display:block;padding:0;margin-top:0;border:0;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingSection>summary,.ptcPlusBindingsSurface .ptcPlusBindingDebugSummary{padding:11px 0;cursor:pointer;font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}.ptcPlusEntrySettings .ptcPlusBindingFields{padding:0 0 14px}.ptcPlusBindingsSurface .ptcPlusBindingSourcePreview{display:block}.ptcPlusBindingSourcePreview>.ptcPlusCodeBlock{margin-bottom:12px}.ptcPlusBindingsSurface .ptcPlusBindingDebug{display:block;padding:0;border-top:0}.ptcPlusBindingsSurface .ptcPlusBindingDebugBody{grid-template-columns:minmax(0,1fr) minmax(0,1fr);padding-bottom:12px}
93
105
  .ptcPlusBindingsSurface .ptcPlusBindingRun{gap:6px;margin-top:10px}.ptcPlusBindingsSurface .ptcPlusBindingRun .ptcPlusInput{flex-basis:100%;min-width:0;width:100%;height:32px;font-size:12px}.ptcPlusBindingsSurface .ptcPlusMessage[role=status]{grid-column:1/-1;margin:0}
94
106
  .ptcPlusSessionEmpty{box-sizing:border-box;width:100%;padding:16px 18px;border:1px dashed var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.ptcPlusObservationGrid[data-empty=true]{grid-template-columns:minmax(0,1fr)}.ptcPlusObservationGrid[data-empty=true] .ptcPlusObservations{height:auto;min-height:94px}
95
107
  .ptcPlusSourceSection{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:0 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSourceToggle{display:flex;min-width:0;align-items:center;gap:6px;padding:12px 0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);text-align:left;cursor:pointer;font:500 12px/20px inherit}.ptcPlusSourceToggle svg{flex:none}.ptcPlusSourceFilename{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font:11px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusSourceActions{display:flex;flex-wrap:wrap;gap:6px;padding:6px 0}.ptcPlusSourceBody{grid-column:1/-1;min-width:0;margin-bottom:12px}.ptcPlusSourceCode{max-height:336px;overflow:auto;margin:0;border-radius:6px;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
96
108
  .ptcPlusWorkbenchFeedback{min-height:22px;padding:4px 0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow-wrap:anywhere}.ptcPlusBindings[aria-busy=true] button:disabled,.ptcPlusBindings[aria-busy=true] input:disabled{opacity:1}.ptcPlusBindings[aria-busy=true] button:disabled{cursor:wait}
97
109
  .ptcPlusExecution{min-width:0;margin:0 0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:hidden;background:var(--dsw-alias-bg-layer-3)}.ptcPlusExecution>summary{padding:10px 12px;cursor:pointer;font-size:12px;font-weight:500;line-height:20px;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionToolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusExecutionLanguage{font:11px/18px ui-monospace,SFMono-Regular,Consolas,monospace;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionState{font-size:11px;line-height:18px;color:var(--dsw-alias-label-tertiary)}.ptcPlusExecutionActions{display:flex;align-items:center;gap:6px;margin-left:auto}.ptcPlusExecutionActions .ptcPlusButton{min-width:68px;min-height:30px;padding:3px 10px;font-size:12px}
98
- .ptcPlusExecutionHistory{min-height:48px;max-height:320px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.ptcPlusExecutionHistory:empty{min-height:0}.ptcPlusExecutionRecord{min-width:0;padding:10px 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusExecutionCommand,.ptcPlusExecutionOutput{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusExecutionCommand{color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionCommand>span{color:var(--dsw-alias-label-tertiary)}.ptcPlusExecutionResult{flex-direction:row;gap:12px;margin-top:8px;padding:12px 16px}.ptcPlusExecutionOutputLabel{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.ptcPlusExecutionOutput{flex:1;min-width:0;max-height:240px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionOutput:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}.ptcPlusExecutionOutput[data-error=true]{color:var(--dsw-alias-state-error-primary)}.ptcPlusExecutionDuration{display:block;margin-top:4px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px}.ptcPlusExecutionInput .ptcPlusCodeEditor{border:0;border-radius:0}.ptcPlusExecutionInput .cm-editor{height:108px}.ptcPlusExecutionInput .cm-content{min-height:88px}
110
+ .ptcPlusExecutionHistory{min-height:48px;max-height:320px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.ptcPlusExecutionHistory:empty{min-height:0}.ptcPlusExecutionRecord{min-width:0;padding:10px 12px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusExecutionCommand,.ptcPlusExecutionOutput{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font:12px/20px ui-monospace,SFMono-Regular,Consolas,monospace}.ptcPlusExecutionCommand{color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionCommand>span{color:var(--dsw-alias-label-tertiary)}.ptcPlusExecutionResult{flex-direction:row;gap:12px;margin-top:8px;padding:12px 16px}.ptcPlusExecutionOutputLabel{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}.ptcPlusExecutionOutput{flex:1;min-width:0;max-height:240px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;color:var(--dsw-alias-label-secondary)}.ptcPlusExecutionOutput:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}.ptcPlusExecutionOutput[data-error=true]{color:var(--dsw-alias-state-error-primary)}.ptcPlusExecutionDuration{display:block;margin-top:4px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px}.ptcPlusExecutionInput .ptcPlusCodeEditor{border:0;border-radius:0}.ptcPlusExecutionInput .cm-editor{height:108px}.ptcPlusExecutionInput .cm-content{min-height:88px}
99
111
  @container(max-width:460px){.ptcPlusSourceSection{grid-template-columns:minmax(0,1fr)}.ptcPlusSourceToggle{padding-bottom:6px}.ptcPlusSourceActions{justify-content:flex-end}.ptcPlusExecutionToolbar{gap:6px;padding:8px}.ptcPlusExecutionActions{gap:4px}.ptcPlusSourceFilename{display:none}}
100
- .ptcPlusBindingsModal.ptcPlusBindingsModal{width:min(1200px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 40px);border-radius:8px}.ptcPlusBindingsDialog{box-sizing:border-box;max-height:calc(100dvh - 40px);overflow:auto;padding:24px}.ptcPlusBindingsDialogHead{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px}.ptcPlusBindingsDialogHead h2{margin:0;font-size:17px;line-height:24px}.ptcPlusDialogClose{display:flex;flex:none;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer}.ptcPlusDialogClose:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusConsole button:focus-visible,.ptcPlusBindingsDialog button:focus-visible{outline:2px solid var(--dsw-alias-interactive-primary);outline-offset:-2px}
112
+ .ptcPlusBindingsModal.ptcPlusBindingsModal{width:min(1200px,calc(100vw - 32px));max-width:none;max-height:calc(100dvh - 40px);border-radius:8px}.ptcPlusBindingsDialog{box-sizing:border-box;max-height:calc(100dvh - 40px);overflow:auto;padding:24px}.ptcPlusBindingsDialogHead{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px}.ptcPlusBindingsDialogHead h2{margin:0;font-size:17px;line-height:24px}.ptcPlusDialogClose{display:flex;flex:none;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer}.ptcPlusDialogClose:hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusConsole button:focus-visible,.ptcPlusBindingsDialog button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}
101
113
  @container(max-width:780px){.ptcPlusObservationGrid{grid-template-columns:minmax(0,1fr);gap:16px}.ptcPlusBindingInspector{max-height:none;padding:12px 0 0;border-left:0;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusObservations{height:200px}.ptcPlusBindingsSurface .ptcPlusBindingsGrid{grid-template-columns:minmax(0,1fr);gap:18px}.ptcPlusBindingsSurface .ptcPlusBindingList{max-height:180px}.ptcPlusBindingsSurface .ptcPlusBindingFields,.ptcPlusBindingsSurface .ptcPlusBindingDebugBody{grid-template-columns:minmax(0,1fr)}.ptcPlusObservationTable th:first-child{width:35%}.ptcPlusObservationTable th:nth-child(2){width:64px}.ptcPlusObservationTable th:nth-child(3){width:64px}}
102
114
  @media(max-width:560px){.ptcPlusConsole{padding:14px 12px}.ptcPlusBindingsModal.ptcPlusBindingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusBindingsDialog{padding:16px;max-height:calc(100dvh - 16px)}.ptcPlusObservationFilters>.ptcPlusSelect{width:105px}.ptcPlusObservationTable th,.ptcPlusObservationTable td{padding:0 6px}.ptcPlusObservationValue{gap:3px}.ptcPlusObservationState{font-size:10px}.ptcPlusEditorHead{align-items:flex-start}.ptcPlusEditorHead>.ptcPlusBindingLifecycle{margin-left:auto}.ptcPlusSourceBody .cm-editor{height:300px}}
103
115
  .ptcPlusReplIdentity{grid-column:1}.ptcPlusReplReuse{flex:none;padding:0 5px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.06));color:var(--dsw-alias-label-tertiary,#74777d);font:500 10px/15px system-ui,sans-serif;white-space:nowrap}
104
116
  .ptcPlusObservationReuseTotal{font-size:13px;color:var(--dsw-alias-label-tertiary)}.ptcPlusObservationReuse{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums}
105
117
  `
106
118
 
107
- /** Install the plugin stylesheet once; returns the disposer that removes it. */
119
+ /**
120
+ * Package name this bundle was built for. DSH attributes a client plugin's
121
+ * stylesheets by exactly this string, so the browser entry substitutes it at
122
+ * build time and the Client test entry sets the same global.
123
+ */
124
+ const CLIENT_PLUGIN_ID = typeof __PTC_PLUS_CLIENT_MODULE_ID__ === 'string'
125
+ ? __PTC_PLUS_CLIENT_MODULE_ID__
126
+ : 'dsh-ptc-plus'
127
+ /** Stable identity of each stylesheet this plugin owns. */
128
+ const CLIENT_STYLE_TAG = `${CLIENT_PLUGIN_ID}/client.css`
129
+ const CODEMIRROR_STYLE_TAG = `${CLIENT_PLUGIN_ID}/codemirror.css`
130
+
131
+ /**
132
+ * Install the plugin stylesheet and return the disposer that removes it.
133
+ *
134
+ * The tag carries its DSH attribution from creation. The Client module system
135
+ * claims every untagged `style` it finds while materializing a plugin and
136
+ * deletes that plugin's tags when the plugin leaves, so an untagged sheet
137
+ * inserted from `apply` — after this plugin's own materialization — would be
138
+ * claimed by whichever plugin loads next and deleted with it.
139
+ */
108
140
  function installStyles() {
109
- if (document.getElementById(CLIENT_STYLE_ID) !== null) return () => {}
141
+ if (typeof document === 'undefined') return () => {}
110
142
  const style = document.createElement('style')
111
143
  style.id = CLIENT_STYLE_ID
144
+ style.dataset.plugin = CLIENT_PLUGIN_ID
145
+ style.dataset.pluginCss = CLIENT_STYLE_TAG
112
146
  style.textContent = `${CLIENT_CSS}${BINDING_WORKBENCH_CSS}${REPL_CONSOLE_CSS}`
113
147
  document.head.append(style)
114
148
  return () => style.remove()
115
149
  }
116
150
 
117
- export { CLIENT_STYLE_ID, CLIENT_CSS, BINDING_WORKBENCH_CSS, REPL_CONSOLE_CSS, installStyles }
151
+ /** Snapshot the untagged stylesheets so a later adoption can name only new ones. */
152
+ function captureUnownedStyles() {
153
+ if (typeof document === 'undefined') return new Set()
154
+ return new Set(document.querySelectorAll('style:not([data-plugin])'))
155
+ }
156
+
157
+ /**
158
+ * Attribute the stylesheets a dependency injected while this plugin ran.
159
+ * CodeMirror's style-mod mounts one global sheet per document and cannot tag
160
+ * it, so the plugin that mounted the editor claims it; only tags absent from
161
+ * `known` are claimed, leaving another plugin's concurrent sheet alone.
162
+ */
163
+ function adoptUnownedStyles(known, tagId = CODEMIRROR_STYLE_TAG) {
164
+ if (typeof document === 'undefined') return
165
+ for (const style of document.querySelectorAll('style:not([data-plugin])')) {
166
+ if (known?.has(style)) continue
167
+ style.dataset.plugin = CLIENT_PLUGIN_ID
168
+ style.dataset.pluginCss = tagId
169
+ }
170
+ }
171
+
172
+ export {
173
+ CLIENT_STYLE_ID, CLIENT_CSS, BINDING_WORKBENCH_CSS, REPL_CONSOLE_CSS,
174
+ CLIENT_PLUGIN_ID, CLIENT_STYLE_TAG, CODEMIRROR_STYLE_TAG,
175
+ installStyles, captureUnownedStyles, adoptUnownedStyles,
176
+ }
@@ -1,4 +1,5 @@
1
1
  import { derivePtcToolView } from './client-activity.js'
2
+ import { isHostComponent } from './client-host-compat.js'
2
3
 
3
4
  /**
4
5
  * run_code / edit_run_code tool rows. The row is a pure projection of the
@@ -8,8 +9,7 @@ import { derivePtcToolView } from './client-activity.js'
8
9
  export function createPtcToolView(React, deps) {
9
10
  const { CodeBlock, DisclosureRow, icons } = deps
10
11
  const h = React.createElement
11
- const hasDisclosureRow = typeof DisclosureRow === 'function'
12
- || (typeof DisclosureRow === 'object' && DisclosureRow !== null)
12
+ const hasDisclosureRow = isHostComponent(DisclosureRow)
13
13
 
14
14
  function PTCPlusToolRow({ toolName, block, inspect, t }) {
15
15
  const [open, setOpen] = React.useState(false)
@@ -38,7 +38,7 @@ export function createPtcToolView(React, deps) {
38
38
  const body = !open ? null : h('div', { className: 'ptcPlusToolBody' },
39
39
  view.code === '' ? null : h('div', { className: 'ptcPlusToolSection' },
40
40
  h('span', { className: 'ptcPlusToolSectionLabel' }, t('tool.source')),
41
- typeof CodeBlock === 'function'
41
+ isHostComponent(CodeBlock)
42
42
  ? h(CodeBlock, {
43
43
  code: view.code, lang: 'typescript', className: 'ptcPlusToolCode',
44
44
  copyLabel: t('tool.copy'), copiedLabel: t('tool.copied'),
@@ -75,6 +75,11 @@ export function createPtcToolView(React, deps) {
75
75
  expandOnRowClick: true,
76
76
  previewChevron: false,
77
77
  keepContentWhenOpen: true,
78
+ className: 'ptcPlusToolDisclosure',
79
+ rowClassName: 'ptcPlusToolRow',
80
+ contentClassName: 'ptcPlusToolDisclosureContent',
81
+ contentLayoutClassName: 'ptcPlusToolDisclosureLayout',
82
+ titleClassName: 'ptcPlusToolTitle',
78
83
  collapsedContent,
79
84
  children: body,
80
85
  }))
@@ -1,5 +1,5 @@
1
1
  import { blankBinding, editableBinding, bindingPayload } from './client-bindings-data.js'
2
- import { isHostIconComponent } from './client-host-compat.js'
2
+ import { isHostComponent, isHostIconComponent } from './client-host-compat.js'
3
3
 
4
4
  /**
5
5
  * User Bindings workbench. The controller owns every piece of edit state in one
@@ -391,7 +391,7 @@ export function createUserBindingsWorkbench(React, deps) {
391
391
  h('details', { className: 'ptcPlusBindingSection ptcPlusBindingSourcePreview', open: true },
392
392
  h('summary', { className: 'ptcPlusBindingFieldLabel' }, t('bindings.declaration')),
393
393
  state.declaration === '' ? h('p', { className: 'ptcPlusMessage' }, t('bindings.unvalidated'))
394
- : typeof CodeBlock === 'function'
394
+ : isHostComponent(CodeBlock)
395
395
  ? h(CodeBlock, { code: state.declaration, lang: 'typescript', className: 'ptcPlusCodeBlock',
396
396
  copyLabel: t('tool.copy'), copiedLabel: t('tool.copied') })
397
397
  : h('pre', { className: 'ptcPlusDeclaration' }, state.declaration)),
@@ -420,7 +420,7 @@ export function createUserBindingsWorkbench(React, deps) {
420
420
  state.editing
421
421
  ? h(TypeScriptEditor, { documentId: state.documentId, value: state.draft.source, disabled: state.busy,
422
422
  label: t('bindings.source'), onChange: value => edit('source', value) })
423
- : state.sourceOpen && typeof CodeBlock === 'function'
423
+ : state.sourceOpen && isHostComponent(CodeBlock)
424
424
  ? h(CodeBlock, { code: state.draft.source, lang: 'typescript', className: 'ptcPlusSourceCode',
425
425
  copyLabel: t('tool.copy'), copiedLabel: t('tool.copied') })
426
426
  : state.sourceOpen ? h('pre', { className: 'ptcPlusSourceCode' }, state.draft.source) : null)),
@@ -484,11 +484,13 @@ export function createUserBindingsWorkbench(React, deps) {
484
484
  const content = React.useRef(null)
485
485
  const localReturnFocus = React.useRef(null)
486
486
  const returnFocus = returnFocusRef ?? localReturnFocus
487
- React.useEffect(() => {
487
+ const attachContent = React.useCallback(element => {
488
+ content.current = element
489
+ if (element === null) return
488
490
  const previous = document.activeElement
489
491
  // A resumed mount may have no focused control; keep the last valid entry.
490
- if (!content.current.contains(previous) && canReturnFocus(previous)) returnFocus.current = previous
491
- content.current.querySelector('button')?.focus()
492
+ if (!element.contains(previous) && canReturnFocus(previous)) returnFocus.current = previous
493
+ element.querySelector('button')?.focus()
492
494
  }, [returnFocus])
493
495
  const close = () => {
494
496
  const target = canReturnFocus(returnFocus.current) ? returnFocus.current : getReturnFocus?.()
@@ -509,7 +511,7 @@ export function createUserBindingsWorkbench(React, deps) {
509
511
  }
510
512
  }
511
513
  return h(Modal, { open: true, onClose: close, title: t('bindings.title'), headless: true, className: 'ptcPlusBindingsModal' },
512
- h('div', { className: 'ptcPlusBindingsDialog', ref: content, onKeyDown: trapFocus },
514
+ h('div', { className: 'ptcPlusBindingsDialog', ref: attachContent, onKeyDown: trapFocus },
513
515
  h('div', { className: 'ptcPlusBindingsDialogHead' },
514
516
  h('h2', null, t('bindings.title')),
515
517
  h('button', { type: 'button', className: 'ptcPlusDialogClose', onClick: close,
package/src/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createClientRpc } from './client-rpc.js'
2
2
  import { RPC_CONTRACTS } from '../internal/rpc-contract.js'
3
- import { SETTINGS_NAMESPACE } from '../internal/config-spec.js'
3
+ import { CONFIG_DEFAULTS, SETTINGS_NAMESPACE } from '../internal/config-spec.js'
4
4
  import { createPtcToolView } from './client-tool-view.js'
5
5
  import { createPtcSettingsView } from './client-settings-view.js'
6
6
  import { createReplView } from './client-repl-view.js'
@@ -11,6 +11,7 @@ import { createBindingConsole } from './client-console.js'
11
11
  import {
12
12
  createMenuChildrenEvidence,
13
13
  hostIconComponents,
14
+ isHostComponent,
14
15
  isHostIconComponent,
15
16
  isIdleSessionComposer,
16
17
  publishSettingsCard,
@@ -29,22 +30,85 @@ import { featureEnabled, registerGated } from './client-feature-gates.js'
29
30
  import { createCatalogOwner } from './client-catalog.js'
30
31
  import { createUserBindingsWorkbench } from './client-workbench.js'
31
32
  import { createBindingCommandAvailability, createReplObserver } from './client-transport.js'
33
+ import { createActionButton, resolvePrimitives } from './client-primitives.js'
34
+
35
+ /** Settings snapshot used until the installed generation serves a transport. */
36
+ const UNAVAILABLE_PREFERENCE = Object.freeze({
37
+ status: 'unavailable',
38
+ writable: false,
39
+ value: CONFIG_DEFAULTS,
40
+ })
41
+
42
+ /**
43
+ * Resolve the settings preference scope of the running generation without
44
+ * depending on that generation publishing a particular transport name: the
45
+ * current one serves `configForms` and the preceding one served
46
+ * `settingsScope`. The plugin exposes the shipped Config defaults until a
47
+ * transport appears, prefers the current one, and retains live alternatives.
48
+ * A renamed or omitted transport degrades the settings surface instead of
49
+ * suspending apply() before any contribution is registered.
50
+ */
51
+ function createPreferenceScope(ctx) {
52
+ const listeners = new Set()
53
+ const registrations = new Map()
54
+ let bound
55
+ const notify = () => { for (const listener of [...listeners]) listener() }
56
+ const sync = () => {
57
+ const next = registrations.get('configForms') ?? registrations.get('settingsScope')
58
+ if (bound === next) return
59
+ bound = next
60
+ notify()
61
+ }
62
+ const adopt = (name, scope) => {
63
+ if (scope === undefined || scope === null) return undefined
64
+ const registration = { scope }
65
+ const unsubscribe = typeof scope.subscribe === 'function' ? scope.subscribe(() => {
66
+ if (bound === registration) notify()
67
+ }) : undefined
68
+ registrations.set(name, registration)
69
+ sync()
70
+ return () => {
71
+ unsubscribe?.()
72
+ if (registrations.get(name) !== registration) return
73
+ registrations.delete(name)
74
+ sync()
75
+ }
76
+ }
77
+ ctx.inject(['configForms'], scope => adopt('configForms', scope.configForms.get(SETTINGS_NAMESPACE)))
78
+ ctx.inject(['settingsScope'], scope => adopt('settingsScope', scope.settingsScope.bind({ namespace: SETTINGS_NAMESPACE })))
79
+ return Object.freeze({
80
+ getSnapshot: () => bound?.scope.getSnapshot() ?? UNAVAILABLE_PREFERENCE,
81
+ subscribe(listener) {
82
+ listeners.add(listener)
83
+ return () => listeners.delete(listener)
84
+ },
85
+ set: (key, value) => bound?.scope.set(key, value),
86
+ mutate: patch => bound?.scope.mutate(patch),
87
+ })
88
+ }
32
89
 
33
90
  window.__ModuleLoader__.load({
34
91
  // Replaced by the bundle entry with the package name from package.json.
35
92
  id: __PTC_PLUS_CLIENT_MODULE_ID__,
36
93
  factory: (require) => {
37
94
  const React = require('react')
38
- const primitives = require('@deepseek-ai/dsh-client-ui-primitives')
95
+ const { createPortal } = require('react-dom')
96
+ let primitives
97
+ try {
98
+ primitives = require('@deepseek-ai/dsh-client-ui-primitives') ?? {}
99
+ } catch {
100
+ primitives = {}
101
+ }
39
102
  const {
40
103
  Button,
41
104
  CodeBlock,
42
105
  DisclosureRow,
43
106
  Menu,
107
+ MenuFallback,
44
108
  Modal,
45
109
  Toast,
46
110
  Tooltip,
47
- } = primitives
111
+ } = resolvePrimitives(primitives, React, createPortal)
48
112
  const {
49
113
  check: IconCheckOutline14,
50
114
  chevron: IconChevronDownOutline14,
@@ -66,17 +130,10 @@ window.__ModuleLoader__.load({
66
130
  function IconButton({ icon: Icon, label, ...props }) {
67
131
  const button = h('button', { ...props, type: 'button', className: 'ptcPlusIconButton',
68
132
  'aria-label': label, title: label }, isHostIconComponent(Icon) ? h(Icon, { size: 16 }) : label)
69
- return typeof Tooltip === 'function' ? h(Tooltip, { label, delayMs: 400 }, button) : button
133
+ return isHostComponent(Tooltip) ? h(Tooltip, { label, delayMs: 400 }, button) : button
70
134
  }
71
135
 
72
- function ActionButton({ className = '', 'data-kind': kind, ...props }) {
73
- return typeof Button === 'function'
74
- ? h(Button, {
75
- ...props, size: 'sm', variant: kind === 'primary' ? 'primary' : kind === 'ghost' ? 'ghost' : 'outline',
76
- className: className.split(' ').filter(name => name !== 'ptcPlusButton').join(' '),
77
- })
78
- : h('button', { ...props, className, 'data-kind': kind })
79
- }
136
+ const ActionButton = createActionButton(React, Button)
80
137
 
81
138
  const BindingConsole = createBindingConsole(React, { TypeScriptEditor, IconButton, ActionButton,
82
139
  icons: { play: IconPlayOutline16, stop: IconStopFill16, reset: IconRefreshOutline16, clear: IconTrashOutline16 } })
@@ -85,40 +142,9 @@ window.__ModuleLoader__.load({
85
142
  icons: { chevron: IconChevronDownOutline14, check: IconCheckOutline14, inspect: IconInspectOutline12 },
86
143
  })
87
144
 
88
- /**
89
- * Resolve the settings transport of the running generation. The current
90
- * release publishes `configForms`; the preceding one published
91
- * `settingsScope`. Both are optional child injections so the client entry
92
- * does not stay pending on the name the installed generation does not use.
93
- */
94
- function settingsPreferenceScope(ctx) {
95
- return new Promise((resolve, reject) => {
96
- let settled = false
97
- let configFormsWatcher
98
- let settingsScopeWatcher
99
- const take = (name, scope) => {
100
- if (settled) return
101
- settled = true
102
- if (name !== 'configForms' && typeof configFormsWatcher === 'function') configFormsWatcher()
103
- if (name !== 'settingsScope' && typeof settingsScopeWatcher === 'function') settingsScopeWatcher()
104
- resolve(name === 'configForms'
105
- ? scope.configForms.get(SETTINGS_NAMESPACE)
106
- : scope.settingsScope.bind({ namespace: SETTINGS_NAMESPACE }))
107
- }
108
- try {
109
- configFormsWatcher = ctx.inject(['configForms'], scope => take('configForms', scope))
110
- if (!settled) {
111
- settingsScopeWatcher = ctx.inject(['settingsScope'], scope => take('settingsScope', scope))
112
- }
113
- } catch (error) {
114
- reject(error)
115
- }
116
- })
117
- }
118
-
119
145
  async function apply(ctx) {
120
146
  const rpc = await createClientRpc(ctx)
121
- const preferenceScope = await settingsPreferenceScope(ctx)
147
+ const preferenceScope = createPreferenceScope(ctx)
122
148
  ctx.effect(() => ctx.locale.register(LOCALE_NS, SETTINGS_COPY), 'ptc-plus: settings dictionaries')
123
149
  ctx.effect(installStyles, 'ptc-plus: client styles')
124
150
 
@@ -255,7 +281,7 @@ window.__ModuleLoader__.load({
255
281
  // One probe answer serves every session's composer entry for this Client.
256
282
  const menuChildren = createMenuChildrenEvidence()
257
283
  const { BindingAuthorButton, BindingReviewDock, BindingCommandCard } = createAuthoringView(React, {
258
- ActionButton, IconButton, Menu, Toast, Tooltip, CodeBlock, BindingsDialog, PTCPlusSettingsDialog,
284
+ ActionButton, IconButton, Menu, MenuFallback, Toast, Tooltip, CodeBlock, Modal, createPortal, BindingsDialog, PTCPlusSettingsDialog,
259
285
  useWorkbenchController, useBindingReview, catalogOwner, callUserBindings, subscribeReset,
260
286
  settingsCardSeat: settingsCard.seat, updateSetting, menuChildren,
261
287
  icons: {
@@ -280,7 +306,7 @@ window.__ModuleLoader__.load({
280
306
  }, props => h(BindingCommandCard, { ...props, key: props.node.commandId })))))
281
307
  ctx.slots.inject('conversation.input.dock', () => ctx.slots.inject('conversation.input.left', () =>
282
308
  registerGated(ctx, settingsGate('bindings', () => ctx.slots.register({
283
- name: 'conversation.input.dock', id: 'ptc-plus-binding-review', order: 30, locale: LOCALE_NS,
309
+ name: 'conversation.input.dock', id: 'ptc-plus-binding-review', order: -30, locale: LOCALE_NS,
284
310
  }, props => typeof props.useProjection === 'function' && props.sessionId !== undefined
285
311
  ? h(BindingReviewDock, { ...props, key: props.sessionId }) : null)))))
286
312
  const availability = createBindingCommandAvailability(ctx)
Binary file
Binary file
Binary file
Binary file