@custardui/custardui 2.0.0 → 2.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/custardui.js +1296 -455
  2. package/dist/custardui.js.map +1 -1
  3. package/dist/custardui.min.js +2 -2
  4. package/dist/custardui.min.js.map +1 -1
  5. package/dist/types/src/lib/features/adaptation/adaptation-manager.d.ts +1 -1
  6. package/dist/types/src/lib/features/adaptation/adaptation-manager.d.ts.map +1 -1
  7. package/dist/types/src/lib/features/anchor/descriptor.d.ts +6 -0
  8. package/dist/types/src/lib/features/anchor/descriptor.d.ts.map +1 -0
  9. package/dist/types/src/lib/features/anchor/index.d.ts +5 -0
  10. package/dist/types/src/lib/features/anchor/index.d.ts.map +1 -0
  11. package/dist/types/src/lib/features/anchor/resolver.d.ts +8 -0
  12. package/dist/types/src/lib/features/anchor/resolver.d.ts.map +1 -0
  13. package/dist/types/src/lib/features/anchor/serializer.d.ts +21 -0
  14. package/dist/types/src/lib/features/anchor/serializer.d.ts.map +1 -0
  15. package/dist/types/src/lib/features/anchor/stable-text.d.ts +41 -0
  16. package/dist/types/src/lib/features/anchor/stable-text.d.ts.map +1 -0
  17. package/dist/types/src/lib/features/anchor/types.d.ts +17 -0
  18. package/dist/types/src/lib/features/anchor/types.d.ts.map +1 -0
  19. package/dist/types/src/lib/features/highlight/services/highlight-colors.d.ts.map +1 -1
  20. package/dist/types/src/lib/features/highlight/services/highlight-service.svelte.d.ts +1 -1
  21. package/dist/types/src/lib/features/highlight/services/highlight-service.svelte.d.ts.map +1 -1
  22. package/dist/types/src/lib/features/share/stores/share-store.svelte.d.ts.map +1 -1
  23. package/dist/types/src/lib/stores/active-state-store.svelte.d.ts +4 -4
  24. package/dist/types/src/lib/stores/active-state-store.svelte.d.ts.map +1 -1
  25. package/dist/types/src/lib/utils/scroll-utils.d.ts +43 -11
  26. package/dist/types/src/lib/utils/scroll-utils.d.ts.map +1 -1
  27. package/dist/types/tests/lib/features/anchor/anchor.test.d.ts +2 -0
  28. package/dist/types/tests/lib/features/anchor/anchor.test.d.ts.map +1 -0
  29. package/package.json +2 -2
  30. package/dist/types/src/lib/utils/dom-element-locator.d.ts +0 -35
  31. package/dist/types/src/lib/utils/dom-element-locator.d.ts.map +0 -1
  32. package/dist/types/tests/lib/utils/dom-element-locator.test.d.ts +0 -2
  33. package/dist/types/tests/lib/utils/dom-element-locator.test.d.ts.map +0 -1
package/dist/custardui.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @custardui/custardui v2.0.0
2
+ * @custardui/custardui v2.0.1-beta.0
3
3
  * (c) 2026 Chan Ger Teck
4
4
  * Released under the MIT License.
5
5
  */
@@ -4100,6 +4100,19 @@
4100
4100
  }
4101
4101
  }
4102
4102
 
4103
+ /**
4104
+ * Returns a promise that resolves once any pending state changes have been applied.
4105
+ * @returns {Promise<void>}
4106
+ */
4107
+ async function tick() {
4108
+
4109
+ await Promise.resolve();
4110
+
4111
+ // By calling flushSync we guarantee that any pending state changes are applied after one tick.
4112
+ // TODO look into whether we can make flushing subsequent updates synchronously in the future.
4113
+ flushSync();
4114
+ }
4115
+
4103
4116
  /**
4104
4117
  * @template V
4105
4118
  * @param {Value<V>} signal
@@ -6199,6 +6212,29 @@
6199
6212
  }
6200
6213
  }
6201
6214
 
6215
+ /** @import { TemplateNode, Dom } from '#client' */
6216
+
6217
+ /**
6218
+ * @template P
6219
+ * @template {(props: P) => void} C
6220
+ * @param {TemplateNode} node
6221
+ * @param {() => C} get_component
6222
+ * @param {(anchor: TemplateNode, component: C) => Dom | void} render_fn
6223
+ * @returns {void}
6224
+ */
6225
+ function component(node, get_component, render_fn) {
6226
+ if (hydrating) {
6227
+ hydrate_next();
6228
+ }
6229
+
6230
+ var branches = new BranchManager(node);
6231
+
6232
+ block(() => {
6233
+ var component = get_component() ?? null;
6234
+ branches.ensure(component, component && ((target) => render_fn(target, component)));
6235
+ }, EFFECT_TRANSPARENT);
6236
+ }
6237
+
6202
6238
  /** @import { Raf } from '#client' */
6203
6239
 
6204
6240
  const now = () => performance.now() ;
@@ -9352,12 +9388,12 @@
9352
9388
 
9353
9389
  // --- Actions ---
9354
9390
  /**
9355
- * Set the pinned tab for a specific tab group.
9391
+ * Set the marked tab for a specific tab group.
9356
9392
  * This syncs across all tab groups with the same ID.
9357
9393
  * @param groupId The ID of the tab group.
9358
- * @param tabId The ID of the tab to pin.
9394
+ * @param tabId The ID of the tab to mark.
9359
9395
  */
9360
- setPinnedTab(groupId, tabId) {
9396
+ setMarkedTab(groupId, tabId) {
9361
9397
  if (!this.state.tabs) this.state.tabs = {};
9362
9398
 
9363
9399
  this.state.tabs[groupId] = tabId;
@@ -9497,14 +9533,7 @@
9497
9533
  const tabs = {};
9498
9534
  const placeholders = {};
9499
9535
 
9500
- // 1. Process global placeholders
9501
- for (const p of this.config.placeholders ?? []) {
9502
- if (p.defaultValue !== undefined) {
9503
- placeholders[p.name] = p.defaultValue;
9504
- }
9505
- }
9506
-
9507
- // 2. Process toggles
9536
+ // 1. Process toggles
9508
9537
  for (const toggle of this.config.toggles ?? []) {
9509
9538
  if (toggle.default === 'peek') {
9510
9539
  peekToggles.push(toggle.toggleId);
@@ -9513,7 +9542,7 @@
9513
9542
  }
9514
9543
  }
9515
9544
 
9516
- // 3. Process tab groups
9545
+ // 2. Process tab groups
9517
9546
  for (const group of this.config.tabGroups ?? []) {
9518
9547
  let defaultTabId = group.default;
9519
9548
 
@@ -9540,6 +9569,15 @@
9540
9569
  }
9541
9570
  }
9542
9571
 
9572
+ // 3. Seed author-controlled (adaptationPlaceholder) defaults.
9573
+ // These are set by adaptations when active, and fall back to defaultValue when no adaptation is active.
9574
+ // This is intentionally separate from regular user-settable placeholder defaults (see PR #206).
9575
+ for (const def of placeholderRegistryStore.definitions) {
9576
+ if (def.adaptationPlaceholder && def.defaultValue !== undefined && def.defaultValue !== '') {
9577
+ placeholders[def.name] = def.defaultValue;
9578
+ }
9579
+ }
9580
+
9543
9581
  return { shownToggles, peekToggles, tabs, placeholders };
9544
9582
  }
9545
9583
 
@@ -9989,15 +10027,15 @@
9989
10027
 
9990
10028
  const derivedStore = new DerivedStateStore();
9991
10029
 
9992
- var root$t = from_html(`<div><div role="alert"><button class="close-btn svelte-ysaqmb" aria-label="Dismiss intro">×</button> <p class="text svelte-ysaqmb"> </p></div></div>`);
10030
+ var root$w = from_html(`<div><div role="alert"><button type="button" class="close-btn svelte-ysaqmb" aria-label="Dismiss intro">×</button> <p class="text svelte-ysaqmb"> </p></div></div>`);
9993
10031
 
9994
- const $$css$m = {
10032
+ const $$css$o = {
9995
10033
  hash: 'svelte-ysaqmb',
9996
10034
  code: '\n /* Animation */\n @keyframes svelte-ysaqmb-popIn {\n 0% {\n opacity: 0;\n transform: scale(0.9) translateY(-50%);\n }\n 100% {\n opacity: 1;\n transform: scale(1) translateY(-50%);\n }\n }\n\n /* Reset transform for top/bottom positions */\n @keyframes svelte-ysaqmb-popInVertical {\n 0% {\n opacity: 0;\n transform: scale(0.9);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Simplified Pulse Animation - Shadow Only */\n @keyframes svelte-ysaqmb-pulse {\n 0% {\n transform: scale(1);\n box-shadow:\n 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n 0 0 0 0 rgba(62, 132, 244, 0.7);\n }\n 50% {\n transform: scale(1);\n box-shadow:\n 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n 0 0 0 10px rgba(62, 132, 244, 0);\n }\n 100% {\n transform: scale(1);\n box-shadow:\n 0 4px 6px -1px rgba(0, 0, 0, 0.1),\n 0 0 0 0 rgba(62, 132, 244, 0);\n }\n }\n\n /* Wrapper handles Positioning & Entry Animation */.cv-callout-wrapper.svelte-ysaqmb {position:fixed;z-index:9999;\n\n /* Default animation (centered ones) */\n animation: svelte-ysaqmb-popIn 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;}\n\n /* Inner handles Visuals & Pulse Animation */.cv-callout.svelte-ysaqmb {background:var(--cv-callout-bg, var(--cv-bg));padding:1rem 1.25rem;border-radius:0.5rem;box-shadow:0 4px 6px -1px var(--cv-shadow),\n 0 2px 4px -1px var(--cv-shadow); /* adapt shadow? */max-width:250px;font-size:0.9rem;line-height:1.5;color:var(--cv-callout-text, var(--cv-text));display:flex;align-items:flex-start;gap:0.75rem;font-family:inherit;border:2px solid var(--cv-border);}\n\n /* Apply pulse to inner callout if enabled */.cv-callout.cv-pulse.svelte-ysaqmb {\n animation: svelte-ysaqmb-pulse 2s infinite 0.5s;}\n\n /* Arrow Base */.cv-callout.svelte-ysaqmb::before {content:\'\';position:absolute;width:1rem;height:1rem;background:var(--cv-callout-bg, var(--cv-bg));transform:rotate(45deg);border:2px solid var(--cv-border);z-index:-1;}.close-btn.svelte-ysaqmb {background:transparent;border:none;color:currentColor;opacity:0.7;font-size:1.25rem;line-height:1;cursor:pointer;padding:0;margin:-0.25rem -0.5rem 0 0;transition:opacity 0.15s;flex-shrink:0;}.close-btn.svelte-ysaqmb:hover {color:currentColor;opacity:1;}.text.svelte-ysaqmb {margin:0;flex:1;font-weight:500;}\n\n /* \n Position Specifics (Applied to Wrapper)\n */\n\n /* Right-side positions (Icon on Right -> Callout on Left) */.pos-top-right.svelte-ysaqmb,\n .pos-middle-right.svelte-ysaqmb,\n .pos-bottom-right.svelte-ysaqmb {right:80px;}.pos-top-right.svelte-ysaqmb,\n .pos-bottom-right.svelte-ysaqmb {\n animation-name: svelte-ysaqmb-popInVertical;}\n\n /* X Button Spacing Adjustments */.pos-top-right.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb),\n .pos-middle-right.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb),\n .pos-bottom-right.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb) {margin-right:0;margin-left:-0.5rem;}\n\n /* Left-side positions (Icon on Left -> Callout on Right) */.pos-top-left.svelte-ysaqmb,\n .pos-middle-left.svelte-ysaqmb,\n .pos-bottom-left.svelte-ysaqmb {left:80px;}.pos-top-left.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb),\n .pos-middle-left.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb),\n .pos-bottom-left.svelte-ysaqmb .close-btn:where(.svelte-ysaqmb) {order:2; /* Move to end */margin-right:-0.5rem;margin-left:0;}.pos-top-left.svelte-ysaqmb,\n .pos-bottom-left.svelte-ysaqmb {\n animation-name: svelte-ysaqmb-popInVertical;}\n\n /* Vertical Alignment */.pos-middle-right.svelte-ysaqmb,\n .pos-middle-left.svelte-ysaqmb {top:50%;\n /* transform handled by popIn animation (translateY -50%) */}.pos-top-right.svelte-ysaqmb,\n .pos-top-left.svelte-ysaqmb {top:20px;}.pos-bottom-right.svelte-ysaqmb,\n .pos-bottom-left.svelte-ysaqmb {bottom:20px;}\n\n /* Arrow Positioning (Child of .callout, dependent on Wrapper .pos-*) */\n\n /* Pointing Right */.pos-top-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-middle-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-bottom-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before {right:-0.5rem;border-left:none;border-bottom:none;}\n\n /* Pointing Left */.pos-top-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-middle-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-bottom-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before {left:-0.5rem;border-right:none;border-top:none;}\n\n /* Vertical placement of arrow */.pos-middle-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-middle-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before {top:50%;margin-top:-0.5rem;}.pos-top-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-top-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before {top:1.25rem;}.pos-bottom-right.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before,\n .pos-bottom-left.svelte-ysaqmb .cv-callout:where(.svelte-ysaqmb)::before {bottom:1.25rem;}\n\n @media print {.cv-callout-wrapper.svelte-ysaqmb {display:none !important;}\n }'
9997
10035
  };
9998
10036
 
9999
10037
  function IntroCallout($$anchor, $$props) {
10000
- append_styles$1($$anchor, $$css$m);
10038
+ append_styles$1($$anchor, $$css$o);
10001
10039
 
10002
10040
  let position = prop($$props, 'position', 3, 'middle-left'),
10003
10041
  message = prop($$props, 'message', 3, 'Customize your reading experience here.'),
@@ -10014,7 +10052,7 @@
10014
10052
  "top" -> aligned top
10015
10053
  "bottom" -> aligned bottom
10016
10054
  */
10017
- div = root$t();
10055
+ div = root$w();
10018
10056
 
10019
10057
  var div_1 = child(div);
10020
10058
  let styles;
@@ -10048,11 +10086,11 @@
10048
10086
 
10049
10087
  delegate(['click']);
10050
10088
 
10051
- var root$s = from_svg(`<svg><path xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" d="M12 8.00002C9.79085 8.00002 7.99999 9.79088 7.99999 12C7.99999 14.2092 9.79085 16 12 16C14.2091 16 16 14.2092 16 12C16 9.79088 14.2091 8.00002 12 8.00002ZM9.99999 12C9.99999 10.8955 10.8954 10 12 10C13.1046 10 14 10.8955 14 12C14 13.1046 13.1046 14 12 14C10.8954 14 9.99999 13.1046 9.99999 12Z" fill="#0F1729"></path><path xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" d="M10.7673 1.01709C10.9925 0.999829 11.2454 0.99993 11.4516 1.00001L12.5484 1.00001C12.7546 0.99993 13.0075 0.999829 13.2327 1.01709C13.4989 1.03749 13.8678 1.08936 14.2634 1.26937C14.7635 1.49689 15.1915 1.85736 15.5007 2.31147C15.7454 2.67075 15.8592 3.0255 15.9246 3.2843C15.9799 3.50334 16.0228 3.75249 16.0577 3.9557L16.1993 4.77635L16.2021 4.77788C16.2369 4.79712 16.2715 4.81659 16.306 4.8363L16.3086 4.83774L17.2455 4.49865C17.4356 4.42978 17.6693 4.34509 17.8835 4.28543C18.1371 4.2148 18.4954 4.13889 18.9216 4.17026C19.4614 4.20998 19.9803 4.39497 20.4235 4.70563C20.7734 4.95095 21.0029 5.23636 21.1546 5.4515C21.2829 5.63326 21.4103 5.84671 21.514 6.02029L22.0158 6.86003C22.1256 7.04345 22.2594 7.26713 22.3627 7.47527C22.4843 7.7203 22.6328 8.07474 22.6777 8.52067C22.7341 9.08222 22.6311 9.64831 22.3803 10.1539C22.1811 10.5554 21.9171 10.8347 21.7169 11.0212C21.5469 11.1795 21.3428 11.3417 21.1755 11.4746L20.5 12L21.1755 12.5254C21.3428 12.6584 21.5469 12.8205 21.7169 12.9789C21.9171 13.1653 22.1811 13.4446 22.3802 13.8461C22.631 14.3517 22.7341 14.9178 22.6776 15.4794C22.6328 15.9253 22.4842 16.2797 22.3626 16.5248C22.2593 16.7329 22.1255 16.9566 22.0158 17.14L21.5138 17.9799C21.4102 18.1535 21.2828 18.3668 21.1546 18.5485C21.0028 18.7637 20.7734 19.0491 20.4234 19.2944C19.9803 19.6051 19.4613 19.7901 18.9216 19.8298C18.4954 19.8612 18.1371 19.7852 17.8835 19.7146C17.6692 19.6549 17.4355 19.5703 17.2454 19.5014L16.3085 19.1623L16.306 19.1638C16.2715 19.1835 16.2369 19.2029 16.2021 19.2222L16.1993 19.2237L16.0577 20.0443C16.0228 20.2475 15.9799 20.4967 15.9246 20.7157C15.8592 20.9745 15.7454 21.3293 15.5007 21.6886C15.1915 22.1427 14.7635 22.5032 14.2634 22.7307C13.8678 22.9107 13.4989 22.9626 13.2327 22.983C13.0074 23.0002 12.7546 23.0001 12.5484 23H11.4516C11.2454 23.0001 10.9925 23.0002 10.7673 22.983C10.5011 22.9626 10.1322 22.9107 9.73655 22.7307C9.23648 22.5032 8.80849 22.1427 8.49926 21.6886C8.25461 21.3293 8.14077 20.9745 8.07542 20.7157C8.02011 20.4967 7.97723 20.2475 7.94225 20.0443L7.80068 19.2237L7.79791 19.2222C7.7631 19.2029 7.72845 19.1835 7.69396 19.1637L7.69142 19.1623L6.75458 19.5014C6.5645 19.5702 6.33078 19.6549 6.11651 19.7146C5.86288 19.7852 5.50463 19.8611 5.07841 19.8298C4.53866 19.7901 4.01971 19.6051 3.57654 19.2944C3.2266 19.0491 2.99714 18.7637 2.84539 18.5485C2.71718 18.3668 2.58974 18.1534 2.4861 17.9798L1.98418 17.14C1.87447 16.9566 1.74067 16.7329 1.63737 16.5248C1.51575 16.2797 1.36719 15.9253 1.32235 15.4794C1.26588 14.9178 1.36897 14.3517 1.61976 13.8461C1.81892 13.4446 2.08289 13.1653 2.28308 12.9789C2.45312 12.8205 2.65717 12.6584 2.82449 12.5254L3.47844 12.0054V11.9947L2.82445 11.4746C2.65712 11.3417 2.45308 11.1795 2.28304 11.0212C2.08285 10.8347 1.81888 10.5554 1.61972 10.1539C1.36893 9.64832 1.26584 9.08224 1.3223 8.52069C1.36714 8.07476 1.51571 7.72032 1.63732 7.47528C1.74062 7.26715 1.87443 7.04347 1.98414 6.86005L2.48605 6.02026C2.58969 5.84669 2.71714 5.63326 2.84534 5.45151C2.9971 5.23637 3.22655 4.95096 3.5765 4.70565C4.01966 4.39498 4.53862 4.20999 5.07837 4.17027C5.50458 4.1389 5.86284 4.21481 6.11646 4.28544C6.33072 4.34511 6.56444 4.4298 6.75451 4.49867L7.69141 4.83775L7.69394 4.8363C7.72844 4.8166 7.7631 4.79712 7.79791 4.77788L7.80068 4.77635L7.94225 3.95571C7.97723 3.7525 8.02011 3.50334 8.07542 3.2843C8.14077 3.0255 8.25461 2.67075 8.49926 2.31147C8.80849 1.85736 9.23648 1.49689 9.73655 1.26937C10.1322 1.08936 10.5011 1.03749 10.7673 1.01709ZM14.0938 4.3363C14.011 3.85634 13.9696 3.61637 13.8476 3.43717C13.7445 3.2858 13.6019 3.16564 13.4352 3.0898C13.2378 3.00002 12.9943 3.00002 12.5073 3.00002H11.4927C11.0057 3.00002 10.7621 3.00002 10.5648 3.0898C10.3981 3.16564 10.2555 3.2858 10.1524 3.43717C10.0304 3.61637 9.98895 3.85634 9.90615 4.3363L9.75012 5.24064C9.69445 5.56333 9.66662 5.72467 9.60765 5.84869C9.54975 5.97047 9.50241 6.03703 9.40636 6.13166C9.30853 6.22804 9.12753 6.3281 8.76554 6.52822C8.73884 6.54298 8.71227 6.55791 8.68582 6.57302C8.33956 6.77078 8.16643 6.86966 8.03785 6.90314C7.91158 6.93602 7.83293 6.94279 7.70289 6.93196C7.57049 6.92094 7.42216 6.86726 7.12551 6.7599L6.11194 6.39308C5.66271 6.2305 5.43809 6.14921 5.22515 6.16488C5.04524 6.17811 4.87225 6.23978 4.72453 6.34333C4.5497 6.46589 4.42715 6.67094 4.18206 7.08103L3.72269 7.84965C3.46394 8.2826 3.33456 8.49907 3.31227 8.72078C3.29345 8.90796 3.32781 9.09665 3.41141 9.26519C3.51042 9.4648 3.7078 9.62177 4.10256 9.9357L4.82745 10.5122C5.07927 10.7124 5.20518 10.8126 5.28411 10.9199C5.36944 11.036 5.40583 11.1114 5.44354 11.2504C5.47844 11.379 5.47844 11.586 5.47844 12C5.47844 12.414 5.47844 12.621 5.44354 12.7497C5.40582 12.8887 5.36944 12.9641 5.28413 13.0801C5.20518 13.1875 5.07927 13.2876 4.82743 13.4879L4.10261 14.0643C3.70785 14.3783 3.51047 14.5352 3.41145 14.7349C3.32785 14.9034 3.29349 15.0921 3.31231 15.2793C3.33461 15.501 3.46398 15.7174 3.72273 16.1504L4.1821 16.919C4.4272 17.3291 4.54974 17.5342 4.72457 17.6567C4.8723 17.7603 5.04528 17.8219 5.2252 17.8352C5.43813 17.8508 5.66275 17.7695 6.11199 17.607L7.12553 17.2402C7.42216 17.1328 7.5705 17.0791 7.7029 17.0681C7.83294 17.0573 7.91159 17.064 8.03786 17.0969C8.16644 17.1304 8.33956 17.2293 8.68582 17.427C8.71228 17.4421 8.73885 17.4571 8.76554 17.4718C9.12753 17.6719 9.30853 17.772 9.40635 17.8684C9.50241 17.963 9.54975 18.0296 9.60765 18.1514C9.66662 18.2754 9.69445 18.4367 9.75012 18.7594L9.90615 19.6637C9.98895 20.1437 10.0304 20.3837 10.1524 20.5629C10.2555 20.7142 10.3981 20.8344 10.5648 20.9102C10.7621 21 11.0057 21 11.4927 21H12.5073C12.9943 21 13.2378 21 13.4352 20.9102C13.6019 20.8344 13.7445 20.7142 13.8476 20.5629C13.9696 20.3837 14.011 20.1437 14.0938 19.6637L14.2499 18.7594C14.3055 18.4367 14.3334 18.2754 14.3923 18.1514C14.4502 18.0296 14.4976 17.963 14.5936 17.8684C14.6915 17.772 14.8725 17.6719 15.2344 17.4718C15.2611 17.4571 15.2877 17.4421 15.3141 17.427C15.6604 17.2293 15.8335 17.1304 15.9621 17.0969C16.0884 17.064 16.167 17.0573 16.2971 17.0681C16.4295 17.0791 16.5778 17.1328 16.8744 17.2402L17.888 17.607C18.3372 17.7696 18.5619 17.8509 18.7748 17.8352C18.9547 17.8219 19.1277 17.7603 19.2754 17.6567C19.4502 17.5342 19.5728 17.3291 19.8179 16.919L20.2773 16.1504C20.536 15.7175 20.6654 15.501 20.6877 15.2793C20.7065 15.0921 20.6721 14.9034 20.5885 14.7349C20.4895 14.5353 20.2921 14.3783 19.8974 14.0643L19.1726 13.4879C18.9207 13.2876 18.7948 13.1875 18.7159 13.0801C18.6306 12.9641 18.5942 12.8887 18.5564 12.7497C18.5215 12.6211 18.5215 12.414 18.5215 12C18.5215 11.586 18.5215 11.379 18.5564 11.2504C18.5942 11.1114 18.6306 11.036 18.7159 10.9199C18.7948 10.8126 18.9207 10.7124 19.1725 10.5122L19.8974 9.9357C20.2922 9.62176 20.4896 9.46479 20.5886 9.26517C20.6722 9.09664 20.7065 8.90795 20.6877 8.72076C20.6654 8.49906 20.5361 8.28259 20.2773 7.84964L19.8179 7.08102C19.5728 6.67093 19.4503 6.46588 19.2755 6.34332C19.1277 6.23977 18.9548 6.1781 18.7748 6.16486C18.5619 6.14919 18.3373 6.23048 17.888 6.39307L16.8745 6.75989C16.5778 6.86725 16.4295 6.92093 16.2971 6.93195C16.167 6.94278 16.0884 6.93601 15.9621 6.90313C15.8335 6.86965 15.6604 6.77077 15.3142 6.57302C15.2877 6.55791 15.2611 6.54298 15.2345 6.52822C14.8725 6.3281 14.6915 6.22804 14.5936 6.13166C14.4976 6.03703 14.4502 5.97047 14.3923 5.84869C14.3334 5.72467 14.3055 5.56332 14.2499 5.24064L14.0938 4.3363Z" fill="#0F1729"></path></svg>`);
10089
+ var root$v = from_svg(`<svg><path xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" d="M12 8.00002C9.79085 8.00002 7.99999 9.79088 7.99999 12C7.99999 14.2092 9.79085 16 12 16C14.2091 16 16 14.2092 16 12C16 9.79088 14.2091 8.00002 12 8.00002ZM9.99999 12C9.99999 10.8955 10.8954 10 12 10C13.1046 10 14 10.8955 14 12C14 13.1046 13.1046 14 12 14C10.8954 14 9.99999 13.1046 9.99999 12Z" fill="#0F1729"></path><path xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" d="M10.7673 1.01709C10.9925 0.999829 11.2454 0.99993 11.4516 1.00001L12.5484 1.00001C12.7546 0.99993 13.0075 0.999829 13.2327 1.01709C13.4989 1.03749 13.8678 1.08936 14.2634 1.26937C14.7635 1.49689 15.1915 1.85736 15.5007 2.31147C15.7454 2.67075 15.8592 3.0255 15.9246 3.2843C15.9799 3.50334 16.0228 3.75249 16.0577 3.9557L16.1993 4.77635L16.2021 4.77788C16.2369 4.79712 16.2715 4.81659 16.306 4.8363L16.3086 4.83774L17.2455 4.49865C17.4356 4.42978 17.6693 4.34509 17.8835 4.28543C18.1371 4.2148 18.4954 4.13889 18.9216 4.17026C19.4614 4.20998 19.9803 4.39497 20.4235 4.70563C20.7734 4.95095 21.0029 5.23636 21.1546 5.4515C21.2829 5.63326 21.4103 5.84671 21.514 6.02029L22.0158 6.86003C22.1256 7.04345 22.2594 7.26713 22.3627 7.47527C22.4843 7.7203 22.6328 8.07474 22.6777 8.52067C22.7341 9.08222 22.6311 9.64831 22.3803 10.1539C22.1811 10.5554 21.9171 10.8347 21.7169 11.0212C21.5469 11.1795 21.3428 11.3417 21.1755 11.4746L20.5 12L21.1755 12.5254C21.3428 12.6584 21.5469 12.8205 21.7169 12.9789C21.9171 13.1653 22.1811 13.4446 22.3802 13.8461C22.631 14.3517 22.7341 14.9178 22.6776 15.4794C22.6328 15.9253 22.4842 16.2797 22.3626 16.5248C22.2593 16.7329 22.1255 16.9566 22.0158 17.14L21.5138 17.9799C21.4102 18.1535 21.2828 18.3668 21.1546 18.5485C21.0028 18.7637 20.7734 19.0491 20.4234 19.2944C19.9803 19.6051 19.4613 19.7901 18.9216 19.8298C18.4954 19.8612 18.1371 19.7852 17.8835 19.7146C17.6692 19.6549 17.4355 19.5703 17.2454 19.5014L16.3085 19.1623L16.306 19.1638C16.2715 19.1835 16.2369 19.2029 16.2021 19.2222L16.1993 19.2237L16.0577 20.0443C16.0228 20.2475 15.9799 20.4967 15.9246 20.7157C15.8592 20.9745 15.7454 21.3293 15.5007 21.6886C15.1915 22.1427 14.7635 22.5032 14.2634 22.7307C13.8678 22.9107 13.4989 22.9626 13.2327 22.983C13.0074 23.0002 12.7546 23.0001 12.5484 23H11.4516C11.2454 23.0001 10.9925 23.0002 10.7673 22.983C10.5011 22.9626 10.1322 22.9107 9.73655 22.7307C9.23648 22.5032 8.80849 22.1427 8.49926 21.6886C8.25461 21.3293 8.14077 20.9745 8.07542 20.7157C8.02011 20.4967 7.97723 20.2475 7.94225 20.0443L7.80068 19.2237L7.79791 19.2222C7.7631 19.2029 7.72845 19.1835 7.69396 19.1637L7.69142 19.1623L6.75458 19.5014C6.5645 19.5702 6.33078 19.6549 6.11651 19.7146C5.86288 19.7852 5.50463 19.8611 5.07841 19.8298C4.53866 19.7901 4.01971 19.6051 3.57654 19.2944C3.2266 19.0491 2.99714 18.7637 2.84539 18.5485C2.71718 18.3668 2.58974 18.1534 2.4861 17.9798L1.98418 17.14C1.87447 16.9566 1.74067 16.7329 1.63737 16.5248C1.51575 16.2797 1.36719 15.9253 1.32235 15.4794C1.26588 14.9178 1.36897 14.3517 1.61976 13.8461C1.81892 13.4446 2.08289 13.1653 2.28308 12.9789C2.45312 12.8205 2.65717 12.6584 2.82449 12.5254L3.47844 12.0054V11.9947L2.82445 11.4746C2.65712 11.3417 2.45308 11.1795 2.28304 11.0212C2.08285 10.8347 1.81888 10.5554 1.61972 10.1539C1.36893 9.64832 1.26584 9.08224 1.3223 8.52069C1.36714 8.07476 1.51571 7.72032 1.63732 7.47528C1.74062 7.26715 1.87443 7.04347 1.98414 6.86005L2.48605 6.02026C2.58969 5.84669 2.71714 5.63326 2.84534 5.45151C2.9971 5.23637 3.22655 4.95096 3.5765 4.70565C4.01966 4.39498 4.53862 4.20999 5.07837 4.17027C5.50458 4.1389 5.86284 4.21481 6.11646 4.28544C6.33072 4.34511 6.56444 4.4298 6.75451 4.49867L7.69141 4.83775L7.69394 4.8363C7.72844 4.8166 7.7631 4.79712 7.79791 4.77788L7.80068 4.77635L7.94225 3.95571C7.97723 3.7525 8.02011 3.50334 8.07542 3.2843C8.14077 3.0255 8.25461 2.67075 8.49926 2.31147C8.80849 1.85736 9.23648 1.49689 9.73655 1.26937C10.1322 1.08936 10.5011 1.03749 10.7673 1.01709ZM14.0938 4.3363C14.011 3.85634 13.9696 3.61637 13.8476 3.43717C13.7445 3.2858 13.6019 3.16564 13.4352 3.0898C13.2378 3.00002 12.9943 3.00002 12.5073 3.00002H11.4927C11.0057 3.00002 10.7621 3.00002 10.5648 3.0898C10.3981 3.16564 10.2555 3.2858 10.1524 3.43717C10.0304 3.61637 9.98895 3.85634 9.90615 4.3363L9.75012 5.24064C9.69445 5.56333 9.66662 5.72467 9.60765 5.84869C9.54975 5.97047 9.50241 6.03703 9.40636 6.13166C9.30853 6.22804 9.12753 6.3281 8.76554 6.52822C8.73884 6.54298 8.71227 6.55791 8.68582 6.57302C8.33956 6.77078 8.16643 6.86966 8.03785 6.90314C7.91158 6.93602 7.83293 6.94279 7.70289 6.93196C7.57049 6.92094 7.42216 6.86726 7.12551 6.7599L6.11194 6.39308C5.66271 6.2305 5.43809 6.14921 5.22515 6.16488C5.04524 6.17811 4.87225 6.23978 4.72453 6.34333C4.5497 6.46589 4.42715 6.67094 4.18206 7.08103L3.72269 7.84965C3.46394 8.2826 3.33456 8.49907 3.31227 8.72078C3.29345 8.90796 3.32781 9.09665 3.41141 9.26519C3.51042 9.4648 3.7078 9.62177 4.10256 9.9357L4.82745 10.5122C5.07927 10.7124 5.20518 10.8126 5.28411 10.9199C5.36944 11.036 5.40583 11.1114 5.44354 11.2504C5.47844 11.379 5.47844 11.586 5.47844 12C5.47844 12.414 5.47844 12.621 5.44354 12.7497C5.40582 12.8887 5.36944 12.9641 5.28413 13.0801C5.20518 13.1875 5.07927 13.2876 4.82743 13.4879L4.10261 14.0643C3.70785 14.3783 3.51047 14.5352 3.41145 14.7349C3.32785 14.9034 3.29349 15.0921 3.31231 15.2793C3.33461 15.501 3.46398 15.7174 3.72273 16.1504L4.1821 16.919C4.4272 17.3291 4.54974 17.5342 4.72457 17.6567C4.8723 17.7603 5.04528 17.8219 5.2252 17.8352C5.43813 17.8508 5.66275 17.7695 6.11199 17.607L7.12553 17.2402C7.42216 17.1328 7.5705 17.0791 7.7029 17.0681C7.83294 17.0573 7.91159 17.064 8.03786 17.0969C8.16644 17.1304 8.33956 17.2293 8.68582 17.427C8.71228 17.4421 8.73885 17.4571 8.76554 17.4718C9.12753 17.6719 9.30853 17.772 9.40635 17.8684C9.50241 17.963 9.54975 18.0296 9.60765 18.1514C9.66662 18.2754 9.69445 18.4367 9.75012 18.7594L9.90615 19.6637C9.98895 20.1437 10.0304 20.3837 10.1524 20.5629C10.2555 20.7142 10.3981 20.8344 10.5648 20.9102C10.7621 21 11.0057 21 11.4927 21H12.5073C12.9943 21 13.2378 21 13.4352 20.9102C13.6019 20.8344 13.7445 20.7142 13.8476 20.5629C13.9696 20.3837 14.011 20.1437 14.0938 19.6637L14.2499 18.7594C14.3055 18.4367 14.3334 18.2754 14.3923 18.1514C14.4502 18.0296 14.4976 17.963 14.5936 17.8684C14.6915 17.772 14.8725 17.6719 15.2344 17.4718C15.2611 17.4571 15.2877 17.4421 15.3141 17.427C15.6604 17.2293 15.8335 17.1304 15.9621 17.0969C16.0884 17.064 16.167 17.0573 16.2971 17.0681C16.4295 17.0791 16.5778 17.1328 16.8744 17.2402L17.888 17.607C18.3372 17.7696 18.5619 17.8509 18.7748 17.8352C18.9547 17.8219 19.1277 17.7603 19.2754 17.6567C19.4502 17.5342 19.5728 17.3291 19.8179 16.919L20.2773 16.1504C20.536 15.7175 20.6654 15.501 20.6877 15.2793C20.7065 15.0921 20.6721 14.9034 20.5885 14.7349C20.4895 14.5353 20.2921 14.3783 19.8974 14.0643L19.1726 13.4879C18.9207 13.2876 18.7948 13.1875 18.7159 13.0801C18.6306 12.9641 18.5942 12.8887 18.5564 12.7497C18.5215 12.6211 18.5215 12.414 18.5215 12C18.5215 11.586 18.5215 11.379 18.5564 11.2504C18.5942 11.1114 18.6306 11.036 18.7159 10.9199C18.7948 10.8126 18.9207 10.7124 19.1725 10.5122L19.8974 9.9357C20.2922 9.62176 20.4896 9.46479 20.5886 9.26517C20.6722 9.09664 20.7065 8.90795 20.6877 8.72076C20.6654 8.49906 20.5361 8.28259 20.2773 7.84964L19.8179 7.08102C19.5728 6.67093 19.4503 6.46588 19.2755 6.34332C19.1277 6.23977 18.9548 6.1781 18.7748 6.16486C18.5619 6.14919 18.3373 6.23048 17.888 6.39307L16.8745 6.75989C16.5778 6.86725 16.4295 6.92093 16.2971 6.93195C16.167 6.94278 16.0884 6.93601 15.9621 6.90313C15.8335 6.86965 15.6604 6.77077 15.3142 6.57302C15.2877 6.55791 15.2611 6.54298 15.2345 6.52822C14.8725 6.3281 14.6915 6.22804 14.5936 6.13166C14.4976 6.03703 14.4502 5.97047 14.3923 5.84869C14.3334 5.72467 14.3055 5.56332 14.2499 5.24064L14.0938 4.3363Z" fill="#0F1729"></path></svg>`);
10052
10090
 
10053
10091
  function IconGear($$anchor, $$props) {
10054
10092
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10055
- var svg = root$s();
10093
+ var svg = root$v();
10056
10094
 
10057
10095
  attribute_effect(svg, () => ({
10058
10096
  class: 'cv-modal-icon-svg',
@@ -10065,17 +10103,17 @@
10065
10103
  append($$anchor, svg);
10066
10104
  }
10067
10105
 
10068
- var root_1$c = from_html(`<button class="cv-dismiss-btn svelte-122ln5" aria-label="Dismiss settings icon">✕</button>`);
10069
- var root$r = from_html(`<div role="none"><button class="cv-settings-main-btn svelte-122ln5"><span class="cv-gear svelte-122ln5"><!></span></button> <button class="cv-collapse-btn svelte-122ln5" aria-label="Collapse settings icon"> </button> <!></div>`);
10106
+ var root_1$f = from_html(`<button type="button" class="cv-dismiss-btn svelte-122ln5" aria-label="Dismiss settings icon">✕</button>`);
10107
+ var root$u = from_html(`<div role="none"><button type="button" class="cv-settings-main-btn svelte-122ln5"><span class="cv-gear svelte-122ln5"><!></span></button> <button type="button" class="cv-collapse-btn svelte-122ln5" aria-label="Collapse settings icon"> </button> <!></div>`);
10070
10108
 
10071
- const $$css$l = {
10109
+ const $$css$n = {
10072
10110
  hash: 'svelte-122ln5',
10073
10111
  code: '.cv-settings-main-btn.svelte-122ln5 {appearance:none;-webkit-appearance:none;background:transparent;border:none;padding:0;margin:0;flex:1;height:100%;width:100%;display:flex;align-items:inherit;justify-content:inherit;color:inherit;cursor:inherit;border-radius:inherit;}.cv-settings-main-btn.svelte-122ln5:focus-visible {outline:2px solid currentColor;outline-offset:-2px;}.cv-gear.svelte-122ln5 {display:flex;align-items:center;justify-content:center;width:18px;height:18px;}.cv-gear.svelte-122ln5 svg {width:18px;height:18px;}.cv-gear.svelte-122ln5 svg path {fill:currentColor;}.cv-settings-icon.svelte-122ln5 {position:fixed;background:var(--cv-icon-bg, rgba(255, 255, 255, 0.92));color:var(--cv-icon-color, rgba(0, 0, 0, 0.9));opacity:var(--cv-icon-opacity, 0.6);display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:bold;cursor:grab; /* Default cursor */box-shadow:0 4px 12px rgba(0, 0, 0, 0.15);border:2px solid rgba(0, 0, 0, 0.2);z-index:9998;transition:width 0.3s ease,\n background 0.3s ease,\n color 0.3s ease,\n opacity 0.3s ease,\n border-color 0.3s ease,\n transform 0.4s ease; /* transform transition drives the peek slide animation */touch-action:none; /* Crucial for touch dragging */font-family:-apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;box-sizing:border-box;user-select:none; /* Prevent text selection while dragging */}.cv-settings-icon.svelte-122ln5:active {cursor:grabbing;}.cv-settings-icon.svelte-122ln5:hover {background:var(--cv-icon-bg, rgba(255, 255, 255, 1));color:var(--cv-icon-color, rgba(0, 0, 0, 1));opacity:1;border-color:rgba(0, 0, 0, 0.3);}\n\n /* Remove transform transition during drag so it tracks the pointer without lag */.cv-settings-icon.cv-is-dragging.svelte-122ln5 {transition:width 0.3s ease,\n background 0.3s ease,\n color 0.3s ease,\n opacity 0.3s ease,\n border-color 0.3s ease;}\n\n /* When collapsed, dim the strip */.cv-settings-icon.cv-is-collapsed.svelte-122ln5 {opacity:0.5;}.cv-settings-icon.cv-is-collapsed.svelte-122ln5:hover {opacity:0.85;}.cv-collapse-btn.svelte-122ln5 {position:absolute;top:0;bottom:0;width:16px;display:flex;align-items:center;justify-content:center;background:rgba(0, 0, 0, 0.12);border:none;padding:0;cursor:pointer;font-size:13px;line-height:1;color:inherit;opacity:0.5;transition:opacity 0.15s ease, background 0.15s ease;}.cv-collapse-btn[data-side=\'left\'].svelte-122ln5 {left:0; /* outer = screen-edge side for left icons */border-radius:0 6px 6px 0;}.cv-collapse-btn[data-side=\'right\'].svelte-122ln5 {right:0; /* outer = screen-edge side for right icons */border-radius:6px 0 0 6px;}.cv-collapse-btn.svelte-122ln5:hover {opacity:1;background:rgba(0, 0, 0, 0.22);}\n\n /* Hide collapse tab when already collapsed */.cv-settings-icon.cv-is-collapsed.svelte-122ln5 .cv-collapse-btn:where(.svelte-122ln5) {display:none;}.cv-dismiss-btn.svelte-122ln5 {position:absolute;bottom:calc(100% + 4px);width:16px;height:16px;display:flex;align-items:center;justify-content:center;background:rgba(0, 0, 0, 0.15);border:none;border-radius:50%;padding:0;cursor:pointer;font-size:9px;line-height:1;color:inherit;opacity:0.5;transition:opacity 0.15s ease, background 0.15s ease;}.cv-dismiss-btn[data-side=\'left\'].svelte-122ln5 {left:0;}.cv-dismiss-btn[data-side=\'right\'].svelte-122ln5 {right:0;}.cv-dismiss-btn.svelte-122ln5:hover {opacity:1;background:rgba(0, 0, 0, 0.25);}\n\n\n /* Top-right */.cv-settings-top-right.svelte-122ln5 {top:20px;right:0;border-radius:18px 0 0 18px;padding-left:6px;justify-content:flex-start;border-right:none;}\n\n /* Top-left */.cv-settings-top-left.svelte-122ln5 {top:20px;left:0;border-radius:0 18px 18px 0;padding-right:6px;justify-content:flex-end;border-left:none;}\n\n /* Bottom-right */.cv-settings-bottom-right.svelte-122ln5 {bottom:20px;right:0;border-radius:18px 0 0 18px;padding-left:6px;justify-content:flex-start;border-right:none;}\n\n /* Bottom-left */.cv-settings-bottom-left.svelte-122ln5 {bottom:20px;left:0;border-radius:0 18px 18px 0;padding-right:6px;justify-content:flex-end;border-left:none;}\n\n /* Middle-left */.cv-settings-middle-left.svelte-122ln5 {top:50%;left:0;\n /* transform handled by inline style now */border-radius:0 18px 18px 0;padding-right:6px;justify-content:flex-end;border-left:none;}\n\n /* Middle-right */.cv-settings-middle-right.svelte-122ln5 {top:50%;right:0;\n /* transform handled by inline style now */border-radius:18px 0 0 18px;padding-left:6px;justify-content:flex-start;border-right:none;}.cv-settings-top-right.svelte-122ln5,\n .cv-settings-middle-right.svelte-122ln5,\n .cv-settings-bottom-right.svelte-122ln5,\n .cv-settings-top-left.svelte-122ln5,\n .cv-settings-middle-left.svelte-122ln5,\n .cv-settings-bottom-left.svelte-122ln5 {height:36px;width:36px;}.cv-settings-middle-right.svelte-122ln5:hover,\n .cv-settings-top-right.svelte-122ln5:hover,\n .cv-settings-bottom-right.svelte-122ln5:hover,\n .cv-settings-top-left.svelte-122ln5:hover,\n .cv-settings-middle-left.svelte-122ln5:hover,\n .cv-settings-bottom-left.svelte-122ln5:hover {width:55px;}.cv-pulse {\n animation: svelte-122ln5-pulse 2s infinite;}\n\n @keyframes svelte-122ln5-pulse {\n 0% {\n box-shadow:\n 0 4px 12px rgba(0, 0, 0, 0.15),\n 0 0 0 0 rgba(62, 132, 244, 0.7);\n }\n 70% {\n box-shadow:\n 0 4px 12px rgba(0, 0, 0, 0.15),\n 0 0 0 10px rgba(62, 132, 244, 0);\n }\n 100% {\n box-shadow:\n 0 4px 12px rgba(0, 0, 0, 0.15),\n 0 0 0 0 rgba(62, 132, 244, 0);\n }\n }\n\n @media (max-width: 768px) {.cv-settings-top-right.svelte-122ln5,\n .cv-settings-top-left.svelte-122ln5 {top:10px;}.cv-settings-bottom-right.svelte-122ln5,\n .cv-settings-bottom-left.svelte-122ln5 {bottom:10px;}.cv-settings-top-right.svelte-122ln5,\n .cv-settings-bottom-right.svelte-122ln5,\n .cv-settings-middle-right.svelte-122ln5 {right:0;}.cv-settings-top-left.svelte-122ln5,\n .cv-settings-bottom-left.svelte-122ln5,\n .cv-settings-middle-left.svelte-122ln5 {left:0;}.cv-settings-icon.svelte-122ln5 {width:60px;height:32px;}.cv-settings-icon.svelte-122ln5:hover {width:75px;}\n }\n\n @media print {.cv-settings-icon.svelte-122ln5 {display:none !important;}\n }'
10074
10112
  };
10075
10113
 
10076
10114
  function SettingsIcon($$anchor, $$props) {
10077
10115
  push($$props, true);
10078
- append_styles$1($$anchor, $$css$l);
10116
+ append_styles$1($$anchor, $$css$n);
10079
10117
 
10080
10118
  /* eslint-disable @typescript-eslint/no-explicit-any */
10081
10119
  const iconSettingsStore = getContext(ICON_SETTINGS_CTX);
@@ -10287,7 +10325,7 @@
10287
10325
  return t;
10288
10326
  }
10289
10327
 
10290
- var div = root$r();
10328
+ var div = root$u();
10291
10329
  let classes;
10292
10330
 
10293
10331
  div.__mousedown = onMouseDown;
@@ -10320,7 +10358,7 @@
10320
10358
 
10321
10359
  {
10322
10360
  var consequent = ($$anchor) => {
10323
- var button_2 = root_1$c();
10361
+ var button_2 = root_1$f();
10324
10362
 
10325
10363
  button_2.__click = (e) => {
10326
10364
  e.stopPropagation();
@@ -10508,11 +10546,11 @@
10508
10546
  };
10509
10547
  }
10510
10548
 
10511
- var root$q = from_svg(`<svg><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path></svg>`);
10549
+ var root$t = from_svg(`<svg><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path></svg>`);
10512
10550
 
10513
10551
  function IconClose($$anchor, $$props) {
10514
10552
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10515
- var svg = root$q();
10553
+ var svg = root$t();
10516
10554
 
10517
10555
  attribute_effect(svg, () => ({
10518
10556
  class: 'cv-modal-close-icon',
@@ -10527,11 +10565,11 @@
10527
10565
  append($$anchor, svg);
10528
10566
  }
10529
10567
 
10530
- var root$p = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line><path d="M245 37.0001V39.5001H250V37.0001H247.5H245ZM250 13.0001C250 11.6194 248.881 10.5001C247.5 10.5001C246.119 10.5001 245 11.6194 245 13.0001H247.5H250ZM250 31.0001C250 29.6194 248.881 28.5001C247.5 28.5001C246.119 28.5001 245 29.6194 245 31.0001H247.5H250ZM245 19.0001C245 20.3808 246.119 21.5001C247.5 21.5001C248.881 21.5001 250 20.3808 250 19.0001H247.5H245ZM247.5 37.0001H250V31.0001H247.5H245V37.0001H247.5ZM247.5 19.0001H250V13.0001H247.5H245V19.0001H247.5Z" fill="currentColor"></path><line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></line><path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path></svg>`);
10568
+ var root$s = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line><path d="M245 37.0001V39.5001H250V37.0001H247.5H245ZM250 13.0001C250 11.6194 248.881 10.5001C247.5 10.5001C246.119 10.5001 245 11.6194 245 13.0001H247.5H250ZM250 31.0001C250 29.6194 248.881 28.5001C247.5 28.5001C246.119 28.5001 245 29.6194 245 31.0001H247.5H250ZM245 19.0001C245 20.3808 246.119 21.5001C247.5 21.5001C248.881 21.5001 250 20.3808 250 19.0001H247.5H245ZM247.5 37.0001H250V31.0001H247.5H245V37.0001H247.5ZM247.5 19.0001H250V13.0001H247.5H245V19.0001H247.5Z" fill="currentColor"></path><line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></line><path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path><path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"></path></svg>`);
10531
10569
 
10532
10570
  function IconNavDashed($$anchor, $$props) {
10533
10571
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10534
- var svg = root$p();
10572
+ var svg = root$s();
10535
10573
 
10536
10574
  attribute_effect(svg, () => ({
10537
10575
  xmlns: 'http://www.w3.org/2000/svg',
@@ -10544,11 +10582,11 @@
10544
10582
  append($$anchor, svg);
10545
10583
  }
10546
10584
 
10547
- var root$o = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line><line x1="247.5" y1="43.0001" x2="247.5" y2="13.0001" stroke="currentColor" stroke-width="5" stroke-linecap="round"></line><path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round"></line><path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path></svg>`);
10585
+ var root$r = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line><line x1="247.5" y1="43.0001" x2="247.5" y2="13.0001" stroke="currentColor" stroke-width="5" stroke-linecap="round"></line><path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round"></line><path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path><path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round"></path></svg>`);
10548
10586
 
10549
10587
  function IconNavHeadingOn($$anchor, $$props) {
10550
10588
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10551
- var svg = root$o();
10589
+ var svg = root$r();
10552
10590
 
10553
10591
  attribute_effect(svg, () => ({
10554
10592
  xmlns: 'http://www.w3.org/2000/svg',
@@ -10561,11 +10599,11 @@
10561
10599
  append($$anchor, svg);
10562
10600
  }
10563
10601
 
10564
- var root$n = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62" x2="77" y2="62" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8887" x2="77" y2="77.8887" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4453" x2="221" y2="97.4453" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line></svg>`);
10602
+ var root$q = from_svg(`<svg><rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"></rect><line x1="27" y1="62" x2="77" y2="62" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="77.8887" x2="77" y2="77.8887" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="97.4453" x2="221" y2="97.4453" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"></line><line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"></line></svg>`);
10565
10603
 
10566
10604
  function IconNavHeadingOff($$anchor, $$props) {
10567
10605
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10568
- var svg = root$n();
10606
+ var svg = root$q();
10569
10607
 
10570
10608
  attribute_effect(svg, () => ({
10571
10609
  xmlns: 'http://www.w3.org/2000/svg',
@@ -10579,11 +10617,11 @@
10579
10617
  append($$anchor, svg);
10580
10618
  }
10581
10619
 
10582
- var root$m = from_svg(`<svg><path fill="currentColor" d="M18 8h-2a1 1 0 0 0 0 2h2v8H6v-8h2a1 1 0 0 0 0-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2z"></path><path fill="currentColor" d="M11 6.41V12a1 1 0 0 0 2 0V6.41l1.29 1.3a1 1 0 0 0 1.42 0a1 1 0 0 0 0-1.42l-3-3a1 1 0 0 0-1.42 0l-3 3a1 1 0 1 0 1.42 1.42L11 6.41z"></path></svg>`);
10620
+ var root$p = from_svg(`<svg><path fill="currentColor" d="M18 8h-2a1 1 0 0 0 0 2h2v8H6v-8h2a1 1 0 0 0 0-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2z"></path><path fill="currentColor" d="M11 6.41V12a1 1 0 0 0 2 0V6.41l1.29 1.3a1 1 0 0 0 1.42 0a1 1 0 0 0 0-1.42l-3-3a1 1 0 0 0-1.42 0l-3 3a1 1 0 1 0 1.42 1.42L11 6.41z"></path></svg>`);
10583
10621
 
10584
10622
  function IconShare($$anchor, $$props) {
10585
10623
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10586
- var svg = root$m();
10624
+ var svg = root$p();
10587
10625
 
10588
10626
  attribute_effect(svg, () => ({
10589
10627
  xmlns: 'http://www.w3.org/2000/svg',
@@ -10596,11 +10634,11 @@
10596
10634
  append($$anchor, svg);
10597
10635
  }
10598
10636
 
10599
- var root$l = from_svg(`<svg><g id="surface1"><path d="M 11.273438 0 L 2.546875 0 C 1.746094 0 1.089844 0.613281 1.089844 1.363281 L 1.089844 10.910156 L 2.546875 10.910156 L 2.546875 1.363281 L 11.273438 1.363281 Z M 13.453125 2.726562 L 5.453125 2.726562 C 4.65625 2.726562 4 3.339844 4 4.089844 L 4 13.636719 C 4 14.386719 4.65625 15 5.453125 15 L 13.453125 15 C 14.253906 15 14.910156 14.386719 14.910156 13.636719 L 14.910156 4.089844 C 14.910156 3.339844 14.253906 2.726562 13.453125 2.726562 Z M 13.453125 13.636719 L 5.453125 13.636719 L 5.453125 4.089844 L 13.453125 4.089844 Z M 13.453125 13.636719 "></path></g></svg>`);
10637
+ var root$o = from_svg(`<svg><g id="surface1"><path d="M 11.273438 0 L 2.546875 0 C 1.746094 0 1.089844 0.613281 1.089844 1.363281 L 1.089844 10.910156 L 2.546875 10.910156 L 2.546875 1.363281 L 11.273438 1.363281 Z M 13.453125 2.726562 L 5.453125 2.726562 C 4.65625 2.726562 4 3.339844 4 4.089844 L 4 13.636719 C 4 14.386719 4.65625 15 5.453125 15 L 13.453125 15 C 14.253906 15 14.910156 14.386719 14.910156 13.636719 L 14.910156 4.089844 C 14.910156 3.339844 14.253906 2.726562 13.453125 2.726562 Z M 13.453125 13.636719 L 5.453125 13.636719 L 5.453125 4.089844 L 13.453125 4.089844 Z M 13.453125 13.636719 "></path></g></svg>`);
10600
10638
 
10601
10639
  function IconCopy($$anchor, $$props) {
10602
10640
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10603
- var svg = root$l();
10641
+ var svg = root$o();
10604
10642
 
10605
10643
  attribute_effect(svg, () => ({
10606
10644
  xmlns: 'http://www.w3.org/2000/svg',
@@ -10616,11 +10654,11 @@
10616
10654
  append($$anchor, svg);
10617
10655
  }
10618
10656
 
10619
- var root$k = from_svg(`<svg><path d="M 19.28125 5.28125 L 9 15.5625 L 4.71875 11.28125 L 3.28125 12.71875 L 8.28125 17.71875 L 9 18.40625 L 9.71875 17.71875 L 20.71875 6.71875 Z"></path></svg>`);
10657
+ var root$n = from_svg(`<svg><path d="M 19.28125 5.28125 L 9 15.5625 L 4.71875 11.28125 L 3.28125 12.71875 L 8.28125 17.71875 L 9 18.40625 L 9.71875 17.71875 L 20.71875 6.71875 Z"></path></svg>`);
10620
10658
 
10621
10659
  function IconCheck($$anchor, $$props) {
10622
10660
  let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
10623
- var svg = root$k();
10661
+ var svg = root$n();
10624
10662
 
10625
10663
  attribute_effect(svg, () => ({
10626
10664
  xmlns: 'http://www.w3.org/2000/svg',
@@ -11004,109 +11042,159 @@
11004
11042
  toast.show(message, duration);
11005
11043
  }
11006
11044
 
11045
+ /**
11046
+ * Captures the current viewport-relative position of a given element.
11047
+ * Call this *before* a layout-shifting operation, then pass the result to `restoreScrollAnchor`.
11048
+ *
11049
+ * @param element The element to anchor to.
11050
+ * @returns A `ScrollAnchor` snapshot.
11051
+ */
11052
+ function captureScrollAnchor(element) {
11053
+ return { element, top: element.getBoundingClientRect().top };
11054
+ }
11007
11055
  /**
11008
11056
  * Calculates the total height of fixed or sticky elements at the top of the viewport.
11009
- * This includes the standard site header and any custom elements marked with [data-cv-scroll-offset].
11010
- * Used to offset scroll positions so content isn't hidden behind these fixed elements.
11057
+ * This includes the standard site header and any custom elements marked with
11058
+ * `[data-cv-scroll-offset]`. Used to offset scroll positions so content isn't
11059
+ * hidden behind these fixed elements.
11011
11060
  */
11012
11061
  function getScrollTopOffset() {
11013
11062
  let headerHeight = 0;
11014
11063
  let customOffset = 0;
11015
- // 1. Standard Site Header if applicable
11016
11064
  const headerEl = document.querySelector('header');
11017
11065
  if (headerEl) {
11018
- const headerStyle = window.getComputedStyle(headerEl);
11019
- const isHeaderFixedOrSticky = ['fixed', 'sticky'].includes(headerStyle.position);
11020
- if (isHeaderFixedOrSticky) {
11066
+ const { position } = window.getComputedStyle(headerEl);
11067
+ if (position === 'fixed' || position === 'sticky') {
11021
11068
  headerHeight = headerEl.getBoundingClientRect().height;
11022
11069
  }
11023
11070
  }
11024
- // 2. Custom Views Fixed Elements (e.g. Focus Banner)
11025
- // Elements with [data-cv-scroll-offset] are considered fixed/sticky obstructions.
11026
- // We use scrollHeight to get the full height even during animations (like slide transition).
11071
+ // Elements with [data-cv-scroll-offset] are treated as fixed/sticky obstructions at the top.
11072
+ // We use scrollHeight to account for elements mid-transition.
11027
11073
  document.querySelectorAll('[data-cv-scroll-offset]').forEach((el) => {
11028
- // We assume these elements overlap at the top (top: 0) unless a stacking context is managed.
11029
- // Taking the MAX ensures we clear the tallest obstruction without over-counting.
11030
11074
  customOffset = Math.max(customOffset, el.scrollHeight);
11031
11075
  });
11032
- // Custom elements overlay the standard header.
11033
- // Avoid double-counting while ensuring visibility.
11076
+ // Custom elements overlay the standard header — avoid double-counting.
11034
11077
  return Math.max(headerHeight, customOffset);
11035
11078
  }
11036
11079
  /**
11037
- * Finds the highest element matching the selector that is currently in the viewport.
11038
- * @param selector The CSS selector to match elements against.
11039
- * @returns The HTMLElement of the highest visible element, or null if none are found.
11080
+ * Returns the highest element matching a CSS selector that is visible in the
11081
+ * current viewport (below any fixed/sticky header).
11082
+ *
11083
+ * @param selector CSS selector to match elements.
11084
+ * @returns The highest visible matching element, or `null` if none found.
11040
11085
  */
11041
11086
  function findHighestVisibleElement(selector) {
11042
- const headerOffset = getScrollTopOffset();
11043
- const contentTop = headerOffset; // Viewport-relative position where content begins.
11044
- // 1. Find all matching elements, filtering out any inside the main header (if fixed/sticky).
11045
- const allElements = Array.from(document.querySelectorAll(selector));
11087
+ const topOffset = getScrollTopOffset();
11088
+ const viewportBottom = window.innerHeight;
11046
11089
  const headerEl = document.querySelector('header');
11047
- const candidateElements = allElements.filter((el) => {
11048
- // If header is sticky/fixed, ignore elements inside it to avoid false positives
11049
- if (headerOffset > 0 && headerEl && el.closest('header') === headerEl) {
11050
- return false;
11051
- }
11052
- return true;
11053
- });
11054
- // 2. Find the highest element visible in the content area.
11055
- let highestVisibleEl = null;
11056
- let highestVisibleTop = Infinity;
11057
- for (const el of candidateElements) {
11058
- const rect = el.getBoundingClientRect();
11059
- // Visible if not completely above content area and not completely below viewport
11060
- const isVisibleInContentArea = rect.bottom > contentTop && rect.top < window.innerHeight;
11061
- if (isVisibleInContentArea) {
11062
- // We want the one closest to the top
11063
- if (rect.top < highestVisibleTop) {
11064
- highestVisibleEl = el;
11065
- highestVisibleTop = rect.top;
11066
- }
11090
+ let best = null;
11091
+ let bestTop = Infinity;
11092
+ for (const el of document.querySelectorAll(selector)) {
11093
+ // Ignore elements inside a sticky/fixed header
11094
+ if (topOffset > 0 && headerEl && el.closest('header') === headerEl)
11095
+ continue;
11096
+ const { top, bottom } = el.getBoundingClientRect();
11097
+ const isVisible = bottom > topOffset && top < viewportBottom;
11098
+ if (isVisible && top < bestTop) {
11099
+ best = el;
11100
+ bestTop = top;
11067
11101
  }
11068
11102
  }
11069
- return highestVisibleEl;
11103
+ return best;
11070
11104
  }
11105
+ /** Default implementation with SSR fallback. */
11106
+ const defaultScheduler = (cb) => {
11107
+ if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
11108
+ return window.requestAnimationFrame(cb);
11109
+ }
11110
+ return setTimeout(() => {
11111
+ const now = typeof performance !== 'undefined' && typeof performance.now === 'function'
11112
+ ? performance.now()
11113
+ : Date.now();
11114
+ cb(now);
11115
+ }, 16);
11116
+ };
11117
+ /** Internal scheduler. Can be overridden in tests via setFrameScheduler. */
11118
+ let frameScheduler = defaultScheduler;
11071
11119
  /**
11072
- * Adjusts the scroll position to keep a specific element in the same visual location.
11073
- * Useful when content additions/removals above might cause jumps.
11074
- */
11075
- function handleScrollAnchor(scrollAnchor) {
11076
- requestAnimationFrame(() => {
11077
- const { element, top: initialTop } = scrollAnchor;
11078
- // Check if element is still in document
11079
- if (!element || !document.contains(element))
11080
- return;
11081
- const newTop = element.getBoundingClientRect().top;
11082
- const scrollDelta = newTop - initialTop;
11083
- // Only scroll if there's a noticeable change
11084
- if (Math.abs(scrollDelta) > 1) {
11085
- window.scrollBy({
11086
- top: scrollDelta,
11087
- behavior: 'instant',
11088
- });
11089
- }
11120
+ * Restores the visual scroll position after a layout-shifting operation.
11121
+ *
11122
+ * Pass a `ScrollAnchor` captured *before* the layout change.
11123
+ * Uses two `requestAnimationFrame` ticks to ensure the browser has fully
11124
+ * reflowed the page before measuring and correcting.
11125
+ *
11126
+ * Note: When calling from a Svelte component, prefer using `tick()` before
11127
+ * calling this function so Svelte's DOM updates are applied first.
11128
+ *
11129
+ * @param anchor A `ScrollAnchor` captured before the layout change.
11130
+ */
11131
+ function restoreScrollAnchor(anchor) {
11132
+ // Double-rAF: first frame commits the paint, second ensures layout is stable.
11133
+ frameScheduler(() => {
11134
+ frameScheduler(() => {
11135
+ // Use isConnected instead of document.contains() — the latter returns false
11136
+ // for elements inside Shadow DOM trees, which would silently skip restoration.
11137
+ if (!anchor.element.isConnected)
11138
+ return;
11139
+ const delta = anchor.element.getBoundingClientRect().top - anchor.top;
11140
+ if (Math.abs(delta) > 1) {
11141
+ window.scrollBy({ top: delta, behavior: 'instant' });
11142
+ }
11143
+ });
11090
11144
  });
11091
11145
  }
11092
11146
 
11093
- var root_1$b = from_html(`<p class="description svelte-gwkhja"> </p>`);
11094
- var root_2$9 = from_html(`<button> </button>`);
11095
- var root$j = from_html(`<div class="card svelte-gwkhja"><div class="content svelte-gwkhja"><div><p class="title svelte-gwkhja"> </p> <!></div> <div class="segmented svelte-gwkhja" role="group" aria-label="Visibility"></div></div></div>`);
11147
+ var root$m = from_svg(`<svg><path d="M247.31,124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57,61.26,162.88,48,128,48S61.43,61.26,36.34,86.35C17.51,105.18,9,123.97,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208s66.57-13.26,91.66-38.34c18.83-18.83,27.3-37.61,27.65-38.4A8,8,0,0,0,247.31,124.76ZM128,192c-30.78,0-57.67-11.19-79.93-33.29A169.47,169.47,0,0,1,24.7,128,169.47,169.47,0,0,1,48.07,97.29C70.33,75.19,97.22,64,128,64s57.67,11.19,79.93,33.29A169.47,169.47,0,0,1,231.3,128C223.94,141.07,184.26,192,128,192Zm0-112a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Z"></path></svg>`);
11096
11148
 
11097
- const $$css$k = {
11149
+ function IconEye($$anchor, $$props) {
11150
+ let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
11151
+ var svg = root$m();
11152
+
11153
+ attribute_effect(svg, () => ({
11154
+ fill: 'currentColor',
11155
+ viewBox: '0 0 256 256',
11156
+ xmlns: 'http://www.w3.org/2000/svg',
11157
+ ...rest
11158
+ }));
11159
+
11160
+ append($$anchor, svg);
11161
+ }
11162
+
11163
+ var root$l = from_svg(`<svg><path d="M53.92,34.62A8,8,0,1,0,42.08,45.38L61.32,66.55C25.2,88.84,9.38,123.2,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208a127.11,127.11,0,0,0,52.07-10.83l22,24.21a8,8,0,1,0,11.84-10.76Zm74.07,125a32,32,0,0,1-43.27-44.15l8.64,9.51a16,16,0,0,0,21.61,20.49ZM24.7,128A169.47,169.47,0,0,1,48.07,97.29C70.33,75.19,97.22,64,128,64a112.26,112.26,0,0,1,19.77,1.74l-22,24.2A48,48,0,0,0,80,128c0,1.63.08,3.24.24,4.84L53.92,109A171.58,171.58,0,0,0,24.7,128Zm223,3.26c-.35-.79-8.82-19.58-27.65-38.41C194.57,67.26,162.88,54,128,54a125.07,125.07,0,0,0-23.42,2.19,8,8,0,0,0,3,15.72A109.2,109.2,0,0,1,128,70c30.78,0,57.67,11.19,79.93,33.29A169.47,169.47,0,0,1,231.3,134c-7.09,12.66-37.13,54-90.82,63a8,8,0,0,0,2.73,15.77A128.58,128.58,0,0,0,219.66,169.5c18.83-18.83,27.3-37.61,27.65-38.4A8,8,0,0,0,247.66,131.26Z"></path></svg>`);
11164
+
11165
+ function IconEyeSlash($$anchor, $$props) {
11166
+ let rest = rest_props($$props, ['$$slots', '$$events', '$$legacy']);
11167
+ var svg = root$l();
11168
+
11169
+ attribute_effect(svg, () => ({
11170
+ fill: 'currentColor',
11171
+ viewBox: '0 0 256 256',
11172
+ xmlns: 'http://www.w3.org/2000/svg',
11173
+ ...rest
11174
+ }));
11175
+
11176
+ append($$anchor, svg);
11177
+ }
11178
+
11179
+ var root_1$e = from_html(`<p class="description svelte-gwkhja"> </p>`);
11180
+ var root_3$7 = from_html(`<span class="segment-icon svelte-gwkhja"><!></span>`);
11181
+ var root_2$a = from_html(`<button type="button"><!> <span class="segment-label svelte-gwkhja"> </span></button>`);
11182
+ var root$k = from_html(`<div class="card svelte-gwkhja"><div class="content svelte-gwkhja"><div><p class="title svelte-gwkhja"> </p> <!></div> <div class="segmented svelte-gwkhja" role="group" aria-label="Visibility"></div></div></div>`);
11183
+
11184
+ const $$css$m = {
11098
11185
  hash: 'svelte-gwkhja',
11099
- code: '.card.svelte-gwkhja {background:var(--cv-bg);border:1px solid var(--cv-border);border-radius:var(--cv-card-radius, 0.5rem);transition:background 0.15s ease;}.card.svelte-gwkhja:hover {background:var(--cv-bg-hover);}.content.svelte-gwkhja {display:flex;align-items:center;justify-content:space-between;padding:0.75rem;}.title.svelte-gwkhja {font-weight:500;font-size:0.875rem;color:var(--cv-text);margin:0;}.description.svelte-gwkhja {font-size:0.75rem;color:var(--cv-text-secondary);margin:0.125rem 0 0 0;}.segmented.svelte-gwkhja {display:flex;border:1px solid var(--cv-border);border-radius:0.375rem;overflow:hidden;flex-shrink:0;}.segment-btn.svelte-gwkhja {background:transparent;border:none;border-left:1px solid var(--cv-border);padding:0.3rem 0.6rem;font-size:0.8rem;font-weight:500;color:var(--cv-text-secondary);cursor:pointer;transition:background 0.15s ease, color 0.15s ease;font-family:inherit;line-height:1;}.segment-btn.svelte-gwkhja:first-child {border-left:none;}.segment-btn.svelte-gwkhja:hover:not(.active) {background:var(--cv-bg-hover);color:var(--cv-text);}.segment-btn.active.svelte-gwkhja {background:var(--cv-primary);color:white;box-shadow:0 1px 3px rgba(0, 0, 0, 0.15);}'
11186
+ code: '.card.svelte-gwkhja {background:var(--cv-bg);border:1px solid var(--cv-border);border-radius:var(--cv-card-radius, 0.5rem);transition:background 0.15s ease;}.card.svelte-gwkhja:hover {background:var(--cv-bg-hover);}.content.svelte-gwkhja {display:flex;align-items:center;justify-content:space-between;padding:0.75rem;}.title.svelte-gwkhja {font-weight:500;font-size:0.875rem;color:var(--cv-text);margin:0;}.description.svelte-gwkhja {font-size:0.75rem;color:var(--cv-text-secondary);margin:0.125rem 0 0 0;}.segmented.svelte-gwkhja {display:flex;border:1px solid var(--cv-border);border-radius:0.375rem;overflow:hidden;flex-shrink:0;}.segment-btn.svelte-gwkhja {display:flex;align-items:center;gap:0.25rem;background:transparent;border:none;border-left:1px solid var(--cv-border);padding:0.3rem 0.6rem;font-size:0.8rem;font-weight:500;color:var(--cv-text-secondary);cursor:pointer;transition:background 0.15s ease, color 0.15s ease;font-family:inherit;line-height:1;}.segment-icon.svelte-gwkhja {display:flex;align-items:center;justify-content:center;width:14px;height:14px;flex-shrink:0;}.segment-icon.svelte-gwkhja svg {width:100%;height:100%;}.segment-label.svelte-gwkhja {font-size:0.75rem;}.segment-btn.svelte-gwkhja:first-child {border-left:none;}.segment-btn.svelte-gwkhja:hover:not(.active) {background:var(--cv-bg-hover);color:var(--cv-text);}.segment-btn.active.svelte-gwkhja {background:var(--cv-primary);color:white;box-shadow:0 1px 3px rgba(0, 0, 0, 0.15);}'
11100
11187
  };
11101
11188
 
11102
11189
  function ToggleItem($$anchor, $$props) {
11103
11190
  push($$props, true);
11104
- append_styles$1($$anchor, $$css$k);
11191
+ append_styles$1($$anchor, $$css$m);
11105
11192
 
11106
11193
  let value = prop($$props, 'value', 15, 'show'),
11107
11194
  onchange = prop($$props, 'onchange', 3, () => {});
11108
11195
 
11109
- var div = root$j();
11196
+ const icons = { hide: IconEyeSlash, show: IconEye };
11197
+ var div = root$k();
11110
11198
  var div_1 = child(div);
11111
11199
  var div_2 = child(div_1);
11112
11200
  var p = child(div_2);
@@ -11118,7 +11206,7 @@
11118
11206
 
11119
11207
  {
11120
11208
  var consequent = ($$anchor) => {
11121
- var p_1 = root_1$b();
11209
+ var p_1 = root_1$e();
11122
11210
  var text_1 = child(p_1, true);
11123
11211
 
11124
11212
  reset(p_1);
@@ -11136,24 +11224,51 @@
11136
11224
  var div_3 = sibling(div_2, 2);
11137
11225
 
11138
11226
  each(div_3, 20, () => ['hide', 'peek', 'show'], (option) => option, ($$anchor, option) => {
11139
- var button = root_2$9();
11227
+ var button = root_2$a();
11140
11228
 
11141
11229
  button.__click = () => {
11142
11230
  value(option);
11143
11231
  onchange()({ toggleId: $$props.toggle.toggleId, value: option });
11144
11232
  };
11145
11233
 
11146
- var text_2 = child(button, true);
11234
+ var node_1 = child(button);
11235
+
11236
+ {
11237
+ var consequent_1 = ($$anchor) => {
11238
+ const IconComponent = user_derived(() => icons[option]);
11239
+ var span = root_3$7();
11240
+ var node_2 = child(span);
11241
+
11242
+ component(node_2, () => get(IconComponent), ($$anchor, IconComponent_1) => {
11243
+ IconComponent_1($$anchor, {});
11244
+ });
11245
+
11246
+ reset(span);
11247
+ append($$anchor, span);
11248
+ };
11249
+
11250
+ if_block(node_1, ($$render) => {
11251
+ if (option === 'hide' || option === 'show') $$render(consequent_1);
11252
+ });
11253
+ }
11147
11254
 
11255
+ var span_1 = sibling(node_1, 2);
11256
+ var text_2 = child(span_1, true);
11257
+
11258
+ reset(span_1);
11148
11259
  reset(button);
11149
11260
 
11150
11261
  template_effect(
11151
- ($0) => {
11262
+ ($0, $1) => {
11152
11263
  set_class(button, 1, `segment-btn ${value() === option ? 'active' : ''}`, 'svelte-gwkhja');
11153
11264
  set_attribute(button, 'aria-pressed', value() === option);
11154
- set_text(text_2, $0);
11265
+ set_attribute(button, 'title', $0);
11266
+ set_text(text_2, $1);
11155
11267
  },
11156
- [() => option.charAt(0).toUpperCase() + option.slice(1)]
11268
+ [
11269
+ () => option.charAt(0).toUpperCase() + option.slice(1),
11270
+ () => option.charAt(0).toUpperCase() + option.slice(1)
11271
+ ]
11157
11272
  );
11158
11273
 
11159
11274
  append($$anchor, button);
@@ -11169,18 +11284,18 @@
11169
11284
 
11170
11285
  delegate(['click']);
11171
11286
 
11172
- var root_1$a = from_html(`<p class="description svelte-uub3h8"> </p>`);
11173
- var root_2$8 = from_html(`<option> </option>`);
11174
- var root$i = from_html(`<div class="root svelte-uub3h8"><div class="header svelte-uub3h8"><label class="label svelte-uub3h8"> </label> <!></div> <select class="select svelte-uub3h8"></select></div>`);
11287
+ var root_1$d = from_html(`<p class="description svelte-uub3h8"> </p>`);
11288
+ var root_2$9 = from_html(`<option> </option>`);
11289
+ var root$j = from_html(`<div class="root svelte-uub3h8"><div class="header svelte-uub3h8"><label class="label svelte-uub3h8"> </label> <!></div> <select class="select svelte-uub3h8"></select></div>`);
11175
11290
 
11176
- const $$css$j = {
11291
+ const $$css$l = {
11177
11292
  hash: 'svelte-uub3h8',
11178
11293
  code: '.root.svelte-uub3h8 {display:flex;flex-direction:column;gap:0.5rem;padding:0.75rem;background:var(--cv-bg);border:1px solid var(--cv-border);border-radius:var(--cv-card-radius, 0.5rem);transition:background 0.15s ease;}.root.svelte-uub3h8:hover {background:var(--cv-bg-hover);}\n\n /* Remove special handling for last child since they are now separate cards */.root.svelte-uub3h8:last-child {border-bottom:1px solid var(--cv-border);}.header.svelte-uub3h8 {display:flex;flex-direction:column;gap:0.25rem;}.label.svelte-uub3h8 {font-size:0.875rem;color:var(--cv-text);margin:0;line-height:1.4;font-weight:500;display:block;cursor:pointer;}.description.svelte-uub3h8 {font-size:0.75rem;color:var(--cv-text-secondary);margin:0;line-height:1.4;}.select.svelte-uub3h8 {width:100%;border-radius:0.5rem;background:var(--cv-input-bg);border:1px solid var(--cv-input-border);color:var(--cv-text);padding:0.5rem 0.75rem;font-size:0.875rem;cursor:pointer;transition:all 0.15s ease;font-family:inherit;}.select.svelte-uub3h8:hover {border-color:var(--cv-text-secondary);}.select.svelte-uub3h8:focus {outline:none;border-color:var(--cv-primary);box-shadow:0 0 0 2px var(--cv-focus-ring);}'
11179
11294
  };
11180
11295
 
11181
11296
  function TabGroupItem($$anchor, $$props) {
11182
11297
  push($$props, true);
11183
- append_styles$1($$anchor, $$css$j);
11298
+ append_styles$1($$anchor, $$css$l);
11184
11299
 
11185
11300
  let activeTabId = prop($$props, 'activeTabId', 15, ''),
11186
11301
  onchange = prop($$props, 'onchange', 3, () => {});
@@ -11192,7 +11307,7 @@
11192
11307
  onchange()({ groupId: $$props.group.groupId, tabId: activeTabId() });
11193
11308
  }
11194
11309
 
11195
- var div = root$i();
11310
+ var div = root$j();
11196
11311
  var div_1 = child(div);
11197
11312
  var label = child(div_1);
11198
11313
  var text = child(label, true);
@@ -11203,7 +11318,7 @@
11203
11318
 
11204
11319
  {
11205
11320
  var consequent = ($$anchor) => {
11206
- var p = root_1$a();
11321
+ var p = root_1$d();
11207
11322
  var text_1 = child(p, true);
11208
11323
 
11209
11324
  reset(p);
@@ -11223,7 +11338,7 @@
11223
11338
  select.__change = onChange;
11224
11339
 
11225
11340
  each(select, 21, () => $$props.group.tabs, (tab) => tab.tabId, ($$anchor, tab) => {
11226
- var option = root_2$8();
11341
+ var option = root_2$9();
11227
11342
  var text_2 = child(option, true);
11228
11343
 
11229
11344
  reset(option);
@@ -11267,16 +11382,16 @@
11267
11382
 
11268
11383
  delegate(['change']);
11269
11384
 
11270
- var root$h = from_html(`<div class="placeholder-item svelte-1vp05mb"><label class="placeholder-label svelte-1vp05mb"> </label> <input class="placeholder-input svelte-1vp05mb" type="text"/></div>`);
11385
+ var root$i = from_html(`<div class="placeholder-item svelte-1vp05mb"><label class="placeholder-label svelte-1vp05mb"> </label> <input class="placeholder-input svelte-1vp05mb" type="text"/></div>`);
11271
11386
 
11272
- const $$css$i = {
11387
+ const $$css$k = {
11273
11388
  hash: 'svelte-1vp05mb',
11274
11389
  code: '.placeholder-item.svelte-1vp05mb {display:flex;flex-direction:column;gap:0.25rem;}.placeholder-label.svelte-1vp05mb {font-size:0.85rem;font-weight:500;color:var(--cv-text);}.placeholder-input.svelte-1vp05mb {padding:0.5rem 0.75rem;border:1px solid var(--cv-input-border);border-radius:var(--cv-card-radius, 0.5rem);font-size:0.9rem;transition:border-color 0.2s;background:var(--cv-input-bg);color:var(--cv-text);}.placeholder-input.svelte-1vp05mb:focus {outline:none;border-color:var(--cv-primary);box-shadow:0 0 0 2px var(--cv-focus-ring);}'
11275
11390
  };
11276
11391
 
11277
11392
  function PlaceholderItem($$anchor, $$props) {
11278
11393
  push($$props, true);
11279
- append_styles$1($$anchor, $$css$i);
11394
+ append_styles$1($$anchor, $$css$k);
11280
11395
 
11281
11396
  let value = prop($$props, 'value', 15, ''),
11282
11397
  onchange = prop($$props, 'onchange', 3, () => {});
@@ -11289,7 +11404,7 @@
11289
11404
  }
11290
11405
 
11291
11406
  const sanitizedId = user_derived(() => `cv-placeholder-${$$props.definition.name.replace(/[^a-zA-Z0-9-_]/g, '-')}`);
11292
- var div = root$h();
11407
+ var div = root$i();
11293
11408
  var label = child(div);
11294
11409
  var text = child(label, true);
11295
11410
 
@@ -11356,30 +11471,30 @@
11356
11471
  }
11357
11472
  }
11358
11473
 
11359
- var root_1$9 = from_html(`<button>Customize</button>`);
11360
- var root_3$5 = from_html(`<p class="description svelte-16uy9h6"> </p>`);
11361
- var root_5$1 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Toggles</div> <div class="toggles-container svelte-16uy9h6"></div></div>`);
11362
- var root_7 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Placeholders</div> <div class="placeholders-container svelte-16uy9h6"></div></div>`);
11363
- var root_9 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Tab Groups</div> <div class="tabgroups-container svelte-16uy9h6"><div class="tabgroup-card header-card svelte-16uy9h6" role="group"><div class="tabgroup-row svelte-16uy9h6"><div class="logo-box svelte-16uy9h6" id="cv-nav-icon-box"><div class="nav-icon svelte-16uy9h6"><!></div></div> <div class="tabgroup-info svelte-16uy9h6"><div class="tabgroup-title-container"><p class="tabgroup-title svelte-16uy9h6">Show only the selected tab</p></div> <p class="tabgroup-description svelte-16uy9h6">Hide the navigation headers</p></div> <label class="toggle-switch nav-toggle svelte-16uy9h6"><input class="nav-pref-input svelte-16uy9h6" type="checkbox" aria-label="Show only the selected tab"/> <span class="switch-bg svelte-16uy9h6"></span> <span class="switch-knob svelte-16uy9h6"></span></label></div></div> <div class="tab-groups-list svelte-16uy9h6"></div></div></div>`);
11364
- var root_4$2 = from_html(`<!> <!> <!>`, 1);
11365
- var root_2$7 = from_html(`<div class="tab-content active svelte-16uy9h6"><!> <!></div>`);
11366
- var root_16 = from_html(`<button class="share-action-btn copy-url-btn svelte-16uy9h6"><span class="btn-icon svelte-16uy9h6"><!></span> <span><!></span></button>`);
11474
+ var root_1$c = from_html(`<button type="button">Customize</button>`);
11475
+ var root_3$6 = from_html(`<p class="description svelte-16uy9h6"> </p>`);
11476
+ var root_5$2 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Toggles</div> <div class="toggles-container svelte-16uy9h6"></div></div>`);
11477
+ var root_7$2 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Placeholders</div> <div class="placeholders-container svelte-16uy9h6"></div></div>`);
11478
+ var root_9$1 = from_html(`<div class="section svelte-16uy9h6"><div class="section-heading svelte-16uy9h6">Tab Groups</div> <div class="tabgroups-container svelte-16uy9h6"><div class="tabgroup-card header-card svelte-16uy9h6" role="group"><div class="tabgroup-row svelte-16uy9h6"><div class="logo-box svelte-16uy9h6" id="cv-nav-icon-box"><div class="nav-icon svelte-16uy9h6"><!></div></div> <div class="tabgroup-info svelte-16uy9h6"><div class="tabgroup-title-container"><p class="tabgroup-title svelte-16uy9h6">Show only the selected tab</p></div> <p class="tabgroup-description svelte-16uy9h6">Hide the navigation headers</p></div> <label class="toggle-switch nav-toggle svelte-16uy9h6"><input class="nav-pref-input svelte-16uy9h6" type="checkbox" aria-label="Show only the selected tab"/> <span class="switch-bg svelte-16uy9h6"></span> <span class="switch-knob svelte-16uy9h6"></span></label></div></div> <div class="tab-groups-list svelte-16uy9h6"></div></div></div>`);
11479
+ var root_4$3 = from_html(`<!> <!> <!>`, 1);
11480
+ var root_2$8 = from_html(`<div class="tab-content active svelte-16uy9h6"><!> <!></div>`);
11481
+ var root_16 = from_html(`<button type="button" class="share-action-btn copy-url-btn svelte-16uy9h6"><span class="btn-icon svelte-16uy9h6"><!></span> <span><!></span></button>`);
11367
11482
 
11368
11483
  var root_15 = from_html(`<div class="tab-content active svelte-16uy9h6"><div class="share-content svelte-16uy9h6"><div class="share-instruction svelte-16uy9h6">Create a shareable link for your current customization, or select specific parts of
11369
- the page to share.</div> <button class="share-action-btn primary start-share-btn svelte-16uy9h6"><span class="btn-icon svelte-16uy9h6"><!></span> <span>Select elements to share</span></button> <!></div></div>`);
11484
+ the page to share.</div> <button type="button" class="share-action-btn primary start-share-btn svelte-16uy9h6"><span class="btn-icon svelte-16uy9h6"><!></span> <span>Select elements to share</span></button> <!></div></div>`);
11370
11485
 
11371
- var root_21 = from_html(`<button class="reset-btn svelte-16uy9h6" title="Reset to Default">Reset</button>`);
11486
+ var root_21 = from_html(`<button type="button" class="reset-btn svelte-16uy9h6" title="Reset to Default">Reset</button>`);
11372
11487
  var root_22 = from_html(`<div></div>`);
11373
- var root$g = from_html(`<div class="modal-overlay svelte-16uy9h6" role="presentation"><div class="modal-box cv-custom-state-modal svelte-16uy9h6" role="dialog" aria-modal="true"><header class="header svelte-16uy9h6"><div class="header-content svelte-16uy9h6"><div class="modal-icon svelte-16uy9h6"><!></div> <div class="title svelte-16uy9h6"> </div></div> <button class="close-btn svelte-16uy9h6" aria-label="Close modal"><!></button></header> <main class="main svelte-16uy9h6"><div class="tabs svelte-16uy9h6"><!> <button>Share</button></div> <!></main> <footer class="footer svelte-16uy9h6"><!> <a href="https://custardui.js.org" target="_blank" rel="noopener noreferrer" class="footer-link svelte-16uy9h6">custardui.js.org</a> <button class="done-btn svelte-16uy9h6">Done</button></footer></div></div>`);
11488
+ var root$h = from_html(`<div class="modal-overlay svelte-16uy9h6" role="presentation"><div class="modal-box cv-custom-state-modal svelte-16uy9h6" role="dialog" aria-modal="true"><header class="header svelte-16uy9h6"><div class="header-content svelte-16uy9h6"><div class="modal-icon svelte-16uy9h6"><!></div> <div class="title svelte-16uy9h6"> </div></div> <button type="button" class="close-btn svelte-16uy9h6" aria-label="Close modal"><!></button></header> <main class="main svelte-16uy9h6"><div class="tabs svelte-16uy9h6"><!> <button type="button">Share</button></div> <!></main> <footer class="footer svelte-16uy9h6"><!> <div class="footer-attribution svelte-16uy9h6"><span class="footer-tagline svelte-16uy9h6">Browser-side page customisations provided by</span> <a href="https://custardui.js.org" target="_blank" rel="noopener noreferrer" class="footer-link svelte-16uy9h6">custardui.js.org</a></div> <button type="button" class="done-btn svelte-16uy9h6">Done</button></footer></div></div>`);
11374
11489
 
11375
- const $$css$h = {
11490
+ const $$css$j = {
11376
11491
  hash: 'svelte-16uy9h6',
11377
- code: '\n /* Modal Overlay & Modal Frame */.modal-overlay.svelte-16uy9h6 {position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0, 0, 0, 0.5);display:flex;align-items:center;justify-content:center;z-index:10002;}.modal-box.svelte-16uy9h6 {background:var(--cv-bg);border-radius:var(--cv-modal-radius, 0.75rem);box-shadow:0 25px 50px -12px var(--cv-shadow);max-width:32rem;width:90vw;max-height:80vh;display:flex;flex-direction:column;}.header.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;padding:0.5rem 1rem;border-bottom:1px solid var(--cv-border);}.header-content.svelte-16uy9h6 {display:flex;align-items:center;gap:0.75rem;}.modal-icon.svelte-16uy9h6 {position:relative;width:1rem;height:1rem;display:flex;align-items:center;justify-content:center;border-radius:9999px;color:var(--cv-text);}.modal-icon.svelte-16uy9h6 svg {fill:currentColor;}.title.svelte-16uy9h6 {font-size:1.125rem;font-weight:bold;color:var(--cv-text);margin:0;}.close-btn.svelte-16uy9h6 {width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border-radius:9999px;background:transparent;border:none;color:var(--cv-text-secondary);cursor:pointer;transition:all 0.2s ease;}.close-btn.svelte-16uy9h6:hover {background:rgba(62, 132, 244, 0.1);color:var(--cv-primary);}.main.svelte-16uy9h6 {padding:1rem;flex:1;display:flex;flex-direction:column;overflow-y:auto;max-height:calc(80vh - 8rem);min-height:var(--cv-modal-min-height, 20rem);}.description.svelte-16uy9h6 {font-size:0.875rem;color:var(--cv-text);margin:0 0 1rem 0;line-height:1.4;}\n\n /* Tabs */.tabs.svelte-16uy9h6 {display:flex;margin-bottom:1rem;border-bottom:2px solid var(--cv-border);}.tab.svelte-16uy9h6 {background:transparent;border:none;padding:0.5rem 1rem;font-size:0.9rem;font-weight:600;color:var(--cv-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;}.tab.active.svelte-16uy9h6 {color:var(--cv-primary);border-bottom-color:var(--cv-primary);}.tab-content.svelte-16uy9h6 {display:none;}.tab-content.active.svelte-16uy9h6 {display:block;}\n\n /* Section Styling */.section.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;margin-bottom:1.5rem;}.section-heading.svelte-16uy9h6 {font-size:0.7rem;font-weight:600;color:var(--cv-text-secondary);text-transform:var(--cv-section-label-transform, uppercase);letter-spacing:0.08em;margin:0;}.toggles-container.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.5rem;overflow:hidden;}\n\n /* Tab Groups Section specific */.tabgroups-container.svelte-16uy9h6 {border-radius:0.5rem;}\n\n /* Nav Toggle Card */.tabgroup-card.svelte-16uy9h6 {background:var(--cv-bg);border-bottom:1px solid var(--cv-border);}.tabgroup-card.header-card.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;padding:0.75rem;border:1px solid var(--cv-border);border-radius:0.5rem;margin-bottom:0.75rem;}.tabgroup-row.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem;}.logo-box.svelte-16uy9h6 {width:3rem;height:3rem;background:var(--cv-modal-icon-bg);border-radius:0.5rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;}.nav-icon.svelte-16uy9h6 {width:2rem;height:2rem;color:var(--cv-text);display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color 0.2s ease;}.tabgroup-info.svelte-16uy9h6 {flex:1;display:flex;flex-direction:column;gap:0.25rem;}.tabgroup-title.svelte-16uy9h6 {font-weight:500;font-size:0.875rem;color:var(--cv-text);margin:0 0 0 0;}.tabgroup-description.svelte-16uy9h6 {font-size:0.75rem;color:var(--cv-text-secondary);margin:0;line-height:1.3;}\n\n /* Toggle Switch */.toggle-switch.svelte-16uy9h6 {position:relative;display:inline-flex;align-items:center;width:44px;height:24px;background:var(--cv-switch-bg);border-radius:9999px;padding:2px;box-sizing:border-box;cursor:pointer;transition:background-color 0.2s ease;border:none;}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6) {display:none;}.toggle-switch.svelte-16uy9h6 .switch-bg:where(.svelte-16uy9h6) {position:absolute;inset:0;border-radius:9999px;background:var(--cv-switch-bg);transition:background-color 0.2s ease;pointer-events:none;}.toggle-switch.svelte-16uy9h6 .switch-knob:where(.svelte-16uy9h6) {position:relative;width:20px;height:20px;background:var(--cv-switch-knob);border-radius:50%;box-shadow:0 1px 2px rgba(0, 0, 0, 0.1);transition:transform 0.2s ease;transform:translateX(0);}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6):checked ~ .switch-knob:where(.svelte-16uy9h6) {transform:translateX(20px);}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6):checked ~ .switch-bg:where(.svelte-16uy9h6) {background:var(--cv-primary);}\n\n /* Tab Groups List */.tab-groups-list.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;}\n\n /* Footer */.footer.svelte-16uy9h6 {padding:0.75rem 1rem;border-top:1px solid var(--cv-border);display:flex;align-items:center;justify-content:space-between;background:var(--cv-bg);border-bottom-left-radius:var(--cv-modal-radius, 0.75rem);border-bottom-right-radius:var(--cv-modal-radius, 0.75rem);}.footer-link.svelte-16uy9h6 {align-self:flex-end;color:var(--cv-text-secondary);text-decoration:none;font-size:0.68rem;font-weight:500;letter-spacing:0.08em;opacity:0.5;transition:color 0.15s ease, opacity 0.15s ease;}.footer-link.svelte-16uy9h6:hover {color:var(--cv-primary);opacity:1;}.reset-btn.svelte-16uy9h6 {display:flex;align-items:center;gap:0.4rem;background:transparent;border:none;font-size:0.875rem;font-weight:500;color:var(--cv-text-secondary);cursor:pointer;padding:0.4rem 0.5rem;border-radius:0.5rem;transition:all 0.2s ease;}.reset-btn.svelte-16uy9h6:hover {background:var(--cv-danger-bg);color:var(--cv-danger);}.done-btn.svelte-16uy9h6 {background:var(--cv-primary);color:white;border:none;padding:0.5rem 1.1rem;border-radius:0.5rem;font-weight:600;font-size:0.875rem;cursor:pointer;box-shadow:0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.08);transition:background-color 0.15s ease, box-shadow 0.15s ease;}.done-btn.svelte-16uy9h6:hover {background:var(--cv-primary-hover);box-shadow:0 3px 6px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.08);}\n\n /* Share Tab Styles */.share-content.svelte-16uy9h6 {display:flex;flex-direction:column;gap:1rem;align-items:center;text-align:center;padding:1rem 0;}.share-instruction.svelte-16uy9h6 {font-size:0.95rem;color:var(--cv-text-secondary);margin-bottom:0.5rem;}.share-action-btn.svelte-16uy9h6 {display:flex;align-items:center;justify-content:center;gap:0.75rem;width:100%;max-width:320px;padding:0.75rem 1rem;border-radius:0.5rem;font-weight:500;font-size:0.95rem;cursor:pointer;transition:all 0.2s ease;border:1px solid var(--cv-border);background:var(--cv-bg);color:var(--cv-text);}.share-action-btn.svelte-16uy9h6:hover {border-color:var(--cv-primary);color:var(--cv-primary);background:var(--cv-bg-hover);}.share-action-btn.primary.svelte-16uy9h6 {background:var(--cv-primary);border-color:var(--cv-primary);color:white;}.share-action-btn.primary.svelte-16uy9h6:hover {background:var(--cv-primary-hover);border-color:var(--cv-primary-hover);}.btn-icon.svelte-16uy9h6 {display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;}\n\n /* Placeholder Inputs */.placeholders-container.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;}'
11492
+ code: '\n /* Modal Overlay & Modal Frame */.modal-overlay.svelte-16uy9h6 {position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0, 0, 0, 0.5);display:flex;align-items:center;justify-content:center;z-index:10002;}.modal-box.svelte-16uy9h6 {background:var(--cv-bg);border-radius:var(--cv-modal-radius, 0.75rem);box-shadow:0 25px 50px -12px var(--cv-shadow);max-width:32rem;width:90vw;max-height:80vh;display:flex;flex-direction:column;}.header.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;padding:0.5rem 1rem;border-bottom:1px solid var(--cv-border);}.header-content.svelte-16uy9h6 {display:flex;align-items:center;gap:0.75rem;}.modal-icon.svelte-16uy9h6 {position:relative;width:1rem;height:1rem;display:flex;align-items:center;justify-content:center;border-radius:9999px;color:var(--cv-text);}.modal-icon.svelte-16uy9h6 svg {fill:currentColor;}.title.svelte-16uy9h6 {font-size:1.125rem;font-weight:bold;color:var(--cv-text);margin:0;}.close-btn.svelte-16uy9h6 {width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border-radius:9999px;background:transparent;border:none;color:var(--cv-text-secondary);cursor:pointer;transition:all 0.2s ease;}.close-btn.svelte-16uy9h6:hover {background:rgba(62, 132, 244, 0.1);color:var(--cv-primary);}.main.svelte-16uy9h6 {padding:1rem;flex:1;display:flex;flex-direction:column;overflow-y:auto;max-height:calc(80vh - 8rem);min-height:var(--cv-modal-min-height, 20rem);}.description.svelte-16uy9h6 {font-size:0.875rem;color:var(--cv-text);margin:0 0 1rem 0;line-height:1.4;}\n\n /* Tabs */.tabs.svelte-16uy9h6 {display:flex;margin-bottom:1rem;border-bottom:2px solid var(--cv-border);}.tab.svelte-16uy9h6 {background:transparent;border:none;padding:0.5rem 1rem;font-size:0.9rem;font-weight:600;color:var(--cv-text-secondary);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;}.tab.active.svelte-16uy9h6 {color:var(--cv-primary);border-bottom-color:var(--cv-primary);}.tab-content.svelte-16uy9h6 {display:none;}.tab-content.active.svelte-16uy9h6 {display:block;}\n\n /* Section Styling */.section.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;margin-bottom:1.5rem;}.section-heading.svelte-16uy9h6 {font-size:0.7rem;font-weight:600;color:var(--cv-text-secondary);text-transform:var(--cv-section-label-transform, uppercase);letter-spacing:0.08em;margin:0;}.toggles-container.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.5rem;overflow:hidden;}\n\n /* Tab Groups Section specific */.tabgroups-container.svelte-16uy9h6 {border-radius:0.5rem;}\n\n /* Nav Toggle Card */.tabgroup-card.svelte-16uy9h6 {background:var(--cv-bg);border-bottom:1px solid var(--cv-border);}.tabgroup-card.header-card.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;padding:0.75rem;border:1px solid var(--cv-border);border-radius:0.5rem;margin-bottom:0.75rem;}.tabgroup-row.svelte-16uy9h6 {display:flex;align-items:center;justify-content:space-between;width:100%;gap:1rem;}.logo-box.svelte-16uy9h6 {width:3rem;height:3rem;background:var(--cv-modal-icon-bg);border-radius:0.5rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;}.nav-icon.svelte-16uy9h6 {width:2rem;height:2rem;color:var(--cv-text);display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color 0.2s ease;}.tabgroup-info.svelte-16uy9h6 {flex:1;display:flex;flex-direction:column;gap:0.25rem;}.tabgroup-title.svelte-16uy9h6 {font-weight:500;font-size:0.875rem;color:var(--cv-text);margin:0 0 0 0;}.tabgroup-description.svelte-16uy9h6 {font-size:0.75rem;color:var(--cv-text-secondary);margin:0;line-height:1.3;}\n\n /* Toggle Switch */.toggle-switch.svelte-16uy9h6 {position:relative;display:inline-flex;align-items:center;width:44px;height:24px;background:var(--cv-switch-bg);border-radius:9999px;padding:2px;box-sizing:border-box;cursor:pointer;transition:background-color 0.2s ease;border:none;}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6) {display:none;}.toggle-switch.svelte-16uy9h6 .switch-bg:where(.svelte-16uy9h6) {position:absolute;inset:0;border-radius:9999px;background:var(--cv-switch-bg);transition:background-color 0.2s ease;pointer-events:none;}.toggle-switch.svelte-16uy9h6 .switch-knob:where(.svelte-16uy9h6) {position:relative;width:20px;height:20px;background:var(--cv-switch-knob);border-radius:50%;box-shadow:0 1px 2px rgba(0, 0, 0, 0.1);transition:transform 0.2s ease;transform:translateX(0);}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6):checked ~ .switch-knob:where(.svelte-16uy9h6) {transform:translateX(20px);}.toggle-switch.svelte-16uy9h6 input:where(.svelte-16uy9h6):checked ~ .switch-bg:where(.svelte-16uy9h6) {background:var(--cv-primary);}\n\n /* Tab Groups List */.tab-groups-list.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;}\n\n /* Footer */.footer.svelte-16uy9h6 {padding:0.75rem 1rem;border-top:1px solid var(--cv-border);display:flex;align-items:center;justify-content:space-between;background:var(--cv-bg);border-bottom-left-radius:var(--cv-modal-radius, 0.75rem);border-bottom-right-radius:var(--cv-modal-radius, 0.75rem);}.footer-attribution.svelte-16uy9h6 {display:flex;flex-direction:column;align-items:center;text-align:center;gap:0.1rem;opacity:0.5;transition:opacity 0.15s ease;}.footer-attribution.svelte-16uy9h6:hover {opacity:1;}.footer-tagline.svelte-16uy9h6 {font-size:0.6rem;color:var(--cv-text-secondary);letter-spacing:0.04em;}.footer-link.svelte-16uy9h6 {color:var(--cv-text-secondary);text-decoration:none;font-size:0.68rem;font-weight:600;letter-spacing:0.08em;transition:color 0.15s ease;}.footer-link.svelte-16uy9h6:hover {color:var(--cv-primary);}.reset-btn.svelte-16uy9h6 {display:flex;align-items:center;gap:0.4rem;background:transparent;border:none;font-size:0.875rem;font-weight:500;color:var(--cv-text-secondary);cursor:pointer;padding:0.4rem 0.5rem;border-radius:0.5rem;transition:all 0.2s ease;}.reset-btn.svelte-16uy9h6:hover {background:var(--cv-danger-bg);color:var(--cv-danger);}.done-btn.svelte-16uy9h6 {background:var(--cv-primary);color:white;border:none;padding:0.5rem 1.1rem;border-radius:0.5rem;font-weight:600;font-size:0.875rem;cursor:pointer;box-shadow:0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.08);transition:background-color 0.15s ease, box-shadow 0.15s ease;}.done-btn.svelte-16uy9h6:hover {background:var(--cv-primary-hover);box-shadow:0 3px 6px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.08);}\n\n /* Share Tab Styles */.share-content.svelte-16uy9h6 {display:flex;flex-direction:column;gap:1rem;align-items:center;text-align:center;padding:1rem 0;}.share-instruction.svelte-16uy9h6 {font-size:0.95rem;color:var(--cv-text-secondary);margin-bottom:0.5rem;}.share-action-btn.svelte-16uy9h6 {display:flex;align-items:center;justify-content:center;gap:0.75rem;width:100%;max-width:320px;padding:0.75rem 1rem;border-radius:0.5rem;font-weight:500;font-size:0.95rem;cursor:pointer;transition:all 0.2s ease;border:1px solid var(--cv-border);background:var(--cv-bg);color:var(--cv-text);}.share-action-btn.svelte-16uy9h6:hover {border-color:var(--cv-primary);color:var(--cv-primary);background:var(--cv-bg-hover);}.share-action-btn.primary.svelte-16uy9h6 {background:var(--cv-primary);border-color:var(--cv-primary);color:white;}.share-action-btn.primary.svelte-16uy9h6:hover {background:var(--cv-primary-hover);border-color:var(--cv-primary-hover);}.btn-icon.svelte-16uy9h6 {display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;}\n\n /* Placeholder Inputs */.placeholders-container.svelte-16uy9h6 {display:flex;flex-direction:column;gap:0.75rem;}'
11378
11493
  };
11379
11494
 
11380
11495
  function Modal($$anchor, $$props) {
11381
11496
  push($$props, true);
11382
- append_styles$1($$anchor, $$css$h);
11497
+ append_styles$1($$anchor, $$css$j);
11383
11498
 
11384
11499
  /* eslint-disable @typescript-eslint/no-explicit-any */
11385
11500
  let onclose = prop($$props, 'onclose', 3, () => {}),
@@ -11463,19 +11578,13 @@
11463
11578
 
11464
11579
  function handleTabGroupChange(detail) {
11465
11580
  const { groupId, tabId } = detail;
11466
-
11467
- // Capture element and its current visual position before state change
11468
11581
  const anchorEl = findHighestVisibleElement('cv-tabgroup');
11582
+ const scrollAnchor = anchorEl ? captureScrollAnchor(anchorEl) : null;
11469
11583
 
11470
- const scrollAnchor = anchorEl
11471
- ? { element: anchorEl, top: anchorEl.getBoundingClientRect().top }
11472
- : null;
11473
-
11474
- activeStateStore.setPinnedTab(groupId, tabId);
11584
+ activeStateStore.setMarkedTab(groupId, tabId);
11475
11585
 
11476
- // Restore visual position after layout shift
11477
11586
  if (scrollAnchor) {
11478
- handleScrollAnchor(scrollAnchor);
11587
+ restoreScrollAnchor(scrollAnchor);
11479
11588
  }
11480
11589
  }
11481
11590
 
@@ -11514,7 +11623,7 @@
11514
11623
  return 'hide';
11515
11624
  }
11516
11625
 
11517
- var div = root$g();
11626
+ var div = root$h();
11518
11627
 
11519
11628
  div.__click = (e) => {
11520
11629
  if (e.target === e.currentTarget) onclose()();
@@ -11554,7 +11663,7 @@
11554
11663
 
11555
11664
  {
11556
11665
  var consequent = ($$anchor) => {
11557
- var button_1 = root_1$9();
11666
+ var button_1 = root_1$c();
11558
11667
 
11559
11668
  button_1.__click = () => set(activeTab, 'customize');
11560
11669
  template_effect(() => set_class(button_1, 1, `tab ${get(activeTab) === 'customize' ? 'active' : ''}`, 'svelte-16uy9h6'));
@@ -11575,12 +11684,12 @@
11575
11684
 
11576
11685
  {
11577
11686
  var consequent_7 = ($$anchor) => {
11578
- var div_6 = root_2$7();
11687
+ var div_6 = root_2$8();
11579
11688
  var node_4 = child(div_6);
11580
11689
 
11581
11690
  {
11582
11691
  var consequent_1 = ($$anchor) => {
11583
- var p = root_3$5();
11692
+ var p = root_3$6();
11584
11693
  var text_1 = child(p, true);
11585
11694
 
11586
11695
  reset(p);
@@ -11596,12 +11705,12 @@
11596
11705
  var node_5 = sibling(node_4, 2);
11597
11706
 
11598
11707
  each(node_5, 16, () => get(sectionOrder), (section) => section, ($$anchor, section) => {
11599
- var fragment = root_4$2();
11708
+ var fragment = root_4$3();
11600
11709
  var node_6 = first_child(fragment);
11601
11710
 
11602
11711
  {
11603
11712
  var consequent_2 = ($$anchor) => {
11604
- var div_7 = root_5$1();
11713
+ var div_7 = root_5$2();
11605
11714
  var div_8 = sibling(child(div_7), 2);
11606
11715
 
11607
11716
  each(div_8, 21, () => get(toggles), (toggle) => toggle.toggleId, ($$anchor, toggle) => {
@@ -11636,7 +11745,7 @@
11636
11745
 
11637
11746
  {
11638
11747
  var consequent_3 = ($$anchor) => {
11639
- var div_9 = root_7();
11748
+ var div_9 = root_7$2();
11640
11749
  var div_10 = sibling(child(div_9), 2);
11641
11750
 
11642
11751
  each(div_10, 21, () => get(placeholderDefinitions), (def) => def.name, ($$anchor, def) => {
@@ -11671,7 +11780,7 @@
11671
11780
 
11672
11781
  {
11673
11782
  var consequent_6 = ($$anchor) => {
11674
- var div_11 = root_9();
11783
+ var div_11 = root_9$1();
11675
11784
  var div_12 = sibling(child(div_11), 2);
11676
11785
  var div_13 = child(div_12);
11677
11786
  var div_14 = child(div_13);
@@ -11910,13 +12019,13 @@
11910
12019
  delegate(['click', 'change']);
11911
12020
 
11912
12021
  const HIGHLIGHT_COLORS = [
11913
- { key: 'yellow', label: 'Yellow', hex: '#f5f521' }, // default
12022
+ { key: 'yellow', label: 'Yellow', hex: '#f5f521' },
11914
12023
  { key: 'blue', label: 'Blue', hex: '#3b82f6' },
11915
12024
  { key: 'red', label: 'Red', hex: '#ef4444' },
11916
12025
  { key: 'black', label: 'Black', hex: '#1a1a1a' },
11917
12026
  { key: 'green', label: 'Green', hex: '#22c55e' },
11918
12027
  ];
11919
- const DEFAULT_COLOR_KEY = 'yellow';
12028
+ const DEFAULT_COLOR_KEY = 'red';
11920
12029
 
11921
12030
  const ANNOTATION_CORNERS = ['tl', 'tr', 'bl', 'br'];
11922
12031
  const CORNER_ICONS = [
@@ -11929,7 +12038,6 @@
11929
12038
  const MAX_ANNOTATION_LENGTH = 280;
11930
12039
  const ANNOTATION_PREVIEW_LENGTH = 40;
11931
12040
 
11932
- /* eslint-disable @typescript-eslint/no-explicit-any */
11933
12041
  /**
11934
12042
  * Generates a simple hash code for a string.
11935
12043
  */
@@ -11945,18 +12053,87 @@
11945
12053
  return hash;
11946
12054
  }
11947
12055
  /**
11948
- * Normalizes text content by removing excessive whitespace.
12056
+ * Matches raw (un-hydrated) placeholder tokens in text content, including
12057
+ * escaped forms like \[[ name ]]:
12058
+ * [[ name ]], [[ name : fallback ]], [[ name ? truthy : falsy ]], \[[ name ]]
12059
+ * Captures the placeholder name in group 1. Used to normalize tokens before hashing.
12060
+ *
12061
+ * The optional `(?:\\)?` prefix intentionally consumes the leading backslash so that
12062
+ * \[[ name ]] normalizes to [[name]] — the same canonical form that PlaceholderBinder
12063
+ * emits for escaped tokens ([[ name ]] literal text). This keeps the hash stable
12064
+ * across raw and hydrated DOM states.
12065
+ */
12066
+ const RAW_PLACEHOLDER_RE = /(?:\\)?\[\[\s*([a-zA-Z0-9_-]+)[^\]]*\]\]/g;
12067
+ /**
12068
+ * Recursively walks `node`, appending stable placeholder-canonical text to `parts`.
12069
+ * - Text nodes: raw [[ ... ]] tokens are normalized to [[name]] before appending.
12070
+ * - <cv-placeholder> elements: appends [[name]] from the `name` attribute; skips children
12071
+ * (children hold the live resolved value, not the canonical template form).
12072
+ * - All other elements: recurse into children.
12073
+ */
12074
+ function collectStableText(node, parts) {
12075
+ if (node.nodeType === Node.TEXT_NODE) {
12076
+ const text = node.nodeValue || '';
12077
+ parts.push(text.replace(RAW_PLACEHOLDER_RE, '[[$1]]'));
12078
+ }
12079
+ else if (node.nodeType === Node.ELEMENT_NODE) {
12080
+ const el = node;
12081
+ if (el.tagName === 'CV-PLACEHOLDER') {
12082
+ parts.push(`[[${el.getAttribute('name') || ''}]]`);
12083
+ return; // Skip children — they contain the resolved runtime value
12084
+ }
12085
+ for (let i = 0; i < el.childNodes.length; i++) {
12086
+ collectStableText(el.childNodes[i], parts);
12087
+ }
12088
+ }
12089
+ }
12090
+ /**
12091
+ * Returns the text content of an element with all <cv-placeholder> custom elements
12092
+ * replaced by their canonical [[name]] template form.
12093
+ *
12094
+ * This produces a stable string regardless of the placeholder's current resolved value
12095
+ * or whether it has been hydrated yet — enabling consistent hashing across share and load time.
12096
+ *
12097
+ * Without this, an element containing [[username]] resolved to "alice" would hash as
12098
+ * "Hello alice!" at share-time but "Hello [[username]]!" at load-time, causing resolution to fail.
12099
+ */
12100
+ function getStableTextContent(el) {
12101
+ // Special case: el itself is a <cv-placeholder> — return canonical form directly.
12102
+ if (el.tagName === 'CV-PLACEHOLDER') {
12103
+ return `[[${el.getAttribute('name') || ''}]]`;
12104
+ }
12105
+ // Fast path: if no raw [[ tokens and no <cv-placeholder> descendants,
12106
+ // there are no placeholders — return textContent directly (native, no allocation).
12107
+ // Check textContent first to avoid the querySelector when raw tokens are present
12108
+ // (raw DOM elements with [[ tokens always need the slow path).
12109
+ const rawText = el.textContent || '';
12110
+ if (!rawText.includes('[[')) {
12111
+ const hasHydrated = el.querySelector('cv-placeholder') !== null;
12112
+ if (!hasHydrated) {
12113
+ return rawText;
12114
+ }
12115
+ }
12116
+ // Slow path: walk the DOM to canonicalize all placeholder forms.
12117
+ const parts = [];
12118
+ for (let i = 0; i < el.childNodes.length; i++) {
12119
+ collectStableText(el.childNodes[i], parts);
12120
+ }
12121
+ return parts.join('');
12122
+ }
12123
+ /**
12124
+ * Combines getStableTextContent and normalizeText into a single call.
12125
+ * Used wherever element text is computed for hashing or comparison.
11949
12126
  */
11950
- function normalizeText(text) {
11951
- return text.trim().replace(/\s+/g, ' ');
12127
+ function getStableNormalizedText(el) {
12128
+ return getStableTextContent(el).trim().replace(/\s+/g, ' ');
11952
12129
  }
12130
+
11953
12131
  /**
11954
12132
  * Creates an AnchorDescriptor for a given DOM element.
11955
12133
  */
11956
12134
  function createDescriptor(el) {
11957
12135
  const tag = el.tagName;
11958
- const textContent = el.textContent || '';
11959
- const normalizedText = normalizeText(textContent);
12136
+ const normalizedText = getStableNormalizedText(el);
11960
12137
  // Find nearest parent with an ID
11961
12138
  let parentId;
11962
12139
  let parent = el.parentElement;
@@ -11983,6 +12160,10 @@
11983
12160
  }
11984
12161
  return descriptor;
11985
12162
  }
12163
+
12164
+ /* eslint-disable @typescript-eslint/no-explicit-any */
12165
+ const COLOR_KEYS = new Set(HIGHLIGHT_COLORS.map((c) => c.key));
12166
+ const CORNER_KEYS = new Set(ANNOTATION_CORNERS);
11986
12167
  /**
11987
12168
  * Serializes a list of AnchorDescriptors into a URL-safe string.
11988
12169
  */
@@ -11997,16 +12178,16 @@
11997
12178
  h: d.textHash,
11998
12179
  id: d.elementId,
11999
12180
  ...(d.color && d.color !== DEFAULT_COLOR_KEY ? { c: d.color } : {}),
12181
+ ...(d.annotationCorner && d.annotationCorner !== DEFAULT_ANNOTATION_CORNER ? { nc: d.annotationCorner } : {}),
12000
12182
  ...(d.annotation ? { n: d.annotation } : {}),
12001
- ...(d.annotation && d.annotationCorner && d.annotationCorner !== DEFAULT_ANNOTATION_CORNER
12002
- ? { nc: d.annotationCorner }
12003
- : {}),
12004
12183
  }));
12005
12184
  // When all elements have stable IDs, use a human-readable format.
12006
12185
  // Annotations are encoded via encodeURIComponent so the format stays URL-readable.
12007
12186
  // Format per element:
12008
12187
  // no color, no note → "id"
12009
12188
  // color only → "id:color"
12189
+ // corner only → "id::corner"
12190
+ // color + corner → "id:color:corner"
12010
12191
  // color + note → "id:color:corner:encodedNote" (always 4 parts)
12011
12192
  // note, no color → "id::corner:encodedNote"
12012
12193
  const allHaveIds = minified.every((m) => !!m.id);
@@ -12015,9 +12196,12 @@
12015
12196
  const id = m.id;
12016
12197
  const c = m.c ?? '';
12017
12198
  const n = m.n;
12018
- const nc = m.nc ?? DEFAULT_ANNOTATION_CORNER;
12199
+ const nc = m.nc;
12019
12200
  if (n) {
12020
- return `${id}:${c}:${nc}:${encodeURIComponent(n)}`;
12201
+ return `${id}:${c}:${nc ?? DEFAULT_ANNOTATION_CORNER}:${encodeURIComponent(n)}`;
12202
+ }
12203
+ if (nc) {
12204
+ return `${id}:${c}:${nc}`;
12021
12205
  }
12022
12206
  return c ? `${id}:${c}` : id;
12023
12207
  }).join(',');
@@ -12078,6 +12262,9 @@
12078
12262
  descriptor.annotation = m.n;
12079
12263
  descriptor.annotationCorner = (m.nc ?? DEFAULT_ANNOTATION_CORNER);
12080
12264
  }
12265
+ else if (m.nc) {
12266
+ descriptor.annotationCorner = m.nc;
12267
+ }
12081
12268
  return descriptor;
12082
12269
  });
12083
12270
  }
@@ -12086,13 +12273,13 @@
12086
12273
  return parseIds(encoded);
12087
12274
  }
12088
12275
  }
12089
- const COLOR_KEYS = new Set(HIGHLIGHT_COLORS.map((c) => c.key));
12090
- const CORNER_KEYS = new Set(ANNOTATION_CORNERS);
12091
12276
  /**
12092
12277
  * Parses a space-separated, plus-separated, or comma-separated list of IDs into a list of AnchorDescriptors.
12093
12278
  * Supports:
12094
12279
  * "id" — ID only
12095
12280
  * "id:color" — with color
12281
+ * "id:color:corner" — color + corner, no note
12282
+ * "id::corner" — corner only, no color, no note
12096
12283
  * "id:color:corner:note" — with color + annotation (note is percent-encoded)
12097
12284
  * "id::corner:note" — annotation, no color
12098
12285
  */
@@ -12124,6 +12311,16 @@
12124
12311
  annotation = noteSeg;
12125
12312
  }
12126
12313
  }
12314
+ else if (segs.length === 3) {
12315
+ // "id:color:corner" — corner without note
12316
+ id = segs[0];
12317
+ const colorSeg = segs[1];
12318
+ const cornerSeg = segs[2];
12319
+ if (COLOR_KEYS.has(colorSeg))
12320
+ color = colorSeg;
12321
+ if (CORNER_KEYS.has(cornerSeg))
12322
+ annotationCorner = cornerSeg;
12323
+ }
12127
12324
  else if (segs.length === 2) {
12128
12325
  // "id:color"
12129
12326
  const colorSeg = segs[1];
@@ -12141,13 +12338,14 @@
12141
12338
  };
12142
12339
  if (color !== undefined)
12143
12340
  descriptor.color = color;
12144
- if (annotation !== undefined && annotationCorner !== undefined) {
12341
+ if (annotation !== undefined)
12145
12342
  descriptor.annotation = annotation;
12343
+ if (annotationCorner !== undefined)
12146
12344
  descriptor.annotationCorner = annotationCorner;
12147
- }
12148
12345
  return descriptor;
12149
12346
  });
12150
12347
  }
12348
+
12151
12349
  const SCORE_EXACT_HASH = 50;
12152
12350
  const SCORE_SNIPPET_START = 30;
12153
12351
  const SCORE_INDEX_MATCH = 10;
@@ -12189,12 +12387,14 @@
12189
12387
  // Optimization: Structural Check First (Fastest)
12190
12388
  // If we trust the structure hasn't changed, the element at the specific index
12191
12389
  // is effectively O(1) access if we assume `querySelectorAll` order is stable.
12390
+ // Cache the computed text so the full scan can reuse it if this check fails.
12391
+ let indexCandidateText = null;
12192
12392
  if (candidates[descriptor.index]) {
12193
12393
  const candidate = candidates[descriptor.index];
12194
- const text = normalizeText(candidate.textContent || '');
12394
+ indexCandidateText = getStableNormalizedText(candidate);
12195
12395
  // Perfect Match Check: If index + hash match, it's virtually guaranteed.
12196
12396
  // This avoids checking every other candidate.
12197
- if (hashCode(text) === descriptor.textHash) {
12397
+ if (hashCode(indexCandidateText) === descriptor.textHash) {
12198
12398
  return [candidate];
12199
12399
  }
12200
12400
  }
@@ -12205,7 +12405,10 @@
12205
12405
  for (let i = 0; i < candidates.length; i++) {
12206
12406
  const candidate = candidates[i];
12207
12407
  let score = 0;
12208
- const text = normalizeText(candidate.textContent || '');
12408
+ // Reuse already-computed text for the index candidate to avoid duplicate DOM walk.
12409
+ const text = i === descriptor.index && indexCandidateText !== null
12410
+ ? indexCandidateText
12411
+ : getStableNormalizedText(candidate);
12209
12412
  // Content Match
12210
12413
  if (hashCode(text) === descriptor.textHash) {
12211
12414
  score += SCORE_EXACT_HASH;
@@ -12349,7 +12552,7 @@
12349
12552
  set(this.#isActive, value, true);
12350
12553
  }
12351
12554
 
12352
- #selectionMode = state('show');
12555
+ #selectionMode = state('highlight');
12353
12556
 
12354
12557
  get selectionMode() {
12355
12558
  return get(this.#selectionMode);
@@ -12492,7 +12695,11 @@
12492
12695
  const trimmed = text.trim();
12493
12696
 
12494
12697
  if (trimmed.length === 0) {
12495
- this.highlightAnnotations.delete(el);
12698
+ if (corner !== DEFAULT_ANNOTATION_CORNER) {
12699
+ this.highlightAnnotations.set(el, { text: '', corner });
12700
+ } else {
12701
+ this.highlightAnnotations.delete(el);
12702
+ }
12496
12703
  } else {
12497
12704
  const validatedText = trimmed.length > MAX_ANNOTATION_LENGTH ? trimmed.substring(0, MAX_ANNOTATION_LENGTH) : trimmed;
12498
12705
 
@@ -12756,23 +12963,23 @@
12756
12963
  return zoom;
12757
12964
  }
12758
12965
 
12759
- var root_1$8 = from_html(`<div role="alert" aria-live="polite"> </div>`);
12760
- var root$f = from_html(`<div class="toast-container svelte-14irt8g"></div>`);
12966
+ var root_1$b = from_html(`<div role="alert" aria-live="polite"> </div>`);
12967
+ var root$g = from_html(`<div class="toast-container svelte-14irt8g"></div>`);
12761
12968
 
12762
- const $$css$g = {
12969
+ const $$css$i = {
12763
12970
  hash: 'svelte-14irt8g',
12764
12971
  code: '.toast-container.svelte-14irt8g {position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:20000;display:flex;flex-direction:column;align-items:center;gap:10px;pointer-events:none; /* Let clicks pass through container */}.toast-item.svelte-14irt8g {background:rgba(0, 0, 0, 0.85);color:white;padding:10px 20px;border-radius:4px;font-size:14px;box-shadow:0 4px 6px rgba(0, 0, 0, 0.1);pointer-events:auto; /* Re-enable clicks on toasts */max-width:300px;text-align:center;}'
12765
12972
  };
12766
12973
 
12767
12974
  function Toast($$anchor, $$props) {
12768
12975
  push($$props, false);
12769
- append_styles$1($$anchor, $$css$g);
12976
+ append_styles$1($$anchor, $$css$i);
12770
12977
  init();
12771
12978
 
12772
- var div = root$f();
12979
+ var div = root$g();
12773
12980
 
12774
12981
  each(div, 13, () => toast.items, (t) => t.id, ($$anchor, t) => {
12775
- var div_1 = root_1$8();
12982
+ var div_1 = root_1$b();
12776
12983
  var text = child(div_1, true);
12777
12984
 
12778
12985
  reset(div_1);
@@ -12793,16 +13000,16 @@
12793
13000
  pop();
12794
13001
  }
12795
13002
 
12796
- var root$e = from_html(`<div class="floating-bar svelte-bs8cbd"><div class="mode-toggle svelte-bs8cbd"><button title="Show only selected elements">Show</button> <button title="Hide selected elements">Hide</button> <button title="Highlight selected elements">Highlight</button></div> <span class="divider svelte-bs8cbd"></span> <span class="count svelte-bs8cbd"> </span> <button class="btn clear svelte-bs8cbd">Clear</button> <button class="btn preview svelte-bs8cbd">Preview</button> <button class="btn generate svelte-bs8cbd">Copy Link</button> <button class="btn exit svelte-bs8cbd">Exit</button></div>`);
13003
+ var root$f = from_html(`<div class="floating-bar svelte-bs8cbd"><div class="mode-toggle svelte-bs8cbd"><button type="button" title="Highlight selected elements">Highlight</button> <button type="button" title="Show only selected elements">Show</button> <button type="button" title="Hide selected elements">Hide</button></div> <span class="divider svelte-bs8cbd"></span> <span class="count svelte-bs8cbd"> </span> <button type="button" class="btn clear svelte-bs8cbd">Clear</button> <button type="button" class="btn preview svelte-bs8cbd">Preview</button> <button type="button" class="btn generate svelte-bs8cbd">Copy Link</button> <button type="button" class="btn exit svelte-bs8cbd">Exit</button></div>`);
12797
13004
 
12798
- const $$css$f = {
13005
+ const $$css$h = {
12799
13006
  hash: 'svelte-bs8cbd',
12800
13007
  code: '.floating-bar.svelte-bs8cbd {position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:#2c2c2c;color:#f1f1f1;border-radius:8px;padding:8px 12px;box-shadow:0 8px 20px rgba(0, 0, 0, 0.4);display:grid;grid-template-columns:auto auto 1fr auto auto auto auto;align-items:center;gap:12px;z-index:99999;font-family:system-ui,\n -apple-system,\n sans-serif;font-size:14px;border:1px solid #4a4a4a;pointer-events:auto;white-space:nowrap;min-width:500px;}.mode-toggle.svelte-bs8cbd {display:flex;background:#1a1a1a;border-radius:6px;padding:2px;border:1px solid #4a4a4a;}.mode-btn.svelte-bs8cbd {background:transparent;color:#aeaeae;border:none;padding:4px 10px;border-radius:4px;cursor:pointer;font-weight:500;font-size:13px;transition:all 0.2s;}.mode-btn.svelte-bs8cbd:hover {color:#fff;}.mode-btn.active.svelte-bs8cbd {background:#4a4a4a;color:#fff;box-shadow:0 1px 3px rgba(0, 0, 0, 0.2);}.divider.svelte-bs8cbd {width:1px;height:20px;background:#4a4a4a;margin:0 4px;}.count.svelte-bs8cbd {font-weight:500;min-width:120px;text-align:center;font-size:13px;color:#ccc;}.btn.svelte-bs8cbd {background-color:#0078d4;color:white;border:none;padding:6px 12px;border-radius:5px;cursor:pointer;font-weight:500;transition:background-color 0.2s;font-size:13px;}.btn.svelte-bs8cbd:hover {background-color:#005a9e;}.btn.clear.svelte-bs8cbd {background-color:transparent;border:1px solid #5a5a5a;color:#dadada;}.btn.clear.svelte-bs8cbd:hover {background-color:#3a3a3a;color:white;}.btn.preview.svelte-bs8cbd {background-color:#333;border:1px solid #555;}.btn.preview.svelte-bs8cbd:hover {background-color:#444;}.btn.exit.svelte-bs8cbd {background-color:transparent;color:#ff6b6b;padding:6px 10px;}.btn.exit.svelte-bs8cbd:hover {background-color:rgba(255, 107, 107, 0.1);}\n\n @media (max-width: 600px) {.floating-bar.svelte-bs8cbd {display:flex;flex-wrap:wrap;min-width:unset;width:90%;max-width:400px;height:auto;padding:12px;gap:10px;bottom:30px;}.mode-toggle.svelte-bs8cbd {margin-right:auto;order:1;}.btn.exit.svelte-bs8cbd {margin-left:auto;order:2;}.divider.svelte-bs8cbd {display:none;}.count.svelte-bs8cbd {width:100%;text-align:center;order:3;padding:8px 0;border-top:1px solid #3a3a3a;border-bottom:1px solid #3a3a3a;margin:4px 0;}.btn.clear.svelte-bs8cbd,\n .btn.preview.svelte-bs8cbd,\n .btn.generate.svelte-bs8cbd {flex:1;text-align:center;font-size:12px;padding:8px 4px;order:4;}.btn.generate.svelte-bs8cbd {flex:1.5;}\n }'
12801
13008
  };
12802
13009
 
12803
13010
  function ShareToolbar($$anchor, $$props) {
12804
13011
  push($$props, false);
12805
- append_styles$1($$anchor, $$css$f);
13012
+ append_styles$1($$anchor, $$css$h);
12806
13013
 
12807
13014
  function handleClear() {
12808
13015
  shareStore.clearAllSelections();
@@ -12822,19 +13029,19 @@
12822
13029
 
12823
13030
  init();
12824
13031
 
12825
- var div = root$e();
13032
+ var div = root$f();
12826
13033
  var div_1 = child(div);
12827
13034
  var button = child(div_1);
12828
13035
 
12829
- button.__click = () => shareStore.setSelectionMode('show');
13036
+ button.__click = () => shareStore.setSelectionMode('highlight');
12830
13037
 
12831
13038
  var button_1 = sibling(button, 2);
12832
13039
 
12833
- button_1.__click = () => shareStore.setSelectionMode('hide');
13040
+ button_1.__click = () => shareStore.setSelectionMode('show');
12834
13041
 
12835
13042
  var button_2 = sibling(button_1, 2);
12836
13043
 
12837
- button_2.__click = () => shareStore.setSelectionMode('highlight');
13044
+ button_2.__click = () => shareStore.setSelectionMode('hide');
12838
13045
  reset(div_1);
12839
13046
 
12840
13047
  var span = sibling(div_1, 4);
@@ -12860,12 +13067,12 @@
12860
13067
  reset(div);
12861
13068
 
12862
13069
  template_effect(() => {
12863
- set_class(button, 1, `mode-btn ${shareStore.selectionMode === 'show' ? 'active' : ''}`, 'svelte-bs8cbd');
12864
- set_attribute(button, 'aria-pressed', shareStore.selectionMode === 'show');
12865
- set_class(button_1, 1, `mode-btn ${shareStore.selectionMode === 'hide' ? 'active' : ''}`, 'svelte-bs8cbd');
12866
- set_attribute(button_1, 'aria-pressed', shareStore.selectionMode === 'hide');
12867
- set_class(button_2, 1, `mode-btn ${shareStore.selectionMode === 'highlight' ? 'active' : ''}`, 'svelte-bs8cbd');
12868
- set_attribute(button_2, 'aria-pressed', shareStore.selectionMode === 'highlight');
13070
+ set_class(button, 1, `mode-btn ${shareStore.selectionMode === 'highlight' ? 'active' : ''}`, 'svelte-bs8cbd');
13071
+ set_attribute(button, 'aria-pressed', shareStore.selectionMode === 'highlight');
13072
+ set_class(button_1, 1, `mode-btn ${shareStore.selectionMode === 'show' ? 'active' : ''}`, 'svelte-bs8cbd');
13073
+ set_attribute(button_1, 'aria-pressed', shareStore.selectionMode === 'show');
13074
+ set_class(button_2, 1, `mode-btn ${shareStore.selectionMode === 'hide' ? 'active' : ''}`, 'svelte-bs8cbd');
13075
+ set_attribute(button_2, 'aria-pressed', shareStore.selectionMode === 'hide');
12869
13076
 
12870
13077
  set_text(text, `${shareStore.shareCount ?? ''} item${shareStore.shareCount === 1 ? '' : 's'} to
12871
13078
  ${shareStore.selectionMode === 'show'
@@ -12880,18 +13087,18 @@
12880
13087
 
12881
13088
  delegate(['click']);
12882
13089
 
12883
- var root_2$6 = from_html(`<span class="id-badge svelte-64gpkh" title="ID detection active"> </span>`);
12884
- var root_3$4 = from_html(`<button class="action-btn up svelte-64gpkh" title="Select Parent">↰</button>`);
12885
- var root_1$7 = from_html(`<div class="hover-helper svelte-64gpkh"><div class="info svelte-64gpkh"><span class="tag svelte-64gpkh"> </span> <!></div> <button> </button> <!></div>`);
13090
+ var root_2$7 = from_html(`<span class="id-badge svelte-64gpkh" title="ID detection active"> </span>`);
13091
+ var root_3$5 = from_html(`<button type="button" class="action-btn up svelte-64gpkh" title="Select Parent">↰</button>`);
13092
+ var root_1$a = from_html(`<div class="hover-helper svelte-64gpkh"><div class="info svelte-64gpkh"><span class="tag svelte-64gpkh"> </span> <!></div> <button type="button"> </button> <!></div>`);
12886
13093
 
12887
- const $$css$e = {
13094
+ const $$css$g = {
12888
13095
  hash: 'svelte-64gpkh',
12889
13096
  code: '.hover-helper.svelte-64gpkh {position:fixed;z-index:99999;background-color:#333;color:white;padding:4px 8px;border-radius:4px;display:flex;align-items:center;gap:8px;box-shadow:0 2px 5px rgba(0, 0, 0, 0.2);font-family:monospace;pointer-events:auto;}.info.svelte-64gpkh {display:flex;flex-direction:column;align-items:flex-start;line-height:1;gap:2px;}.tag.svelte-64gpkh {font-size:12px;font-weight:bold;color:#aeaeae;}.id-badge.svelte-64gpkh {font-size:10px;color:#64d2ff;max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.action-btn.svelte-64gpkh {background:#555;border:none;color:white;border-radius:3px;cursor:pointer;padding:2px 6px;font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;transition:background-color 0.1s;}.action-btn.svelte-64gpkh:hover {background:#777;}.action-btn.deselect.svelte-64gpkh {background-color:#d13438;}.action-btn.deselect.svelte-64gpkh:hover {background-color:#a42628;}'
12890
13097
  };
12891
13098
 
12892
13099
  function HoverHelper($$anchor, $$props) {
12893
13100
  push($$props, true);
12894
- append_styles$1($$anchor, $$css$e);
13101
+ append_styles$1($$anchor, $$css$g);
12895
13102
 
12896
13103
  // Derived state for easier access
12897
13104
  let target = user_derived(() => shareStore.currentHoverTarget);
@@ -12990,7 +13197,7 @@
12990
13197
 
12991
13198
  {
12992
13199
  var consequent_2 = ($$anchor) => {
12993
- var div = root_1$7();
13200
+ var div = root_1$a();
12994
13201
  var div_1 = child(div);
12995
13202
  var span = child(div_1);
12996
13203
  var text = child(span, true);
@@ -13001,7 +13208,7 @@
13001
13208
 
13002
13209
  {
13003
13210
  var consequent = ($$anchor) => {
13004
- var span_1 = root_2$6();
13211
+ var span_1 = root_2$7();
13005
13212
  var text_1 = child(span_1);
13006
13213
 
13007
13214
  reset(span_1);
@@ -13028,7 +13235,7 @@
13028
13235
 
13029
13236
  {
13030
13237
  var consequent_1 = ($$anchor) => {
13031
- var button_1 = root_3$4();
13238
+ var button_1 = root_3$5();
13032
13239
 
13033
13240
  button_1.__click = handleSelectParent;
13034
13241
  append($$anchor, button_1);
@@ -13065,18 +13272,18 @@
13065
13272
 
13066
13273
  delegate(['click']);
13067
13274
 
13068
- var root_2$5 = from_html(`<button></button>`);
13069
- var root_1$6 = from_html(`<div class="cv-color-swatches svelte-1r78n4c" role="none"></div>`);
13070
- var root$d = from_html(`<div class="cv-color-picker svelte-1r78n4c" role="none"><button class="cv-color-trigger svelte-1r78n4c" title="Choose highlight color" aria-label="Choose highlight color"><span class="cv-color-dot svelte-1r78n4c"></span></button> <!></div>`);
13275
+ var root_2$6 = from_html(`<button type="button"></button>`);
13276
+ var root_1$9 = from_html(`<div class="cv-color-swatches svelte-1r78n4c" role="none"></div>`);
13277
+ var root$e = from_html(`<div class="cv-color-picker svelte-1r78n4c" role="none"><button type="button" class="cv-color-trigger svelte-1r78n4c" title="Choose highlight color" aria-label="Choose highlight color"><span class="cv-color-dot svelte-1r78n4c"></span></button> <!></div>`);
13071
13278
 
13072
- const $$css$d = {
13279
+ const $$css$f = {
13073
13280
  hash: 'svelte-1r78n4c',
13074
13281
  code: '.cv-color-picker.svelte-1r78n4c {position:fixed;transform:translateX(-50%) translateY(-100%);display:flex;flex-direction:column;align-items:center;gap:4px;pointer-events:auto;z-index:9500;\n /* Nudge down so the trigger peeks above the element edge */margin-top:8px;}.cv-color-trigger.svelte-1r78n4c {width:22px;height:16px;border-radius:100px;border:1.5px solid rgba(0, 0, 0, 0.18);background:white;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0;box-shadow:0 2px 8px rgba(0, 0, 0, 0.15);transition:box-shadow 0.15s;}.cv-color-trigger.svelte-1r78n4c:hover {box-shadow:0 3px 12px rgba(0, 0, 0, 0.22);}.cv-color-dot.svelte-1r78n4c {width:10px;height:10px;border-radius:50%;display:block;border:1px solid rgba(0, 0, 0, 0.12);}.cv-color-swatches.svelte-1r78n4c {display:flex;flex-direction:row;gap:4px;background:white;border-radius:100px;padding:4px 6px;box-shadow:0 4px 16px rgba(0, 0, 0, 0.18);border:1px solid rgba(0, 0, 0, 0.1);}.cv-color-swatch.svelte-1r78n4c {width:16px;height:16px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;transition:transform 0.1s, border-color 0.1s;}.cv-color-swatch.svelte-1r78n4c:hover {transform:scale(1.2);border-color:rgba(0, 0, 0, 0.3);}.cv-color-swatch.active.svelte-1r78n4c {border-color:rgba(0, 0, 0, 0.5);transform:scale(1.15);}'
13075
13282
  };
13076
13283
 
13077
13284
  function HighlightColorPicker($$anchor, $$props) {
13078
13285
  push($$props, true);
13079
- append_styles$1($$anchor, $$css$d);
13286
+ append_styles$1($$anchor, $$css$f);
13080
13287
 
13081
13288
  let isExpanded = state(false);
13082
13289
  let rect = state(proxy({ top: 0, left: 0, width: 0 }));
@@ -13137,7 +13344,7 @@
13137
13344
 
13138
13345
  let centerX = user_derived(() => get(rect).left + get(rect).width / 2);
13139
13346
  let topY = user_derived(() => get(rect).top);
13140
- var div = root$d();
13347
+ var div = root$e();
13141
13348
  var button = child(div);
13142
13349
 
13143
13350
  button.__click = handleTriggerClick;
@@ -13150,10 +13357,10 @@
13150
13357
 
13151
13358
  {
13152
13359
  var consequent = ($$anchor) => {
13153
- var div_1 = root_1$6();
13360
+ var div_1 = root_1$9();
13154
13361
 
13155
13362
  each(div_1, 21, () => HIGHLIGHT_COLORS, index, ($$anchor, color) => {
13156
- var button_1 = root_2$5();
13363
+ var button_1 = root_2$6();
13157
13364
  let classes;
13158
13365
 
13159
13366
  button_1.__click = (e) => handleSwatchClick(e, get(color).key);
@@ -13193,20 +13400,20 @@
13193
13400
 
13194
13401
  delegate(['click', 'dblclick']);
13195
13402
 
13196
- var root_1$5 = from_html(`<span class="cv-annotation-tab-preview svelte-1r1spmr"> </span>`);
13197
- var root_2$4 = from_html(`<span class="cv-annotation-tab-icon svelte-1r1spmr">+ note</span>`);
13198
- var root_4$1 = from_html(`<button> </button>`);
13199
- var root_3$3 = from_html(`<div class="cv-annotation-panel svelte-1r1spmr" role="none"><textarea class="cv-annotation-textarea svelte-1r1spmr" placeholder="Add a note…" rows="3"></textarea> <div class="cv-annotation-footer svelte-1r1spmr"><div class="cv-corner-selector svelte-1r1spmr" role="group" aria-label="Anchor corner"></div> <span class="cv-char-counter svelte-1r1spmr"> </span></div></div>`);
13200
- var root$c = from_html(`<div class="cv-annotation-editor svelte-1r1spmr" role="none"><button aria-label="Annotation"><!></button> <!></div>`);
13403
+ var root_1$8 = from_html(`<span class="cv-annotation-tab-preview svelte-1r1spmr"> </span>`);
13404
+ var root_2$5 = from_html(`<span class="cv-annotation-tab-icon svelte-1r1spmr"> </span>`);
13405
+ var root_4$2 = from_html(`<button type="button"> </button>`);
13406
+ var root_3$4 = from_html(`<div class="cv-annotation-panel svelte-1r1spmr" role="none"><textarea class="cv-annotation-textarea svelte-1r1spmr" placeholder="Add a note…" rows="3"></textarea> <div class="cv-annotation-footer svelte-1r1spmr"><div class="cv-corner-selector svelte-1r1spmr" role="group" aria-label="Anchor corner"></div> <span class="cv-char-counter svelte-1r1spmr"> </span></div></div>`);
13407
+ var root$d = from_html(`<div class="cv-annotation-editor svelte-1r1spmr" role="none"><button type="button" aria-label="Annotation"><!></button> <!></div>`);
13201
13408
 
13202
- const $$css$c = {
13409
+ const $$css$e = {
13203
13410
  hash: 'svelte-1r1spmr',
13204
13411
  code: '.cv-annotation-editor.svelte-1r1spmr {position:fixed;z-index:9400;pointer-events:auto;display:flex;flex-direction:column;align-items:flex-start;gap:2px;}.cv-annotation-tab.svelte-1r1spmr {height:20px;padding:0 8px;border-radius:100px;border:1.5px solid rgba(0, 0, 0, 0.18);background:white;cursor:pointer;display:flex;align-items:center;gap:4px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.15);transition:box-shadow 0.15s;max-width:160px;overflow:hidden;}.cv-annotation-tab.svelte-1r1spmr:hover {box-shadow:0 3px 12px rgba(0, 0, 0, 0.22);}.cv-annotation-tab--has-text.svelte-1r1spmr {background:#fffbe6;border-color:rgba(180, 83, 9, 0.4);}.cv-annotation-tab-icon.svelte-1r1spmr {font-size:10px;line-height:1;color:#6b7280;}.cv-annotation-tab-preview.svelte-1r1spmr {font-size:9px;font-weight:600;color:#1a1a1a;font-family:ui-sans-serif, system-ui, sans-serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:130px;}.cv-annotation-panel.svelte-1r1spmr {background:white;border-radius:8px;border:1px solid rgba(0, 0, 0, 0.12);box-shadow:0 4px 16px rgba(0, 0, 0, 0.18);padding:8px;width:220px;display:flex;flex-direction:column;gap:6px;}.cv-annotation-textarea.svelte-1r1spmr {width:100%;box-sizing:border-box;resize:vertical;border:1px solid rgba(0, 0, 0, 0.15);border-radius:4px;padding:5px 7px;font-size:11px;font-family:ui-sans-serif, system-ui, sans-serif;color:#1a1a1a;line-height:1.5;outline:none;min-height:56px;}.cv-annotation-textarea.svelte-1r1spmr:focus {border-color:#b45309;box-shadow:0 0 0 2px rgba(180, 83, 9, 0.15);}.cv-annotation-footer.svelte-1r1spmr {display:flex;align-items:center;justify-content:space-between;}.cv-corner-selector.svelte-1r1spmr {display:flex;gap:2px;}.cv-corner-btn.svelte-1r1spmr {width:20px;height:20px;border-radius:4px;border:1px solid rgba(0, 0, 0, 0.12);background:white;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:10px;color:#6b7280;padding:0;transition:background 0.1s, border-color 0.1s;}.cv-corner-btn.svelte-1r1spmr:hover {background:#fef3c7;border-color:#b45309;color:#1a1a1a;}.cv-corner-btn.active.svelte-1r1spmr {background:#fef3c7;border-color:#b45309;color:#92400e;font-weight:700;}.cv-char-counter.svelte-1r1spmr {font-size:9px;color:#9ca3af;font-family:ui-sans-serif, system-ui, sans-serif;font-variant-numeric:tabular-nums;}'
13205
13412
  };
13206
13413
 
13207
13414
  function HighlightAnnotationEditor($$anchor, $$props) {
13208
13415
  push($$props, true);
13209
- append_styles$1($$anchor, $$css$c);
13416
+ append_styles$1($$anchor, $$css$e);
13210
13417
 
13211
13418
  let isExpanded = state(false);
13212
13419
  let rect = state(proxy({ top: 0, left: 0, width: 0, height: 0, bottom: 0, right: 0 }));
@@ -13255,10 +13462,7 @@
13255
13462
 
13256
13463
  function setCorner(c) {
13257
13464
  set(localCorner, c, true);
13258
-
13259
- if (get(localText).trim().length > 0) {
13260
- shareStore.setAnnotation($$props.element, get(localText), c);
13261
- }
13465
+ shareStore.setAnnotation($$props.element, get(localText), c);
13262
13466
  }
13263
13467
 
13264
13468
  function handleTabClick(e) {
@@ -13286,7 +13490,7 @@
13286
13490
  ? get(localText).slice(0, ANNOTATION_PREVIEW_LENGTH) + (get(localText).length > ANNOTATION_PREVIEW_LENGTH ? '…' : '')
13287
13491
  : null);
13288
13492
 
13289
- var div = root$c();
13493
+ var div = root$d();
13290
13494
  var button = child(div);
13291
13495
  let classes;
13292
13496
 
@@ -13296,7 +13500,7 @@
13296
13500
 
13297
13501
  {
13298
13502
  var consequent = ($$anchor) => {
13299
- var span = root_1$5();
13503
+ var span = root_1$8();
13300
13504
  var text = child(span, true);
13301
13505
 
13302
13506
  reset(span);
@@ -13305,8 +13509,11 @@
13305
13509
  };
13306
13510
 
13307
13511
  var alternate = ($$anchor) => {
13308
- var span_1 = root_2$4();
13512
+ var span_1 = root_2$5();
13513
+ var text_1 = child(span_1, true);
13309
13514
 
13515
+ reset(span_1);
13516
+ template_effect(() => set_text(text_1, get(isExpanded) ? '- note' : '+ note'));
13310
13517
  append($$anchor, span_1);
13311
13518
  };
13312
13519
 
@@ -13321,7 +13528,7 @@
13321
13528
 
13322
13529
  {
13323
13530
  var consequent_1 = ($$anchor) => {
13324
- var div_1 = root_3$3();
13531
+ var div_1 = root_3$4();
13325
13532
  var textarea = child(div_1);
13326
13533
 
13327
13534
  remove_textarea_child(textarea);
@@ -13333,7 +13540,7 @@
13333
13540
  each(div_3, 21, () => CORNER_ICONS, ({ key, icon }) => key, ($$anchor, $$item) => {
13334
13541
  let key = () => get($$item).key;
13335
13542
  let icon = () => get($$item).icon;
13336
- var button_1 = root_4$1();
13543
+ var button_1 = root_4$2();
13337
13544
  let classes_1;
13338
13545
 
13339
13546
  button_1.__click = (e) => {
@@ -13341,7 +13548,7 @@
13341
13548
  setCorner(key());
13342
13549
  };
13343
13550
 
13344
- var text_1 = child(button_1, true);
13551
+ var text_2 = child(button_1, true);
13345
13552
 
13346
13553
  reset(button_1);
13347
13554
 
@@ -13350,7 +13557,7 @@
13350
13557
  set_attribute(button_1, 'title', `Anchor to ${key() ?? ''}`);
13351
13558
  set_attribute(button_1, 'aria-label', `Anchor to ${key() ?? ''}`);
13352
13559
  set_attribute(button_1, 'aria-pressed', get(localCorner) === key());
13353
- set_text(text_1, icon());
13560
+ set_text(text_2, icon());
13354
13561
  });
13355
13562
 
13356
13563
  append($$anchor, button_1);
@@ -13359,7 +13566,7 @@
13359
13566
  reset(div_3);
13360
13567
 
13361
13568
  var span_2 = sibling(div_3, 2);
13362
- var text_2 = child(span_2, true);
13569
+ var text_3 = child(span_2, true);
13363
13570
 
13364
13571
  reset(span_2);
13365
13572
  reset(div_2);
@@ -13368,7 +13575,7 @@
13368
13575
  template_effect(() => {
13369
13576
  set_attribute(textarea, 'maxlength', MAX_ANNOTATION_LENGTH);
13370
13577
  set_value(textarea, get(localText));
13371
- set_text(text_2, MAX_ANNOTATION_LENGTH - get(localText).length);
13578
+ set_text(text_3, MAX_ANNOTATION_LENGTH - get(localText).length);
13372
13579
  });
13373
13580
 
13374
13581
  append($$anchor, div_1);
@@ -13394,18 +13601,18 @@
13394
13601
 
13395
13602
  delegate(['click', 'input']);
13396
13603
 
13397
- var root_2$3 = from_html(`<!> <!>`, 1);
13398
- var root_3$2 = from_html(`<div><span class="selection-label svelte-1dbf58w"> </span></div>`);
13399
- var root$b = from_html(`<div class="share-overlay-ui"><!> <!> <!> <!></div>`);
13604
+ var root_2$4 = from_html(`<!> <!>`, 1);
13605
+ var root_3$3 = from_html(`<div><span class="selection-label svelte-1dbf58w"> </span></div>`);
13606
+ var root$c = from_html(`<div class="share-overlay-ui"><!> <!> <!> <!></div>`);
13400
13607
 
13401
- const $$css$b = {
13608
+ const $$css$d = {
13402
13609
  hash: 'svelte-1dbf58w',
13403
13610
  code: '\n /* Global styles injected when active */body.cv-share-active {cursor:default;user-select:none;-webkit-user-select:none;}\n\n /* Highlight outlines */.cv-highlight-target {outline:2px dashed #0078d4 !important;outline-offset:2px;cursor:crosshair;}.cv-share-selected {outline:3px solid #005a9e !important;outline-offset:2px;background-color:rgba(0, 120, 212, 0.05);}.cv-highlight-target-hide {outline:2px dashed #d13438 !important;outline-offset:2px;cursor:crosshair;}.cv-share-selected-hide {outline:3px solid #a4262c !important;outline-offset:2px;background-color:rgba(209, 52, 56, 0.05);}.cv-highlight-target-mode {outline:2px dashed #d97706 !important;outline-offset:2px;cursor:crosshair;}.cv-share-selected-highlight {outline:3px solid #b45309 !important;outline-offset:2px;background-color:rgba(245, 158, 11, 0.05);}.selection-box.svelte-1dbf58w {position:fixed;border:1px solid rgba(0, 120, 212, 0.4);background-color:rgba(0, 120, 212, 0.1);pointer-events:none;z-index:10000;box-sizing:border-box;}.selection-box.hide-mode.svelte-1dbf58w {border:1px solid rgba(209, 52, 56, 0.4);background-color:rgba(209, 52, 56, 0.1);}.selection-box.highlight-mode.svelte-1dbf58w {border:1px solid rgba(255, 140, 0, 0.6); /* Orange/Gold for highlight */background-color:rgba(255, 140, 0, 0.1);}.selection-label.svelte-1dbf58w {position:absolute;top:-24px;left:0;background:#0078d4;color:white;padding:2px 6px;font-size:11px;border-radius:3px;white-space:nowrap;font-family:sans-serif;opacity:0.9;}.hide-mode.svelte-1dbf58w .selection-label:where(.svelte-1dbf58w) {background:#d13438;}.highlight-mode.svelte-1dbf58w .selection-label:where(.svelte-1dbf58w) {background:#d97706; /* Darker orange for text bg */}'
13404
13611
  };
13405
13612
 
13406
13613
  function ShareOverlay($$anchor, $$props) {
13407
13614
  push($$props, true);
13408
- append_styles$1($$anchor, $$css$b);
13615
+ append_styles$1($$anchor, $$css$d);
13409
13616
 
13410
13617
  let excludedTags = prop($$props, 'excludedTags', 19, () => ['HEADER', 'NAV', 'FOOTER']),
13411
13618
  excludedIds = prop($$props, 'excludedIds', 19, () => []);
@@ -13634,7 +13841,7 @@
13634
13841
  return isExcluded(el, get(excludedTagSet), get(excludedIdSet));
13635
13842
  }
13636
13843
 
13637
- var div = root$b();
13844
+ var div = root$c();
13638
13845
 
13639
13846
  event('mouseover', $window, handleHover);
13640
13847
  event('mousedown', $window, handleMouseDown);
@@ -13659,7 +13866,7 @@
13659
13866
  var node_4 = first_child(fragment);
13660
13867
 
13661
13868
  each(node_4, 16, () => [...shareStore.selectedElements], (el) => el, ($$anchor, el) => {
13662
- var fragment_1 = root_2$3();
13869
+ var fragment_1 = root_2$4();
13663
13870
  var node_5 = first_child(fragment_1);
13664
13871
 
13665
13872
  HighlightColorPicker(node_5, {
@@ -13691,7 +13898,7 @@
13691
13898
 
13692
13899
  {
13693
13900
  var consequent_1 = ($$anchor) => {
13694
- var div_1 = root_3$2();
13901
+ var div_1 = root_3$3();
13695
13902
  var span = child(div_1);
13696
13903
  var text = child(span, true);
13697
13904
 
@@ -13728,16 +13935,16 @@
13728
13935
  pop();
13729
13936
  }
13730
13937
 
13731
- var root_1$4 = from_html(`<div class="cv-focus-banner-wrapper svelte-1yqpn7e"><div id="cv-exit-focus-banner" data-cv-scroll-offset="" class="svelte-1yqpn7e"><span>You are viewing a focused selection.</span> <button class="svelte-1yqpn7e">Show Full Page</button></div></div>`);
13938
+ var root_1$7 = from_html(`<div class="cv-focus-banner-wrapper svelte-1yqpn7e"><div id="cv-exit-focus-banner" data-cv-scroll-offset="" class="svelte-1yqpn7e"><span>You are viewing a 'focused view' generated by CustardUI.</span> <button type="button" class="svelte-1yqpn7e">See Original Page</button></div></div>`);
13732
13939
 
13733
- const $$css$a = {
13940
+ const $$css$c = {
13734
13941
  hash: 'svelte-1yqpn7e',
13735
13942
  code: '.cv-focus-banner-wrapper.svelte-1yqpn7e {position:fixed;top:0;left:0;right:0;z-index:9000;background-color:#f3cb52;box-shadow:0 2px 8px rgba(44, 26, 14, 0.15);font-family:system-ui, sans-serif;}#cv-exit-focus-banner.svelte-1yqpn7e {color:#2c1a0e;padding:10px 20px;display:flex;align-items:center;justify-content:center;gap:16px;}button.svelte-1yqpn7e {background:#804b18;color:#fdf6e3;border:none;padding:4px 12px;border-radius:4px;cursor:pointer;font-weight:600;}button.svelte-1yqpn7e:hover {background:#c4853a;}'
13736
13943
  };
13737
13944
 
13738
13945
  function FocusBanner($$anchor, $$props) {
13739
13946
  push($$props, false);
13740
- append_styles$1($$anchor, $$css$a);
13947
+ append_styles$1($$anchor, $$css$c);
13741
13948
 
13742
13949
  function handleExit() {
13743
13950
  focusStore.exit();
@@ -13750,7 +13957,7 @@
13750
13957
 
13751
13958
  {
13752
13959
  var consequent = ($$anchor) => {
13753
- var div = root_1$4();
13960
+ var div = root_1$7();
13754
13961
  var div_1 = child(div);
13755
13962
  var button = sibling(child(div_1), 2);
13756
13963
 
@@ -13994,16 +14201,16 @@
13994
14201
  }
13995
14202
  }
13996
14203
 
13997
- var root$a = from_html(`<div class="cv-widget-root" data-cv-share-ignore=""><!> <!> <!> <!> <!> <!></div>`);
14204
+ var root$b = from_html(`<div class="cv-widget-root" data-cv-share-ignore=""><!> <!> <!> <!> <!> <!></div>`);
13998
14205
 
13999
- const $$css$9 = {
14206
+ const $$css$b = {
14000
14207
  hash: 'svelte-1vlfixd',
14001
14208
  code: '\n /* Root should allow clicks to pass through to the page unless hitting checking/interactive element */.cv-widget-root {position:fixed;top:0;left:0;width:0;height:0;z-index:9999;pointer-events:none; /* Crucial: Allow clicks to pass through */\n\n /* Light Theme Defaults */--cv-bg: white;--cv-text: rgba(0, 0, 0, 0.9);--cv-text-secondary: rgba(0, 0, 0, 0.6);--cv-border: rgba(0, 0, 0, 0.1);--cv-bg-hover: rgba(0, 0, 0, 0.05);--cv-primary: #3e84f4;--cv-primary-hover: #2563eb;--cv-danger: #dc2626;--cv-danger-bg: rgba(220, 38, 38, 0.1);--cv-shadow: rgba(0, 0, 0, 0.25);--cv-input-bg: white;--cv-input-border: rgba(0, 0, 0, 0.15);--cv-switch-bg: rgba(0, 0, 0, 0.1);--cv-switch-knob: white;--cv-modal-icon-bg: rgba(0, 0, 0, 0.08);--cv-icon-bg: rgba(255, 255, 255, 0.92);--cv-icon-color: rgba(0, 0, 0, 0.9);--cv-focus-ring: rgba(62, 132, 244, 0.2);--cv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.1);--cv-modal-radius: 0.75rem;--cv-card-radius: 0.5rem;--cv-section-label-transform: uppercase;font-family:inherit; /* Inherit font from host */}\n\n /* But interactive children need pointer-events back */.cv-widget-root > * {pointer-events:auto;}\n\n /* Exception: ShareOverlay manages its own pointer events */.cv-widget-root .cv-share-overlay {pointer-events:none; /* Overlay often passes clicks until specialized handles active */}.cv-widget-root[data-theme=\'dark\'] {\n /* Dark Theme Overrides */--cv-bg: #101722;--cv-text: #e2e8f0;--cv-text-secondary: rgba(255, 255, 255, 0.6);--cv-border: rgba(255, 255, 255, 0.1);--cv-bg-hover: rgba(255, 255, 255, 0.05);--cv-primary: #3e84f4;--cv-primary-hover: #60a5fa;--cv-danger: #f87171;--cv-danger-bg: rgba(248, 113, 113, 0.1);--cv-shadow: rgba(0, 0, 0, 0.5);--cv-input-bg: #1e293b;--cv-input-border: rgba(255, 255, 255, 0.1);--cv-switch-bg: rgba(255, 255, 255, 0.1);--cv-switch-knob: #e2e8f0;--cv-modal-icon-bg: rgba(255, 255, 255, 0.08);--cv-icon-bg: #1e293b;--cv-icon-color: #e2e8f0;--cv-focus-ring: rgba(62, 132, 244, 0.5);--cv-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);--cv-modal-radius: 0.75rem;--cv-card-radius: 0.5rem;--cv-section-label-transform: uppercase;}.cv-hidden {display:none !important;}'
14002
14209
  };
14003
14210
 
14004
14211
  function UIRoot($$anchor, $$props) {
14005
14212
  push($$props, true);
14006
- append_styles$1($$anchor, $$css$9);
14213
+ append_styles$1($$anchor, $$css$b);
14007
14214
 
14008
14215
  const { persistenceManager, resetToDefault } = getContext(RUNTIME_CALLBACKS_CTX);
14009
14216
  const iconSettingsStore = getContext(ICON_SETTINGS_CTX);
@@ -14066,7 +14273,7 @@
14066
14273
  showToast('Settings reset to default');
14067
14274
  }
14068
14275
 
14069
- function handleStartShare(mode = 'show') {
14276
+ function handleStartShare(mode = 'highlight') {
14070
14277
  closeModal();
14071
14278
  focusStore.exit();
14072
14279
  shareStore.setSelectionMode(mode);
@@ -14076,7 +14283,7 @@
14076
14283
  // --- Icon Visibility ---
14077
14284
  const shouldShowIcon = user_derived(() => get(settingsEnabled) && !iconSettingsStore.isDismissed && (derivedStore.hasMenuOptions || uiStore.uiOptions.showTabGroups || get(isModalOpen)));
14078
14285
 
14079
- var div = root$a();
14286
+ var div = root$b();
14080
14287
  var node = child(div);
14081
14288
 
14082
14289
  {
@@ -14401,7 +14608,7 @@
14401
14608
  *
14402
14609
  * Adaptation JSON files are resolved relative to the site's baseUrl:
14403
14610
  * `{baseUrl}/{id}/{id}.json`
14404
- * e.g. baseUrl="/customviews", id="ntu" → "/customviews/ntu/ntu.json"
14611
+ * e.g. baseUrl="/base", id="nus" → "/base/nus/nus.json"
14405
14612
  *
14406
14613
  * @param baseUrl The site's base URL (from data-base-url, default: '')
14407
14614
  * @param storageKey The project's unique storageKey prefix to use for saving preferences
@@ -14415,7 +14622,8 @@
14415
14622
  const queryParamValue = url.searchParams.get(this.QUERY_PARAM);
14416
14623
  // 2. Handle ?adapt=clear
14417
14624
  if (queryParamValue === 'clear') {
14418
- this.clearStoredId(persistence);
14625
+ persistence.clearAll(); // wipe custardUI-state and tab nav prefs
14626
+ persistence.removeItem(STORAGE_KEY); // wipe the adaptation ID itself
14419
14627
  if (this.hasHashAdaptationId(url.hash)) {
14420
14628
  this.stripHashFromUrl(url);
14421
14629
  }
@@ -14450,7 +14658,12 @@
14450
14658
  this.stripQueryParamFromUrl(url);
14451
14659
  }
14452
14660
  }
14453
- // 7. Persist namespace
14661
+ // 7. Persist namespace — clear old state if explicitly switching to a different adaptation
14662
+ const previousId = persistence.getItem(STORAGE_KEY);
14663
+ const isExplicitUrlSwitch = queryParamValue !== null; // ?adapt= was in the URL
14664
+ if (isExplicitUrlSwitch && previousId !== null && previousId !== id) {
14665
+ persistence.clearAll(); // Remove custardUI-state so new adaptation starts fresh
14666
+ }
14454
14667
  persistence.setItem(STORAGE_KEY, id);
14455
14668
  // 8. Apply theme synchronously (FOUC prevention)
14456
14669
  this.applyTheme(config);
@@ -14471,10 +14684,14 @@
14471
14684
  static rewriteUrlIndicator(adaptationId) {
14472
14685
  const url = new URL(window.location.href);
14473
14686
  const targetHash = this.getHashUrlIndicator(adaptationId);
14474
- if (url.hash === targetHash)
14475
- return;
14476
- if (url.hash === '') {
14687
+ const hashCorrect = url.hash === targetHash;
14688
+ const noStaleParam = !url.searchParams.has(this.QUERY_PARAM);
14689
+ if (hashCorrect && noStaleParam)
14690
+ return; // Already in correct state
14691
+ if (url.hash === '' || url.hash === targetHash) {
14692
+ // Hash is free — use #/id and remove any stale ?adapt= param
14477
14693
  url.hash = targetHash;
14694
+ url.searchParams.delete(this.QUERY_PARAM);
14478
14695
  }
14479
14696
  else {
14480
14697
  // Hash is occupied (page anchor, #cv-open, etc.), use query param
@@ -14576,16 +14793,16 @@
14576
14793
  }
14577
14794
  }
14578
14795
 
14579
- var root$9 = from_html(`<div class="cv-context-divider svelte-1a535nn" role="button" tabindex="0"> </div>`);
14796
+ var root$a = from_html(`<div class="cv-context-divider svelte-1a535nn" role="button" tabindex="0"> </div>`);
14580
14797
 
14581
- const $$css$8 = {
14798
+ const $$css$a = {
14582
14799
  hash: 'svelte-1a535nn',
14583
14800
  code: '.cv-context-divider.svelte-1a535nn {padding:12px;margin:16px 0;background-color:#f8f8f8;border-top:1px dashed #ccc;border-bottom:1px dashed #ccc;color:#555;text-align:center;cursor:pointer;font-family:system-ui, sans-serif;font-size:13px;transition:background-color 0.2s;}.cv-context-divider.svelte-1a535nn:hover {background-color:#e8e8e8;color:#333;}'
14584
14801
  };
14585
14802
 
14586
14803
  function FocusDivider($$anchor, $$props) {
14587
14804
  push($$props, true);
14588
- append_styles$1($$anchor, $$css$8);
14805
+ append_styles$1($$anchor, $$css$a);
14589
14806
 
14590
14807
  // Component is mounted manually via `mount`, use props for communication.
14591
14808
  let hiddenCount = prop($$props, 'hiddenCount', 3, 0);
@@ -14594,7 +14811,7 @@
14594
14811
  if ($$props.onExpand) $$props.onExpand();
14595
14812
  }
14596
14813
 
14597
- var div = root$9();
14814
+ var div = root$a();
14598
14815
 
14599
14816
  div.__click = handleClick;
14600
14817
  div.__keydown = (e) => e.key === 'Enter' && handleClick();
@@ -14727,68 +14944,505 @@
14727
14944
  return groups;
14728
14945
  }
14729
14946
 
14730
- var root_2$2 = from_html(`<button aria-label="Previous highlight">↑</button> <button aria-label="Next highlight">↓</button>`, 1);
14731
- var root_4 = from_html(`<span class="cv-annotation-text svelte-1mz0neo"> </span>`);
14732
- var root_5 = from_html(`<span class="cv-annotation-text svelte-1mz0neo"> </span>`);
14733
- var root_3$1 = from_html(`<button><!></button>`);
14734
- var root_1$3 = from_html(`<div class="cv-highlight-group svelte-1mz0neo"><div class="cv-highlight-marker svelte-1mz0neo"></div> <!> <div class="cv-highlight-pill svelte-1mz0neo"><a href="https://custardui.js.org" target="_blank" rel="noopener noreferrer" class="svelte-1mz0neo">CustardUI highlight↗</a></div> <!></div>`);
14735
- var root$8 = from_html(`<div class="cv-highlight-overlay svelte-1mz0neo"></div>`);
14947
+ var root_4$1 = from_html(`<span>▾</span>`);
14948
+ var root_3$2 = from_html(`<!> <span class="cv-ribbon-text cv-ribbon-text--right svelte-1asb212"> </span> <span class="cv-ribbon-grip svelte-1asb212" aria-hidden="true"><span class="svelte-1asb212"></span><span class="svelte-1asb212"></span> <span class="svelte-1asb212"></span><span class="svelte-1asb212"></span> <span class="svelte-1asb212"></span><span class="svelte-1asb212"></span></span>`, 1);
14949
+ var root_6$1 = from_html(`<span>▾</span>`);
14950
+ var root_5$1 = from_html(`<span class="cv-ribbon-grip svelte-1asb212" aria-hidden="true"><span class="svelte-1asb212"></span><span class="svelte-1asb212"></span> <span class="svelte-1asb212"></span><span class="svelte-1asb212"></span> <span class="svelte-1asb212"></span><span class="svelte-1asb212"></span></span> <span class="cv-ribbon-text svelte-1asb212"> </span> <!>`, 1);
14951
+ var root_1$6 = from_html(`<button type="button"><!></button>`);
14952
+ var root_7$1 = from_html(`<div class="cv-annotation-card svelte-1asb212" role="region" aria-label="Annotation"><button type="button" class="cv-card-close svelte-1asb212" aria-label="Collapse annotation">✕</button> <span class="cv-card-text svelte-1asb212"> </span></div>`);
14953
+ var root$9 = from_html(`<div><!></div>`);
14736
14954
 
14737
- const $$css$7 = {
14738
- hash: 'svelte-1mz0neo',
14739
- code: '.cv-highlight-overlay.svelte-1mz0neo {position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:8000;}.cv-highlight-group.svelte-1mz0neo {position:absolute;pointer-events:none;}.cv-highlight-marker.svelte-1mz0neo {position:absolute;inset:0;pointer-events:none;\n \n /* Marker Style */border:3.5px solid var(--cv-highlight-color);border-radius:200px 15px 225px 15px / 15px 225px 15px 255px;transform:rotate(-0.5deg);\n \n /* 3D INTERNAL VOLUME:\n Adds depth to the yellow border itself so it looks rounded.\n */box-shadow:inset 0 1px 2px rgba(129, 73, 25, 0.2),\n inset 0 -1px 1px rgba(255, 255, 255, 0.7);\n\n /* 2A-3 DOUBLE LIGHT PROJECTION:\n Stacks multiple drop-shadows to cast into the box interior.\n */filter:/* Sharp contact shadow for grounding */\n drop-shadow(0 2px 2px rgba(44, 26, 14, 0.15)) \n /* Light Source A: Casts shadow from top-left to bottom-right */\n drop-shadow(-8px 12px 10px rgba(44, 26, 14, 0.12))\n /* Light Source B: Casts shadow from top-right to bottom-left */\n drop-shadow(8px 12px 10px rgba(44, 26, 14, 0.12));\n \n animation: svelte-1mz0neo-highlightFadeIn 0.3s ease-out forwards;}.cv-nav-arrow.svelte-1mz0neo {position:absolute;z-index:10;right:-5px;pointer-events:auto;width:14px;height:14px;border-radius:100px;border:1px solid var(--cv-highlight-color);background:white;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:7px;color:#814919;font-weight:700;font-family:ui-sans-serif, system-ui, sans-serif;line-height:1;padding:0;box-shadow:0 4px 12px rgba(44, 26, 14, 0.15);opacity:0.7;}.cv-nav-arrow.svelte-1mz0neo:hover {opacity:1;}.cv-nav-arrow--up.svelte-1mz0neo {top:0px;}.cv-nav-arrow--down.svelte-1mz0neo {bottom:0px;}.cv-nav-arrow--hidden.svelte-1mz0neo {visibility:hidden;pointer-events:none;}.cv-highlight-pill.svelte-1mz0neo {position:absolute;z-index:10;bottom:-7px;right:14px;background:white;height:14px;padding:0 8px;display:flex;align-items:center;border-radius:100px;border:1px solid var(--cv-highlight-color);pointer-events:auto;white-space:nowrap;\n \n /* Stronger shadow to match the frame\'s new altitude */box-shadow:0 4px 12px rgba(44, 26, 14, 0.15);}.cv-highlight-pill.svelte-1mz0neo a:where(.svelte-1mz0neo) {font-size:8px;font-weight:700;color:#814919;text-decoration:none;font-family:ui-sans-serif, system-ui, sans-serif;text-transform:uppercase;letter-spacing:0.04em;line-height:1;}.cv-highlight-pill.svelte-1mz0neo:hover a:where(.svelte-1mz0neo) {opacity:0.8;}.cv-annotation-badge.svelte-1mz0neo {position:absolute;z-index:10;pointer-events:auto;max-width:180px;background:white;border:1.5px solid var(--cv-highlight-color);border-radius:6px;padding:4px 7px;cursor:pointer;box-shadow:0 2px 8px rgba(44, 26, 14, 0.15);font-family:ui-sans-serif, system-ui, sans-serif;text-align:left;}.cv-annotation-badge--expanded.svelte-1mz0neo {max-width:260px;z-index:20;}.cv-annotation-text.svelte-1mz0neo {display:block;font-size:9px;font-weight:600;color:#1a1a1a;line-height:1.4;word-break:break-word;white-space:pre-wrap;}\n\n @keyframes svelte-1mz0neo-highlightFadeIn {\n from { \n opacity: 0; \n transform: scale(0.98) rotate(-1deg); \n }\n to { \n opacity: 1; \n transform: scale(1) rotate(-0.5deg); \n }\n }'
14955
+ const $$css$9 = {
14956
+ hash: 'svelte-1asb212',
14957
+ code: '\n /* ==============================\n CONTAINER (position, drag, opacity)\n ============================== */.cv-annotation-container.svelte-1asb212 {position:absolute;z-index:100;pointer-events:auto;touch-action:none;user-select:none;cursor:default;opacity:0.88;transition:opacity 0.2s ease, z-index 0s;}.cv-annotation-container.svelte-1asb212:hover {opacity:1;z-index:110;}\n\n /* ==============================\n RIBBON (home-plate)\n ============================== */.cv-annotation-ribbon.svelte-1asb212 {border:none;padding:6px 20px 6px 8px;min-width:28px;min-height:24px;background:var(--cv-highlight-color);cursor:default;box-shadow:0 2px 8px rgba(0, 0, 0, 0.15);display:flex;align-items:center;justify-content:flex-start;gap:5px;transform-origin:center center;}.cv-annotation-ribbon--intro.svelte-1asb212 {\n animation: svelte-1asb212-cv-wiggle-intro 0.75s ease-in-out forwards;}.cv-annotation-ribbon--periodic.svelte-1asb212 {\n animation: svelte-1asb212-cv-wiggle-periodic 5s ease-in-out infinite;}.cv-annotation-ribbon--right.svelte-1asb212 {padding:6px 8px 6px 20px;justify-content:flex-end;}.cv-annotation-ribbon--empty.svelte-1asb212 {min-width:24px;padding:6px 16px 6px 8px;}.cv-annotation-ribbon--expandable.svelte-1asb212 {cursor:pointer;}.cv-annotation-ribbon--expandable.svelte-1asb212:hover {filter:brightness(1.1);}\n\n /* ==============================\n RIBBON TEXT (single line)\n ============================== */.cv-ribbon-text.svelte-1asb212 {display:block;font-family:\'Segoe Print\', \'Bradley Hand\', \'Chilanka\', cursive;font-size:13px;font-weight:700;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:160px;color:#fff;text-shadow:0 1px 3px rgba(0, 0, 0, 0.25);}.cv-ribbon-text--right.svelte-1asb212 {text-align:right;}.cv-ribbon-chevron.svelte-1asb212 {font-size:22px;opacity:1;flex-shrink:0;line-height:1;color:#fff;text-shadow:0 1px 4px rgba(0, 0, 0, 0.4);}.cv-ribbon-chevron--bounce.svelte-1asb212 {\n animation: svelte-1asb212-cv-chevron-bounce 3s ease-in-out infinite;}\n\n /* ==============================\n DRAG GRIP (6-dot grid on flat side)\n ============================== */.cv-ribbon-grip.svelte-1asb212 {display:grid;grid-template-columns:repeat(2, 3px);gap:3px;flex-shrink:0;opacity:0.7;cursor:grab;padding:2px;}.cv-ribbon-grip.svelte-1asb212:active {cursor:grabbing;}.cv-ribbon-grip.svelte-1asb212 > span:where(.svelte-1asb212) {width:3px;height:3px;border-radius:50%;background:rgba(255, 255, 255, 0.9);box-shadow:0 0 1px rgba(0, 0, 0, 0.4);}\n\n /* ==============================\n CARD (sticky note)\n ============================== */.cv-annotation-card.svelte-1asb212 {background:#FFFDF5;border:1.5px solid var(--cv-highlight-color);border-radius:4px;padding:10px 12px;max-width:280px;min-width:120px;box-shadow:0 4px 20px rgba(0, 0, 0, 0.18);position:relative;\n animation: svelte-1asb212-cv-cardPop 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;}.cv-card-close.svelte-1asb212 {position:absolute;top:3px;right:5px;border:none;background:transparent;cursor:pointer;font-size:12px;color:#aaa;padding:2px 4px;line-height:1;font-family:sans-serif;}.cv-card-close.svelte-1asb212:hover {color:#555;}.cv-card-text.svelte-1asb212 {display:block;font-family:\'Segoe Print\', \'Bradley Hand\', \'Chilanka\', cursive;font-size:13px;font-weight:600;color:#333;line-height:1.45;word-break:break-word;white-space:pre-wrap;padding-right:15px;}\n\n /* ==============================\n ANIMATIONS\n ============================== */\n @keyframes svelte-1asb212-cv-wiggle-intro {\n 0% { transform: rotate(0deg); }\n 10% { transform: rotate(-6deg); }\n 25% { transform: rotate(6deg); }\n 40% { transform: rotate(-5deg); }\n 55% { transform: rotate(5deg); }\n 68% { transform: rotate(-3deg); }\n 80% { transform: rotate(2.5deg); }\n 90% { transform: rotate(-1deg); }\n 100% { transform: rotate(0deg); }\n }\n\n @keyframes svelte-1asb212-cv-wiggle-periodic {\n 0%, 85%, 100% { transform: rotate(0deg); }\n 87% { transform: rotate(1.2deg); }\n 90% { transform: rotate(-1.2deg); }\n 93% { transform: rotate(0.8deg); }\n 96% { transform: rotate(-0.5deg); }\n }\n\n @keyframes svelte-1asb212-cv-cardPop {\n from { opacity: 0; transform: scale(0.9) translateY(5px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n }\n\n @keyframes svelte-1asb212-cv-chevron-bounce {\n 0%, 70%, 100% { transform: translateY(0); }\n 78% { transform: translateY(-3px); }\n 86% { transform: translateY(1px); }\n 93% { transform: translateY(-1.5px); }\n }'
14740
14958
  };
14741
14959
 
14742
- function HighlightOverlay($$anchor, $$props) {
14960
+ function HighlightTextAnnotation($$anchor, $$props) {
14743
14961
  push($$props, true);
14744
- append_styles$1($$anchor, $$css$7);
14962
+ append_styles$1($$anchor, $$css$9);
14745
14963
 
14746
- let rects = user_derived(() => $$props.box.rects);
14747
- let expandedSet = new SvelteSet();
14964
+ const corner = user_derived(() => $$props.annotationCorner ?? DEFAULT_ANNOTATION_CORNER);
14965
+ const hasText = user_derived(() => $$props.annotation.length > 0);
14966
+ const isShort = user_derived(() => $$props.annotation.length <= ANNOTATION_PREVIEW_LENGTH);
14967
+ const isRightCorner = user_derived(() => get(corner) === 'tr' || get(corner) === 'br');
14968
+ let expanded = state(false);
14748
14969
 
14749
- function getColorHex(rect) {
14750
- const key = rect.color ?? DEFAULT_COLOR_KEY;
14970
+ // --- Intro wiggle state ---
14971
+ let introAnimationDone = state(false);
14751
14972
 
14752
- return HIGHLIGHT_COLORS.find((c) => c.key === key)?.hex ?? HIGHLIGHT_COLORS[0].hex;
14753
- }
14973
+ function onIntroAnimationEnd(e) {
14974
+ if (e.target !== e.currentTarget) return;
14754
14975
 
14755
- function scrollToRect(rect) {
14756
- rect.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
14976
+ set(introAnimationDone, true);
14757
14977
  }
14758
14978
 
14759
- function toggleBadge(el) {
14760
- if (expandedSet.has(el)) {
14761
- expandedSet.delete(el);
14762
- } else {
14763
- expandedSet.add(el);
14764
- }
14765
- }
14979
+ // --- Drag-to-move state ---
14980
+ let dragOffsetX = state(0);
14766
14981
 
14767
- function getBadgeStyle(corner) {
14768
- switch (corner) {
14769
- case 'tl':
14770
- return 'top: 6px; left: 6px;';
14982
+ let dragOffsetY = state(0);
14983
+ let isDragging = false;
14984
+ let isPointerDown = false;
14985
+ let dragStartX = 0;
14986
+ let dragStartY = 0;
14987
+ let dragStartOffsetX = 0;
14988
+ let dragStartOffsetY = 0;
14989
+ let containerEl;
14771
14990
 
14772
- case 'tr':
14773
- return 'top: 6px; right: 6px;';
14991
+ function toggle() {
14992
+ if (get(isShort)) return;
14774
14993
 
14775
- case 'bl':
14776
- return 'bottom: 6px; left: 6px;';
14994
+ set(expanded, !get(expanded));
14995
+ }
14777
14996
 
14778
- case 'br':
14779
- return 'bottom: 6px; right: 6px;';
14780
- }
14997
+ function handleInteraction(e) {
14998
+ e.stopPropagation();
14999
+
15000
+ if (!isDragging) toggle();
14781
15001
  }
14782
15002
 
14783
- var div = root$8();
15003
+ function onPointerDown(e) {
15004
+ // Only initiate drag when the pointer starts on the grip handle.
15005
+ if (!e.target.closest('.cv-ribbon-grip')) return;
15006
+
15007
+ isPointerDown = true;
15008
+ isDragging = false;
15009
+ dragStartX = e.clientX;
15010
+ dragStartY = e.clientY;
15011
+ dragStartOffsetX = get(dragOffsetX);
15012
+ dragStartOffsetY = get(dragOffsetY);
15013
+ }
15014
+
15015
+ // Hard clamp so the element can never leave the viewport.
15016
+ function clampToViewport(newX, newY) {
15017
+ if (!containerEl) return { x: newX, y: newY };
15018
+
15019
+ const rect = containerEl.getBoundingClientRect();
15020
+ const pad = 8;
15021
+ const vw = window.innerWidth;
15022
+ const vh = window.innerHeight;
15023
+ const origLeft = rect.left - get(dragOffsetX);
15024
+ const origTop = rect.top - get(dragOffsetY);
15025
+ const newLeft = origLeft + newX;
15026
+ const newTop = origTop + newY;
15027
+ let x = newX;
15028
+ let y = newY;
15029
+
15030
+ if (newLeft < pad) x += pad - newLeft;
15031
+ if (newLeft + rect.width > vw - pad) x -= newLeft + rect.width - (vw - pad);
15032
+ if (newTop < pad) y += pad - newTop;
15033
+ if (newTop + rect.height > vh - pad) y -= newTop + rect.height - (vh - pad);
15034
+
15035
+ return { x, y };
15036
+ }
15037
+
15038
+ function onPointerMove(e) {
15039
+ if (!isPointerDown) return;
15040
+
15041
+ const dx = e.clientX - dragStartX;
15042
+ const dy = e.clientY - dragStartY;
15043
+
15044
+ if (!isDragging && (Math.abs(dx) > 10 || Math.abs(dy) > 10)) {
15045
+ isDragging = true;
15046
+ e.currentTarget.setPointerCapture(e.pointerId);
15047
+ }
15048
+
15049
+ if (isDragging) {
15050
+ const rawX = dragStartOffsetX + dx;
15051
+ const rawY = dragStartOffsetY + dy;
15052
+ const clamped = clampToViewport(rawX, rawY);
15053
+
15054
+ set(dragOffsetX, clamped.x, true);
15055
+ set(dragOffsetY, clamped.y, true);
15056
+ }
15057
+ }
15058
+
15059
+ function onPointerUp(e) {
15060
+ if (!isPointerDown) return;
15061
+
15062
+ isPointerDown = false;
15063
+
15064
+ if (isDragging) {
15065
+ e.currentTarget.releasePointerCapture(e.pointerId);
15066
+
15067
+ setTimeout(
15068
+ () => {
15069
+ isDragging = false;
15070
+ },
15071
+ 50
15072
+ );
15073
+ }
15074
+ }
15075
+
15076
+ // Cancel (e.g. touch interrupted by scroll) — reset all drag state cleanly.
15077
+ function onPointerCancel(_e) {
15078
+ isPointerDown = false;
15079
+ isDragging = false;
15080
+ }
15081
+
15082
+ // Nudge annotation back in-bounds when the viewport shrinks.
15083
+ user_effect(() => {
15084
+ function onResize() {
15085
+ const clamped = clampToViewport(get(dragOffsetX), get(dragOffsetY));
15086
+
15087
+ set(dragOffsetX, clamped.x, true);
15088
+ set(dragOffsetY, clamped.y, true);
15089
+ }
15090
+
15091
+ window.addEventListener('resize', onResize);
15092
+
15093
+ return () => window.removeEventListener('resize', onResize);
15094
+ });
15095
+
15096
+ /**
15097
+ * Returns CSS positioning based on the annotation corner.
15098
+ */
15099
+ function getPositionStyle(c) {
15100
+ switch (c) {
15101
+ case 'tr':
15102
+ return 'top: -6px; right: -6px;';
15103
+
15104
+ case 'bl':
15105
+ return 'bottom: -6px; left: -6px;';
15106
+
15107
+ case 'br':
15108
+ return 'bottom: -6px; right: -6px;';
15109
+
15110
+ case 'tl':
15111
+
15112
+ default:
15113
+ return 'top: -6px; left: -6px;';
15114
+ }
15115
+ }
15116
+
15117
+ /**
15118
+ * Returns the ribbon clip-path. The point faces inward toward the content.
15119
+ */
15120
+ function getRibbonClipPath(c) {
15121
+ const pointsRight = c === 'tl' || c === 'bl';
15122
+
15123
+ if (pointsRight) {
15124
+ return 'polygon(0% 0%, 80% 0%, 100% 50%, 80% 100%, 0% 100%)';
15125
+ } else {
15126
+ return 'polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%, 0% 50%)';
15127
+ }
15128
+ }
15129
+
15130
+ var div = root$9();
15131
+ let classes;
15132
+
15133
+ div.__pointerdown = onPointerDown;
15134
+ div.__pointermove = onPointerMove;
15135
+ div.__pointerup = onPointerUp;
15136
+
15137
+ var node = child(div);
15138
+
15139
+ {
15140
+ var consequent_4 = ($$anchor) => {
15141
+ var button = root_1$6();
15142
+ let classes_1;
15143
+
15144
+ button.__click = handleInteraction;
15145
+
15146
+ var node_1 = child(button);
15147
+
15148
+ {
15149
+ var consequent_3 = ($$anchor) => {
15150
+ var fragment = comment();
15151
+ var node_2 = first_child(fragment);
15152
+
15153
+ {
15154
+ var consequent_1 = ($$anchor) => {
15155
+ var fragment_1 = root_3$2();
15156
+ var node_3 = first_child(fragment_1);
15157
+
15158
+ {
15159
+ var consequent = ($$anchor) => {
15160
+ var span = root_4$1();
15161
+ let classes_2;
15162
+
15163
+ template_effect(() => classes_2 = set_class(span, 1, 'cv-ribbon-chevron svelte-1asb212', null, classes_2, { 'cv-ribbon-chevron--bounce': get(introAnimationDone) }));
15164
+ append($$anchor, span);
15165
+ };
15166
+
15167
+ if_block(node_3, ($$render) => {
15168
+ if (!get(isShort)) $$render(consequent);
15169
+ });
15170
+ }
15171
+
15172
+ var span_1 = sibling(node_3, 2);
15173
+ var text = child(span_1, true);
15174
+
15175
+ reset(span_1);
15176
+ next(2);
15177
+
15178
+ template_effect(($0) => set_text(text, $0), [
15179
+ () => get(isShort)
15180
+ ? $$props.annotation
15181
+ : $$props.annotation.slice(0, ANNOTATION_PREVIEW_LENGTH) + '…'
15182
+ ]);
15183
+
15184
+ append($$anchor, fragment_1);
15185
+ };
15186
+
15187
+ var alternate = ($$anchor) => {
15188
+ var fragment_2 = root_5$1();
15189
+ var span_2 = sibling(first_child(fragment_2), 2);
15190
+ var text_1 = child(span_2, true);
15191
+
15192
+ reset(span_2);
15193
+
15194
+ var node_4 = sibling(span_2, 2);
15195
+
15196
+ {
15197
+ var consequent_2 = ($$anchor) => {
15198
+ var span_3 = root_6$1();
15199
+ let classes_3;
15200
+
15201
+ template_effect(() => classes_3 = set_class(span_3, 1, 'cv-ribbon-chevron svelte-1asb212', null, classes_3, { 'cv-ribbon-chevron--bounce': get(introAnimationDone) }));
15202
+ append($$anchor, span_3);
15203
+ };
15204
+
15205
+ if_block(node_4, ($$render) => {
15206
+ if (!get(isShort)) $$render(consequent_2);
15207
+ });
15208
+ }
15209
+
15210
+ template_effect(($0) => set_text(text_1, $0), [
15211
+ () => get(isShort)
15212
+ ? $$props.annotation
15213
+ : $$props.annotation.slice(0, ANNOTATION_PREVIEW_LENGTH) + '…'
15214
+ ]);
15215
+
15216
+ append($$anchor, fragment_2);
15217
+ };
15218
+
15219
+ if_block(node_2, ($$render) => {
15220
+ if (get(isRightCorner)) $$render(consequent_1); else $$render(alternate, false);
15221
+ });
15222
+ }
15223
+
15224
+ append($$anchor, fragment);
15225
+ };
15226
+
15227
+ if_block(node_1, ($$render) => {
15228
+ if (get(hasText)) $$render(consequent_3);
15229
+ });
15230
+ }
15231
+
15232
+ reset(button);
15233
+
15234
+ template_effect(
15235
+ ($0) => {
15236
+ classes_1 = set_class(button, 1, 'cv-annotation-ribbon svelte-1asb212', null, classes_1, {
15237
+ 'cv-annotation-ribbon--empty': !get(hasText),
15238
+ 'cv-annotation-ribbon--right': get(isRightCorner),
15239
+ 'cv-annotation-ribbon--expandable': !get(isShort),
15240
+ 'cv-annotation-ribbon--intro': !get(introAnimationDone),
15241
+ 'cv-annotation-ribbon--periodic': get(introAnimationDone)
15242
+ });
15243
+
15244
+ set_style(button, `clip-path: ${$0 ?? ''};`);
15245
+
15246
+ set_attribute(button, 'aria-label', get(hasText)
15247
+ ? get(isShort) ? $$props.annotation : 'Expand annotation'
15248
+ : 'Annotation marker');
15249
+
15250
+ set_attribute(button, 'aria-expanded', get(isShort) ? undefined : get(expanded));
15251
+ },
15252
+ [() => getRibbonClipPath(get(corner))]
15253
+ );
15254
+
15255
+ event('animationend', button, onIntroAnimationEnd);
15256
+ append($$anchor, button);
15257
+ };
15258
+
15259
+ var alternate_1 = ($$anchor) => {
15260
+ var div_1 = root_7$1();
15261
+ var button_1 = child(div_1);
15262
+
15263
+ button_1.__click = handleInteraction;
15264
+
15265
+ var span_4 = sibling(button_1, 2);
15266
+ var text_2 = child(span_4, true);
15267
+
15268
+ reset(span_4);
15269
+ reset(div_1);
15270
+ template_effect(() => set_text(text_2, $$props.annotation));
15271
+ append($$anchor, div_1);
15272
+ };
15273
+
15274
+ if_block(node, ($$render) => {
15275
+ if (!get(expanded)) $$render(consequent_4); else $$render(alternate_1, false);
15276
+ });
15277
+ }
15278
+
15279
+ reset(div);
15280
+ bind_this(div, ($$value) => containerEl = $$value, () => containerEl);
15281
+
15282
+ template_effect(
15283
+ ($0) => {
15284
+ classes = set_class(div, 1, 'cv-annotation-container svelte-1asb212', null, classes, { 'cv-annotation-container--expanded': get(expanded) });
15285
+ set_style(div, `${$0 ?? ''} transform: translate(${get(dragOffsetX) ?? ''}px, ${get(dragOffsetY) ?? ''}px);`);
15286
+ },
15287
+ [() => getPositionStyle(get(corner))]
15288
+ );
15289
+
15290
+ event('pointercancel', div, onPointerCancel);
15291
+ append($$anchor, div);
15292
+ pop();
15293
+ }
15294
+
15295
+ delegate(['pointerdown', 'pointermove', 'pointerup', 'click']);
15296
+
15297
+ var root_1$5 = from_html(`<div class="cv-annotation-container svelte-ii1txw"><div role="img" aria-label="Annotation marker"></div> <button type="button" class="cv-empty-dismiss svelte-ii1txw" aria-label="Dismiss marker">✕</button></div>`);
15298
+
15299
+ const $$css$8 = {
15300
+ hash: 'svelte-ii1txw',
15301
+ code: '.cv-annotation-container.svelte-ii1txw {position:absolute;z-index:100;pointer-events:auto;touch-action:none;user-select:none;opacity:0.95;transition:opacity 0.2s ease, z-index 0s;}.cv-annotation-container.svelte-ii1txw:hover {opacity:1;z-index:110;}.cv-empty-ribbon.svelte-ii1txw {min-width:45px;min-height:22px;background:var(--cv-highlight-color);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(0, 0, 0, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.22);transform-origin:center center;padding:5px 22px 5px 10px;opacity:0.95;transition:opacity 0.2s ease;}.cv-annotation-container.svelte-ii1txw:hover .cv-empty-ribbon:where(.svelte-ii1txw) {opacity:1;}.cv-empty-ribbon--right.svelte-ii1txw {padding:5px 10px 5px 22px;}.cv-empty-ribbon--intro.svelte-ii1txw {\n animation: svelte-ii1txw-cv-wiggle-intro 0.75s ease-in-out forwards;}.cv-empty-ribbon--periodic.svelte-ii1txw {\n animation: svelte-ii1txw-cv-wiggle-periodic 5s ease-in-out infinite;}\n\n /* Dismiss button — hidden until container is hovered */.cv-empty-dismiss.svelte-ii1txw {position:absolute;border:none;background:rgba(100, 100, 100, 0.55);color:#fff;font-size:8px;cursor:pointer;width:14px;height:14px;display:flex;align-items:center;justify-content:center;padding:0;line-height:1;border-radius:50%;box-shadow:0 1px 4px rgba(0, 0, 0, 0.2);opacity:0;pointer-events:none;transition:opacity 0.15s ease, background 0.15s ease, color 0.15s ease;}.cv-annotation-container.svelte-ii1txw:hover .cv-empty-dismiss:where(.svelte-ii1txw) {opacity:1;pointer-events:auto;}.cv-empty-dismiss.svelte-ii1txw:hover {background:rgba(80, 80, 80, 0.8);box-shadow:0 1px 6px rgba(0, 0, 0, 0.28);}\n\n @keyframes svelte-ii1txw-cv-wiggle-intro {\n 0% { transform: rotate(0deg); }\n 10% { transform: rotate(-6deg); }\n 25% { transform: rotate(6deg); }\n 40% { transform: rotate(-5deg); }\n 55% { transform: rotate(5deg); }\n 68% { transform: rotate(-3deg); }\n 80% { transform: rotate(2.5deg); }\n 90% { transform: rotate(-1deg); }\n 100% { transform: rotate(0deg); }\n }\n\n @keyframes svelte-ii1txw-cv-wiggle-periodic {\n 0%, 85%, 100% { transform: rotate(0deg); }\n 87% { transform: rotate(1.2deg); }\n 90% { transform: rotate(-1.2deg); }\n 93% { transform: rotate(0.8deg); }\n 96% { transform: rotate(-0.5deg); }\n }'
15302
+ };
15303
+
15304
+ function HighlightEmptyAnnotation($$anchor, $$props) {
15305
+ append_styles$1($$anchor, $$css$8);
15306
+
15307
+ const corner = user_derived(() => $$props.annotationCorner ?? DEFAULT_ANNOTATION_CORNER);
15308
+ const isRightCorner = user_derived(() => get(corner) === 'tr' || get(corner) === 'br');
15309
+ let dismissed = state(false);
15310
+ let introAnimationDone = state(false);
15311
+
15312
+ function onIntroAnimationEnd(e) {
15313
+ if (e.target !== e.currentTarget) return;
15314
+
15315
+ set(introAnimationDone, true);
15316
+ }
15317
+
15318
+ function getPositionStyle(c) {
15319
+ switch (c) {
15320
+ case 'tr':
15321
+ return 'top: 4px; right: -6px;';
15322
+
15323
+ case 'bl':
15324
+ return 'bottom: 4px; left: -6px;';
15325
+
15326
+ case 'br':
15327
+ return 'bottom: 4px; right: -6px;';
15328
+
15329
+ case 'tl':
15330
+
15331
+ default:
15332
+ return 'top: 4px; left: -6px;';
15333
+ }
15334
+ }
15335
+
15336
+ function getRibbonClipPath(c) {
15337
+ const pointsRight = c === 'tl' || c === 'bl';
15338
+
15339
+ if (pointsRight) {
15340
+ return 'polygon(0% 0%, 80% 0%, 100% 50%, 80% 100%, 0% 100%)';
15341
+ } else {
15342
+ return 'polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%, 0% 50%)';
15343
+ }
15344
+ }
15345
+
15346
+ // Position the dismiss button at the outermost corner of the container (furthest from the box).
15347
+ function getDismissStyle(c) {
15348
+ switch (c) {
15349
+ case 'tr':
15350
+ return 'top: -5px; right: -5px;';
15351
+
15352
+ case 'bl':
15353
+ return 'bottom: -5px; left: -5px;';
15354
+
15355
+ case 'br':
15356
+ return 'bottom: -5px; right: -5px;';
15357
+
15358
+ case 'tl':
15359
+
15360
+ default:
15361
+ return 'top: -5px; left: -5px;';
15362
+ }
15363
+ }
15364
+
15365
+ var fragment = comment();
15366
+ var node = first_child(fragment);
15367
+
15368
+ {
15369
+ var consequent = ($$anchor) => {
15370
+ var div = root_1$5();
15371
+ var div_1 = child(div);
15372
+ let classes;
15373
+ var button = sibling(div_1, 2);
15374
+
15375
+ button.__click = () => set(dismissed, true);
15376
+ reset(div);
15377
+
15378
+ template_effect(
15379
+ ($0, $1, $2) => {
15380
+ set_style(div, $0);
15381
+
15382
+ classes = set_class(div_1, 1, 'cv-empty-ribbon svelte-ii1txw', null, classes, {
15383
+ 'cv-empty-ribbon--right': get(isRightCorner),
15384
+ 'cv-empty-ribbon--intro': !get(introAnimationDone),
15385
+ 'cv-empty-ribbon--periodic': get(introAnimationDone)
15386
+ });
15387
+
15388
+ set_style(div_1, `clip-path: ${$1 ?? ''};`);
15389
+ set_style(button, $2);
15390
+ },
15391
+ [
15392
+ () => getPositionStyle(get(corner)),
15393
+ () => getRibbonClipPath(get(corner)),
15394
+ () => getDismissStyle(get(corner))
15395
+ ]
15396
+ );
15397
+
15398
+ event('animationend', div_1, onIntroAnimationEnd);
15399
+ append($$anchor, div);
15400
+ };
15401
+
15402
+ if_block(node, ($$render) => {
15403
+ if (!get(dismissed)) $$render(consequent);
15404
+ });
15405
+ }
15406
+
15407
+ append($$anchor, fragment);
15408
+ }
15409
+
15410
+ delegate(['click']);
15411
+
15412
+ var root_2$3 = from_html(`<button type="button" aria-label="Previous highlight">↑</button> <button type="button" aria-label="Next highlight">↓</button>`, 1);
15413
+ var root_1$4 = from_html(`<div class="cv-highlight-group svelte-1mz0neo"><div class="cv-highlight-marker svelte-1mz0neo"></div> <!> <div class="cv-highlight-pill svelte-1mz0neo"><a href="https://custardui.js.org" target="_blank" rel="noopener noreferrer" class="svelte-1mz0neo">Annotated by: CustardUI↗</a></div> <!></div>`);
15414
+ var root$8 = from_html(`<div class="cv-highlight-overlay svelte-1mz0neo"></div>`);
15415
+
15416
+ const $$css$7 = {
15417
+ hash: 'svelte-1mz0neo',
15418
+ code: '.cv-highlight-overlay.svelte-1mz0neo {position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:8000;}.cv-highlight-group.svelte-1mz0neo {position:absolute;pointer-events:none;}.cv-highlight-marker.svelte-1mz0neo {position:absolute;inset:0;pointer-events:none;\n \n /* Marker Style */border:3.5px solid var(--cv-highlight-color);border-radius:200px 15px 225px 15px / 15px 225px 15px 255px;transform:rotate(-0.5deg);\n \n /* 3D INTERNAL VOLUME:\n Adds depth to the yellow border itself so it looks rounded.\n */box-shadow:inset 0 1px 2px rgba(129, 73, 25, 0.2),\n inset 0 -1px 1px rgba(255, 255, 255, 0.7);\n\n /* 2A-3 DOUBLE LIGHT PROJECTION:\n Stacks multiple drop-shadows to cast into the box interior.\n */filter:/* Sharp contact shadow for grounding */\n drop-shadow(0 2px 2px rgba(44, 26, 14, 0.15)) \n /* Light Source A: Casts shadow from top-left to bottom-right */\n drop-shadow(-8px 12px 10px rgba(44, 26, 14, 0.12))\n /* Light Source B: Casts shadow from top-right to bottom-left */\n drop-shadow(8px 12px 10px rgba(44, 26, 14, 0.12));\n \n animation: svelte-1mz0neo-highlightFadeIn 0.3s ease-out forwards;}.cv-nav-arrow.svelte-1mz0neo {position:absolute;z-index:10;right:-5px;pointer-events:auto;width:14px;height:14px;border-radius:100px;border:1px solid var(--cv-highlight-color);background:white;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:7px;color:#814919;font-weight:700;font-family:ui-sans-serif, system-ui, sans-serif;line-height:1;padding:0;box-shadow:0 4px 12px rgba(44, 26, 14, 0.15);opacity:0.7;}.cv-nav-arrow.svelte-1mz0neo:hover {opacity:1;}.cv-nav-arrow--up.svelte-1mz0neo {top:0px;}.cv-nav-arrow--down.svelte-1mz0neo {bottom:0px;}.cv-nav-arrow--hidden.svelte-1mz0neo {visibility:hidden;pointer-events:none;}.cv-highlight-pill.svelte-1mz0neo {position:absolute;z-index:10;bottom:-2px;right:14px;background:white;height:14px;padding:0 8px;display:flex;align-items:center;border-radius:100px;border:1px solid var(--cv-highlight-color);pointer-events:auto;white-space:nowrap;\n \n /* Stronger shadow to match the frame\'s new altitude */box-shadow:0 4px 12px rgba(44, 26, 14, 0.15);}.cv-highlight-pill.svelte-1mz0neo a:where(.svelte-1mz0neo) {font-size:8px;font-weight:700;color:#814919;text-decoration:none;font-family:ui-sans-serif, system-ui, sans-serif;line-height:1;}.cv-highlight-pill.svelte-1mz0neo:hover a:where(.svelte-1mz0neo) {opacity:0.8;}\n\n @keyframes svelte-1mz0neo-highlightFadeIn {\n from { \n opacity: 0; \n transform: scale(0.98) rotate(-1deg); \n }\n to { \n opacity: 1; \n transform: scale(1) rotate(-0.5deg); \n }\n }'
15419
+ };
15420
+
15421
+ function HighlightOverlay($$anchor, $$props) {
15422
+ push($$props, true);
15423
+ append_styles$1($$anchor, $$css$7);
15424
+
15425
+ let rects = user_derived(() => $$props.box.rects);
15426
+
15427
+ function getColorHex(rect) {
15428
+ const key = rect.color ?? DEFAULT_COLOR_KEY;
15429
+
15430
+ return HIGHLIGHT_COLORS.find((c) => c.key === key)?.hex ?? HIGHLIGHT_COLORS[0].hex;
15431
+ }
15432
+
15433
+ function scrollToRect(rect) {
15434
+ rect.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
15435
+ }
15436
+
15437
+ var div = root$8();
14784
15438
 
14785
15439
  each(div, 23, () => get(rects), (rect) => rect.element, ($$anchor, rect, i) => {
14786
- var div_1 = root_1$3();
15440
+ var div_1 = root_1$4();
14787
15441
  var node = sibling(child(div_1), 2);
14788
15442
 
14789
15443
  {
14790
15444
  var consequent = ($$anchor) => {
14791
- var fragment = root_2$2();
15445
+ var fragment = root_2$3();
14792
15446
  var button = first_child(fragment);
14793
15447
  let classes;
14794
15448
 
@@ -14815,70 +15469,28 @@
14815
15469
  var node_1 = sibling(node, 4);
14816
15470
 
14817
15471
  {
14818
- var consequent_2 = ($$anchor) => {
14819
- var button_2 = root_3$1();
14820
- let classes_2;
14821
-
14822
- button_2.__click = (e) => {
14823
- e.stopPropagation();
14824
- toggleBadge(get(rect).element);
14825
- };
14826
-
14827
- var node_2 = child(button_2);
14828
-
14829
- {
14830
- var consequent_1 = ($$anchor) => {
14831
- var span = root_4();
14832
- var text = child(span, true);
14833
-
14834
- reset(span);
14835
- template_effect(() => set_text(text, get(rect).annotation));
14836
- append($$anchor, span);
14837
- };
14838
-
14839
- var alternate = ($$anchor) => {
14840
- var span_1 = root_5();
14841
- var text_1 = child(span_1, true);
14842
-
14843
- reset(span_1);
14844
-
14845
- template_effect(($0) => set_text(text_1, $0), [
14846
- () => get(rect).annotation.length > ANNOTATION_PREVIEW_LENGTH
14847
- ? get(rect).annotation.slice(0, ANNOTATION_PREVIEW_LENGTH) + '…'
14848
- : get(rect).annotation
14849
- ]);
14850
-
14851
- append($$anchor, span_1);
14852
- };
14853
-
14854
- if_block(node_2, ($$render) => {
14855
- if (expandedSet.has(get(rect).element)) $$render(consequent_1); else $$render(alternate, false);
14856
- });
14857
- }
14858
-
14859
- reset(button_2);
14860
-
14861
- template_effect(
14862
- ($0, $1, $2) => {
14863
- classes_2 = set_class(button_2, 1, 'cv-annotation-badge svelte-1mz0neo', null, classes_2, $0);
14864
- set_style(button_2, $1);
14865
- set_attribute(button_2, 'aria-label', $2);
15472
+ var consequent_1 = ($$anchor) => {
15473
+ HighlightTextAnnotation($$anchor, {
15474
+ get annotation() {
15475
+ return get(rect).annotation;
14866
15476
  },
14867
- [
14868
- () => ({
14869
- 'cv-annotation-badge--expanded': expandedSet.has(get(rect).element)
14870
- }),
14871
15477
 
14872
- () => getBadgeStyle(get(rect).annotationCorner ?? DEFAULT_ANNOTATION_CORNER),
14873
- () => expandedSet.has(get(rect).element) ? 'Collapse annotation' : 'Expand annotation'
14874
- ]
14875
- );
15478
+ get annotationCorner() {
15479
+ return get(rect).annotationCorner;
15480
+ }
15481
+ });
15482
+ };
14876
15483
 
14877
- append($$anchor, button_2);
15484
+ var alternate = ($$anchor) => {
15485
+ HighlightEmptyAnnotation($$anchor, {
15486
+ get annotationCorner() {
15487
+ return get(rect).annotationCorner;
15488
+ }
15489
+ });
14878
15490
  };
14879
15491
 
14880
15492
  if_block(node_1, ($$render) => {
14881
- if (get(rect).annotation) $$render(consequent_2);
15493
+ if (get(rect).annotation !== undefined && get(rect).annotation.length > 0) $$render(consequent_1); else $$render(alternate, false);
14882
15494
  });
14883
15495
  }
14884
15496
 
@@ -15008,7 +15620,8 @@
15008
15620
  rect.color = color;
15009
15621
  const annotation = annotationMap?.get(elements[0]);
15010
15622
  if (annotation !== undefined) {
15011
- rect.annotation = annotation.text;
15623
+ if (annotation.text.length > 0)
15624
+ rect.annotation = annotation.text;
15012
15625
  rect.annotationCorner = annotation.corner;
15013
15626
  }
15014
15627
  resultList.push(rect);
@@ -15067,7 +15680,7 @@
15067
15680
  return targets;
15068
15681
  }
15069
15682
 
15070
- apply(encodedDescriptors) {
15683
+ applyEncodedHighlights(encodedDescriptors) {
15071
15684
  const descriptors = deserialize(encodedDescriptors);
15072
15685
 
15073
15686
  if (!descriptors || descriptors.length === 0) return;
@@ -15086,8 +15699,11 @@
15086
15699
  matchingEls.forEach((el) => colors.set(el, desc.color));
15087
15700
  }
15088
15701
 
15089
- if (desc.annotation && desc.annotationCorner) {
15090
- matchingEls.forEach((el) => annotations.set(el, { text: desc.annotation, corner: desc.annotationCorner }));
15702
+ if (desc.annotation || desc.annotationCorner) {
15703
+ matchingEls.forEach((el) => annotations.set(el, {
15704
+ text: desc.annotation ?? '',
15705
+ corner: desc.annotationCorner ?? DEFAULT_ANNOTATION_CORNER
15706
+ }));
15091
15707
  }
15092
15708
  }
15093
15709
  });
@@ -15325,11 +15941,11 @@
15325
15941
  this.applyHideMode(hideDescriptors, highlightTargets);
15326
15942
  }
15327
15943
 
15328
- // Apply highlight independently can coexist with show/hide.
15329
- // Call highlightService.apply() directly to skip applyHighlightMode()'s guard,
15330
- // which would otherwise see BODY_SHOW_CLASS and clear the show mode above.
15944
+ // Call highlightService.applyEncodedHighlights() directly with the encoded descriptors
15945
+ // to skip applyHighlightMode()'s guard, which would otherwise see BODY_SHOW_CLASS
15946
+ // and clear the show mode above.
15331
15947
  if (highlightDescriptors) {
15332
- this.highlightService.apply(highlightDescriptors);
15948
+ this.highlightService.applyEncodedHighlights(highlightDescriptors);
15333
15949
  }
15334
15950
  }
15335
15951
 
@@ -15428,7 +16044,7 @@
15428
16044
  this.exitShowMode(false);
15429
16045
  }
15430
16046
 
15431
- this.highlightService.apply(encodedDescriptors);
16047
+ this.highlightService.applyEncodedHighlights(encodedDescriptors);
15432
16048
  }
15433
16049
 
15434
16050
  renderHiddenView(targets) {
@@ -16314,13 +16930,20 @@
16314
16930
  }
16315
16931
  }
16316
16932
 
16317
- var root_1$2 = from_html(`<div class="cv-toggle-label svelte-1ka2eec"> </div>`);
16318
- var root_2$1 = from_html(`<button class="cv-expand-btn svelte-1ka2eec"><!></button>`);
16319
- var root$5 = from_html(`<div><!> <div class="cv-toggle-content svelte-1ka2eec"><div class="cv-toggle-inner svelte-1ka2eec"><!></div></div> <!></div>`);
16933
+ var root_2$2 = from_html(`<span class="cv-placeholder-label svelte-1ka2eec"> </span>`);
16934
+ var root_3$1 = from_html(`<button type="button"></button>`);
16935
+ var root_1$3 = from_html(`<div class="cv-toggle-placeholder svelte-1ka2eec" role="group"><!> <div class="cv-state-dots svelte-1ka2eec" role="group" aria-label="Visibility states"></div></div>`);
16936
+ var root_4 = from_html(`<div class="cv-toggle-label svelte-1ka2eec"> </div>`);
16937
+ var root_6 = from_html(`<button type="button"></button>`);
16938
+ var root_5 = from_html(`<div class="cv-state-dots cv-state-dots--floating svelte-1ka2eec" role="group" aria-label="Visibility states"></div>`);
16939
+ var root_8 = from_html(`<!> <span class="cv-expand-label svelte-1ka2eec">Show less</span>`, 1);
16940
+ var root_9 = from_html(`<!> <span class="cv-expand-label svelte-1ka2eec">Show more</span>`, 1);
16941
+ var root_7 = from_html(`<button type="button" class="cv-expand-btn svelte-1ka2eec"><!></button>`);
16942
+ var root$5 = from_html(`<!> <div><!> <!> <div class="cv-toggle-content svelte-1ka2eec"><div class="cv-toggle-inner svelte-1ka2eec"><!></div></div> <!></div>`, 1);
16320
16943
 
16321
16944
  const $$css$6 = {
16322
16945
  hash: 'svelte-1ka2eec',
16323
- code: ':host {display:block;position:relative;z-index:1;overflow:visible;}\n\n /* Host visibility control */:host([hidden]) {display:none;}.cv-toggle-wrapper.svelte-1ka2eec {position:relative;width:100%;transition:all 0.3s ease;margin-bottom:4px;}.cv-toggle-wrapper.hidden.svelte-1ka2eec {margin-bottom:0;}.cv-toggle-wrapper.peek-mode.svelte-1ka2eec {margin-bottom:24px;}.cv-toggle-content.svelte-1ka2eec {overflow:hidden;transition:max-height 0.3s ease,\n opacity 0.3s ease,\n overflow 0s 0s;\n /* CSS max-height defaults are handled by inline styles now */}.cv-toggle-inner.svelte-1ka2eec {display:flow-root; /* Ensures margins of children are contained */}\n\n /* Hidden State */.hidden.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:0;pointer-events:none;}\n\n /* Bordered State */.has-border.svelte-1ka2eec {box-sizing:border-box; /* Ensure padding/border doesn\'t increase width */\n\n /* Dashed border */border:2px dashed rgba(0, 0, 0, 0.15);border-bottom:none;\n\n /* Inner shadow to look like it\'s going into something + outer shadow */box-shadow:0 2px 8px rgba(0, 0, 0, 0.05),\n /* Subtle outer */ inset 0 -15px 10px -10px rgba(0, 0, 0, 0.1); /* Inner bottom shadow */border-radius:8px 8px 0 0;padding:12px 0 0 0; /* bottom 0 px until expanded */margin-top:4px;}\n\n /* Visible / Expanded State */.expanded.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:1;transform:translateY(0);overflow:visible;transition:max-height 0.3s ease,\n opacity 0.3s ease,\n overflow 0s 0.3s;}\n\n /* When expanded, complete the border */.has-border.expanded.svelte-1ka2eec {border-bottom:2px dashed rgba(0, 0, 0, 0.15);border-radius:8px; /* Round all corners */padding-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.05); /* Remove inner shadow when expanded */}\n\n /* Peek State */.peeking.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:1;\n /* Mask for fade out effect */mask-image:linear-gradient(to bottom, black 50%, transparent 100%);-webkit-mask-image:linear-gradient(to bottom, black 50%, transparent 100%);}\n\n /* Label Style */.cv-toggle-label.svelte-1ka2eec {position:absolute;top:-12px;left:0;background:#e0e0e0;color:#333;font-size:0.75rem;font-weight:600;padding:2px 8px;border-radius:4px;z-index:10;pointer-events:auto;box-shadow:0 1px 2px rgba(0, 0, 0, 0.1);}\n\n /* Adjust label position if bordered */.has-border.svelte-1ka2eec .cv-toggle-label:where(.svelte-1ka2eec) {top:-10px;left:0;}\n\n /* Expand Button */.cv-expand-btn.svelte-1ka2eec {position:absolute;bottom:-24px;left:50%;transform:translateX(-50%);display:flex;background:transparent;border:none;border-radius:50%;padding:4px;width:32px;height:32px;cursor:pointer;z-index:100;align-items:center;justify-content:center;color:#888;transition:all 0.2s ease;}.cv-expand-btn.svelte-1ka2eec:hover {background:rgba(0, 0, 0, 0.05);color:#000;transform:translateX(-50%) scale(1.1);}\n\n /* Accessing SVG inside button - might need :global if SVG is injected as HTML or just plain styles since it adheres to current scope */.cv-expand-btn.svelte-1ka2eec svg {display:block;opacity:0.6;width:24px;height:24px;transition:opacity 0.2s;}.cv-expand-btn.svelte-1ka2eec:hover svg {opacity:1;}'
16946
+ code: ':host {display:block;position:relative;z-index:1;overflow:visible;}\n\n /* Host visibility control */:host([hidden]) {display:none;}.cv-toggle-wrapper.svelte-1ka2eec {position:relative;width:100%;transition:all 0.35s cubic-bezier(0.4, 0, 0.2, 1);margin-bottom:4px;}.cv-toggle-wrapper.hidden.svelte-1ka2eec {margin-bottom:0;}.cv-toggle-wrapper.peek-mode.svelte-1ka2eec {margin-bottom:28px;}.cv-toggle-content.svelte-1ka2eec {overflow:hidden;transition:max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.3s ease,\n overflow 0s 0s;}.cv-toggle-inner.svelte-1ka2eec {display:flow-root; /* Ensures margins of children are contained */}\n\n /* Hidden State */.hidden.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:0;pointer-events:none;}\n\n /* Bordered State */.has-border.svelte-1ka2eec {box-sizing:border-box;border:2px dashed rgba(0, 0, 0, 0.15);border-bottom:none;box-shadow:0 2px 8px rgba(0, 0, 0, 0.05),\n inset 0 -15px 10px -10px rgba(0, 0, 0, 0.1);border-radius:8px 8px 0 0;padding:12px 0 0 0;margin-top:4px;}\n\n /* Visible / Expanded State */.expanded.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:1;transform:translateY(0);overflow:visible;transition:max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.3s ease,\n overflow 0s 0.35s;}\n\n /* When expanded, complete the border */.has-border.expanded.svelte-1ka2eec {border-bottom:2px dashed rgba(0, 0, 0, 0.15);border-radius:8px;padding-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.05);}\n\n /* Peek State — smoother gradient */.peeking.svelte-1ka2eec .cv-toggle-content:where(.svelte-1ka2eec) {opacity:1;mask-image:linear-gradient(to bottom, black 30%, rgba(0,0,0,0.5) 70%, transparent 100%);-webkit-mask-image:linear-gradient(to bottom, black 30%, rgba(0,0,0,0.5) 70%, transparent 100%);}\n\n /* Label Style */.cv-toggle-label.svelte-1ka2eec {position:absolute;top:-12px;left:0;background:#e0e0e0;color:#333;font-size:0.75rem;font-weight:600;padding:2px 8px;border-radius:4px;z-index:10;pointer-events:auto;box-shadow:0 1px 2px rgba(0, 0, 0, 0.1);}\n\n /* Adjust label position if bordered */.has-border.svelte-1ka2eec .cv-toggle-label:where(.svelte-1ka2eec) {top:-10px;left:0;}\n\n /* Hidden-state placeholder bar */.cv-toggle-placeholder.svelte-1ka2eec {display:flex;align-items:center;justify-content:space-between;padding:4px 8px;min-height:24px;border:1px solid rgba(0, 0, 0, 0.06);border-radius:6px;background:rgba(0, 0, 0, 0.015);margin-bottom:4px;transition:border-color 0.2s ease, background 0.2s ease;}.cv-toggle-placeholder.svelte-1ka2eec:hover {border-color:rgba(0, 0, 0, 0.12);background:rgba(0, 0, 0, 0.025);}.cv-placeholder-label.svelte-1ka2eec {font-size:0.7rem;font-weight:500;color:rgba(0, 0, 0, 0.35);letter-spacing:0.02em;user-select:none;}\n\n /* 3-dot state indicator */.cv-state-dots.svelte-1ka2eec {display:flex;align-items:center;gap:5px;}\n\n /* Floating position (top-right of content) */.cv-state-dots--floating.svelte-1ka2eec {position:absolute;top:-2px;right:0;z-index:10;opacity:0;transition:opacity 0.2s ease;}.cv-toggle-wrapper.svelte-1ka2eec:hover .cv-state-dots--floating:where(.svelte-1ka2eec),\n .cv-state-dots--floating.svelte-1ka2eec:focus-within {opacity:1;}\n\n /* Adjust floating dots when bordered */.has-border.svelte-1ka2eec .cv-state-dots--floating:where(.svelte-1ka2eec) {top:4px;right:8px;}.cv-dot.svelte-1ka2eec {position:relative;width:7px;height:7px;border-radius:50%;border:1.5px solid rgba(0, 0, 0, 0.2);background:transparent;padding:0;cursor:pointer;transition:all 0.15s ease;flex-shrink:0;}\n\n /* Expand tap target to ~20px while keeping dot visually small */.cv-dot.svelte-1ka2eec::before {content:\'\';position:absolute;top:50%;left:50%;width:20px;height:20px;transform:translate(-50%, -50%);border-radius:50%;}.cv-dot.svelte-1ka2eec:hover {border-color:rgba(0, 0, 0, 0.5);transform:scale(1.3);}.cv-dot.active.svelte-1ka2eec {background:var(--cv-primary, #3E84F4);border-color:var(--cv-primary, #3E84F4);}.cv-dot.active.svelte-1ka2eec:hover {transform:scale(1.3);}\n\n /* Expand Button upgraded to pill style */.cv-expand-btn.svelte-1ka2eec {position:absolute;bottom:-28px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:4px;background:rgba(0, 0, 0, 0.04);border:1px solid rgba(0, 0, 0, 0.08);border-radius:999px;padding:3px 12px;cursor:pointer;z-index:100;color:#666;font-size:0.7rem;font-weight:500;font-family:inherit;line-height:1;transition:all 0.2s ease;}.cv-expand-btn.svelte-1ka2eec:hover {background:rgba(0, 0, 0, 0.08);border-color:rgba(0, 0, 0, 0.15);color:#333;transform:translateX(-50%) scale(1.02);}.cv-expand-btn.svelte-1ka2eec svg {display:block;width:14px;height:14px;opacity:0.6;flex-shrink:0;}.cv-expand-btn.svelte-1ka2eec:hover svg {opacity:1;}.cv-expand-label.svelte-1ka2eec {white-space:nowrap;}'
16324
16947
  };
16325
16948
 
16326
16949
  function Toggle($$anchor, $$props) {
@@ -16332,6 +16955,7 @@
16332
16955
  assetId = prop($$props, 'assetId', 7, ''),
16333
16956
  showPeekBorder = prop($$props, 'showPeekBorder', 7, false),
16334
16957
  showLabel = prop($$props, 'showLabel', 7, false),
16958
+ showInlineControl = prop($$props, 'showInlineControl', 7, false),
16335
16959
  placeholderId = prop($$props, 'placeholderId', 7, '');
16336
16960
 
16337
16961
  // Derive toggle IDs from toggle-id prop (can have multiple space-separated IDs)
@@ -16483,6 +17107,20 @@
16483
17107
  set(localExpanded, !get(localExpanded));
16484
17108
  }
16485
17109
 
17110
+ // Derive current state for inline 3-dot indicator
17111
+ let currentInlineState = user_derived(() => {
17112
+ if (get(showState)) return 'show';
17113
+ if (get(peekState)) return 'peek';
17114
+
17115
+ return 'hide';
17116
+ });
17117
+
17118
+ // Set toggle to a specific state (used by inline dot controls)
17119
+ function setToggleState(e, targetState) {
17120
+ e.stopPropagation();
17121
+ get(toggleIds).forEach((id) => activeStateStore.updateToggleState(id, targetState));
17122
+ }
17123
+
16486
17124
  // Reactive asset rendering - renders assets when toggle becomes visible
16487
17125
  user_effect(() => {
16488
17126
  if (get(showFullContent) && assetId() && !get(hasRendered) && derivedStore.assetsManager && contentEl) {
@@ -16528,6 +17166,15 @@
16528
17166
  flushSync();
16529
17167
  },
16530
17168
 
17169
+ get showInlineControl() {
17170
+ return showInlineControl();
17171
+ },
17172
+
17173
+ set showInlineControl($$value = false) {
17174
+ showInlineControl($$value);
17175
+ flushSync();
17176
+ },
17177
+
16531
17178
  get placeholderId() {
16532
17179
  return placeholderId();
16533
17180
  },
@@ -16538,86 +17185,190 @@
16538
17185
  }
16539
17186
  };
16540
17187
 
16541
- var div = root$5();
16542
- let classes;
16543
- var node = child(div);
17188
+ var fragment = root$5();
17189
+ var node = first_child(fragment);
16544
17190
 
16545
17191
  {
16546
- var consequent = ($$anchor) => {
16547
- var div_1 = root_1$2();
16548
- var text = child(div_1, true);
17192
+ var consequent_1 = ($$anchor) => {
17193
+ var div = root_1$3();
17194
+ var node_1 = child(div);
17195
+
17196
+ {
17197
+ var consequent = ($$anchor) => {
17198
+ var span = root_2$2();
17199
+ var text = child(span, true);
17200
+
17201
+ reset(span);
17202
+ template_effect(() => set_text(text, get(labelText)));
17203
+ append($$anchor, span);
17204
+ };
17205
+
17206
+ if_block(node_1, ($$render) => {
17207
+ if (get(labelText)) $$render(consequent);
17208
+ });
17209
+ }
17210
+
17211
+ var div_1 = sibling(node_1, 2);
17212
+
17213
+ each(div_1, 20, () => ['hide', 'peek', 'show'], index, ($$anchor, dotState) => {
17214
+ var button = root_3$1();
17215
+
17216
+ button.__click = (e) => setToggleState(e, dotState);
17217
+
17218
+ template_effect(
17219
+ ($0, $1) => {
17220
+ set_class(button, 1, `cv-dot ${get(currentInlineState) === dotState ? 'active' : ''}`, 'svelte-1ka2eec');
17221
+ set_attribute(button, 'aria-label', $0);
17222
+ set_attribute(button, 'title', $1);
17223
+ set_attribute(button, 'aria-pressed', get(currentInlineState) === dotState);
17224
+ },
17225
+ [
17226
+ () => dotState.charAt(0).toUpperCase() + dotState.slice(1),
17227
+ () => dotState.charAt(0).toUpperCase() + dotState.slice(1)
17228
+ ]
17229
+ );
17230
+
17231
+ append($$anchor, button);
17232
+ });
16549
17233
 
16550
17234
  reset(div_1);
16551
- template_effect(() => set_text(text, get(labelText)));
16552
- append($$anchor, div_1);
17235
+ reset(div);
17236
+ template_effect(() => set_attribute(div, 'aria-label', `Toggle: ${get(labelText) ?? ''}`));
17237
+ append($$anchor, div);
16553
17238
  };
16554
17239
 
16555
17240
  if_block(node, ($$render) => {
16556
- if (showLabel() && get(labelText) && !get(isHidden)) $$render(consequent);
17241
+ if (showInlineControl() && !get(isPlaceholderMode) && get(isHidden)) $$render(consequent_1);
16557
17242
  });
16558
17243
  }
16559
17244
 
16560
17245
  var div_2 = sibling(node, 2);
17246
+ let classes;
17247
+ var node_2 = child(div_2);
17248
+
17249
+ {
17250
+ var consequent_2 = ($$anchor) => {
17251
+ var div_3 = root_4();
17252
+ var text_1 = child(div_3, true);
17253
+
17254
+ reset(div_3);
17255
+ template_effect(() => set_text(text_1, get(labelText)));
17256
+ append($$anchor, div_3);
17257
+ };
17258
+
17259
+ if_block(node_2, ($$render) => {
17260
+ if (showLabel() && get(labelText) && !get(isHidden)) $$render(consequent_2);
17261
+ });
17262
+ }
17263
+
17264
+ var node_3 = sibling(node_2, 2);
17265
+
17266
+ {
17267
+ var consequent_3 = ($$anchor) => {
17268
+ var div_4 = root_5();
17269
+
17270
+ each(div_4, 20, () => ['hide', 'peek', 'show'], index, ($$anchor, dotState) => {
17271
+ var button_1 = root_6();
17272
+
17273
+ button_1.__click = (e) => setToggleState(e, dotState);
17274
+
17275
+ template_effect(
17276
+ ($0, $1) => {
17277
+ set_class(button_1, 1, `cv-dot ${get(currentInlineState) === dotState ? 'active' : ''}`, 'svelte-1ka2eec');
17278
+ set_attribute(button_1, 'aria-label', $0);
17279
+ set_attribute(button_1, 'title', $1);
17280
+ set_attribute(button_1, 'aria-pressed', get(currentInlineState) === dotState);
17281
+ },
17282
+ [
17283
+ () => dotState.charAt(0).toUpperCase() + dotState.slice(1),
17284
+ () => dotState.charAt(0).toUpperCase() + dotState.slice(1)
17285
+ ]
17286
+ );
17287
+
17288
+ append($$anchor, button_1);
17289
+ });
17290
+
17291
+ reset(div_4);
17292
+ append($$anchor, div_4);
17293
+ };
17294
+
17295
+ if_block(node_3, ($$render) => {
17296
+ if (showInlineControl() && !get(isPlaceholderMode) && !get(isHidden)) $$render(consequent_3);
17297
+ });
17298
+ }
17299
+
17300
+ var div_5 = sibling(node_3, 2);
16561
17301
  let styles;
16562
- var div_3 = child(div_2);
16563
- var node_1 = child(div_3);
17302
+ var div_6 = child(div_5);
17303
+ var node_4 = child(div_6);
16564
17304
 
16565
- slot(node_1, $$props, 'default', {});
16566
- reset(div_3);
16567
- bind_this(div_3, ($$value) => innerEl = $$value, () => innerEl);
16568
- reset(div_2);
16569
- bind_this(div_2, ($$value) => contentEl = $$value, () => contentEl);
17305
+ slot(node_4, $$props, 'default', {});
17306
+ reset(div_6);
17307
+ bind_this(div_6, ($$value) => innerEl = $$value, () => innerEl);
17308
+ reset(div_5);
17309
+ bind_this(div_5, ($$value) => contentEl = $$value, () => contentEl);
16570
17310
 
16571
- var node_2 = sibling(div_2, 2);
17311
+ var node_5 = sibling(div_5, 2);
16572
17312
 
16573
17313
  {
16574
- var consequent_2 = ($$anchor) => {
16575
- var button = root_2$1();
17314
+ var consequent_5 = ($$anchor) => {
17315
+ var button_2 = root_7();
16576
17316
 
16577
- button.__click = toggleExpand;
17317
+ button_2.__click = toggleExpand;
16578
17318
 
16579
- var node_3 = child(button);
17319
+ var node_6 = child(button_2);
16580
17320
 
16581
17321
  {
16582
- var consequent_1 = ($$anchor) => {
16583
- IconChevronUp($$anchor, {});
17322
+ var consequent_4 = ($$anchor) => {
17323
+ var fragment_1 = root_8();
17324
+ var node_7 = first_child(fragment_1);
17325
+
17326
+ IconChevronUp(node_7, {});
17327
+ next(2);
17328
+ append($$anchor, fragment_1);
16584
17329
  };
16585
17330
 
16586
17331
  var alternate = ($$anchor) => {
16587
- IconChevronDown($$anchor, {});
17332
+ var fragment_2 = root_9();
17333
+ var node_8 = first_child(fragment_2);
17334
+
17335
+ IconChevronDown(node_8, {});
17336
+ next(2);
17337
+ append($$anchor, fragment_2);
16588
17338
  };
16589
17339
 
16590
- if_block(node_3, ($$render) => {
16591
- if (get(localExpanded)) $$render(consequent_1); else $$render(alternate, false);
17340
+ if_block(node_6, ($$render) => {
17341
+ if (get(localExpanded)) $$render(consequent_4); else $$render(alternate, false);
16592
17342
  });
16593
17343
  }
16594
17344
 
16595
- reset(button);
16596
- template_effect(() => set_attribute(button, 'aria-label', get(localExpanded) ? 'Collapse content' : 'Expand content'));
16597
- append($$anchor, button);
17345
+ reset(button_2);
17346
+ template_effect(() => set_attribute(button_2, 'aria-label', get(localExpanded) ? 'Show less' : 'Show more'));
17347
+ append($$anchor, button_2);
16598
17348
  };
16599
17349
 
16600
- if_block(node_2, ($$render) => {
16601
- if (get(peekState) && !get(isSmallContent)) $$render(consequent_2);
17350
+ if_block(node_5, ($$render) => {
17351
+ if (get(peekState) && !get(isSmallContent)) $$render(consequent_5);
16602
17352
  });
16603
17353
  }
16604
17354
 
16605
- reset(div);
17355
+ reset(div_2);
16606
17356
 
16607
17357
  template_effect(() => {
16608
- classes = set_class(div, 1, 'cv-toggle-wrapper svelte-1ka2eec', null, classes, {
17358
+ classes = set_class(div_2, 1, 'cv-toggle-wrapper svelte-1ka2eec', null, classes, {
16609
17359
  expanded: get(showFullContent) && !get(showPeekContent),
16610
17360
  peeking: get(showPeekContent),
16611
17361
  'peek-mode': get(peekState),
16612
17362
  hidden: get(isHidden),
16613
- 'has-border': showPeekBorder() && get(peekState)
17363
+ 'has-border': showPeekBorder() && get(peekState),
17364
+ 'has-inline-control': showInlineControl() && !get(isPlaceholderMode)
16614
17365
  });
16615
17366
 
16616
- styles = set_style(div_2, '', styles, { 'max-height': get(currentMaxHeight) });
17367
+ styles = set_style(div_5, '', styles, { 'max-height': get(currentMaxHeight) });
16617
17368
  });
16618
17369
 
16619
- event('transitionend', div_2, handleTransitionEnd);
16620
- append($$anchor, div);
17370
+ event('transitionend', div_5, handleTransitionEnd);
17371
+ append($$anchor, fragment);
16621
17372
 
16622
17373
  return pop($$exports);
16623
17374
  }
@@ -16637,6 +17388,13 @@
16637
17388
  },
16638
17389
 
16639
17390
  showLabel: { attribute: 'show-label', reflect: true, type: 'Boolean' },
17391
+
17392
+ showInlineControl: {
17393
+ attribute: 'show-inline-control',
17394
+ reflect: true,
17395
+ type: 'Boolean'
17396
+ },
17397
+
16640
17398
  placeholderId: { attribute: 'placeholder-id', reflect: true, type: 'String' }
16641
17399
  },
16642
17400
  ['default'],
@@ -16695,14 +17453,16 @@
16695
17453
  true
16696
17454
  ));
16697
17455
 
16698
- var root$3 = from_svg(`<svg><g transform="rotate(45 8 8)"><path d="M10.5 2H12V0H4V2H5.5V6L4 7.5V9H7.2V15H8.8V9H12V7.5L10.5 6V2Z"></path></g></svg>`);
17456
+ var root_1$2 = from_svg(`<path d="M4 2v13l4-2.5L12 15V2H4z"></path>`);
17457
+ var root_2$1 = from_svg(`<path d="M4 2v13l4-2.5L12 15V2H4zm1 1h6v10.5l-3-1.88L5 13.5V3z"></path>`);
17458
+ var root$3 = from_svg(`<svg><!></svg>`);
16699
17459
 
16700
- function IconPin($$anchor, $$props) {
16701
- let isPinned = prop($$props, 'isPinned', 3, false),
16702
- rest = rest_props($$props, ['$$slots', '$$events', '$$legacy', 'isPinned']);
17460
+ function IconMark($$anchor, $$props) {
17461
+ let isMarked = prop($$props, 'isMarked', 3, false),
17462
+ rest = rest_props($$props, ['$$slots', '$$events', '$$legacy', 'isMarked']);
16703
17463
 
16704
- // Derived opacity based on isPinned
16705
- const extraOpacity = user_derived(() => isPinned() ? '1' : '0.6');
17464
+ // Derived opacity based on isMarked
17465
+ const extraOpacity = user_derived(() => isMarked() ? '1' : '0.6');
16706
17466
 
16707
17467
  var svg = root$3();
16708
17468
 
@@ -16716,17 +17476,38 @@
16716
17476
  ...rest
16717
17477
  }));
16718
17478
 
17479
+ var node = child(svg);
17480
+
17481
+ {
17482
+ var consequent = ($$anchor) => {
17483
+ var path = root_1$2();
17484
+
17485
+ append($$anchor, path);
17486
+ };
17487
+
17488
+ var alternate = ($$anchor) => {
17489
+ var path_1 = root_2$1();
17490
+
17491
+ append($$anchor, path_1);
17492
+ };
17493
+
17494
+ if_block(node, ($$render) => {
17495
+ if (isMarked()) $$render(consequent); else $$render(alternate, false);
17496
+ });
17497
+ }
17498
+
17499
+ reset(svg);
16719
17500
  append($$anchor, svg);
16720
17501
  }
16721
17502
 
16722
- var root_2 = from_html(`<li class="nav-item svelte-1ujqpe3"><a role="tab" title="Double-click a tab to 'pin' it in all similar tab groups."><span class="cv-tab-header-container svelte-1ujqpe3"><span class="cv-tab-header-text svelte-1ujqpe3"><!></span> <span class="cv-tab-pin-icon svelte-1ujqpe3"><!></span></span></a></li>`);
16723
- var root_1$1 = from_html(`<ul class="cv-tabs-nav nav-tabs svelte-1ujqpe3" role="tablist"></ul>`);
17503
+ var root_2 = from_html(`<li class="cv-tabgroup-item svelte-1ujqpe3"><div><a role="tab" title="Double-click a tab to 'mark' it in all similar tab groups."><span class="cv-tab-header-text svelte-1ujqpe3"><!></span></a> <button type="button"><!></button></div></li>`);
17504
+ var root_1$1 = from_html(`<ul class="cv-tabgroup-nav svelte-1ujqpe3" role="tablist"></ul>`);
16724
17505
  var root_3 = from_html(`<link rel="stylesheet"/>`);
16725
17506
  var root$2 = from_html(`<div class="cv-tabgroup-container"><!> <!> <div class="cv-tabgroup-content"><!></div> <div class="cv-tabgroup-bottom-border svelte-1ujqpe3"></div></div>`);
16726
17507
 
16727
17508
  const $$css$4 = {
16728
17509
  hash: 'svelte-1ujqpe3',
16729
- code: ':host {display:block;margin-bottom:24px;}\n\n /* Tab navigation styles */ul.nav-tabs.svelte-1ujqpe3 {display:flex;flex-wrap:wrap;padding-left:0;margin-top:0.5rem;margin-bottom:0;list-style:none;border-bottom:1px solid #dee2e6;align-items:stretch;}.nav-item.svelte-1ujqpe3 {margin-bottom:-1px;list-style:none;display:flex;align-items:stretch;}.nav-link.svelte-1ujqpe3 {display:flex;align-items:center;justify-content:center;padding:0.5rem 1rem;color:#495057;text-decoration:none;background-color:transparent;border:1px solid transparent;border-top-left-radius:0.25rem;border-top-right-radius:0.25rem;transition:color 0.15s ease-in-out,\n background-color 0.15s ease-in-out,\n border-color 0.15s ease-in-out;cursor:pointer;min-height:2.5rem;box-sizing:border-box;}.nav-link.svelte-1ujqpe3 p {margin:0;display:inline;}.nav-link.svelte-1ujqpe3:hover,\n .nav-link.svelte-1ujqpe3:focus {border-color:#e9ecef #e9ecef #dee2e6;isolation:isolate;}.nav-link.active.svelte-1ujqpe3 {color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff;}.nav-link.svelte-1ujqpe3:focus {outline:0;}.cv-tab-header-container.svelte-1ujqpe3 {display:flex;align-items:center;gap:6px;}.cv-tab-header-text.svelte-1ujqpe3 {flex:1;}.cv-tab-pin-icon.svelte-1ujqpe3 {display:inline-flex;align-items:center;line-height:0;flex-shrink:0;}.cv-tab-pin-icon.svelte-1ujqpe3 svg {vertical-align:middle;width:14px;height:14px;}.cv-tabgroup-bottom-border.svelte-1ujqpe3 {border-bottom:1px solid #dee2e6;}\n\n @media print {ul.cv-tabs-nav.svelte-1ujqpe3 {display:none !important;}\n }'
17510
+ code: ':host {display:block;margin-bottom:24px;}\n\n /* Tab navigation styles */ul.cv-tabgroup-nav.svelte-1ujqpe3 {display:flex;flex-wrap:wrap;padding-left:0;margin-top:0.5rem;margin-bottom:0;list-style:none;border-bottom:1px solid var(--cv-border, rgba(128, 128, 128, 0.3));align-items:stretch;gap:0.5rem;}.cv-tabgroup-item.svelte-1ujqpe3 {margin-bottom:-1px;list-style:none;display:flex;align-items:stretch;}.cv-tabgroup-link.svelte-1ujqpe3 {display:flex;align-items:center;justify-content:center;padding:0.5rem 0.75rem;color:inherit;opacity:0.7;text-decoration:none;background-color:transparent !important;border:none;border-bottom:2px solid transparent;transition:opacity 0.15s ease-in-out,\n border-color 0.15s ease-in-out;cursor:pointer;min-height:2.5rem;box-sizing:border-box;font-weight:500;}.cv-tabgroup-link.svelte-1ujqpe3 p {margin:0;display:inline;}.cv-tabgroup-link.svelte-1ujqpe3:hover,\n .cv-tabgroup-link.svelte-1ujqpe3:focus {opacity:1;border-bottom-color:var(--cv-border, rgba(128, 128, 128, 0.3));isolation:isolate;}.cv-tabgroup-link.active.svelte-1ujqpe3 {opacity:1;background-color:transparent !important;}.cv-tabgroup-link.svelte-1ujqpe3:focus {outline:0;}.cv-tab-wrapper.svelte-1ujqpe3 {display:flex;align-items:center;border-bottom:2px solid transparent;transition:border-color 0.15s ease-in-out;}.cv-tab-wrapper.svelte-1ujqpe3:hover,\n .cv-tab-wrapper.svelte-1ujqpe3:focus-within {border-bottom-color:var(--cv-border, rgba(128, 128, 128, 0.3));}.cv-tab-wrapper.active.svelte-1ujqpe3 {border-bottom-color:currentColor;}.cv-tab-header-text.svelte-1ujqpe3 {line-height:1;}.cv-tab-marked-icon.svelte-1ujqpe3 {display:inline-flex;align-items:center;justify-content:center;line-height:0;flex-shrink:0;opacity:0;transition:opacity 0.15s ease-out;background:none;border:none;padding:0 8px 0 0;margin:0;cursor:pointer;color:inherit;height:100%;}.cv-tab-wrapper.svelte-1ujqpe3:hover .cv-tab-marked-icon:where(.svelte-1ujqpe3),\n .cv-tab-wrapper.svelte-1ujqpe3:focus-within .cv-tab-marked-icon:where(.svelte-1ujqpe3),\n .cv-tab-marked-icon.is-marked.svelte-1ujqpe3 {opacity:1;}.cv-tab-marked-icon.svelte-1ujqpe3 svg {vertical-align:middle;width:14px;height:14px;}.cv-tabgroup-bottom-border.svelte-1ujqpe3 {border-bottom:1px solid var(--cv-border, rgba(128, 128, 128, 0.3));}\n\n @media print {ul.cv-tabgroup-nav.svelte-1ujqpe3 {display:none !important;}\n }'
16730
17511
  };
16731
17512
 
16732
17513
  function TabGroup($$anchor, $$props) {
@@ -16734,13 +17515,15 @@
16734
17515
  append_styles$1($$anchor, $$css$4);
16735
17516
 
16736
17517
  // ID of the tabgroup Group
16737
- let groupId = prop($$props, 'groupId', 7);
17518
+ let groupId = prop($$props, 'groupId', 7),
17519
+ stabilizeScroll = prop($$props, 'stabilizeScroll', 7, true);
16738
17520
 
16739
17521
  user_effect(() => {
16740
17522
  if (groupId()) elementStore.registerTabGroup(groupId());
16741
17523
  });
16742
17524
 
16743
17525
  let tabs = state(proxy([]));
17526
+ let containerEl = state(void 0);
16744
17527
  let contentWrapper = state(void 0);
16745
17528
  let slotEl = state(null);
16746
17529
  let initialized = state(false);
@@ -16748,8 +17531,8 @@
16748
17531
  // Local active tab state (independent per group instance)
16749
17532
  let localActiveTabId = state('');
16750
17533
 
16751
- // Derive pinnedTab from store (shared across groups with same ID)
16752
- let pinnedTab = user_derived(() => {
17534
+ // Derive markedTab from store (shared across groups with same ID)
17535
+ let markedTab = user_derived(() => {
16753
17536
  const tabs$ = activeStateStore.state.tabs ?? {};
16754
17537
 
16755
17538
  return groupId() && tabs$[groupId()] ? tabs$[groupId()] : null;
@@ -16758,18 +17541,18 @@
16758
17541
  // Track the last seen store state to detect real changes
16759
17542
  let lastSeenStoreState = state(null);
16760
17543
 
16761
- // Authoritative Sync: Only sync when store actually changes
17544
+ // Authoritative Sync: Only sync when store actually changes.
17545
+ // NOTE: Scroll stabilization is NOT done here — it's the responsibility of
17546
+ // the initiating action (handleTabDoubleClick, handleMarkClick, or Modal).
17547
+ // If this $effect also stabilized, its rAF would compete with the initiator's
17548
+ // rAF and undo the correction.
16762
17549
  user_effect(() => {
16763
- // If store state has changed from what we last saw
16764
- // Note: strict inequality works here because both are strings or null
16765
- if (get(pinnedTab) !== get(lastSeenStoreState)) {
16766
- set(lastSeenStoreState, get(pinnedTab), true);
16767
-
16768
- // If there is a pinned tab, it overrides local state
16769
- if (get(pinnedTab)) {
16770
- // Check if we actually need to update (avoid redundant DOM work)
16771
- if (get(localActiveTabId) !== get(pinnedTab)) {
16772
- set(localActiveTabId, get(pinnedTab), true);
17550
+ if (get(markedTab) !== get(lastSeenStoreState)) {
17551
+ set(lastSeenStoreState, get(markedTab), true);
17552
+
17553
+ if (get(markedTab)) {
17554
+ if (get(localActiveTabId) !== get(markedTab)) {
17555
+ set(localActiveTabId, get(markedTab), true);
16773
17556
  updateVisibility();
16774
17557
  }
16775
17558
  }
@@ -16887,24 +17670,54 @@
16887
17670
  function handleTabClick(tabId, event) {
16888
17671
  event.preventDefault();
16889
17672
 
16890
- // Optimistic Update: Update local state immediately
16891
17673
  if (get(localActiveTabId) !== tabId) {
17674
+ const anchor = stabilizeScroll() && get(containerEl) ? captureScrollAnchor(get(containerEl)) : null;
17675
+
16892
17676
  set(localActiveTabId, tabId, true);
16893
17677
  updateVisibility();
17678
+
17679
+ if (anchor) restoreScrollAnchor(anchor);
16894
17680
  }
16895
17681
  }
16896
17682
 
16897
17683
  /**
16898
17684
  * Handles double-click events on the navigation tabs.
16899
- * Updates the store to "pin" the tab globally across all tab groups with the same ID.
17685
+ * Updates the store to "mark" the tab globally across all tab groups with the same ID.
17686
+ * Stabilizes scroll position because syncing may change height of OTHER groups above.
17687
+ */
17688
+ async function handleTabDoubleClick(tabId, event) {
17689
+ event.preventDefault();
17690
+
17691
+ if (!groupId()) return;
17692
+
17693
+ const anchor = stabilizeScroll() && get(containerEl) ? captureScrollAnchor(get(containerEl)) : null;
17694
+
17695
+ activeStateStore.setMarkedTab(groupId(), tabId);
17696
+
17697
+ if (anchor) {
17698
+ await tick();
17699
+ restoreScrollAnchor(anchor);
17700
+ }
17701
+ }
17702
+
17703
+ /**
17704
+ * Handles click events specifically on the mark icon.
17705
+ * Stabilizes scroll position because syncing may change height of OTHER groups above.
16900
17706
  */
16901
- function handleTabDoubleClick(tabId, event) {
17707
+ async function handleMarkClick(tabId, event) {
16902
17708
  event.preventDefault();
17709
+ event.stopPropagation();
16903
17710
 
16904
17711
  if (!groupId()) return;
16905
17712
 
16906
- // Update store directly - this will sync to all tab groups with same group-id
16907
- activeStateStore.setPinnedTab(groupId(), tabId);
17713
+ const anchor = stabilizeScroll() && get(containerEl) ? captureScrollAnchor(get(containerEl)) : null;
17714
+
17715
+ activeStateStore.setMarkedTab(groupId(), tabId);
17716
+
17717
+ if (anchor) {
17718
+ await tick();
17719
+ restoreScrollAnchor(anchor);
17720
+ }
16908
17721
  }
16909
17722
 
16910
17723
  var $$exports = {
@@ -16915,6 +17728,15 @@
16915
17728
  set groupId($$value) {
16916
17729
  groupId($$value);
16917
17730
  flushSync();
17731
+ },
17732
+
17733
+ get stabilizeScroll() {
17734
+ return stabilizeScroll();
17735
+ },
17736
+
17737
+ set stabilizeScroll($$value = true) {
17738
+ stabilizeScroll($$value);
17739
+ flushSync();
16918
17740
  }
16919
17741
  };
16920
17742
 
@@ -16928,44 +17750,56 @@
16928
17750
  each(ul, 21, () => get(tabs), (tab) => tab.id, ($$anchor, tab) => {
16929
17751
  const splitIds = user_derived(() => splitTabIds(get(tab).rawId));
16930
17752
  const isActive = user_derived(() => get(splitIds).includes(get(localActiveTabId)));
16931
- const isPinned = user_derived(() => get(pinnedTab) && get(splitIds).includes(get(pinnedTab)));
17753
+ const isMarked = user_derived(() => get(markedTab) && get(splitIds).includes(get(markedTab)));
16932
17754
  var li = root_2();
16933
- var a = child(li);
17755
+ var div_1 = child(li);
16934
17756
  let classes;
17757
+ var a = child(div_1);
17758
+ let classes_1;
16935
17759
 
16936
17760
  a.__click = (e) => handleTabClick(get(tab).id, e);
16937
17761
  a.__dblclick = (e) => handleTabDoubleClick(get(tab).id, e);
16938
17762
 
16939
17763
  var span = child(a);
16940
- var span_1 = child(span);
16941
- var node_1 = child(span_1);
17764
+ var node_1 = child(span);
16942
17765
 
16943
17766
  html(node_1, () => get(tab).header);
16944
- reset(span_1);
17767
+ reset(span);
17768
+ reset(a);
17769
+
17770
+ var button = sibling(a, 2);
17771
+ let classes_2;
16945
17772
 
16946
- var span_2 = sibling(span_1, 2);
16947
- let styles;
16948
- var node_2 = child(span_2);
17773
+ button.__click = (e) => handleMarkClick(get(tab).id, e);
16949
17774
 
16950
- IconPin(node_2, {
16951
- get isPinned() {
16952
- return get(isPinned);
17775
+ button.__dblclick = (e) => {
17776
+ e.stopPropagation();
17777
+ };
17778
+
17779
+ var node_2 = child(button);
17780
+
17781
+ IconMark(node_2, {
17782
+ get isMarked() {
17783
+ return get(isMarked);
16953
17784
  }
16954
17785
  });
16955
17786
 
16956
- reset(span_2);
16957
- reset(span);
16958
- reset(a);
17787
+ reset(button);
17788
+ reset(div_1);
16959
17789
  reset(li);
16960
17790
 
16961
17791
  template_effect(() => {
16962
- classes = set_class(a, 1, 'nav-link svelte-1ujqpe3', null, classes, { active: get(isActive) });
17792
+ classes = set_class(div_1, 1, 'cv-tab-wrapper svelte-1ujqpe3', null, classes, { active: get(isActive) });
17793
+ classes_1 = set_class(a, 1, 'cv-tabgroup-link svelte-1ujqpe3', null, classes_1, { active: get(isActive) });
16963
17794
  set_attribute(a, 'href', '#' + get(tab).id);
16964
17795
  set_attribute(a, 'aria-selected', get(isActive));
16965
17796
  set_attribute(a, 'data-tab-id', get(tab).id);
16966
17797
  set_attribute(a, 'data-raw-tab-id', get(tab).rawId);
16967
17798
  set_attribute(a, 'data-group-id', groupId());
16968
- styles = set_style(span_2, '', styles, { display: get(isPinned) ? 'inline-flex' : 'none' });
17799
+ classes_2 = set_class(button, 1, 'cv-tab-marked-icon svelte-1ujqpe3', null, classes_2, { 'is-marked': get(isMarked) });
17800
+ set_attribute(button, 'title', get(isMarked) ? "Unmark this tab" : "Mark this tab");
17801
+ set_attribute(button, 'aria-label', get(isMarked) ? "Unmark this tab" : "Mark this tab");
17802
+ set_attribute(button, 'aria-pressed', !!get(isMarked));
16969
17803
  });
16970
17804
 
16971
17805
  append($$anchor, li);
@@ -16989,14 +17823,15 @@
16989
17823
  append($$anchor, link_1);
16990
17824
  });
16991
17825
 
16992
- var div_1 = sibling(node_3, 2);
16993
- var node_4 = child(div_1);
17826
+ var div_2 = sibling(node_3, 2);
17827
+ var node_4 = child(div_2);
16994
17828
 
16995
17829
  slot(node_4, $$props, 'default', {});
16996
- reset(div_1);
16997
- bind_this(div_1, ($$value) => set(contentWrapper, $$value), () => get(contentWrapper));
17830
+ reset(div_2);
17831
+ bind_this(div_2, ($$value) => set(contentWrapper, $$value), () => get(contentWrapper));
16998
17832
  next(2);
16999
17833
  reset(div);
17834
+ bind_this(div, ($$value) => set(containerEl, $$value), () => get(containerEl));
17000
17835
  append($$anchor, div);
17001
17836
 
17002
17837
  return pop($$exports);
@@ -17007,7 +17842,13 @@
17007
17842
  customElements.define('cv-tabgroup', create_custom_element(
17008
17843
  TabGroup,
17009
17844
  {
17010
- groupId: { attribute: 'group-id', reflect: true, type: 'String' }
17845
+ groupId: { attribute: 'group-id', reflect: true, type: 'String' },
17846
+
17847
+ stabilizeScroll: {
17848
+ attribute: 'stabilize-scroll',
17849
+ reflect: true,
17850
+ type: 'Boolean'
17851
+ }
17011
17852
  },
17012
17853
  ['default'],
17013
17854
  [],