vanilla-breeze 0.2.0 → 0.3.1

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 (138) hide show
  1. package/custom-elements.json +11251 -18739
  2. package/dist/cdn/components/icon-wc.js +2 -2
  3. package/dist/cdn/components/manifest.json +2 -146
  4. package/dist/cdn/components/settings-panel.js +3 -3
  5. package/dist/cdn/components/theme-picker.js +12 -12
  6. package/dist/cdn/packs/journal.effects.css +2 -0
  7. package/dist/cdn/packs/journal.full.css +2 -0
  8. package/dist/cdn/packs/manifest.json +11 -21
  9. package/dist/cdn/packs/ui.full.js +4 -4
  10. package/dist/cdn/themes/8bit.tokens.json +1 -1
  11. package/dist/cdn/themes/alpha1999-dark.tokens.json +1 -1
  12. package/dist/cdn/themes/alpha1999.tokens.json +1 -1
  13. package/dist/cdn/themes/anthropic.tokens.json +1 -1
  14. package/dist/cdn/themes/art-deco-dark.tokens.json +1 -1
  15. package/dist/cdn/themes/art-deco.tokens.json +1 -1
  16. package/dist/cdn/themes/bauhaus-dark.tokens.json +1 -1
  17. package/dist/cdn/themes/bauhaus.tokens.json +1 -1
  18. package/dist/cdn/themes/brutalist-dark.tokens.json +1 -1
  19. package/dist/cdn/themes/brutalist.tokens.json +1 -1
  20. package/dist/cdn/themes/catppuccin-frappe.tokens.json +1 -1
  21. package/dist/cdn/themes/catppuccin-latte-dark.tokens.json +1 -1
  22. package/dist/cdn/themes/catppuccin-latte.tokens.json +1 -1
  23. package/dist/cdn/themes/catppuccin-macchiato.tokens.json +1 -1
  24. package/dist/cdn/themes/catppuccin-mocha.tokens.json +1 -1
  25. package/dist/cdn/themes/classic-dark.tokens.json +1 -1
  26. package/dist/cdn/themes/classic.tokens.json +1 -1
  27. package/dist/cdn/themes/claymorphism-dark.tokens.json +1 -1
  28. package/dist/cdn/themes/claymorphism.tokens.json +1 -1
  29. package/dist/cdn/themes/clinical-dark.tokens.json +1 -1
  30. package/dist/cdn/themes/clinical.tokens.json +1 -1
  31. package/dist/cdn/themes/cottagecore-dark.tokens.json +1 -1
  32. package/dist/cdn/themes/cottagecore.tokens.json +1 -1
  33. package/dist/cdn/themes/cyber.tokens.json +1 -1
  34. package/dist/cdn/themes/dawn-dark.tokens.json +1 -1
  35. package/dist/cdn/themes/dawn.tokens.json +1 -1
  36. package/dist/cdn/themes/dracula.tokens.json +1 -1
  37. package/dist/cdn/themes/dusk.tokens.json +1 -1
  38. package/dist/cdn/themes/editorial-dark.tokens.json +1 -1
  39. package/dist/cdn/themes/editorial.tokens.json +1 -1
  40. package/dist/cdn/themes/financial-dark.tokens.json +1 -1
  41. package/dist/cdn/themes/financial.tokens.json +1 -1
  42. package/dist/cdn/themes/genai.tokens.json +1 -1
  43. package/dist/cdn/themes/glassmorphism-dark.tokens.json +1 -1
  44. package/dist/cdn/themes/glassmorphism.tokens.json +1 -1
  45. package/dist/cdn/themes/government-dark.tokens.json +1 -1
  46. package/dist/cdn/themes/government.tokens.json +1 -1
  47. package/dist/cdn/themes/gruvbox-dark.tokens.json +1 -1
  48. package/dist/cdn/themes/gruvbox.tokens.json +1 -1
  49. package/dist/cdn/themes/high-noon-dark.tokens.json +1 -1
  50. package/dist/cdn/themes/high-noon.tokens.json +1 -1
  51. package/dist/cdn/themes/ibm.tokens.json +1 -1
  52. package/dist/cdn/themes/journal-dark.tokens.json +406 -0
  53. package/dist/cdn/themes/journal.css +2 -0
  54. package/dist/cdn/themes/journal.tokens.json +583 -0
  55. package/dist/cdn/themes/kawaii-dark.tokens.json +1 -1
  56. package/dist/cdn/themes/kawaii.tokens.json +1 -1
  57. package/dist/cdn/themes/magna-dark.tokens.json +1 -1
  58. package/dist/cdn/themes/magna.tokens.json +1 -1
  59. package/dist/cdn/themes/manifest.json +7 -0
  60. package/dist/cdn/themes/mcdonalds.tokens.json +1 -1
  61. package/dist/cdn/themes/midnight.tokens.json +1 -1
  62. package/dist/cdn/themes/minimal-dark.tokens.json +1 -1
  63. package/dist/cdn/themes/minimal.tokens.json +1 -1
  64. package/dist/cdn/themes/modern-dark.tokens.json +1 -1
  65. package/dist/cdn/themes/modern.tokens.json +1 -1
  66. package/dist/cdn/themes/nes-dark.tokens.json +1 -1
  67. package/dist/cdn/themes/nes.tokens.json +1 -1
  68. package/dist/cdn/themes/neumorphism-dark.tokens.json +1 -1
  69. package/dist/cdn/themes/neumorphism.tokens.json +1 -1
  70. package/dist/cdn/themes/nord-dark.tokens.json +1 -1
  71. package/dist/cdn/themes/nord.tokens.json +1 -1
  72. package/dist/cdn/themes/organic-dark.tokens.json +1 -1
  73. package/dist/cdn/themes/organic.tokens.json +1 -1
  74. package/dist/cdn/themes/rose-pine-dark.tokens.json +1 -1
  75. package/dist/cdn/themes/rose-pine.tokens.json +1 -1
  76. package/dist/cdn/themes/rough-dark.tokens.json +1 -1
  77. package/dist/cdn/themes/rough.tokens.json +1 -1
  78. package/dist/cdn/themes/solarized-dark.tokens.json +1 -1
  79. package/dist/cdn/themes/solarized.tokens.json +1 -1
  80. package/dist/cdn/themes/starbucks.tokens.json +1 -1
  81. package/dist/cdn/themes/startup-dark.tokens.json +1 -1
  82. package/dist/cdn/themes/startup.tokens.json +1 -1
  83. package/dist/cdn/themes/super2026-dark.tokens.json +1 -1
  84. package/dist/cdn/themes/super2026.tokens.json +1 -1
  85. package/dist/cdn/themes/swiss-dark.tokens.json +1 -1
  86. package/dist/cdn/themes/swiss.tokens.json +1 -1
  87. package/dist/cdn/themes/terminal.tokens.json +1 -1
  88. package/dist/cdn/themes/tokyo-night-dark.tokens.json +1 -1
  89. package/dist/cdn/themes/tokyo-night.tokens.json +1 -1
  90. package/dist/cdn/themes/vaporwave-dark.tokens.json +1 -1
  91. package/dist/cdn/themes/vaporwave.tokens.json +1 -1
  92. package/dist/cdn/themes/win9x-dark.tokens.json +1 -1
  93. package/dist/cdn/themes/win9x.tokens.json +1 -1
  94. package/dist/cdn/vanilla-breeze-core.js +17 -17
  95. package/dist/cdn/vanilla-breeze-extras.js +36 -222
  96. package/dist/cdn/vanilla-breeze.css +1 -1
  97. package/dist/cdn/vanilla-breeze.js +232 -2608
  98. package/package.json +2 -3
  99. package/dist/cdn/components/accessibility-specimen.js +0 -11
  100. package/dist/cdn/components/adr-wc.js +0 -403
  101. package/dist/cdn/components/breakpoint-specimen.js +0 -26
  102. package/dist/cdn/components/burndown-chart.js +0 -2
  103. package/dist/cdn/components/capacity-plan.js +0 -25
  104. package/dist/cdn/components/color-palette.js +0 -16
  105. package/dist/cdn/components/component-sampler.js +0 -45
  106. package/dist/cdn/components/empathy-map.js +0 -582
  107. package/dist/cdn/components/font-pairer.js +0 -108
  108. package/dist/cdn/components/gantt-chart.js +0 -2
  109. package/dist/cdn/components/gradient-builder.js +0 -52
  110. package/dist/cdn/components/impact-effort.js +0 -2
  111. package/dist/cdn/components/iron-triangle.js +0 -2
  112. package/dist/cdn/components/kanban-board.js +0 -2
  113. package/dist/cdn/components/layout-specimen.js +0 -35
  114. package/dist/cdn/components/motion-specimen.js +0 -21
  115. package/dist/cdn/components/palette-generator.js +0 -15
  116. package/dist/cdn/components/product-roadmap.js +0 -3
  117. package/dist/cdn/components/quadrant-grid.js +0 -3
  118. package/dist/cdn/components/quality-target.js +0 -12
  119. package/dist/cdn/components/requirement-card.js +0 -122
  120. package/dist/cdn/components/review-surface.js +0 -535
  121. package/dist/cdn/components/risk-register.js +0 -25
  122. package/dist/cdn/components/semantic-palette.js +0 -30
  123. package/dist/cdn/components/spacing-specimen.js +0 -6
  124. package/dist/cdn/components/story-map.js +0 -2
  125. package/dist/cdn/components/theme-catalog.js +0 -28
  126. package/dist/cdn/components/theme-export.js +0 -26
  127. package/dist/cdn/components/theme-import.js +0 -44
  128. package/dist/cdn/components/token-specimen.js +0 -26
  129. package/dist/cdn/components/traceability-matrix.js +0 -3
  130. package/dist/cdn/components/type-specimen.js +0 -19
  131. package/dist/cdn/components/user-journey.js +0 -366
  132. package/dist/cdn/components/user-persona.js +0 -402
  133. package/dist/cdn/components/user-story.js +0 -411
  134. package/dist/cdn/components/work-item.js +0 -447
  135. package/dist/cdn/packs/design-system.full.css +0 -2
  136. package/dist/cdn/packs/design-system.full.js +0 -175
  137. package/dist/cdn/packs/ux-planning.full.css +0 -2
  138. package/dist/cdn/packs/ux-planning.full.js +0 -3160
@@ -1,3160 +0,0 @@
1
- var pe=window.matchMedia("(prefers-reduced-motion: reduce)");var St=new Map;function x(c,t,e={}){let r=e.priority??10,s={impl:t,bundle:e.bundle,contract:e.contract,priority:r},a=St.get(c);if(customElements.get(c)){if(!a||a.priority>=r){a&&a.priority===r&&a.impl!==t&&console.warn(`[VB Bundle] Tag <${c}> already registered by "${a.bundle}" (priority ${a.priority}). Skipping "${e.bundle}".`);return}console.warn(`[VB Bundle] Tag <${c}> defined by "${a.bundle}" cannot be replaced (customElements.define is permanent). "${e.bundle}" has higher priority but arrived late.`);return}if(a&&a.priority>=r){a.priority===r&&console.warn(`[VB Bundle] Tag <${c}> already registered by "${a.bundle}". Skipping "${e.bundle}" (first wins at equal priority).`);return}St.set(c,s),customElements.define(c,t)}var C=class extends HTMLElement{#e=[];#t;connectedCallback(){this.hasAttribute("data-upgraded")||this.setup()!==!1&&(this.setAttribute("data-upgraded",""),queueMicrotask(()=>{this.dispatchEvent(new CustomEvent(`${this.localName}:upgraded`,{bubbles:!0}))}))}disconnectedCallback(){for(let t of this.#e)t();this.#e=[],this.removeAttribute("data-upgraded"),this.teardown()}listen(t,e,r,s){t.addEventListener(e,r,s),this.#e.push(()=>t.removeEventListener(e,r,s))}setup(){}teardown(){}setState(t,e){this.#t||(this.#t=this.attachInternals());let r=this.#t.states;try{e?r.add(t):r.delete(t)}catch{let s=`--${t}`;e?r.add(s):r.delete(s)}}_adoptInternals(t){this.#t||(this.#t=t)}};var J=class c extends C{#e=null;#t=null;#r=!1;#i=null;setup(){this.setAttribute("role","list"),this.#r=window.matchMedia("(prefers-reduced-motion: reduce)").matches,this.#o(),this.#n(),this.#f(),this.#s()}teardown(){this.#e&&(this.#e.remove(),this.#e=null),c.#_?.source===this&&(c.#_=null)}get draggableChildren(){return[...this.querySelectorAll(':scope > [draggable="true"]')]}get group(){return this.getAttribute("group")||null}get orientation(){return this.getAttribute("orientation")||"vertical"}get sortedOrder(){return this.draggableChildren.map(t=>t.dataset.id)}#s(){for(let t of this.draggableChildren)t.getAttribute("role")||t.setAttribute("role","listitem"),t.hasAttribute("tabindex")||t.setAttribute("tabindex","0"),t.hasAttribute("aria-grabbed")||t.setAttribute("aria-grabbed","false")}#o(){this.#e=document.createElement("div"),this.#e.setAttribute("role","status"),this.#e.setAttribute("aria-live","polite"),this.#e.setAttribute("aria-atomic","true"),this.#e.style.cssText="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);",this.prepend(this.#e)}#a(t){let e=this.#e;e&&(e.textContent="",requestAnimationFrame(()=>{e.textContent=t}))}#n(){this.listen(this,"pointerdown",t=>{this.#i=t.target}),this.listen(this,"dragstart",this.#c.bind(this)),this.listen(this,"dragover",this.#d.bind(this)),this.listen(this,"dragleave",this.#b.bind(this)),this.listen(this,"drop",this.#m.bind(this)),this.listen(this,"dragend",this.#u.bind(this))}#c(t){let e=t.target.closest('[draggable="true"]');if(!e||e.parentElement!==this||this.hasAttribute("disabled"))return;let r=e.querySelector("[data-drag-handle]");if(r&&!r.contains(this.#i)){t.preventDefault();return}e.setAttribute("data-dragging",""),t.dataTransfer.effectAllowed="move",t.dataTransfer.setData("text/plain",e.dataset.id||""),t.dataTransfer.setData("application/x-drag-surface-group",this.group||"");let s=this.#g(e);c.#_={item:e,source:this,originalIndex:s},this.dispatchEvent(new CustomEvent("drag-surface:reorder-start",{bubbles:!0}))}#d(t){let e=c.#_;if(!e||(this.group||e.source.group)&&this.group!==e.source.group)return;t.preventDefault(),t.dataTransfer.dropEffect="move",this.setAttribute("data-drag-over","");let r=this.orientation==="horizontal"?t.clientX:t.clientY;this.#w(r)}#b(t){t.relatedTarget&&!this.contains(t.relatedTarget)&&(this.removeAttribute("data-drag-over"),this.#A())}#m(t){t.preventDefault(),this.removeAttribute("data-drag-over"),this.#A();let e=c.#_;if(!e)return;let{item:r,source:s,originalIndex:a}=e,i=this.orientation==="horizontal"?t.clientX:t.clientY,o=this.#k(i);if(s===this){this.#p(r,o),this.#x();let n=this.#g(r);this.#l(r),this.dispatchEvent(new CustomEvent("drag-surface:reorder",{bubbles:!0,detail:{item:r,itemId:r.dataset.id,oldIndex:a,newIndex:n,order:this.sortedOrder}}))}else this.#p(r,o),this.#x(),s.#x(),this.#l(r),this.dispatchEvent(new CustomEvent("drag-surface:transfer",{bubbles:!0,detail:{item:r,itemId:r.dataset.id,fromSurface:s,toSurface:this,newIndex:this.#g(r),fromOrder:s.sortedOrder,toOrder:this.sortedOrder}}))}#u(){let t=c.#_;t?.item&&t.item.removeAttribute("data-dragging"),this.removeAttribute("data-drag-over"),this.#A(),c.#_=null,this.dispatchEvent(new CustomEvent("drag-surface:reorder-end",{bubbles:!0}))}#f(){this.listen(this,"keydown",this.#v.bind(this))}#v(t){let e=t.target.closest('[draggable="true"]');if(!e||e.parentElement!==this||this.hasAttribute("disabled"))return;let r=e.getAttribute("aria-grabbed")==="true",s=this.orientation==="horizontal",a=s?"ArrowLeft":"ArrowUp",i=s?"ArrowRight":"ArrowDown";if(t.key===" "||t.key==="Enter"){if(t.preventDefault(),r){e.setAttribute("aria-grabbed","false"),this.removeAttribute("data-reorder-mode"),this.#x(),this.#l(e);let l=this.#g(e),d=this.draggableChildren;this.#a(`${this.#y(e)}, dropped at position ${l+1} of ${d.length}`),this.dispatchEvent(new CustomEvent("drag-surface:reorder",{bubbles:!0,detail:{item:e,itemId:e.dataset.id,oldIndex:this.#t,newIndex:l,order:this.sortedOrder}})),this.dispatchEvent(new CustomEvent("drag-surface:reorder-end",{bubbles:!0})),this.#t=null}else{this.#t=this.#g(e),e.setAttribute("aria-grabbed","true"),this.setAttribute("data-reorder-mode","");let l=this.draggableChildren;this.#a(`${this.#y(e)}, grabbed. Position ${this.#t+1} of ${l.length}. Use arrow keys to move, Enter to drop, Escape to cancel.`),this.dispatchEvent(new CustomEvent("drag-surface:reorder-start",{bubbles:!0}))}return}if(!r&&(t.key===a||t.key===i)){t.preventDefault();let l=this.draggableChildren,d=l.indexOf(e),p=t.key===a?Math.max(0,d-1):Math.min(l.length-1,d+1);p!==d&&l[p].focus();return}if(r&&(t.key===a||t.key===i)){t.preventDefault();let l=this.draggableChildren,d=l.indexOf(e),p=t.key===a?Math.max(0,d-1):Math.min(l.length-1,d+1);p!==d&&(this.#p(e,p),e.focus(),this.#a(`Position ${p+1} of ${l.length}`));return}let o=s?"ArrowUp":"ArrowLeft",n=s?"ArrowDown":"ArrowRight";if(r&&(t.key===o||t.key===n)){if(t.preventDefault(),!this.group)return;let l=t.key===n?1:-1,d=this.#h(l);if(!d)return;d.appendChild(e),d.#x(),this.#x(),d.#l(e),e.focus();let p=d.getAttribute("aria-label")||"next surface";d.#a(`Moved to ${p}`),d.dispatchEvent(new CustomEvent("drag-surface:transfer",{bubbles:!0,detail:{item:e,itemId:e.dataset.id,fromSurface:this,toSurface:d,newIndex:d.draggableChildren.indexOf(e),fromOrder:this.sortedOrder,toOrder:d.sortedOrder}})),this.removeAttribute("data-reorder-mode"),d.setAttribute("data-reorder-mode",""),this.#t=null;return}if(r&&t.key==="Escape"){t.preventDefault(),e.setAttribute("aria-grabbed","false"),this.removeAttribute("data-reorder-mode"),this.#t!=null&&(this.#p(e,this.#t),e.focus()),this.#a("Reorder cancelled"),this.dispatchEvent(new CustomEvent("drag-surface:reorder-end",{bubbles:!0})),this.#t=null;return}!r&&t.key==="Escape"&&(t.preventDefault(),e.blur())}#l(t){t.setAttribute("data-just-dropped",""),t.addEventListener("animationend",()=>{t.removeAttribute("data-just-dropped")},{once:!0}),setTimeout(()=>t.removeAttribute("data-just-dropped"),500)}#h(t){if(!this.group)return null;let e=[...document.querySelectorAll(`drag-surface[group="${this.group}"]`)];if(e.length<2)return null;e.sort((a,i)=>{let o=a.getBoundingClientRect(),n=i.getBoundingClientRect();return o.left-n.left||o.top-n.top});let r=e.indexOf(this);return e[r+t]||null}#y(t){return t.dataset.id||t.textContent.trim().slice(0,40)}#g(t){return this.draggableChildren.indexOf(t)}#p(t,e){let s=this.draggableChildren.filter(a=>a!==t)[e]||null;s?this.insertBefore(t,s):this.appendChild(t)}#x(){this.draggableChildren.forEach((t,e)=>{t.dataset.sortOrder=String(e+1)})}#k(t){let e=this.orientation==="horizontal",r=this.draggableChildren.filter(s=>!s.hasAttribute("data-dragging"));for(let s=0;s<r.length;s++){let a=r[s].getBoundingClientRect(),i=e?a.left+a.width/2:a.top+a.height/2;if(t<i)return s}return r.length}#w(t){this.#A();let e=this.orientation==="horizontal",r=this.draggableChildren.filter(s=>!s.hasAttribute("data-dragging"));for(let s=0;s<r.length;s++){let a=r[s].getBoundingClientRect(),i=e?a.left+a.width/2:a.top+a.height/2;if(t<i){r[s].setAttribute("data-drop-target","before");return}}r.length>0&&r[r.length-1].setAttribute("data-drop-target","after")}#A(){for(let t of this.querySelectorAll("[data-drop-target]"))t.removeAttribute("data-drop-target")}static#_=null};x("drag-surface",J);var $t=`
2
- :host {
3
- display: block;
4
- font-family: var(--user-persona-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
5
- --_bg: var(--user-persona-bg, var(--color-surface, #ffffff));
6
- --_text: var(--user-persona-text, var(--color-text, #1a1a1a));
7
- --_border: var(--user-persona-border, var(--color-border, #e0e0e0));
8
- --_muted: var(--user-persona-muted, var(--color-text-muted, #666));
9
- --_accent: var(--user-persona-accent, var(--color-interactive, #0066cc));
10
- --_card-bg: var(--user-persona-card-bg, var(--color-surface-raised, #f8f9fa));
11
- --_radius: var(--user-persona-radius, var(--radius-xl, 1rem));
12
- --_avatar-size: var(--user-persona-avatar-size, 80px);
13
- --_goals: var(--user-persona-goals, #22c55e);
14
- --_frustrations: var(--user-persona-frustrations, #ef4444);
15
- --_behaviors: var(--user-persona-behaviors, #8b5cf6);
16
- --_stories: var(--user-persona-stories, #3b82f6);
17
- --_shadow: var(--user-persona-shadow, var(--shadow-md));
18
- --_space-2xs: var(--user-persona-space-2xs, var(--size-2xs, 0.25rem));
19
- --_space-xs: var(--user-persona-space-xs, var(--size-xs, 0.5rem));
20
- --_space-s: var(--user-persona-space-s, var(--size-s, 0.75rem));
21
- --_space-m: var(--user-persona-space-m, var(--size-m, 1rem));
22
- --_space-l: var(--user-persona-space-l, var(--size-l, 1.5rem));
23
- --_font-xs: var(--user-persona-font-xs, var(--font-size-xs, 0.75rem));
24
- --_font-sm: var(--user-persona-font-sm, var(--font-size-sm, 0.875rem));
25
- --_font-md: var(--user-persona-font-md, var(--font-size-md, 1rem));
26
- --_font-2xl: var(--user-persona-font-2xl, var(--font-size-2xl, 1.5rem));
27
- --_radius-m: var(--user-persona-radius-m, var(--radius-m, 0.5rem));
28
- --_radius-l: var(--user-persona-radius-l, var(--radius-l, 0.75rem));
29
- }
30
-
31
- .persona-card {
32
- background: var(--_bg);
33
- border: 1px solid var(--_border);
34
- border-radius: var(--_radius);
35
- overflow: hidden;
36
- box-shadow: var(--_shadow);
37
- }
38
-
39
- .persona-header {
40
- display: flex;
41
- align-items: center;
42
- gap: var(--_space-l);
43
- padding: var(--_space-l);
44
- background: var(--_card-bg);
45
- border-bottom: 1px solid var(--_border);
46
- }
47
-
48
- :host([compact]) .persona-header {
49
- padding: var(--_space-m);
50
- gap: var(--_space-m);
51
- }
52
-
53
- .avatar {
54
- width: var(--_avatar-size);
55
- height: var(--_avatar-size);
56
- border-radius: 50%;
57
- display: flex;
58
- align-items: center;
59
- justify-content: center;
60
- font-size: 28px;
61
- font-weight: 600;
62
- color: white;
63
- flex-shrink: 0;
64
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
65
- }
66
-
67
- :host([compact]) .avatar {
68
- width: 56px;
69
- height: 56px;
70
- font-size: 20px;
71
- }
72
-
73
- .header-info {
74
- flex: 1;
75
- min-width: 0;
76
- }
77
-
78
- .persona-name {
79
- font-size: var(--_font-2xl);
80
- font-weight: 700;
81
- color: var(--_text);
82
- margin: 0 0 var(--_space-2xs) 0;
83
- }
84
-
85
- :host([compact]) .persona-name {
86
- font-size: 18px;
87
- }
88
-
89
- .persona-role {
90
- font-size: var(--_font-md);
91
- color: var(--_accent);
92
- font-weight: 500;
93
- margin: 0;
94
- }
95
-
96
- :host([compact]) .persona-role {
97
- font-size: var(--_font-sm);
98
- }
99
-
100
- .persona-meta {
101
- display: flex;
102
- gap: var(--_space-m);
103
- margin-top: var(--_space-xs);
104
- flex-wrap: wrap;
105
- }
106
-
107
- .meta-item {
108
- display: flex;
109
- align-items: center;
110
- gap: 6px;
111
- font-size: 13px;
112
- color: var(--_muted);
113
- }
114
-
115
- .meta-item svg {
116
- width: 14px;
117
- height: 14px;
118
- fill: currentColor;
119
- opacity: 0.7;
120
- }
121
-
122
- .persona-quote {
123
- padding: 20px var(--_space-l);
124
- background: var(--_card-bg);
125
- border-bottom: 1px solid var(--_border);
126
- position: relative;
127
- }
128
-
129
- :host([compact]) .persona-quote {
130
- padding: var(--_space-m);
131
- }
132
-
133
- .quote-mark {
134
- position: absolute;
135
- top: 12px;
136
- left: 16px;
137
- font-size: 48px;
138
- line-height: 1;
139
- color: var(--_accent);
140
- opacity: 0.2;
141
- font-family: Georgia, serif;
142
- }
143
-
144
- .quote-text {
145
- font-size: var(--_font-md);
146
- font-style: italic;
147
- color: var(--_text);
148
- line-height: 1.6;
149
- margin: 0;
150
- padding-left: var(--_space-l);
151
- }
152
-
153
- :host([compact]) .quote-text {
154
- font-size: var(--_font-sm);
155
- }
156
-
157
- .persona-body {
158
- padding: var(--_space-l);
159
- display: grid;
160
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
161
- gap: var(--_space-l);
162
- }
163
-
164
- :host([compact]) .persona-body {
165
- padding: var(--_space-m);
166
- gap: var(--_space-m);
167
- }
168
-
169
- .section {
170
- background: var(--_card-bg);
171
- border-radius: var(--_radius-l);
172
- padding: var(--_space-m);
173
- }
174
-
175
- .section-header {
176
- display: flex;
177
- align-items: center;
178
- gap: var(--_space-xs);
179
- margin-bottom: var(--_space-s);
180
- }
181
-
182
- .section-icon {
183
- width: 28px;
184
- height: 28px;
185
- border-radius: var(--_radius-m);
186
- display: flex;
187
- align-items: center;
188
- justify-content: center;
189
- }
190
-
191
- .section-icon svg {
192
- width: 16px;
193
- height: 16px;
194
- fill: white;
195
- }
196
-
197
- .section-icon.bio { background: var(--_accent); }
198
- .section-icon.goals { background: var(--_goals); }
199
- .section-icon.frustrations { background: var(--_frustrations); }
200
- .section-icon.behaviors { background: var(--_behaviors); }
201
- .section-icon.stories { background: var(--_stories); }
202
-
203
- /* Stories section \u2014 auto-rendered list of related <user-story> elements */
204
- .section-count {
205
- margin-inline-start: var(--_space-2xs);
206
- padding: 0.05em 0.5ch;
207
- border-radius: 999px;
208
- background: var(--color-surface-raised, oklch(95% 0 0));
209
- color: var(--color-text-muted);
210
- font-size: 0.75em;
211
- font-weight: 600;
212
- }
213
- .story-list {
214
- list-style: none;
215
- margin: 0;
216
- padding: 0;
217
- display: grid;
218
- gap: var(--_space-2xs);
219
- }
220
- .story-item {
221
- display: flex;
222
- align-items: center;
223
- gap: var(--_space-s);
224
- padding-block: var(--_space-2xs);
225
- border-block-end: 1px solid var(--color-border-muted, var(--color-border, #e5e7eb));
226
- }
227
- .story-item:last-child { border-block-end: none; }
228
- .story-item a {
229
- color: var(--color-interactive, currentColor);
230
- text-decoration: none;
231
- flex: 1;
232
- }
233
- .story-item a:hover { text-decoration: underline; }
234
- .story-meta {
235
- font-size: var(--_font-xs);
236
- color: var(--color-text-muted);
237
- text-transform: uppercase;
238
- letter-spacing: 0.05em;
239
- padding: 0 0.5ch;
240
- border: 1px solid var(--color-border-muted, var(--color-border, #e5e7eb));
241
- border-radius: var(--_radius-m);
242
- }
243
- .empty-stories {
244
- margin: 0;
245
- color: var(--color-text-muted);
246
- font-style: italic;
247
- }
248
-
249
- .section-title {
250
- font-size: var(--_font-sm);
251
- font-weight: 600;
252
- color: var(--_text);
253
- text-transform: uppercase;
254
- letter-spacing: 0.5px;
255
- }
256
-
257
- .section-content {
258
- color: var(--_text);
259
- font-size: var(--_font-sm);
260
- line-height: 1.6;
261
- }
262
-
263
- .section-content ::slotted(ul),
264
- .section-content ::slotted(ol) {
265
- margin: 0;
266
- padding-left: 20px;
267
- }
268
-
269
- .section-content ::slotted(li) {
270
- margin-bottom: var(--_space-xs);
271
- }
272
-
273
- .section-content ::slotted(p) {
274
- margin: 0;
275
- }
276
-
277
- @media (max-width: 600px) {
278
- .persona-header {
279
- flex-direction: column;
280
- text-align: center;
281
- }
282
-
283
- .persona-meta {
284
- justify-content: center;
285
- }
286
-
287
- .persona-body {
288
- grid-template-columns: 1fr;
289
- }
290
- }
291
-
292
- @media (prefers-reduced-motion: reduce) {
293
- * {
294
- transition: none !important;
295
- }
296
- }
297
- `;function h(c){return String(c).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function z(c){return c.split(" ").map(t=>t[0]).join("").toUpperCase().slice(0,2)}function L(c){let t=0;for(let r=0;r<c.length;r++)t=c.charCodeAt(r)+((t<<5)-t);return`hsl(${(t%360+360)%360}, 65%, 55%)`}function A(c){return`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${c}</svg>`}var k={user:'<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',pencil:'<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/>',check:'<path d="M20 6 9 17l-5-5"/>',target:'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/>',alertTriangle:'<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>',messageCircle:'<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"/>',lightbulb:'<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/>',wrench:'<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/>',heart:'<path d="M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5"/>',mapPin:'<path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/>',checkCircle:'<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',send:'<path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/>'},Z={says:{label:"Says",icon:k.messageCircle,color:"#3b82f6"},thinks:{label:"Thinks",icon:k.lightbulb,color:"#8b5cf6"},does:{label:"Does",icon:k.wrench,color:"#f59e0b"},feels:{label:"Feels",icon:k.heart,color:"#ef4444"}},q={delighted:{emoji:"\u{1F604}",score:.95,color:"#16a34a"},satisfied:{emoji:"\u{1F60A}",score:.8,color:"#22c55e"},hopeful:{emoji:"\u{1F642}",score:.68,color:"#84cc16"},curious:{emoji:"\u{1F914}",score:.55,color:"#eab308"},neutral:{emoji:"\u{1F610}",score:.5,color:"#94a3b8"},uncertain:{emoji:"\u{1F615}",score:.4,color:"#f97316"},confused:{emoji:"\u{1F635}",score:.3,color:"#fb923c"},frustrated:{emoji:"\u{1F624}",score:.18,color:"#ef4444"},angry:{emoji:"\u{1F620}",score:.05,color:"#dc2626"}};var Ft="https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait",B=[32,64,128,256,512];function Bt(c){let t=0;for(let e=0;e<c.length;e++)t=c.charCodeAt(e)+((t<<5)-t);return t}function Ht(c){let t=B[0],e=Math.abs(c-t);for(let r=1;r<B.length;r++){let s=Math.abs(c-B[r]);s<e&&(t=B[r],e=s)}return t}function qt(c,t=128){let e=Bt(String(c)),r=(e%100+100)%100,s=(e>>>16&1)===0?"female":"male",a=Ht(t);return`${Ft}/${s}/${a}/${r}.jpg`}function tt(c){let t=0;for(let e=0;e<c.length;e++)t=c.charCodeAt(e)+((t<<5)-t);return t}var Ut=["Sarah Chen","Marcus Johnson","Aisha Patel","James O'Brien","Yuki Tanaka","Elena Rodriguez","David Kim","Fatima Al-Hassan","Lucas Silva","Priya Sharma","Noah Williams","Mei Lin","Carlos Mendez","Amara Osei","Henrik Larsson","Zara Ahmed"],Vt=["Product Manager","UX Designer","Frontend Developer","Data Analyst","Marketing Lead","QA Engineer","DevOps Lead","Content Strategist","Startup Founder","IT Director","Customer Success Lead","Research Scientist"],Qt=["San Francisco, CA","Austin, TX","London, UK","Toronto, CA","Berlin, DE","Tokyo, JP","Sydney, AU","S\xE3o Paulo, BR"],Xt=["I need tools that help me stay organized without slowing me down.","The dashboard is where I live \u2014 it has to be fast and reliable.","I want to understand the data, not fight the interface.","If it takes more than two clicks, I\u2019ll find another way.","Collaboration shouldn\u2019t mean endless notification noise.","I just want it to work the way I expect it to.","Give me the big picture first, then let me drill into details.","Accessibility isn\u2019t a nice-to-have \u2014 it\u2019s how I use the web."],Yt=["Streamline daily workflows","Reduce context-switching","Stay aligned with the team","Make data-driven decisions quickly","Ship features on a predictable cadence","Automate repetitive tasks","Improve onboarding experience","Keep documentation up to date"],Kt=["Too many disconnected tools","Slow page loads break focus","Unclear ownership of tasks","Settings that reset unexpectedly","Notifications that bury important updates","Poor mobile experience","Inconsistent design across features","No offline support"],Wt=["Checks dashboards every morning","Prefers keyboard shortcuts over mouse","Skims docs, reads deeply only when stuck","Shares screenshots in Slack","Batches email to twice a day","Tests features in incognito first","Bookmarks frequently used reports","Uses dark mode exclusively"],et=class extends HTMLElement{static get observedAttributes(){return["role","age","location","avatar","compact","src","data-list-stories","id"]}#e=new Map;#t=null;constructor(){super(),this.attachShadow({mode:"open"})}relatedStories(){if(!this.id)return[];let t=this.getRootNode(),e=t.querySelectorAll?t:document;return Array.from(e.querySelectorAll(`user-story[persona-id="${Gt(this.id)}"]`))}#r(){for(let t of[...this.children]){let e=t.getAttribute("slot");e&&!this.getAttribute(e)&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}get data(){return{name:this.personaName,role:this.personaRole||void 0,age:this.age||void 0,location:this.location||void 0,avatar:this.avatar||void 0,quote:this.quote||void 0,bio:this.#e.get("bio")||void 0,goals:this.#e.get("goals")||void 0,frustrations:this.#e.get("frustrations")||void 0,behaviors:this.#e.get("behaviors")||void 0}}set data(t){!t||typeof t!="object"||(this._applyData(t),this.shadowRoot&&this.#n(),this.dispatchEvent(new CustomEvent("user-persona:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0})))}_applyData(t){for(let e of["role","age","location","avatar"])t[e]&&this.setAttribute(e,String(t[e]));if(t.name&&!this.querySelector('[slot="name"]')){let e=document.createElement("h2");e.slot="name",e.textContent=String(t.name),this.appendChild(e)}if(t.quote&&!this.querySelector('[slot="quote"]')){let e=document.createElement("p");e.slot="quote",e.textContent=String(t.quote),this.appendChild(e)}for(let e of["bio","goals","frustrations","behaviors"])t[e]&&this.#e.set(e,String(t[e]))}async _loadSrc(t){if(t)try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();this._applyData(r),this.#n()}catch(e){console.warn(`[user-persona] Failed to load src="${t}":`,e)}}connectedCallback(){this.#r(),this.hasAttribute("data-mock")?this.#a():this.hasAttribute("src")&&this._loadSrc(this.getAttribute("src")),this.#n(),this.#i(),this.setAttribute("data-upgraded",""),this.dispatchEvent(new CustomEvent("persona-ready",{bubbles:!0,composed:!0,detail:{name:this.personaName,role:this.personaRole}}))}disconnectedCallback(){this.removeAttribute("data-upgraded"),this.#t?.disconnect(),this.#t=null}#i(){if(!this.hasAttribute("data-list-stories")||!this.id){this.#t?.disconnect(),this.#t=null;return}this.#t||(this.#t=new MutationObserver(()=>this.#s()),this.#t.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["persona-id"]}))}#s(){if(!this.shadowRoot)return;let t=this.shadowRoot.querySelector("[data-stories-section]");t&&(t.outerHTML=this.#o())}#o(){if(!this.hasAttribute("data-list-stories")||!this.id)return"";let t=this.relatedStories();return`
298
- <section class="section" part="section-stories" data-stories-section>
299
- <div class="section-header">
300
- <div class="section-icon stories" aria-hidden="true">
301
- <svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
302
- </div>
303
- <span class="section-title">Stories <span class="section-count">${t.length}</span></span>
304
- </div>
305
- <div class="section-content">
306
- ${t.length===0?'<p class="empty-stories">No user stories reference this persona yet.</p>':`<ul class="story-list">${t.map(e=>{let r=e.id||e.getAttribute("story-id")||"",s=e.querySelector('[slot="action"]')?.textContent?.trim()||e.getAttribute("action")||e.id||"untitled",a=e.getAttribute("priority")||"",i=e.getAttribute("status")||"";return`<li class="story-item" data-priority="${h(a)}" data-status="${h(i)}">${r?`<a href="#${h(r)}">${h(s)}</a>`:`<span>${h(s)}</span>`}${a?`<span class="story-meta">${h(a)}</span>`:""}${i?`<span class="story-meta">${h(i)}</span>`:""}</li>`}).join("")}</ul>`}
307
- </div>
308
- </section>
309
- `}attributeChangedCallback(t,e,r){if(!(e===r||!this.shadowRoot)){if(t==="src"&&this.isConnected){this._loadSrc(r);return}(t==="data-list-stories"||t==="id")&&this.#i(),this.#n()}}get personaName(){return this.querySelector('[slot="name"]')?.textContent?.trim()||this.#e.get("name")||"Unnamed Persona"}get personaRole(){return this.getAttribute("role")||""}get age(){return this.getAttribute("age")||""}get location(){return this.getAttribute("location")||""}get avatar(){return this.getAttribute("avatar")||""}get quote(){return this.querySelector('[slot="quote"]')?.textContent?.trim()||this.#e.get("quote")||""}get compact(){return this.hasAttribute("compact")}#a(){let t=this.dataset.seed||this.dataset.mock||String(Date.now()),e=a=>a[(tt(t+a.length)%a.length+a.length)%a.length],r=(a,i)=>{let o=[];for(let n=0;n<i;n++)o.push(a[(tt(t+n+a.length)%a.length+a.length)%a.length]);return[...new Set(o)]};if(!this.querySelector('[slot="name"]')){let a=document.createElement("h2");a.slot="name",a.textContent=e(Ut),this.appendChild(a)}if(this.getAttribute("role")||this.setAttribute("role",e(Vt)),this.getAttribute("age")||this.setAttribute("age",String(25+(tt(t)%30+30)%30)),this.getAttribute("location")||this.setAttribute("location",e(Qt)),!this.getAttribute("avatar")){let a=this.querySelector('[slot="name"]')?.textContent?.trim()||"Persona";this.setAttribute("avatar",qt(a,256))}if(!this.querySelector('[slot="quote"]')){let a=document.createElement("p");a.slot="quote",a.textContent=e(Xt),this.appendChild(a)}let s=(a,i)=>{if(this.querySelector(`[slot="${a}"]`))return;let o=document.createElement("ul");o.setAttribute("slot",a);for(let n of i){let l=document.createElement("li");l.textContent=n,o.appendChild(l)}this.appendChild(o)};s("goals",r(Yt,3)),s("frustrations",r(Kt,3)),s("behaviors",r(Wt,3))}#n(){let t=this.personaName,e=this.personaRole,r=this.age,s=this.location,a=this.avatar,i=this.quote,o=L(t),n=a?`background:url(${h(a)}) center/cover`:`background:${o}`;this.shadowRoot.innerHTML=`
310
- <style>${$t}</style>
311
-
312
- <article class="persona-card" part="card" role="article"
313
- aria-label="User persona: ${h(t)}">
314
-
315
- <header class="persona-header" part="header">
316
- <div class="avatar" part="avatar" style="${n}"
317
- role="img" aria-label="Avatar for ${h(t)}">
318
- ${a?"":h(z(t))}
319
- </div>
320
- <div class="header-info">
321
- <div class="persona-name-wrap" part="name">
322
- <slot name="name"><h2 class="persona-name-fallback">${h(t)}</h2></slot>
323
- </div>
324
- ${e?`<p class="persona-role" part="role">${h(e)}</p>`:""}
325
- <div class="persona-meta" part="meta">
326
- ${r?`
327
- <span class="meta-item">
328
- <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></svg>
329
- ${h(r)} years old
330
- </span>
331
- `:""}
332
- ${s?`
333
- <span class="meta-item">
334
- <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
335
- ${h(s)}
336
- </span>
337
- `:""}
338
- </div>
339
- </div>
340
- </header>
341
-
342
- ${i||this.querySelector('[slot="quote"]')?`
343
- <div class="persona-quote" part="quote">
344
- <span class="quote-mark" aria-hidden="true">&ldquo;</span>
345
- <div class="quote-text-wrap"><slot name="quote"><p class="quote-text">${h(i)}</p></slot></div>
346
- </div>
347
- `:""}
348
-
349
- <div class="persona-body" part="body">
350
- <div class="section" part="section-bio">
351
- <div class="section-header">
352
- <div class="section-icon bio" aria-hidden="true">
353
- <svg viewBox="0 0 24 24"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
354
- </div>
355
- <span class="section-title">Background</span>
356
- </div>
357
- <div class="section-content">
358
- <slot name="bio">No background information provided.</slot>
359
- </div>
360
- </div>
361
-
362
- <div class="section" part="section-goals">
363
- <div class="section-header">
364
- <div class="section-icon goals" aria-hidden="true">
365
- <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
366
- </div>
367
- <span class="section-title">Goals</span>
368
- </div>
369
- <div class="section-content">
370
- <slot name="goals">No goals specified.</slot>
371
- </div>
372
- </div>
373
-
374
- <div class="section" part="section-frustrations">
375
- <div class="section-header">
376
- <div class="section-icon frustrations" aria-hidden="true">
377
- <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>
378
- </div>
379
- <span class="section-title">Frustrations</span>
380
- </div>
381
- <div class="section-content">
382
- <slot name="frustrations">No frustrations listed.</slot>
383
- </div>
384
- </div>
385
-
386
- <div class="section" part="section-behaviors">
387
- <div class="section-header">
388
- <div class="section-icon behaviors" aria-hidden="true">
389
- <svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/></svg>
390
- </div>
391
- <span class="section-title">Behaviors</span>
392
- </div>
393
- <div class="section-content">
394
- <slot name="behaviors">No behaviors documented.</slot>
395
- </div>
396
- </div>
397
-
398
- ${this.#o()}
399
- </div>
400
- </article>
401
- `}};function Gt(c){return typeof CSS<"u"&&CSS.escape?CSS.escape(String(c)):String(c).replace(/["\\]/g,"\\$&")}x("user-persona",et);var rt=`
402
- :host {
403
- --_bg: var(--user-story-bg, var(--color-surface, #ffffff));
404
- --_text: var(--user-story-text, var(--color-text, #1a1a1a));
405
- --_muted: var(--user-story-muted, var(--color-text-muted, #666));
406
- --_border: var(--user-story-border, var(--color-border, #e0e0e0));
407
- --_accent: var(--user-story-accent, var(--color-interactive, #0066cc));
408
- --_card-bg: var(--user-story-card-bg, var(--color-surface-raised, #f8f9fa));
409
- --_highlight: var(--user-story-highlight, color-mix(in srgb, var(--_accent) 8%, transparent));
410
- --_radius: var(--user-story-radius, var(--radius-l, 0.75rem));
411
- --_shadow: var(--user-story-shadow, var(--shadow-sm));
412
- --_shadow-hover: var(--user-story-shadow-hover, var(--shadow-md));
413
- --_duration: var(--user-story-duration, var(--duration-normal, 200ms));
414
- --_ease: var(--user-story-ease, var(--ease-default, ease));
415
- --_space-xs: var(--user-story-space-xs, var(--size-xs, 0.5rem));
416
- --_space-s: var(--user-story-space-s, var(--size-s, 0.75rem));
417
- --_space-m: var(--user-story-space-m, var(--size-m, 1rem));
418
- --_font-xs: var(--user-story-font-xs, var(--font-size-xs, 0.75rem));
419
- --_font-sm: var(--user-story-font-sm, var(--font-size-sm, 0.875rem));
420
- --_font-md: var(--user-story-font-md, var(--font-size-md, 1rem));
421
- --_font-lg: var(--user-story-font-lg, var(--font-size-lg, 1.125rem));
422
- --_font-mono: var(--user-story-font-mono, var(--font-mono, ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace));
423
- --_radius-s: var(--user-story-radius-s, var(--radius-s, 0.25rem));
424
- --_radius-full: var(--user-story-radius-full, var(--radius-full, 9999px));
425
-
426
- display: block;
427
- font-family: var(--user-story-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
428
- }
429
-
430
- .story-card {
431
- background: var(--_bg);
432
- border: 1px solid var(--_border);
433
- border-radius: var(--_radius);
434
- overflow: hidden;
435
- box-shadow: var(--_shadow);
436
- transition: box-shadow var(--_duration) var(--_ease), transform var(--_duration) var(--_ease);
437
- }
438
-
439
- .story-card:hover {
440
- box-shadow: var(--_shadow-hover);
441
- }
442
-
443
- .story-header {
444
- display: flex;
445
- align-items: center;
446
- justify-content: space-between;
447
- padding: var(--_space-s) var(--_space-m);
448
- background: var(--_card-bg);
449
- border-bottom: 1px solid var(--_border);
450
- gap: var(--_space-s);
451
- flex-wrap: wrap;
452
- }
453
-
454
- .story-meta {
455
- display: flex;
456
- align-items: center;
457
- gap: var(--_space-xs);
458
- flex-wrap: wrap;
459
- }
460
-
461
- .story-id {
462
- font-size: var(--_font-xs);
463
- font-weight: 600;
464
- color: var(--_muted);
465
- font-family: var(--_font-mono);
466
- }
467
-
468
- .epic-badge {
469
- font-size: 11px;
470
- padding: 3px 8px;
471
- border-radius: var(--_radius-s);
472
- background: var(--_highlight);
473
- color: var(--_accent);
474
- font-weight: 500;
475
- }
476
-
477
- .story-badges {
478
- display: flex;
479
- align-items: center;
480
- gap: var(--_space-xs);
481
- }
482
-
483
- .priority-badge,
484
- .status-badge {
485
- font-size: 11px;
486
- padding: 4px 10px;
487
- border-radius: var(--_radius-full);
488
- font-weight: 600;
489
- text-transform: uppercase;
490
- letter-spacing: 0.3px;
491
- }
492
-
493
- .points-badge {
494
- width: 28px;
495
- height: 28px;
496
- border-radius: var(--_radius-full);
497
- background: var(--_accent);
498
- color: white;
499
- font-size: var(--_font-xs);
500
- font-weight: 700;
501
- display: flex;
502
- align-items: center;
503
- justify-content: center;
504
- }
505
-
506
- .story-body {
507
- padding: 20px;
508
- }
509
-
510
- :host([compact]) .story-body {
511
- padding: var(--_space-m);
512
- }
513
-
514
- .story-statement {
515
- font-size: var(--_font-lg);
516
- line-height: 1.6;
517
- color: var(--_text);
518
- margin: 0;
519
- }
520
-
521
- :host([compact]) .story-statement {
522
- font-size: 15px;
523
- }
524
-
525
- .keyword {
526
- font-weight: 600;
527
- color: var(--_accent);
528
- }
529
-
530
- .persona-text {
531
- background: var(--_highlight);
532
- padding: 2px 6px;
533
- border-radius: var(--_radius-s);
534
- font-weight: 500;
535
- }
536
-
537
- .persona-text--link {
538
- display: inline-flex;
539
- align-items: center;
540
- gap: 3px;
541
- color: var(--_accent);
542
- text-decoration: none;
543
- }
544
-
545
- .persona-text--link svg {
546
- width: 13px;
547
- height: 13px;
548
- flex-shrink: 0;
549
- }
550
-
551
- .persona-text--link:hover {
552
- text-decoration: underline;
553
- }
554
-
555
- .action-text {
556
- font-weight: 500;
557
- }
558
-
559
- .benefit-text {
560
- font-style: italic;
561
- color: var(--_muted);
562
- }
563
-
564
- .story-sections {
565
- border-top: 1px solid var(--_border);
566
- }
567
-
568
- .section {
569
- padding: 16px 20px;
570
- border-bottom: 1px solid var(--_border);
571
- }
572
-
573
- .section:last-child {
574
- border-bottom: none;
575
- }
576
-
577
- .section-header {
578
- display: flex;
579
- align-items: center;
580
- gap: var(--_space-xs);
581
- margin-bottom: var(--_space-s);
582
- }
583
-
584
- .section-icon {
585
- width: 24px;
586
- height: 24px;
587
- border-radius: 6px;
588
- display: flex;
589
- align-items: center;
590
- justify-content: center;
591
- background: var(--_accent);
592
- }
593
-
594
- .section-icon svg {
595
- width: 14px;
596
- height: 14px;
597
- fill: white;
598
- }
599
-
600
- /* Semantic section-icon colors \u2014 driven by VB theme tokens so they shift
601
- with the active theme rather than fighting it. */
602
- .section-icon.acceptance { background: var(--color-success, #22c55e); }
603
- .section-icon.notes { background: var(--color-warning, #f59e0b); }
604
- .section-icon.tasks { background: var(--color-accent, #8b5cf6); }
605
-
606
- .section-title {
607
- font-size: var(--_font-xs);
608
- font-weight: 600;
609
- color: var(--_muted);
610
- text-transform: uppercase;
611
- letter-spacing: 0.5px;
612
- }
613
-
614
- .section-content {
615
- color: var(--_text);
616
- font-size: var(--_font-sm);
617
- line-height: 1.6;
618
- }
619
-
620
- /* Slotted content styling */
621
- .section-content ::slotted(ul),
622
- .section-content ::slotted(ol) {
623
- margin: 0;
624
- padding-left: 20px;
625
- }
626
-
627
- .section-content ::slotted(li) {
628
- margin-bottom: 6px;
629
- }
630
-
631
- .section-content ::slotted(p) {
632
- margin: 0;
633
- }
634
-
635
- /* Empty-slot fallback */
636
- .slot-fallback {
637
- color: var(--_muted);
638
- font-style: italic;
639
- }
640
-
641
- @media (max-width: 480px) {
642
- .story-header {
643
- flex-direction: column;
644
- align-items: flex-start;
645
- }
646
-
647
- .story-badges {
648
- width: 100%;
649
- justify-content: flex-start;
650
- }
651
- }
652
-
653
- @media (prefers-reduced-motion: reduce) {
654
- .story-card {
655
- transition: none;
656
- }
657
- }
658
-
659
- /* \u2500\u2500 Slotted title (minimal mode heading) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
660
- .story-title-wrap {
661
- margin: 0;
662
- }
663
-
664
- ::slotted([slot="title"]) {
665
- font-size: var(--_font-sm) !important;
666
- font-weight: 600 !important;
667
- color: var(--_text) !important;
668
- margin: 0 !important;
669
- }
670
-
671
- .story-title-fallback {
672
- font-size: var(--_font-sm);
673
- font-weight: 600;
674
- color: var(--_text);
675
- }
676
-
677
- /* Minimal detail level */
678
- :host([detail="minimal"]) .story-card {
679
- padding: var(--_space-xs);
680
- }
681
-
682
- :host([detail="minimal"]) .story-header {
683
- display: none;
684
- }
685
-
686
- :host([detail="minimal"]) .story-sections {
687
- display: none;
688
- }
689
-
690
- :host([detail="minimal"]) .story-body {
691
- padding: var(--_space-xs) var(--_space-s);
692
- }
693
-
694
- :host([detail="minimal"]) .story-card {
695
- cursor: pointer;
696
- }
697
-
698
- :host([detail="minimal"]) .story-card:hover {
699
- box-shadow: var(--_shadow-hover);
700
- }
701
-
702
- :host([detail="minimal"]) .story-card:focus-visible {
703
- outline: 2px solid var(--_accent);
704
- outline-offset: 2px;
705
- }
706
-
707
- :host([detail="minimal"]) .story-id {
708
- display: block;
709
- margin-bottom: var(--_space-2xs);
710
- }
711
-
712
- :host([detail="minimal"]) .benefit-text {
713
- display: none;
714
- }
715
-
716
- /* Compact detail level \u2014 hide empty sections */
717
- :host([detail="compact"]) .section[data-empty] {
718
- display: none;
719
- }
720
-
721
- :host([detail="compact"]) .slot-fallback {
722
- display: none;
723
- }
724
- `;var st=class c extends HTMLElement{static get observedAttributes(){return["persona-id","priority","points","status","epic","story-id","compact","detail","src"]}static PRIORITIES={critical:{label:"Critical",color:"#dc2626",bg:"rgba(220, 38, 38, 0.1)"},high:{label:"High",color:"#ea580c",bg:"rgba(234, 88, 12, 0.1)"},medium:{label:"Medium",color:"#ca8a04",bg:"rgba(202, 138, 4, 0.1)"},low:{label:"Low",color:"#16a34a",bg:"rgba(22, 163, 74, 0.1)"}};static STATUSES={backlog:{label:"Backlog",color:"#6b7280",bg:"rgba(107, 114, 128, 0.1)"},"to-do":{label:"To Do",color:"#3b82f6",bg:"rgba(59, 130, 246, 0.1)"},"in-progress":{label:"In Progress",color:"#8b5cf6",bg:"rgba(139, 92, 246, 0.1)"},review:{label:"Review",color:"#f59e0b",bg:"rgba(245, 158, 11, 0.1)"},done:{label:"Done",color:"#22c55e",bg:"rgba(34, 197, 94, 0.1)"}};#e=new Map;#t=null;constructor(){super(),this.attachShadow({mode:"open"})}#r(){for(let t of[...this.children]){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}get data(){return{storyId:this.storyId||void 0,personaId:this.personaId||void 0,priority:this.priority,status:this.status,points:this.points||void 0,epic:this.epic||void 0,detail:this.getAttribute("detail")||void 0,persona:this.persona||void 0,action:this.action||void 0,benefit:this.benefit||void 0,title:this.storyTitle||void 0}}set data(t){!t||typeof t!="object"||(this._applyData(t),this.#r(),this.shadowRoot&&this.#n(),this.dispatchEvent(new CustomEvent("user-story:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0})))}_applyData(t){for(let[e,r]of[["storyId","story-id"],["personaId","persona-id"],["priority","priority"],["status","status"],["points","points"],["epic","epic"],["detail","detail"]])t[e]!=null&&this.setAttribute(r,String(t[e]));if(t.persona&&!this.querySelector('[slot="persona"]')){let e=document.createElement("span");e.slot="persona",e.textContent=String(t.persona),this.appendChild(e)}if(t.action&&!this.querySelector('[slot="action"]')){let e=document.createElement("span");e.slot="action",e.textContent=String(t.action),this.appendChild(e)}if(t.benefit&&!this.querySelector('[slot="benefit"]')){let e=document.createElement("span");e.slot="benefit",e.textContent=String(t.benefit),this.appendChild(e)}if(t.title&&!this.querySelector('[slot="title"]')){let e=document.createElement("h3");e.slot="title",e.textContent=String(t.title),this.appendChild(e)}for(let e of["acceptance-criteria","tasks","notes"]){let r=e==="acceptance-criteria"?"acceptanceCriteria":e;if(t[r]&&!this.querySelector(`[slot="${e}"]`))if(Array.isArray(t[r])){let s=document.createElement("ul");s.slot=e;for(let a of t[r]){let i=document.createElement("li");i.textContent=String(a),s.appendChild(i)}this.appendChild(s)}else{let s=document.createElement("p");s.slot=e,s.textContent=String(t[r]),this.appendChild(s)}}}async _loadSrc(t){if(t)try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();this._applyData(r),this.#r(),this.#n()}catch(e){console.warn(`[user-story] Failed to load src="${t}":`,e)}}connectedCallback(){this.#r(),this.storyId&&!this.id&&(this.id=this.storyId),this.hasAttribute("src")&&this._loadSrc(this.getAttribute("src")),this.#n(),this.#i(),this.setAttribute("data-upgraded","")}disconnectedCallback(){this.removeAttribute("data-upgraded"),this.#t?.disconnect(),this.#t=null}attributeChangedCallback(t,e,r){e!==r&&this.shadowRoot&&(t==="src"&&this.isConnected?this._loadSrc(r):(this.#n(),t==="persona-id"&&this.#i()))}#i(){if(this.#t?.disconnect(),this.#t=null,!this.personaId||this.#s())return;let t=this.getRootNode(),r=(t&&typeof t.getElementById=="function"?t:document).getElementById(this.personaId);!r||r.tagName!=="USER-PERSONA"||(this.#t=new MutationObserver(()=>this.#n()),this.#t.observe(r,{attributes:!0,attributeFilter:["role"]}))}get persona(){return this.#s()||this.#o()||"user"}get personaId(){return this.getAttribute("persona-id")||""}#s(){return this.querySelector('[slot="persona"]')?.textContent?.trim()||this.#e.get("persona")||""}#o(){if(!this.personaId)return"";let t=this.getRootNode(),r=(t&&typeof t.getElementById=="function"?t:document).getElementById(this.personaId);return!r||r.tagName!=="USER-PERSONA"?"":r.getAttribute("role")?.trim()||""}#a(){return/^[aeio]/i.test(this.persona.trim())?"an":"a"}get action(){return this.querySelector('[slot="action"]')?.textContent?.trim()||this.#e.get("action")||""}get benefit(){return this.querySelector('[slot="benefit"]')?.textContent?.trim()||this.#e.get("benefit")||""}get priority(){return this.getAttribute("priority")||"medium"}get points(){return this.getAttribute("points")||""}get status(){return this.getAttribute("status")||"backlog"}get epic(){return this.getAttribute("epic")||""}get storyId(){return this.getAttribute("story-id")||""}get storyTitle(){return this.querySelector('[slot="title"]')?.textContent?.trim()||this.#e.get("title")||""}get _minimalLabel(){if(this.storyTitle)return this.storyTitle;let t=this.action;return t.length>40?t.slice(0,40)+"\u2026":t}get compact(){return this.hasAttribute("compact")}get _detailLevel(){return this.getAttribute("detail")?this.getAttribute("detail"):this.hasAttribute("compact")?"compact":"full"}updateStatus(t){c.STATUSES[t]&&(this.setAttribute("status",t),this.dispatchEvent(new CustomEvent("status-changed",{detail:{status:t,storyId:this.storyId},bubbles:!0,composed:!0})))}updatePriority(t){c.PRIORITIES[t]&&(this.setAttribute("priority",t),this.dispatchEvent(new CustomEvent("priority-changed",{detail:{priority:t,storyId:this.storyId},bubbles:!0,composed:!0})))}showDetail(){let t=`story-dialog-${this.storyId||this.id||"detail"}`,e=document.getElementById(t);e||(e=document.createElement("dialog"),e.id=t,e.setAttribute("data-size","l"),document.body.appendChild(e));let r=document.createElement("form");r.method="dialog";let s=document.createElement("header"),a=document.createElement("h3");a.textContent=this.storyTitle||this.storyId||"Story Detail";let i=document.createElement("button");i.type="submit",i.setAttribute("aria-label","Close"),i.textContent="\xD7",s.appendChild(a),s.appendChild(i);let o=document.createElement("section"),n=document.createElement("user-story");for(let d of this.getAttributeNames())d==="detail"||d==="compact"||d==="data-upgraded"||d==="draggable"||d==="data-id"||d==="data-quadrant"||n.setAttribute(d,this.getAttribute(d)??"");let l=[...this.children].some(d=>d.getAttribute("slot")&&d.tagName!=="DIALOG");n.setAttribute("detail",l?"full":"compact"),n.removeAttribute("id");for(let d of[...this.children])d.tagName!=="DIALOG"&&n.appendChild(d.cloneNode(!0));o.appendChild(n),r.appendChild(s),r.appendChild(o),e.innerHTML="",e.appendChild(r),e.addEventListener("close",()=>{e.innerHTML=""},{once:!0}),e.showModal()}#n(){let t=c.PRIORITIES[this.priority]||c.PRIORITIES.medium,e=c.STATUSES[this.status]||c.STATUSES.backlog,r=this._detailLevel,s=this.storyId?`User story: ${h(this.storyId)}`:"User story";if(this.shadowRoot){if(r==="minimal"){this.shadowRoot.innerHTML=`
725
- <style>${rt}</style>
726
- <article class="story-card story-card--minimal" role="article" aria-label="${s}"
727
- tabindex="0">
728
- <div class="story-body">
729
- ${this.storyId?`<span class="story-id">${h(this.storyId)}</span>`:""}
730
- <div class="story-title-wrap">
731
- <slot name="title"><span class="story-title-fallback">${h(this._minimalLabel||"[describe the action]")}</span></slot>
732
- </div>
733
- </div>
734
- </article>
735
- `;let a=this.shadowRoot.querySelector(".story-card--minimal");if(!a)return;a.addEventListener("click",()=>this.showDetail()),a.addEventListener("keydown",i=>{let o=i;(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),this.showDetail())})}else this.shadowRoot.innerHTML=`
736
- <style>${rt}</style>
737
-
738
- <article class="story-card story-card--${r}" part="card" role="article" aria-label="${s}">
739
- <header class="story-header" part="header">
740
- <div class="story-meta">
741
- ${this.storyId?`<span class="story-id" part="id">${h(this.storyId)}</span>`:""}
742
- ${this.epic?`<span class="epic-badge" part="epic">${h(this.epic)}</span>`:""}
743
- </div>
744
- <div class="story-badges">
745
- <span class="priority-badge" part="priority"
746
- style="color: ${t.color}; background: ${t.bg};"
747
- >${h(t.label)}</span>
748
- <span class="status-badge" part="status"
749
- style="color: ${e.color}; background: ${e.bg};"
750
- >${h(e.label)}</span>
751
- ${this.points?`<span class="points-badge" part="points">${h(this.points)}</span>`:""}
752
- </div>
753
- </header>
754
-
755
- <div class="story-body" part="body">
756
- <p class="story-statement" part="statement">
757
- <span class="keyword">As ${this.#a()}</span>
758
- ${this.personaId?`<a class="persona-text persona-text--link" href="#${h(this.personaId)}">${A(k.user)} <slot name="persona"><span>${h(this.#o()||"user")}</span></slot></a>`:'<span class="persona-text"><slot name="persona"><span>user</span></slot></span>'},
759
- <span class="keyword">I want</span>
760
- <span class="action-text"><slot name="action"><span>[describe the action]</span></slot></span>${this.benefit||this.querySelector('[slot="benefit"]')?`
761
- <span class="keyword">so that</span>
762
- <span class="benefit-text"><slot name="benefit"></slot></span>`:""}
763
- </p>
764
- </div>
765
-
766
- <div class="story-sections" part="sections">
767
- <div class="section" part="section">
768
- <div class="section-header">
769
- <div class="section-icon acceptance">
770
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
771
- </div>
772
- <span class="section-title">Acceptance Criteria</span>
773
- </div>
774
- <div class="section-content">
775
- <slot name="acceptance-criteria">
776
- <em class="slot-fallback">No acceptance criteria defined.</em>
777
- </slot>
778
- </div>
779
- </div>
780
-
781
- <div class="section" part="section">
782
- <div class="section-header">
783
- <div class="section-icon tasks">
784
- <svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/></svg>
785
- </div>
786
- <span class="section-title">Tasks</span>
787
- </div>
788
- <div class="section-content">
789
- <slot name="tasks">
790
- <em class="slot-fallback">No tasks added yet.</em>
791
- </slot>
792
- </div>
793
- </div>
794
-
795
- <div class="section" part="section">
796
- <div class="section-header">
797
- <div class="section-icon notes">
798
- <svg viewBox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
799
- </div>
800
- <span class="section-title">Notes</span>
801
- </div>
802
- <div class="section-content">
803
- <slot name="notes">
804
- <em class="slot-fallback">No additional notes.</em>
805
- </slot>
806
- </div>
807
- </div>
808
- </div>
809
- </article>
810
- `,r==="compact"&&this.shadowRoot.querySelectorAll(".section").forEach(i=>{let o=i.querySelector("slot");o&&o.assignedNodes().length===0&&i.setAttribute("data-empty","")});this.dispatchEvent(new CustomEvent("story-ready",{detail:{id:this.storyId,persona:this.persona,action:this.action,benefit:this.benefit,priority:this.priority,status:this.status,points:this.points},bubbles:!0,composed:!0}))}}};x("user-story",st);var H=`
811
- :host {
812
- display: block;
813
- font-family: var(--_font-sans);
814
- line-height: 1.6;
815
- color: var(--_text);
816
- container-type: inline-size;
817
-
818
- --_bg: var(--user-journey-bg, var(--color-surface-raised, #f8f9fa));
819
- --_card: var(--user-journey-card, var(--color-surface, #ffffff));
820
- --_border: var(--user-journey-border, var(--color-border, #e0e0e0));
821
- --_muted: var(--user-journey-muted, var(--color-text-muted, #666666));
822
- --_text: var(--user-journey-text, var(--color-text, #1a1a1a));
823
- --_inverted: var(--user-journey-text-inverted, var(--color-text-inverted, #ffffff));
824
- --_primary: var(--user-journey-primary, var(--color-primary, var(--color-interactive, #6366f1)));
825
- --_accent: var(--user-journey-accent, var(--color-accent, #8b5cf6));
826
- --_link: var(--user-journey-link, var(--color-interactive, var(--color-primary, #6366f1)));
827
- --_curve-stroke: var(--user-journey-curve-stroke, var(--_primary));
828
- --_radius: var(--user-journey-radius, var(--radius-l, 0.75rem));
829
-
830
- --_font-sans: var(--user-journey-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
831
- --_font-mono: var(--user-journey-font-mono, var(--font-mono, ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace));
832
- --_font-xs: var(--user-journey-font-xs, var(--font-size-xs, 0.75rem));
833
- --_font-sm: var(--user-journey-font-sm, var(--font-size-sm, 0.875rem));
834
- --_font-md: var(--user-journey-font-md, var(--font-size-md, 1rem));
835
- --_font-xl: var(--user-journey-font-xl, var(--font-size-xl, 1.25rem));
836
- --_space-2xs: var(--user-journey-space-2xs, var(--size-2xs, 0.25rem));
837
- --_space-xs: var(--user-journey-space-xs, var(--size-xs, 0.5rem));
838
- --_space-s: var(--user-journey-space-s, var(--size-s, 0.75rem));
839
- --_space-m: var(--user-journey-space-m, var(--size-m, 1rem));
840
- --_space-l: var(--user-journey-space-l, var(--size-l, 1.5rem));
841
-
842
- /* Semantic tints derived from theme tokens via color-mix.
843
- Subtle backgrounds (10\u201314%) for body cells, header at 22%. */
844
- --_tint-pos: color-mix(in oklch, var(--color-success, #22c55e) 14%, var(--_card));
845
- --_tint-neu: color-mix(in oklch, var(--color-warning, #f59e0b) 12%, var(--_card));
846
- --_tint-neg: color-mix(in oklch, var(--color-error, #ef4444) 12%, var(--_card));
847
- --_tint-row-pain: color-mix(in oklch, var(--color-error, #ef4444) 8%, var(--_card));
848
- --_tint-row-opp: color-mix(in oklch, var(--color-success, #22c55e) 8%, var(--_card));
849
- --_chip-type-bg: color-mix(in oklch, var(--_accent) 18%, var(--_card));
850
- --_chip-type-fg: var(--color-accent-text, var(--_accent));
851
- --_chip-story-bg: color-mix(in oklch, var(--_link) 18%, var(--_card));
852
- --_chip-story-bg-hover: color-mix(in oklch, var(--_link) 28%, var(--_card));
853
- --_chip-story-fg: var(--_link);
854
- --_grid-head-bg: color-mix(in oklch, var(--_primary) 85%, var(--color-text, #000));
855
- }
856
-
857
- *, *::before, *::after { box-sizing: border-box; margin: 0; }
858
-
859
- /* Card */
860
- .journey {
861
- background: var(--_card);
862
- border: 1px solid var(--_border);
863
- border-radius: var(--_radius);
864
- overflow: hidden;
865
- }
866
-
867
- /* Header */
868
- .journey__header {
869
- padding: 20px 24px 16px 28px;
870
- border-block-end: 1px solid var(--_border);
871
- position: relative;
872
- }
873
-
874
- /* Left accent bar */
875
- .journey__header::before {
876
- content: '';
877
- position: absolute;
878
- inset-block: 0;
879
- inset-inline-start: 0;
880
- width: 4px;
881
- background: linear-gradient(135deg, var(--_primary), var(--_accent));
882
- }
883
-
884
- .journey__header-top {
885
- display: flex;
886
- align-items: flex-start;
887
- justify-content: space-between;
888
- gap: var(--_space-s);
889
- flex-wrap: wrap;
890
- margin-block-end: var(--_space-xs);
891
- }
892
-
893
- .journey__chips {
894
- display: flex;
895
- flex-wrap: wrap;
896
- align-items: center;
897
- gap: 6px;
898
- }
899
-
900
- /* Chips */
901
- .chip {
902
- display: inline-block;
903
- font-size: 11px;
904
- font-weight: 700;
905
- letter-spacing: 0.05em;
906
- padding: 2px 9px;
907
- border-radius: 99px;
908
- text-decoration: none;
909
- line-height: 1.6;
910
- }
911
-
912
- .chip--type {
913
- color: var(--_chip-type-fg);
914
- background: var(--_chip-type-bg);
915
- }
916
-
917
- .chip--story {
918
- color: var(--_chip-story-fg);
919
- background: var(--_chip-story-bg);
920
- }
921
-
922
- .chip--story:hover { background: var(--_chip-story-bg-hover); }
923
-
924
- /* Persona ref */
925
- .persona-ref {
926
- display: inline-flex;
927
- align-items: center;
928
- gap: 4px;
929
- font-size: 13px;
930
- font-weight: 600;
931
- color: var(--_muted);
932
- text-decoration: none;
933
- white-space: nowrap;
934
- }
935
- .persona-ref svg { width: 14px; height: 14px; flex-shrink: 0; }
936
- a.persona-ref:hover { color: var(--_link); text-decoration: underline; }
937
-
938
- /* Title & summary (slotted content) */
939
- .journey__title-wrap {
940
- margin-block-end: var(--_space-2xs);
941
- }
942
-
943
- .journey__title {
944
- font-size: var(--_font-xl);
945
- font-weight: 700;
946
- color: var(--_text);
947
- margin: 0;
948
- }
949
-
950
- ::slotted([slot="title"]) {
951
- font-size: var(--_font-xl) !important;
952
- font-weight: 700 !important;
953
- color: var(--_text) !important;
954
- margin: 0 !important;
955
- }
956
-
957
- .journey--compact .journey__title,
958
- .journey--compact ::slotted([slot="title"]) { font-size: var(--_font-md) !important; }
959
-
960
- .journey__summary-wrap {
961
- max-width: 72ch;
962
- }
963
-
964
- ::slotted([slot="summary"]) {
965
- font-size: var(--_font-sm) !important;
966
- color: var(--_muted) !important;
967
- margin: 0 !important;
968
- }
969
-
970
- /* Emotion curve */
971
- .journey__curve {
972
- background: var(--_bg);
973
- border-block-end: 1px solid var(--_border);
974
- overflow: hidden;
975
- }
976
-
977
- .curve-svg {
978
- display: block;
979
- width: 100%;
980
- height: 80px;
981
- }
982
-
983
- .journey--compact .curve-svg { height: 54px; }
984
-
985
- .zone { opacity: 0.55; }
986
- .zone--pos { fill: var(--_tint-pos); }
987
- .zone--neu { fill: var(--_tint-neu); }
988
- .zone--neg { fill: var(--_tint-neg); }
989
-
990
- .vline { stroke: var(--_border); stroke-width: 1; stroke-dasharray: 3 4; }
991
- .curve-line { stroke: var(--_curve-stroke); stroke-width: 2.5; stroke-linecap: round; }
992
- .dot { stroke: var(--_card); stroke-width: 2.5; }
993
-
994
- /* Grid */
995
- .journey__grid-wrap { overflow-x: auto; }
996
-
997
- .journey__grid {
998
- width: 100%;
999
- border-collapse: collapse;
1000
- font-size: 13px;
1001
- }
1002
-
1003
- /* Head row */
1004
- .journey__grid thead tr {
1005
- background: var(--_grid-head-bg);
1006
- color: var(--_inverted);
1007
- }
1008
-
1009
- .corner {
1010
- padding: 10px 12px;
1011
- font-size: 10px;
1012
- font-weight: 700;
1013
- text-transform: uppercase;
1014
- letter-spacing: 0.08em;
1015
- opacity: 0.55;
1016
- text-align: left;
1017
- white-space: nowrap;
1018
- min-width: 100px;
1019
- position: sticky;
1020
- left: 0;
1021
- background: var(--_grid-head-bg);
1022
- z-index: 2;
1023
- }
1024
-
1025
- .phase-head {
1026
- padding: 10px 14px;
1027
- text-align: left;
1028
- vertical-align: top;
1029
- border-inline-start: 1px solid color-mix(in oklch, var(--_inverted) 12%, transparent);
1030
- min-width: 160px;
1031
- position: relative;
1032
- }
1033
-
1034
- /* Emotion-coloured top accent per phase */
1035
- .phase-head::before {
1036
- content: '';
1037
- position: absolute;
1038
- inset-block-start: 0;
1039
- inset-inline: 0;
1040
- height: 3px;
1041
- background: var(--ec, var(--_primary));
1042
- }
1043
-
1044
- .ph-num { display: block; font-size: 10px; opacity: 0.5; margin-block-end: 2px; }
1045
- .ph-name { display: block; font-size: var(--_font-sm); font-weight: 700; line-height: 1.2; }
1046
- .ph-emoji { display: block; font-size: var(--_font-xl); line-height: 1; margin-block: 4px 2px; }
1047
-
1048
- .ph-stories { display: flex; flex-wrap: wrap; gap: var(--_space-2xs); margin-block-start: var(--_space-2xs); }
1049
-
1050
- /* Body rows */
1051
- .grid-row th,
1052
- .grid-row td {
1053
- padding: 10px 12px;
1054
- border-block-end: 1px solid var(--_border);
1055
- border-inline-start: 1px solid var(--_border);
1056
- vertical-align: top;
1057
- }
1058
-
1059
- .grid-row th:first-child { border-inline-start: none; }
1060
-
1061
- .row-label {
1062
- font-size: 11px;
1063
- font-weight: 700;
1064
- text-transform: uppercase;
1065
- letter-spacing: 0.07em;
1066
- color: var(--_muted);
1067
- white-space: nowrap;
1068
- background: var(--_bg);
1069
- text-align: left;
1070
- position: sticky;
1071
- left: 0;
1072
- z-index: 1;
1073
- }
1074
-
1075
- .data-cell { font-size: 13px; line-height: 1.45; }
1076
- .data-cell p { margin-block: 0 4px; }
1077
- .data-cell p:last-child { margin-block-end: 0; }
1078
- .data-cell--empty { color: var(--_muted); opacity: 0.35; }
1079
-
1080
- /* Semantic row tints */
1081
- .grid-row--painpoints .data-cell { background: var(--_tint-row-pain); }
1082
- .grid-row--opportunities .data-cell { background: var(--_tint-row-opp); }
1083
-
1084
- /* Compact */
1085
- .journey--compact .phase-head { min-width: 120px; padding: 8px 10px; }
1086
- .journey--compact .data-cell { font-size: 12px; padding: 7px 10px; }
1087
- .journey--compact .corner { min-width: 80px; }
1088
-
1089
- /* Utility */
1090
- .state-msg { padding: var(--_space-l); font-size: var(--_font-sm); color: var(--_muted); font-style: italic; }
1091
- .state-msg--error { color: var(--color-error-text, var(--color-error, #dc2626)); }
1092
- .journey__placeholder { padding: 20px 24px; font-size: var(--_font-sm); color: var(--_muted); }
1093
- code { font-family: var(--_font-mono); font-size: 0.88em; }
1094
-
1095
- /* Responsive */
1096
- @container (max-width: 500px) {
1097
- .journey__header { padding: 14px 16px 12px 20px; }
1098
- .journey__title { font-size: 17px; }
1099
- .corner, .row-label { min-width: 72px; font-size: 9px; }
1100
- .phase-head { min-width: 110px; padding: 8px 10px; }
1101
- .data-cell { font-size: 12px; padding: 8px 10px; }
1102
- }
1103
-
1104
- @media print {
1105
- .journey__grid-wrap { overflow: visible; }
1106
- .row-label, .corner { position: relative; }
1107
- }
1108
- `;var Jt=0;function S(c,t,e="vb-vt"){if(!c?.isConnected||typeof document>"u"||!("startViewTransition"in document)||matchMedia("(prefers-reduced-motion: reduce)").matches)return t(),null;let r=`${e}-${++Jt}`;c.style.viewTransitionName=r;let s=document.startViewTransition(t);return s.finished.finally(()=>{c.style.viewTransitionName===r&&(c.style.viewTransitionName="")}),s}var Zt=[{key:"actions",label:"Actions"},{key:"thoughts",label:"Thoughts"},{key:"touchpoints",label:"Touchpoints"},{key:"painPoints",label:"Pain Points"},{key:"opportunities",label:"Opportunities"}],at=class extends HTMLElement{static get observedAttributes(){return["src","persona","persona-id","story-ids","compact"]}#e=new Map;constructor(){super(),this.attachShadow({mode:"open"}),this.__phases=null}get phases(){return this.__phases}set phases(t){this.__phases!==t&&(this.__phases=t,this.isConnected&&this._render(),this.dispatchEvent(new CustomEvent("user-journey:phases-changed",{detail:{phases:t,source:"property"},bubbles:!0,composed:!0})))}get data(){return{persona:this.getAttribute("persona")||void 0,personaId:this.getAttribute("persona-id")||void 0,title:this.querySelector('[slot="title"]')?.textContent?.trim()||void 0,summary:this.querySelector('[slot="summary"]')?.textContent?.trim()||void 0,phases:this.__phases||void 0}}set data(t){if(!(!t||typeof t!="object")){if(t.persona&&this.setAttribute("persona",String(t.persona)),t.personaId&&this.setAttribute("persona-id",String(t.personaId)),t.title&&!this.querySelector('[slot="title"]')){let e=document.createElement("h2");e.slot="title",e.textContent=t.title,this.appendChild(e)}if(t.summary&&!this.querySelector('[slot="summary"]')){let e=document.createElement("p");e.slot="summary",e.textContent=t.summary,this.appendChild(e)}t.phases!=null&&(this.__phases=t.phases),this.isConnected&&this._render(),this.dispatchEvent(new CustomEvent("user-journey:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0}))}}#t(){for(let t of this.children){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}connectedCallback(){this.#t(),this.setAttribute("data-upgraded",""),this.hasAttribute("src")?this._loadSrc(this.getAttribute("src")):this._render()}disconnectedCallback(){this.removeAttribute("data-upgraded")}attributeChangedCallback(t){this.isConnected&&(t==="src"?this._loadSrc(this.getAttribute("src")):this._render())}async _loadSrc(t){if(!t)return;let e=this.shadowRoot;e.innerHTML=`<style>${H}</style><div class="state-msg">Loading\u2026</div>`;try{let r=await fetch(t);if(!r.ok)throw new Error(`HTTP ${r.status}`);let s=await r.json();if(s.persona&&this.setAttribute("persona",s.persona),s.personaId&&this.setAttribute("persona-id",s.personaId),s.title&&!this.querySelector('[slot="title"]')){let a=document.createElement("h2");a.slot="title",a.textContent=s.title,this.appendChild(a)}if(s.summary&&!this.querySelector('[slot="summary"]')){let a=document.createElement("p");a.slot="summary",a.textContent=s.summary,this.appendChild(a)}this.__phases=s.phases||[],this._render()}catch(r){e.innerHTML=`<style>${H}</style><div class="state-msg state-msg--error">Could not load journey: ${h(r.message)}</div>`}}_render(){let t=this._resolve("persona")||"",e=this._resolve("persona-id")||"",r=(this.getAttribute("story-ids")||"").split(",").map(p=>p.trim()).filter(Boolean),s=this.hasAttribute("compact"),a=this.__phases,i=!!this.querySelector('[slot="summary"]')||this.#e.has("summary"),o=this.querySelector('[slot="title"]')?.textContent?.trim()||this.#e.get("title")||"",n=`<style>${H}</style>
1109
- <article class="journey${s?" journey--compact":""}">
1110
-
1111
- <header class="journey__header">
1112
- <div class="journey__header-top">
1113
- <div class="journey__chips">
1114
- <span class="chip chip--type">Journey Map</span>
1115
- ${r.map(p=>`<a class="chip chip--story" href="#${p}">${this._label(p)}</a>`).join("")}
1116
- </div>
1117
- ${t?`
1118
- <div class="journey__persona">
1119
- ${e?`<a class="persona-ref" href="#${e}">${A(k.user)} ${h(t)}</a>`:`<span class="persona-ref">${A(k.user)} ${h(t)}</span>`}
1120
- </div>`:""}
1121
- </div>
1122
- <div class="journey__title-wrap">
1123
- <slot name="title"><h2 class="journey__title">User Journey</h2></slot>
1124
- </div>
1125
- ${i?'<div class="journey__summary-wrap"><slot name="summary"></slot></div>':""}
1126
- </header>
1127
-
1128
- ${a&&a.length?this._curve(a)+this._grid(a):`<div class="journey__placeholder">
1129
- <p>Add phase data via <code>src</code> (JSON) or set <code>.phases</code> programmatically.</p>
1130
- </div>`}
1131
-
1132
- </article>`,l=this.shadowRoot,d=()=>{l.innerHTML=n};l.querySelector("article")?S(this,d,"uj-vt"):d(),this.dispatchEvent(new CustomEvent("journey-ready",{bubbles:!0,composed:!0,detail:{title:o,persona:t,phaseCount:a?a.length:0}}))}_curve(t){let n=t.length,l=g=>28+(n<2?944/2:g/(n-1)*944),d=g=>14+(1-(q[g.emotion]||q.neutral).score)*72,p=t.map((g,v)=>({x:l(v),y:d(g),ph:g})),u=`M ${p[0].x},${p[0].y}`;for(let g=1;g<p.length;g++){let v=p[g-1],y=p[g],_=(v.x+y.x)/2;u+=` C ${_},${v.y} ${_},${y.y} ${y.x},${y.y}`}let m=`uj-${Math.random().toString(36).slice(2,8)}`,f=p.at(-1);return`
1133
- <div class="journey__curve" aria-hidden="true">
1134
- <svg viewBox="0 0 1000 100" preserveAspectRatio="none" class="curve-svg">
1135
- <defs>
1136
- <linearGradient id="${m}" x1="0" y1="0" x2="0" y2="1">
1137
- <stop offset="0%" stop-color="#6366f1" stop-opacity="0.22"/>
1138
- <stop offset="100%" stop-color="#6366f1" stop-opacity="0"/>
1139
- </linearGradient>
1140
- </defs>
1141
- <rect x="0" y="0" width="1000" height="${100*.4}" class="zone zone--pos"/>
1142
- <rect x="0" y="${100*.4}" width="1000" height="${100*.2}" class="zone zone--neu"/>
1143
- <rect x="0" y="${100*.6}" width="1000" height="${100*.4}" class="zone zone--neg"/>
1144
- ${p.map(({x:g})=>`<line x1="${g}" y1="0" x2="${g}" y2="100" class="vline"/>`).join("")}
1145
- <path d="${u} L ${f.x},100 L ${p[0].x},100 Z" fill="url(#${m})"/>
1146
- <path d="${u}" fill="none" class="curve-line"/>
1147
- ${p.map(({x:g,y:v,ph:y})=>{let _=q[y.emotion]||q.neutral;return`<circle cx="${g}" cy="${v}" r="5" class="dot" style="fill:${_.color}"/>`}).join("")}
1148
- </svg>
1149
- </div>`}_grid(t){let e=t.map((s,a)=>{let i=q[s.emotion]||q.neutral,o=s.storyIds||[];return`
1150
- <th class="phase-head" data-emotion="${s.emotion||"neutral"}"
1151
- style="--ec:${i.color}">
1152
- <span class="ph-num">${a+1}</span>
1153
- <span class="ph-name">${h(s.name||"")}</span>
1154
- <span class="ph-emoji" title="${s.emotion||"neutral"}"><span role="img" aria-label="${h(s.emotion||"neutral")}">${i.emoji}</span></span>
1155
- ${o.length?`<div class="ph-stories">${o.map(n=>`<a class="chip chip--story" href="#${n}">${this._label(n)}</a>`).join("")}</div>`:""}
1156
- </th>`}).join(""),r=Zt.map(({key:s,label:a})=>{let i=t.map(o=>{let n=o[s]||[];return n.length?`<td class="data-cell data-cell--${s.toLowerCase()}">
1157
- ${n.map(l=>`<p>${h(l)}</p>`).join("")}
1158
- </td>`:'<td class="data-cell data-cell--empty">\u2014</td>'}).join("");return`
1159
- <tr class="grid-row grid-row--${s.toLowerCase()}">
1160
- <th class="row-label">${a}</th>
1161
- ${i}
1162
- </tr>`}).join("");return`
1163
- <div class="journey__grid-wrap">
1164
- <table class="journey__grid"
1165
- aria-label="${h(this.getAttribute("title")||"User Journey")} \u2014 phase breakdown">
1166
- <thead>
1167
- <tr>
1168
- <th class="corner">Stage</th>
1169
- ${e}
1170
- </tr>
1171
- </thead>
1172
- <tbody>${r}</tbody>
1173
- </table>
1174
- </div>`}_label(t){return t.replace(/^(activity|persona|journey|story|user)-/,"").replace(/-/g," ").replace(/\b\w/g,e=>e.toUpperCase())}};x("user-journey",at);var U=`
1175
- :host {
1176
- display: block;
1177
- font-family: var(--_font-sans);
1178
- line-height: 1.6;
1179
- color: var(--_text);
1180
- container-type: inline-size;
1181
-
1182
- --_bg: var(--empathy-map-bg, var(--color-surface, #ffffff));
1183
- --_card: var(--empathy-map-card, var(--color-surface-raised, #f8f9fa));
1184
- --_border: var(--empathy-map-border, var(--color-border, #e0e0e0));
1185
- --_muted: var(--empathy-map-muted, var(--color-text-muted, #666666));
1186
- --_text: var(--empathy-map-text, var(--color-text, #1a1a1a));
1187
- --_radius: var(--empathy-map-radius, var(--radius-xl, 1rem));
1188
- --_accent: var(--empathy-map-accent, var(--color-interactive, var(--color-primary, #0066cc)));
1189
- --_link: var(--empathy-map-link, var(--color-interactive, var(--color-primary, #6366f1)));
1190
- --_primary: var(--empathy-map-primary, var(--color-primary, #6366f1));
1191
- --_accent-bar: var(--empathy-map-accent-bar, var(--color-accent, #8b5cf6));
1192
- --_says: var(--empathy-map-says, var(--color-info, #3b82f6));
1193
- --_thinks: var(--empathy-map-thinks, var(--color-accent, #8b5cf6));
1194
- --_does: var(--empathy-map-does, var(--color-warning, #f59e0b));
1195
- --_feels: var(--empathy-map-feels, var(--color-error, #ef4444));
1196
- --_says-bg: color-mix(in oklch, var(--_says) 16%, var(--_card));
1197
- --_thinks-bg: color-mix(in oklch, var(--_thinks) 16%, var(--_card));
1198
- --_does-bg: color-mix(in oklch, var(--_does) 16%, var(--_card));
1199
- --_feels-bg: color-mix(in oklch, var(--_feels) 16%, var(--_card));
1200
- --_chip-type-bg: color-mix(in oklch, var(--_accent-bar) 18%, var(--_card));
1201
- --_chip-type-fg: var(--_accent-bar);
1202
- --_font-sans: var(--empathy-map-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
1203
- --_font-xs: var(--empathy-map-font-xs, var(--font-size-xs, 0.75rem));
1204
- --_font-sm: var(--empathy-map-font-sm, var(--font-size-sm, 0.875rem));
1205
- --_font-md: var(--empathy-map-font-md, var(--font-size-md, 1rem));
1206
- --_font-xl: var(--empathy-map-font-xl, var(--font-size-xl, 1.25rem));
1207
- --_space-2xs: var(--empathy-map-space-2xs, var(--size-2xs, 0.25rem));
1208
- --_space-xs: var(--empathy-map-space-xs, var(--size-xs, 0.5rem));
1209
- --_space-s: var(--empathy-map-space-s, var(--size-s, 0.75rem));
1210
- --_space-m: var(--empathy-map-space-m, var(--size-m, 1rem));
1211
- --_space-l: var(--empathy-map-space-l, var(--size-l, 1.5rem));
1212
- --_radius-m: var(--empathy-map-radius-m, var(--radius-m, 0.5rem));
1213
- --_radius-full: var(--empathy-map-radius-full, var(--radius-full, 9999px));
1214
- --_duration: var(--empathy-map-duration, var(--duration-normal, 200ms));
1215
- --_duration-fast: var(--empathy-map-duration-fast, var(--duration-fast, 100ms));
1216
- --_ease: var(--empathy-map-ease, var(--ease-default, ease));
1217
- }
1218
-
1219
- *, *::before, *::after { box-sizing: border-box; margin: 0; }
1220
-
1221
- /* \u2500\u2500 Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1222
- .empathy-map {
1223
- background: var(--_card);
1224
- border: 1px solid var(--_border);
1225
- border-radius: var(--_radius);
1226
- overflow: hidden;
1227
- }
1228
-
1229
- /* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1230
- .empathy-map__header {
1231
- padding: 20px 24px 16px 28px;
1232
- border-block-end: 1px solid var(--_border);
1233
- position: relative;
1234
- }
1235
-
1236
- /* Left accent bar */
1237
- .empathy-map__header::before {
1238
- content: '';
1239
- position: absolute;
1240
- inset-block: 0;
1241
- inset-inline-start: 0;
1242
- width: 4px;
1243
- background: linear-gradient(135deg, var(--_primary), var(--_accent-bar));
1244
- }
1245
-
1246
- .empathy-map__header-top {
1247
- display: flex;
1248
- align-items: flex-start;
1249
- justify-content: space-between;
1250
- gap: var(--_space-s);
1251
- flex-wrap: wrap;
1252
- margin-block-end: var(--_space-xs);
1253
- }
1254
-
1255
- .empathy-map__chips {
1256
- display: flex;
1257
- flex-wrap: wrap;
1258
- align-items: center;
1259
- gap: 6px;
1260
- }
1261
-
1262
- /* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1263
- .chip {
1264
- display: inline-block;
1265
- font-size: 11px;
1266
- font-weight: 700;
1267
- letter-spacing: 0.05em;
1268
- padding: 2px 9px;
1269
- border-radius: var(--_radius-full);
1270
- text-decoration: none;
1271
- line-height: 1.6;
1272
- }
1273
-
1274
- .chip--type {
1275
- color: var(--_chip-type-fg);
1276
- background: var(--_chip-type-bg);
1277
- }
1278
-
1279
- /* \u2500\u2500 Persona ref \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1280
- .persona-ref {
1281
- display: inline-flex;
1282
- align-items: center;
1283
- gap: 4px;
1284
- font-size: 13px;
1285
- font-weight: 600;
1286
- color: var(--_muted);
1287
- text-decoration: none;
1288
- white-space: nowrap;
1289
- }
1290
-
1291
- .persona-ref svg {
1292
- width: 14px;
1293
- height: 14px;
1294
- flex-shrink: 0;
1295
- }
1296
-
1297
- a.persona-ref:hover { color: var(--_link); text-decoration: underline; }
1298
-
1299
- /* \u2500\u2500 Title & summary (slotted content) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1300
- .empathy-map__title-wrap {
1301
- margin-block-end: var(--_space-2xs);
1302
- }
1303
-
1304
- .empathy-map__title {
1305
- font-size: var(--_font-xl);
1306
- font-weight: 700;
1307
- color: var(--_text);
1308
- margin: 0;
1309
- }
1310
-
1311
- ::slotted([slot="title"]) {
1312
- font-size: var(--_font-xl) !important;
1313
- font-weight: 700 !important;
1314
- color: var(--_text) !important;
1315
- margin: 0 !important;
1316
- }
1317
-
1318
- .empathy-map__summary-wrap {
1319
- max-width: 72ch;
1320
- }
1321
-
1322
- ::slotted([slot="summary"]) {
1323
- font-size: var(--_font-sm) !important;
1324
- color: var(--_muted) !important;
1325
- margin: 0 !important;
1326
- }
1327
-
1328
- /* \u2500\u2500 Grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1329
- .empathy-map__grid {
1330
- display: grid;
1331
- grid-template-columns: 1fr 1fr;
1332
- gap: 1px;
1333
- background: var(--_border);
1334
- }
1335
-
1336
- /* \u2500\u2500 Quadrant \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1337
- .quadrant {
1338
- background: var(--_card);
1339
- padding: 0;
1340
- position: relative;
1341
- display: grid;
1342
- }
1343
-
1344
- .quadrant::before {
1345
- content: '';
1346
- position: absolute;
1347
- inset-block-start: 0;
1348
- inset-inline: 0;
1349
- height: 3px;
1350
- }
1351
-
1352
- .quadrant--says::before { background: var(--_says); }
1353
- .quadrant--thinks::before { background: var(--_thinks); }
1354
- .quadrant--does::before { background: var(--_does); }
1355
- .quadrant--feels::before { background: var(--_feels); }
1356
-
1357
- .quadrant__inner {
1358
- display: grid;
1359
- padding: 16px 20px;
1360
- padding-block-start: 19px; /* 16 + 3px top border */
1361
- }
1362
-
1363
- /* \u2500\u2500 Quadrant header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1364
- .quadrant__header {
1365
- display: flex;
1366
- align-items: center;
1367
- gap: 10px;
1368
- margin-block-end: var(--_space-s);
1369
- }
1370
-
1371
- .quadrant__icon {
1372
- display: flex;
1373
- align-items: center;
1374
- justify-content: center;
1375
- width: 32px;
1376
- height: 32px;
1377
- border-radius: var(--_radius-m);
1378
- flex-shrink: 0;
1379
- }
1380
-
1381
- .quadrant__icon svg {
1382
- width: 16px;
1383
- height: 16px;
1384
- }
1385
-
1386
- .quadrant--says .quadrant__icon { background: var(--_says-bg); color: var(--_says); }
1387
- .quadrant--thinks .quadrant__icon { background: var(--_thinks-bg); color: var(--_thinks); }
1388
- .quadrant--does .quadrant__icon { background: var(--_does-bg); color: var(--_does); }
1389
- .quadrant--feels .quadrant__icon { background: var(--_feels-bg); color: var(--_feels); }
1390
-
1391
- .quadrant__label {
1392
- font-size: 13px;
1393
- font-weight: 700;
1394
- text-transform: uppercase;
1395
- letter-spacing: 0.06em;
1396
- color: var(--_muted);
1397
- flex: 1;
1398
- }
1399
-
1400
- /* \u2500\u2500 Quadrant content / faces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1401
- .quadrant__face {
1402
- grid-area: 1 / 1;
1403
- transition: opacity var(--_duration) var(--_ease), transform var(--_duration) var(--_ease);
1404
- }
1405
-
1406
- .quadrant__face--front {
1407
- opacity: 1;
1408
- transform: scale(1);
1409
- }
1410
-
1411
- .quadrant__face--back {
1412
- opacity: 0;
1413
- transform: scale(0.95);
1414
- pointer-events: none;
1415
- }
1416
-
1417
- [data-editing] .quadrant__face--front {
1418
- opacity: 0;
1419
- transform: scale(0.95);
1420
- pointer-events: none;
1421
- }
1422
-
1423
- [data-editing] .quadrant__face--back {
1424
- opacity: 1;
1425
- transform: scale(1);
1426
- pointer-events: auto;
1427
- }
1428
-
1429
- .quadrant__content {
1430
- font-size: 14px;
1431
- line-height: 1.55;
1432
- color: var(--_text);
1433
- }
1434
-
1435
- .quadrant__content p {
1436
- margin-block: 0 6px;
1437
- }
1438
-
1439
- .quadrant__content p:last-child {
1440
- margin-block-end: 0;
1441
- }
1442
-
1443
- /* \u2500\u2500 Slot fallback / placeholder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1444
- .placeholder {
1445
- font-size: 13px;
1446
- color: var(--_muted);
1447
- font-style: italic;
1448
- }
1449
-
1450
- ::slotted(ul),
1451
- ::slotted(ol) {
1452
- margin: 0;
1453
- padding-inline-start: 1.4em;
1454
- font-size: 14px;
1455
- line-height: 1.55;
1456
- }
1457
-
1458
- /* \u2500\u2500 Emotion tags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1459
- .emotion-tag {
1460
- display: inline-block;
1461
- font-size: 12px;
1462
- font-weight: 600;
1463
- padding: 2px 10px;
1464
- border-radius: var(--_radius-full);
1465
- margin-block-end: 6px;
1466
- margin-inline-end: 4px;
1467
- background: color-mix(in srgb, var(--ec, #94a3b8) 15%, transparent);
1468
- color: var(--ec, #94a3b8);
1469
- border: 1px solid color-mix(in srgb, var(--ec, #94a3b8) 30%, transparent);
1470
- }
1471
-
1472
- /* \u2500\u2500 Edit / Done buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1473
- .quadrant__edit-btn,
1474
- .quadrant__done-btn {
1475
- display: inline-flex;
1476
- align-items: center;
1477
- justify-content: center;
1478
- width: 28px;
1479
- height: 28px;
1480
- border: 1px solid var(--_border);
1481
- border-radius: 6px;
1482
- background: var(--_bg);
1483
- color: var(--_muted);
1484
- cursor: pointer;
1485
- line-height: 1;
1486
- padding: 0;
1487
- flex-shrink: 0;
1488
- transition: background var(--_duration-fast) var(--_ease), color var(--_duration-fast) var(--_ease);
1489
- }
1490
-
1491
- .quadrant__edit-btn svg,
1492
- .quadrant__done-btn svg {
1493
- width: 14px;
1494
- height: 14px;
1495
- }
1496
-
1497
- .quadrant__edit-btn:hover,
1498
- .quadrant__done-btn:hover {
1499
- background: var(--_border);
1500
- color: var(--_text);
1501
- }
1502
-
1503
- .quadrant__done-btn {
1504
- margin-block-start: 8px;
1505
- width: auto;
1506
- padding: 0 12px;
1507
- font-size: 12px;
1508
- font-weight: 600;
1509
- gap: 4px;
1510
- }
1511
-
1512
- /* \u2500\u2500 Editor textarea \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1513
- .quadrant__editor {
1514
- width: 100%;
1515
- min-height: 100px;
1516
- padding: 10px 12px;
1517
- border: 1px solid var(--_border);
1518
- border-radius: var(--_radius-m);
1519
- font-family: inherit;
1520
- font-size: 13px;
1521
- line-height: 1.55;
1522
- color: var(--_text);
1523
- background: var(--_bg);
1524
- resize: vertical;
1525
- }
1526
-
1527
- .quadrant__editor:focus {
1528
- outline: 2px solid var(--_accent);
1529
- outline-offset: -1px;
1530
- border-color: var(--_accent);
1531
- }
1532
-
1533
- /* \u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1534
- .empathy-map__footer {
1535
- display: flex;
1536
- gap: 1px;
1537
- background: var(--_border);
1538
- border-block-start: 1px solid var(--_border);
1539
- }
1540
-
1541
- .summary-row {
1542
- flex: 1;
1543
- background: var(--_card);
1544
- padding: 16px 20px;
1545
- display: flex;
1546
- align-items: flex-start;
1547
- gap: 10px;
1548
- }
1549
-
1550
- .summary-row__icon {
1551
- line-height: 1;
1552
- flex-shrink: 0;
1553
- margin-block-start: 2px;
1554
- color: var(--_muted);
1555
- }
1556
-
1557
- .summary-row__icon svg {
1558
- width: 18px;
1559
- height: 18px;
1560
- }
1561
-
1562
- .summary-row__body {
1563
- flex: 1;
1564
- min-width: 0;
1565
- }
1566
-
1567
- .summary-row__label {
1568
- font-size: 11px;
1569
- font-weight: 700;
1570
- text-transform: uppercase;
1571
- letter-spacing: 0.06em;
1572
- color: var(--_muted);
1573
- margin-block-end: 4px;
1574
- }
1575
-
1576
- .summary-row__content {
1577
- font-size: 14px;
1578
- line-height: 1.55;
1579
- color: var(--_text);
1580
- }
1581
-
1582
- .summary-row__content p {
1583
- margin-block: 0 4px;
1584
- }
1585
-
1586
- .summary-row__content p:last-child {
1587
- margin-block-end: 0;
1588
- }
1589
-
1590
- /* \u2500\u2500 Compact variant \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1591
- :host([compact]) .empathy-map__header {
1592
- padding: 14px 18px 12px 22px;
1593
- }
1594
-
1595
- :host([compact]) .empathy-map__title {
1596
- font-size: 16px;
1597
- }
1598
-
1599
- :host([compact]) .empathy-map__summary {
1600
- font-size: 12px;
1601
- }
1602
-
1603
- :host([compact]) .quadrant__inner {
1604
- padding: 12px 14px;
1605
- padding-block-start: 15px;
1606
- }
1607
-
1608
- :host([compact]) .quadrant__icon {
1609
- width: 26px;
1610
- height: 26px;
1611
- font-size: 13px;
1612
- border-radius: 6px;
1613
- }
1614
-
1615
- :host([compact]) .quadrant__label {
1616
- font-size: 11px;
1617
- }
1618
-
1619
- :host([compact]) .quadrant__content {
1620
- font-size: 12px;
1621
- }
1622
-
1623
- :host([compact]) .summary-row {
1624
- padding: 12px 14px;
1625
- }
1626
-
1627
- :host([compact]) .summary-row__content {
1628
- font-size: 12px;
1629
- }
1630
-
1631
- /* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1632
- @container (max-width: 500px) {
1633
- .empathy-map__grid {
1634
- grid-template-columns: 1fr;
1635
- }
1636
-
1637
- .empathy-map__header {
1638
- padding: 14px 16px 12px 20px;
1639
- }
1640
-
1641
- .empathy-map__title {
1642
- font-size: 17px;
1643
- }
1644
-
1645
- .empathy-map__footer {
1646
- flex-direction: column;
1647
- }
1648
- }
1649
-
1650
- /* \u2500\u2500 Motion \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1651
- @media (prefers-reduced-motion: reduce) {
1652
- .quadrant__face {
1653
- transition: none;
1654
- }
1655
-
1656
- .quadrant__edit-btn,
1657
- .quadrant__done-btn {
1658
- transition: none;
1659
- }
1660
- }
1661
-
1662
- /* \u2500\u2500 Print \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1663
- @media print {
1664
- .empathy-map {
1665
- break-inside: avoid;
1666
- border-color: var(--_border);
1667
- }
1668
-
1669
- .quadrant__edit-btn,
1670
- .quadrant__done-btn {
1671
- display: none;
1672
- }
1673
-
1674
- .quadrant__face--back {
1675
- display: none;
1676
- }
1677
-
1678
- .empathy-map__footer {
1679
- flex-direction: column;
1680
- }
1681
- }
1682
-
1683
- /* \u2500\u2500 Utility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1684
- .state-msg { padding: var(--_space-l); font-size: var(--_font-sm); color: var(--_muted); font-style: italic; }
1685
- .state-msg--error { color: var(--color-error-text, var(--color-error, #dc2626)); }
1686
- code { font-family: var(--font-mono, Monaco, Menlo, monospace); font-size: 0.88em; }
1687
- `;var it=["says","thinks","does","feels"],ot=class extends HTMLElement{static get observedAttributes(){return["persona","persona-id","src","editable","compact"]}#e=new Map;constructor(){super(),this.attachShadow({mode:"open"}),this.__quadrants=null,this.__goals=null,this.__painPoints=null,this._editingQuadrants=new Set}get quadrants(){return this.__quadrants}set quadrants(t){this.__quadrants=t,this.isConnected&&this._render()}get goals(){return this.__goals}set goals(t){this.__goals=t,this.isConnected&&this._render()}get painPoints(){return this.__painPoints}set painPoints(t){this.__painPoints=t,this.isConnected&&this._render()}#t(){for(let t of this.children){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}connectedCallback(){this.#t(),this.setAttribute("data-upgraded",""),this.hasAttribute("src")?this._loadSrc(this.getAttribute("src")):this._render()}disconnectedCallback(){this.removeAttribute("data-upgraded")}attributeChangedCallback(t){this.isConnected&&(t==="src"?this._loadSrc(this.getAttribute("src")):this._render())}get data(){let t=this.querySelector('[slot="title"]'),e=this.querySelector('[slot="summary"]');return{persona:this.getAttribute("persona")||void 0,personaId:this.getAttribute("persona-id")||void 0,title:t?.textContent?.trim()||void 0,summary:e?.textContent?.trim()||void 0,quadrants:this.__quadrants||void 0,goals:this.__goals||void 0,painPoints:this.__painPoints||void 0}}set data(t){if(!(!t||typeof t!="object")){if(t.persona&&this.setAttribute("persona",String(t.persona)),t.personaId&&this.setAttribute("persona-id",String(t.personaId)),t.title&&!this.querySelector('[slot="title"]')){let e=document.createElement("h2");e.slot="title",e.textContent=t.title,this.appendChild(e)}if(t.summary&&!this.querySelector('[slot="summary"]')){let e=document.createElement("p");e.slot="summary",e.textContent=t.summary,this.appendChild(e)}t.quadrants!=null&&(this.__quadrants=t.quadrants),t.goals!=null&&(this.__goals=t.goals),t.painPoints!=null&&(this.__painPoints=t.painPoints),this.isConnected&&this._render(),this.dispatchEvent(new CustomEvent("empathy-map:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0}))}}editQuadrant(t){it.includes(t)&&this.hasAttribute("editable")&&this._openEdit(t)}closeQuadrant(t){it.includes(t)&&this._closeEdit(t)}async _loadSrc(t){if(!(!t||!this.shadowRoot)){this.shadowRoot.innerHTML=`<style>${U}</style><div class="state-msg">Loading\u2026</div>`;try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();if(r.persona&&this.setAttribute("persona",r.persona),r.personaId&&this.setAttribute("persona-id",r.personaId),r.title&&!this.querySelector('[slot="title"]')){let s=document.createElement("h2");s.slot="title",s.textContent=r.title,this.appendChild(s)}if(r.summary&&!this.querySelector('[slot="summary"]')){let s=document.createElement("p");s.slot="summary",s.textContent=r.summary,this.appendChild(s)}this.__quadrants=r.quadrants||null,this.__goals=r.goals||null,this.__painPoints=r.painPoints||null,this._render()}catch(e){if(!this.shadowRoot)return;let r=e instanceof Error?e.message:String(e);this.shadowRoot.innerHTML=`<style>${U}</style><div class="state-msg state-msg--error">Could not load empathy map: ${h(r)}</div>`}}}_render(){let t=this._resolve("persona")||"",e=this._resolve("persona-id")||"",r=this.hasAttribute("compact"),s=this.hasAttribute("editable"),a=!!this.querySelector('[slot="title"]')||this.#e.has("title"),i=!!this.querySelector('[slot="summary"]')||this.#e.has("summary"),o=this.__goals?.length||this.querySelector('[slot="goals"]'),n=this.__painPoints?.length||this.querySelector('[slot="pain-points"]'),l=`<style>${U}</style>
1688
- <article class="empathy-map${r?" empathy-map--compact":""}">
1689
-
1690
- <header class="empathy-map__header">
1691
- <div class="empathy-map__header-top">
1692
- <div class="empathy-map__chips">
1693
- <span class="chip chip--type">Empathy Map</span>
1694
- </div>
1695
- ${t?`
1696
- <div class="empathy-map__persona">
1697
- ${e?`<a class="persona-ref" href="#${h(e)}">${A(k.user)} ${h(t)}</a>`:`<span class="persona-ref">${A(k.user)} ${h(t)}</span>`}
1698
- </div>`:""}
1699
- </div>
1700
- <div class="empathy-map__title-wrap">
1701
- <slot name="title"><h2 class="empathy-map__title">Empathy Map</h2></slot>
1702
- </div>
1703
- ${i?'<div class="empathy-map__summary-wrap"><slot name="summary"></slot></div>':""}
1704
- </header>
1705
-
1706
- <div class="empathy-map__grid">
1707
- ${it.map(p=>this._renderQuadrant(p,s)).join("")}
1708
- </div>
1709
-
1710
- ${o||n?`
1711
- <footer class="empathy-map__footer">
1712
- ${this._renderSummaryRow("goals",A(k.target),"Goals")}
1713
- ${this._renderSummaryRow("pain-points",A(k.alertTriangle),"Pain Points")}
1714
- </footer>
1715
- `:""}
1716
-
1717
- </article>`,d=()=>{this.shadowRoot&&(this.shadowRoot.innerHTML=l,s&&this._bindEditListeners())};this.shadowRoot?.querySelector("article")?S(this,d,"em-vt"):d(),this.dispatchEvent(new CustomEvent("empathy-map:ready",{bubbles:!0,composed:!0,detail:{title:this.querySelector('[slot="title"]')?.textContent?.trim()||"Empathy Map",persona:t}}))}_renderQuadrant(t,e){let r=Z[t],s=this.__quadrants?.[t],a=this._editingQuadrants.has(t),i=s&&s.length?t==="feels"?s.map(n=>this._renderEmotion(n)).join(""):s.map(n=>`<p>${h(n)}</p>`).join(""):`<slot name="${t}"><p class="placeholder">Add ${r.label.toLowerCase()} items\u2026</p></slot>`,o=s?.length?s.join(`
1718
- `):"";return`
1719
- <section class="quadrant quadrant--${t}"${a?" data-editing":""}>
1720
- <div class="quadrant__inner">
1721
- <div class="quadrant__header">
1722
- <div class="quadrant__icon" aria-hidden="true">${A(r.icon)}</div>
1723
- <span class="quadrant__label">${r.label}</span>
1724
- ${e?`<button class="quadrant__edit-btn" data-quadrant="${t}"
1725
- aria-label="Edit ${r.label}" title="Edit ${r.label}">${A(k.pencil)}</button>`:""}
1726
- </div>
1727
- <div class="quadrant__faces">
1728
- <div class="quadrant__face quadrant__face--front"${a?" inert":""}>
1729
- <div class="quadrant__content">
1730
- ${i}
1731
- </div>
1732
- </div>
1733
- ${e?`
1734
- <div class="quadrant__face quadrant__face--back"${a?"":" inert"}>
1735
- <textarea class="quadrant__editor" data-quadrant="${t}"
1736
- placeholder="One item per line\u2026"
1737
- aria-label="Edit ${r.label} items">${h(o)}</textarea>
1738
- <button class="quadrant__done-btn" data-quadrant="${t}"
1739
- aria-label="Done editing ${r.label}">${A(k.check)} Done</button>
1740
- </div>
1741
- `:""}
1742
- </div>
1743
- </div>
1744
- </section>`}_renderEmotion(t){let e=t.toLowerCase().trim(),r=q[e];return r?`<span class="emotion-tag" style="--ec:${r.color}"><span role="img" aria-label="${h(t)}">${r.emoji}</span> ${h(t)}</span>`:`<p>${h(t)}</p>`}_renderSummaryRow(t,e,r){let a=(t==="pain-points"?"painPoints":t)==="painPoints"?this.__painPoints:this.__goals,i=a?.length?a.map(o=>`<p>${h(o)}</p>`).join(""):`<slot name="${t}"><p class="placeholder">No ${r.toLowerCase()} specified.</p></slot>`;return`
1745
- <div class="summary-row">
1746
- <span class="summary-row__icon" aria-hidden="true">${e}</span>
1747
- <div class="summary-row__body">
1748
- <div class="summary-row__label">${r}</div>
1749
- <div class="summary-row__content">${i}</div>
1750
- </div>
1751
- </div>`}_bindEditListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".quadrant__edit-btn").forEach(e=>{e.addEventListener("click",()=>{let r=e.dataset.quadrant;r&&this._openEdit(r)})}),t.querySelectorAll(".quadrant__done-btn").forEach(e=>{e.addEventListener("click",()=>{let r=e.dataset.quadrant;r&&this._closeEdit(r)})}),t.querySelectorAll(".quadrant__editor").forEach(e=>{let r=e;r.addEventListener("keydown",s=>{let a=s;if(a.key==="Escape"){a.preventDefault();let i=r.dataset.quadrant;i&&this._closeEdit(i)}})}))}_openEdit(t){this._editingQuadrants.add(t);let e=this.shadowRoot?.querySelector(`.quadrant--${t}`);if(!e)return;e.setAttribute("data-editing","");let r=e.querySelector(".quadrant__face--front"),s=e.querySelector(".quadrant__face--back");r&&r.setAttribute("inert",""),s&&s.removeAttribute("inert");let a=e.querySelector(".quadrant__editor");if(a){let i=this.__quadrants?.[t];if(i?.length)a.value=i.join(`
1752
- `);else{let o=e.querySelector(`slot[name="${t}"]`);if(o){let n=o.assignedElements();if(n.length){let l=[];n.forEach(d=>{let p=d.querySelectorAll("li");p.length?p.forEach(u=>l.push(u.textContent?.trim()??"")):l.push(d.textContent?.trim()??"")}),a.value=l.filter(Boolean).join(`
1753
- `)}}}a.focus()}}_closeEdit(t){let e=this.shadowRoot?.querySelector(`.quadrant--${t}`);if(!e)return;let r=e.querySelector(".quadrant__editor");if(r){let i=r.value.split(`
1754
- `).map(n=>n.trim()).filter(Boolean);this.__quadrants||(this.__quadrants={}),this.__quadrants[t]=i;let o=e.querySelector(".quadrant__content");if(o)if(i.length)o.innerHTML=t==="feels"?i.map(n=>this._renderEmotion(n)).join(""):i.map(n=>`<p>${h(n)}</p>`).join("");else{let n=Z[t];o.innerHTML=`<p class="placeholder">Add ${n.label.toLowerCase()} items\u2026</p>`}}this._editingQuadrants.delete(t),e.removeAttribute("data-editing");let s=e.querySelector(".quadrant__face--front"),a=e.querySelector(".quadrant__face--back");s&&s.removeAttribute("inert"),a&&a.setAttribute("inert",""),this.dispatchEvent(new CustomEvent("empathy-map:update",{bubbles:!0,composed:!0,detail:{quadrant:t,items:this.__quadrants?.[t]||[]}}))}};x("empathy-map",ot);function V({newItems:c,nodes:t,keyOf:e,renderItem:r,containerFor:s}){let a=[],i=[],o=[],n=new Set;for(let d of c)n.add(e(d));for(let[d,p]of[...t])n.has(d)||(p.remove(),t.delete(d),o.push(d));let l=new Map;for(let d of c){let p=e(d),u=t.get(p)||null,m=s(d,u);l.has(m)||l.set(m,[]),l.get(m)?.push({item:d,key:p,existing:u})}for(let[d,p]of l)for(let u=0;u<p.length;u++){let{item:m,key:f,existing:g}=p[u],v=g;v?(v.parentElement!==d||d.children[u]!==v)&&i.push(f):(v=r(m),t.set(f,v),a.push(f));let y=d.children[u];y!==v&&d.insertBefore(v,y||null)}return{added:a,moved:i,removed:o}}var nt=class c extends C{static QUADRANTS=["quick-wins","big-bets","fill-ins","money-pit"];static LABELS={"quick-wins":"Quick Wins","big-bets":"Big Bets","fill-ins":"Fill-Ins","money-pit":"Money Pit"};static DESCRIPTIONS={"quick-wins":"High impact \xB7 Low effort","big-bets":"High impact \xB7 High effort","fill-ins":"Low impact \xB7 Low effort","money-pit":"Low impact \xB7 High effort"};static#e=0;static get observedAttributes(){return["src","compact","title"]}#t=null;#r={};#i=null;#s="";#o=null;setup(){this.#s=`ie-${++c.#e}`;let t=[...this.querySelectorAll(":scope > [data-quadrant], :scope > [draggable]")],e=document.createElement("div");e.className="ie-wrapper";let r=document.createElement("div");r.className="ie-y-label",r.setAttribute("aria-hidden","true"),r.textContent="Impact \u2191";let s=document.createElement("div");s.style.cssText="display:flex;flex-direction:column;flex:1;min-width:0;";let a=document.createElement("div");a.className="ie-grid",a.setAttribute("role","region"),a.setAttribute("aria-label","Impact-Effort prioritization matrix");let i=document.createElement("div");i.className="ie-x-label",i.setAttribute("aria-hidden","true"),i.textContent="Effort \u2192";for(let d of c.QUADRANTS){let p=document.createElement("section");p.className="ie-quadrant",p.dataset.quadrantZone=d,p.setAttribute("aria-label",`${c.LABELS[d]}: ${c.DESCRIPTIONS[d]}`);let u=document.createElement("header");u.className="ie-quadrant-label",u.innerHTML=`${c.LABELS[d]}<br><span class="ie-quadrant-desc">${c.DESCRIPTIONS[d]}</span>`;let m=document.createElement("drag-surface");m.setAttribute("group",this.#s),m.setAttribute("aria-label",c.LABELS[d]),m.setAttribute("data-layout","stack"),m.setAttribute("data-layout-gap","xs"),p.appendChild(u),p.appendChild(m),a.appendChild(p),this.#r[d]=m}t.forEach((d,p)=>{let u=d,m=u.getAttribute("data-quadrant")||"quick-wins",f=this.#r[m]||this.#r["quick-wins"];u.hasAttribute("draggable")||u.setAttribute("draggable","true"),u.hasAttribute("data-id")||(u.dataset.id=`ie-item-${p}`),f.appendChild(u)});let o=document.createElement("div");o.className="ie-live-region",o.setAttribute("role","status"),o.setAttribute("aria-live","polite"),o.setAttribute("aria-atomic","true");let n=this.getAttribute("title");if(n){let d=document.createElement("h3");d.className="ie-title",d.textContent=n,this.prepend(d)}s.appendChild(a),s.appendChild(i),e.appendChild(r),e.appendChild(s),this.appendChild(e),this.appendChild(o),this.#t=a,this.#i=o,this.#o=e,this.listen(this,"drag-surface:transfer",d=>{let{item:p,fromSurface:u,toSurface:m}=d.detail,f=this.#d(u),g=this.#d(m);!f||!g||(p.setAttribute("data-quadrant",g),this.#b(`Moved ${this.#m(p)} to ${c.LABELS[g]}`),this.dispatchEvent(new CustomEvent("impact-effort:move",{bubbles:!0,detail:{itemId:p.dataset.id,from:f,to:g,item:p}})))});let l=this.getAttribute("src");l&&this.#c(l),this.#u()}teardown(){this.#o&&(this.#o.remove(),this.#o=null),this.#i&&(this.#i.remove(),this.#i=null),this.#t=null,this.#r={},this.#n.clear(),this.#a=[]}#a=[];#n=new Map;get items(){if(this.#a.length)return this.#a;let t=[];for(let[e,r]of Object.entries(this.#r))for(let s of r.querySelectorAll(':scope > [draggable="true"]'))t.push({id:s.getAttribute("data-id")||void 0,quadrant:e,text:s.textContent?.trim()||void 0});return t}set items(t){if(!this.#t)return;let e=Array.isArray(t)?t:[];V({newItems:e,nodes:this.#n,keyOf:r=>r.id??`${r.quadrant}:${r.text}`,renderItem:r=>{let s=this;if(typeof s.renderItem=="function"){let i=s.renderItem(r);if(i instanceof Element)return i.hasAttribute("draggable")||i.setAttribute("draggable","true"),i.hasAttribute("data-id")||i.setAttribute("data-id",String(r.id??"")),i}let a=document.createElement("article");return a.className="ie-card",a.setAttribute("draggable","true"),r.id&&a.setAttribute("data-id",String(r.id)),a.textContent=r.text||r.id||"",a},containerFor:r=>this.#r[r.quadrant]||this.#r["quick-wins"]}),this.#a=e,this.dispatchEvent(new CustomEvent("impact-effort:items-changed",{detail:{items:e,source:"property"},bubbles:!0}))}attributeChangedCallback(t,e,r){this.hasAttribute("data-upgraded")&&t==="src"&&r&&r!==e&&this.#c(r)}async#c(t){try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();if(!Array.isArray(r))return;let s=()=>{for(let a of c.QUADRANTS){let i=this.#r[a];if(i)for(let o of[...i.querySelectorAll("[draggable]")])o.remove()}r.forEach((a,i)=>{let o=a.quadrant||"quick-wins",n=a.id||`ie-item-${i}`,l;a.persona||a.action||a.storyId?(l=document.createElement("user-story"),l.setAttribute("detail","minimal"),a.storyId&&l.setAttribute("story-id",a.storyId),a.persona&&l.setAttribute("persona",a.persona),a.action&&l.setAttribute("action",a.action),a.benefit&&l.setAttribute("benefit",a.benefit),a.priority&&l.setAttribute("priority",a.priority),a.status&&l.setAttribute("status",a.status),a.points&&l.setAttribute("points",String(a.points))):(l=document.createElement("article"),l.textContent=a.label||a.text||""),l.setAttribute("draggable","true"),l.dataset.id=n,l.dataset.quadrant=o,(this.#r[o]||this.#r["quick-wins"]).appendChild(l)})};this.hasAttribute("data-upgraded")&&this.#t?S(this,s,"ie-vt"):s(),this.#u()}catch(e){console.warn(`[impact-effort] Failed to load src="${t}":`,e)}}#d(t){for(let[e,r]of Object.entries(this.#r))if(r===t)return e;return null}#b(t){let e=this.#i;e&&(e.textContent="",requestAnimationFrame(()=>{e.textContent=t}))}#m(t){return t.dataset.id||t.textContent.trim().slice(0,40)}#u(){let t={};for(let e of c.QUADRANTS){let r=this.#r[e];t[e]=r?r.querySelectorAll('[draggable="true"]').length:0}this.dispatchEvent(new CustomEvent("impact-effort:ready",{bubbles:!0,detail:{quadrantCounts:t}}))}};x("impact-effort",nt);var ct=class c extends C{static#e=0;setup(){this.#m=`qg-${++c.#e}`;let t=this.getAttribute("x-label")||"",e=this.getAttribute("y-label")||"",r=this.getAttribute("x-low")||"Low",s=this.getAttribute("x-high")||"High",a=this.getAttribute("y-low")||"Low",i=this.getAttribute("y-high")||"High",o=[this.getAttribute("q1-label")||"Q1",this.getAttribute("q2-label")||"Q2",this.getAttribute("q3-label")||"Q3",this.getAttribute("q4-label")||"Q4"],n=this.hasAttribute("draggable"),l=[...this.querySelectorAll(":scope > [data-quadrant], :scope > [data-x][data-y]")],d=document.createElement("section");d.className="qg-wrapper",d.setAttribute("role","region"),d.setAttribute("aria-label",`${e} \xD7 ${t} quadrant grid`);let p=document.createElement("header");p.className="qg-y-label",p.setAttribute("aria-hidden","true"),p.textContent=`\u2191 ${e}`;let u=document.createElement("aside");u.className="qg-y-scale",u.setAttribute("aria-hidden","true"),u.innerHTML=`<span>${i}</span><span>${a}</span>`;let m=document.createElement("div");m.className="qg-grid";let f=document.createElement("aside");f.className="qg-x-scale",f.setAttribute("aria-hidden","true"),f.innerHTML=`<span>${r}</span><span>${s}</span>`;let g=document.createElement("footer");g.className="qg-x-label",g.setAttribute("aria-hidden","true"),g.textContent=`${t} \u2192`;for(let y=0;y<4;y++){let _=document.createElement("section");_.className="qg-quadrant",_.dataset.quadrantZone=String(y),_.setAttribute("aria-label",o[y]);let b=document.createElement("header");if(b.className="qg-quadrant-label",b.textContent=o[y],_.appendChild(b),n){let w=document.createElement("drag-surface");w.setAttribute("group",this.#m),w.setAttribute("aria-label",o[y]),w.setAttribute("data-layout","stack"),w.setAttribute("data-layout-gap","xs"),_.appendChild(w),this.#u[y]=w}else{let w=document.createElement("ul");w.className="qg-items",_.appendChild(w),this.#f[y]=w}m.appendChild(_),this.#v[y]=_}l.forEach((y,_)=>{let b=y,w=this.#n(b),T=n?this.#u[w]:this.#f[w];if(n&&(b.hasAttribute("draggable")||b.setAttribute("draggable","true")),b.hasAttribute("data-id")||(b.dataset.id=`qg-item-${_}`),b.hasAttribute("data-x")&&b.hasAttribute("data-y")){let E=parseFloat(b.getAttribute("data-x")??""),M=parseFloat(b.getAttribute("data-y")??"");if(Number.isFinite(E)&&Number.isFinite(M)){let $=w===0||w===3?(E-.5)*2:E*2,F=w===0||w===1?(M-.5)*2:M*2;if(b.style.setProperty("--qg-local-x",$.toFixed(4)),b.style.setProperty("--qg-local-y",F.toFixed(4)),b.classList.add("qg-pinned"),!b.style.getPropertyValue("--qg-pin-hue")){let Ot=b.dataset.id||(b.textContent||"").trim();b.style.setProperty("--qg-pin-hue",`${c.#o(Ot)}deg`)}}}if(n)T.appendChild(b);else{let E=document.createElement("li");E.appendChild(b),T.appendChild(E)}});let v=document.createElement("div");v.className="qg-live-region visually-hidden",v.setAttribute("role","status"),v.setAttribute("aria-live","polite"),d.appendChild(p),d.appendChild(u),d.appendChild(m),d.appendChild(f),d.appendChild(g),this.appendChild(d),this.appendChild(v),this.#l=m,this.#h=v,this.#y=o,n&&this.listen(this,"drag-surface:transfer",this.#a),this.#t()}#t(){if(typeof ResizeObserver>"u")return;let t=e=>{let r=e.offsetWidth,s=e.offsetHeight;r>0&&e.style.setProperty("--qg-pin-half-w",`${r/2}px`),s>0&&e.style.setProperty("--qg-pin-half-h",`${s/2}px`)};this.#g=new ResizeObserver(e=>{for(let r of e)t(r.target);this.#r()});for(let e of this.querySelectorAll(".qg-pinned"))this.#g.observe(e);this.#r()}#r(){this.#p||(this.#p=requestAnimationFrame(()=>{this.#p=0,this.#i()}))}#i(){for(let e of this.querySelectorAll(".qg-pinned")){let r=e;r.classList.remove("qg-clustered"),r.style.removeProperty("--qg-cluster-i"),r.style.removeProperty("--qg-cluster-n"),delete r.dataset.cluster,r.dataset.qgTabbed!==void 0&&(r.removeAttribute("tabindex"),delete r.dataset.qgTabbed)}let t=0;for(let e=0;e<4;e++){let r=this.#v[e];if(!r)continue;let s=[...r.querySelectorAll(".qg-pinned")];if(s.length<2)continue;let a=s.map(d=>d.getBoundingClientRect()),i=Array.from({length:s.length},(d,p)=>p),o=d=>i[d]===d?d:i[d]=o(i[d]),n=(d,p)=>{let u=o(d),m=o(p);u!==m&&(i[u]=m)};for(let d=0;d<s.length;d++)for(let p=d+1;p<s.length;p++)c.#s(a[d],a[p])&&n(d,p);let l=new Map;for(let d=0;d<s.length;d++){let p=o(d);l.has(p)||l.set(p,[]),l.get(p)?.push(d)}for(let d of l.values()){if(d.length<2)continue;let p=`c${++t}`;d.forEach((u,m)=>{let f=s[u];f.classList.add("qg-clustered"),f.dataset.cluster=p,f.style.setProperty("--qg-cluster-i",String(m)),f.style.setProperty("--qg-cluster-n",String(d.length)),!f.hasAttribute("tabindex")&&!f.matches("a, button, [contenteditable]")&&(f.setAttribute("tabindex","0"),f.dataset.qgTabbed="")})}}}teardown(){this.#g?.disconnect(),this.#g=null,this.#p&&cancelAnimationFrame(this.#p),this.#p=0}static#s(t,e){return!(t.right<=e.left||e.right<=t.left||t.bottom<=e.top||e.bottom<=t.top)}static#o(t){let e=5381;for(let r=0;r<t.length;r++)e=(e<<5)+e+t.charCodeAt(r)|0;return(e%360+360)%360}#a=t=>{let{item:e,fromSurface:r,toSurface:s}=t.detail,a=this.#c(r),i=this.#c(s);a==null||i==null||(e.setAttribute("data-quadrant",String(i)),this.#b(`Moved ${this.#d(e)} to ${this.#y[i]}`),this.dispatchEvent(new CustomEvent("quadrant-grid:move",{bubbles:!0,detail:{item:e,itemId:e.dataset.id,from:a,to:i}})))};#n(t){let e=parseInt(t.getAttribute("data-quadrant"),10);if(e>=0&&e<=3)return e;if(t.hasAttribute("data-x")&&t.hasAttribute("data-y")){let r=parseFloat(t.getAttribute("data-x")),s=parseFloat(t.getAttribute("data-y"));return c.quadrantFor(r,s)}return 0}static quadrantFor(t,e){let r=t>=.5,s=e>=.5;return s&&r?0:s&&!r?1:!s&&!r?2:3}#c(t){for(let e=0;e<4;e++)if(this.#u[e]===t)return e;return null}#d(t){return(t.textContent||"").trim().split(`
1755
- `)[0]||"item"}#b(t){this.#h&&(this.#h.textContent=t)}#m="";#u={};#f={};#v={};#l=null;#h=null;#y=[];#g=null;#p=0};x("quadrant-grid",ct);var It=5,dt=class c extends C{setup(){let t=this.querySelector(":scope > template"),e=t?c.#t(t):[];if(this.hasAttribute("src")){this.#e(this.getAttribute("src"));return}this.#r(e)}async#e(t){try{let r=await(await fetch(t)).json();this.#r(Array.isArray(r)?r:[])}catch(e){console.warn("risk-register: failed to load src",t,e),this.#r([])}}static#t(t){let e=[],r=t.content.querySelectorAll("tr");for(let s of r){let a=[...s.children],i=a[0]?.textContent?.trim()||"",o=s.getAttribute("data-id")||i.toLowerCase().replace(/\s+/g,"-")||`risk-${e.length}`;e.push({id:o,title:i,likelihood:parseInt(a[1]?.textContent??"",10)||0,impact:parseInt(a[2]?.textContent??"",10)||0,owner:a[3]?.textContent?.trim()||"",mitigation:a[4]?.textContent?.trim()||""})}return e}#r(t){this.#a=t,[...this.children].forEach(s=>{s.tagName!=="TEMPLATE"&&s.remove()});let e=this.getAttribute("label");if(e){let s=document.createElement("header");s.className="rr-label",s.textContent=e,this.appendChild(s)}let r=document.createElement("div");r.className="rr-layout",r.appendChild(this.#i(t)),r.appendChild(this.#s(t)),this.appendChild(r),queueMicrotask(()=>{this.dispatchEvent(new CustomEvent("risk-register:ready",{bubbles:!0,detail:{count:t.length}}))})}#i(t){let e=document.createElement("data-table"),r=document.createElement("table");return r.innerHTML=`
1756
- <thead>
1757
- <tr>
1758
- <th data-sort="string">Title</th>
1759
- <th data-sort="number">Likelihood</th>
1760
- <th data-sort="number">Impact</th>
1761
- <th data-sort="number" data-rollup="product" data-heatmap="low-good">Severity</th>
1762
- <th data-sort="string">Owner</th>
1763
- <th data-sort="string">Mitigation</th>
1764
- </tr>
1765
- </thead>
1766
- <tbody>
1767
- ${t.map(s=>`
1768
- <tr data-id="${c.#o(s.id)}">
1769
- <td>${c.#o(s.title)}</td>
1770
- <td>${s.likelihood||""}</td>
1771
- <td>${s.impact||""}</td>
1772
- <td></td>
1773
- <td>${c.#o(s.owner)}</td>
1774
- <td>${c.#o(s.mitigation)}</td>
1775
- </tr>
1776
- `).join("")}
1777
- </tbody>
1778
- `,e.appendChild(r),e}#s(t){let e=document.createElement("quadrant-grid");e.setAttribute("x-label","Likelihood"),e.setAttribute("y-label","Impact"),e.setAttribute("x-low","Rare"),e.setAttribute("x-high","Likely"),e.setAttribute("y-low","Minor"),e.setAttribute("y-high","Severe"),e.setAttribute("q1-label","Avoid"),e.setAttribute("q2-label","Plan"),e.setAttribute("q3-label","Accept"),e.setAttribute("q4-label","Mitigate");for(let r of t){if(!r.likelihood||!r.impact)continue;let s=document.createElement("span"),a=Math.min(1,Math.max(0,r.likelihood/It)),i=Math.min(1,Math.max(0,r.impact/It));s.setAttribute("data-x",a.toFixed(3)),s.setAttribute("data-y",i.toFixed(3)),s.setAttribute("data-id",r.id),s.setAttribute("title",`${r.title} \u2014 likelihood ${r.likelihood}, impact ${r.impact}`),s.textContent=r.title,e.appendChild(s)}return e}static#o(t){return String(t??"").replace(/[&<>"']/g,e=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[e])}#a=[];get rows(){return[...this.#a]}set rows(t){this.#r(Array.isArray(t)?t:[])}};x("risk-register",dt);var lt=class c extends C{setup(){let t=this.getAttribute("rows"),e=this.getAttribute("cols"),r=this.getAttribute("link-attr");return!t||!e||!r?(console.warn("traceability-matrix: requires rows, cols, and link-attr attributes"),!1):(queueMicrotask(()=>this.#e(t,e,r)),!0)}#e(t,e,r){let s=[...document.querySelectorAll(t)].filter(b=>b!==this&&!this.contains(b)),a=[...document.querySelectorAll(e)].filter(b=>b!==this&&!this.contains(b));if(!s.length||!a.length){this.#i();return}let i=this.getAttribute("row-label")||"",o=this.getAttribute("cell-mark")||"\u2713",n=this.hasAttribute("flag-orphans"),l=[],d=new WeakMap,p=new WeakMap;for(let b of s){let w=c.#s(b.getAttribute(r));for(let T of w){let E=a.find(M=>M.id===T);E&&(l.push({rowEl:b,colEl:E}),d.set(b,(d.get(b)||0)+1),p.set(E,(p.get(E)||0)+1))}}let u=document.createElement("data-table"),m=document.createElement("table"),f=document.createElement("thead"),g=document.createElement("tr"),v=document.createElement("th");v.setAttribute("data-sort","string"),v.textContent=i,g.appendChild(v);for(let b of a){let w=document.createElement("th");w.setAttribute("data-sort","number"),w.textContent=c.#o(b),w.dataset.colId=b.id||"",n&&!p.get(b)&&(w.dataset.orphan=""),g.appendChild(w)}f.appendChild(g),m.appendChild(f);let y=document.createElement("tbody");for(let b of s){let w=document.createElement("tr");w.dataset.rowId=b.id||"",n&&!d.get(b)&&(w.dataset.orphan="");let T=document.createElement("th");T.scope="row",T.textContent=c.#o(b),w.appendChild(T);let E=c.#s(b.getAttribute(r));for(let M of a){let $=document.createElement("td"),F=E.includes(M.id);$.setAttribute("data-sort-value",F?"1":"0"),F?($.dataset.linked="",$.textContent=o,$.setAttribute("aria-label","linked")):$.setAttribute("aria-label","not linked"),$.dataset.colId=M.id||"",w.appendChild($)}y.appendChild(w)}m.appendChild(y),u.appendChild(m),[...this.children].forEach(b=>{b.tagName!=="TEMPLATE"&&b.remove()});let _=this.getAttribute("label");if(_){let b=document.createElement("header");b.className="tm-label",b.textContent=_,this.appendChild(b)}this.appendChild(u),this.#a=u,this.#n=new Map(s.map(b=>[b.id,b])),this.#c=new Map(a.map(b=>[b.id,b])),this.listen(u,"click",this.#t),queueMicrotask(()=>{this.dispatchEvent(new CustomEvent("traceability-matrix:ready",{bubbles:!0,detail:{rowCount:s.length,colCount:a.length,linkCount:l.length}}))})}#t=t=>{let e=t.target.closest('td, th[scope="row"]');if(!e)return;let r=e.closest("tr");if(!r)return;let s=r.dataset.rowId,a=e.dataset.colId,i=s?this.#n.get(s):null,o=a?this.#c.get(a):null,n=e.hasAttribute("data-state-highlighted");if(this.#r(),n){this.dispatchEvent(new CustomEvent("traceability-matrix:highlight",{bubbles:!0,detail:{rowEl:i,colEl:o,on:!1}}));return}e.setAttribute("data-state-highlighted",""),i&&i.setAttribute("data-state-highlighted",""),o&&o!==i&&o.setAttribute("data-state-highlighted",""),r.setAttribute("data-state-highlighted",""),this.dispatchEvent(new CustomEvent("traceability-matrix:highlight",{bubbles:!0,detail:{rowEl:i,colEl:o,on:!0}}))};#r(){this.#a&&(this.#a.querySelectorAll("[data-state-highlighted]").forEach(t=>t.removeAttribute("data-state-highlighted")),document.querySelectorAll("[data-state-highlighted]").forEach(t=>{(this.#n.has(t.id)||this.#c.has(t.id))&&t.removeAttribute("data-state-highlighted")}))}#i(){[...this.children].forEach(e=>{e.tagName!=="TEMPLATE"&&e.remove()});let t=document.createElement("p");t.className="tm-empty",t.textContent="No matching elements found for this matrix.",this.appendChild(t)}static#s(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}static#o(t){return t.getAttribute("data-matrix-label")||t.id||(t.textContent||"").trim().split(`
1779
- `)[0].slice(0,60)||"(unnamed)"}#a=null;#n=new Map;#c=new Map};x("traceability-matrix",lt);var te=864e5,pt=class c extends C{setup(){let t=this.getAttribute("start"),e=this.getAttribute("end"),r=parseFloat(this.getAttribute("total")||"");if(!t||!e||!Number.isFinite(r))return console.warn("burndown-chart: requires start, end, and total attributes"),!1;let s=c.#r(t),a=c.#r(e);if(!s||!a||a<s)return console.warn("burndown-chart: start/end dates invalid",t,e),!1;let i=(this.getAttribute("weekends")||"include")!=="exclude",o=this.getAttribute("unit")||"points",n=this.getAttribute("label")||"",l=this.querySelector(":scope > template"),d=l?c.#t(l):[],p=d.filter(g=>g.delta!==0),u=c.#s(s,a),m=c.#o(u,r,i),f=c.#a(u,d);return this.#e({label:n,unit:o,dayLabels:u,actual:f,ideal:m,scopeChanges:p}),queueMicrotask(()=>{this.dispatchEvent(new CustomEvent("burndown-chart:ready",{bubbles:!0,detail:{dayCount:u.length,total:r,scopeChanges:p.length}}))}),!0}#e({label:t,unit:e,dayLabels:r,actual:s,ideal:a,scopeChanges:i}){if([...this.children].forEach(p=>{p.tagName!=="TEMPLATE"&&p.remove()}),t){let p=document.createElement("header");p.className="bdc-label",p.textContent=t,this.appendChild(p)}let o=document.createElement("chart-wc");o.setAttribute("data-type","line"),o.setAttribute("data-legend",""),o.setAttribute("data-tooltip",""),o.setAttribute("data-label-x","Day"),o.setAttribute("data-label-y",e);let n={},l={};r.forEach((p,u)=>{n[p]=a[u],s[u]!==null&&(l[p]=s[u])});let d=[{name:"Actual",values:l},{name:"Ideal",values:n}];if(o.setAttribute("data-values",JSON.stringify(d)),this.appendChild(o),i.length){let p=document.createElement("aside");p.className="bdc-scope-changes";let u=document.createElement("h4");u.textContent="Scope changes",p.appendChild(u);let m=document.createElement("ul");for(let f of i){let g=document.createElement("li"),v=f.delta>0?"+":"";g.innerHTML=`<time datetime="${f.date}">${f.date}</time>: <strong>${v}${f.delta} ${e}</strong>`,m.appendChild(g)}p.appendChild(m),this.appendChild(p)}}static#t(t){let e=[],r=t.content.querySelectorAll("tr");for(let s of r){let a=[...s.children],i=a[0]?.textContent?.trim(),o=parseFloat(a[1]?.textContent??""),n=parseFloat(a[2]?.textContent??"0")||0;!i||!Number.isFinite(o)||e.push({date:i,remaining:o,delta:n})}return e}static#r(t){let e=String(t).match(/^(\d{4})-(\d{2})-(\d{2})/);return e?new Date(Number(e[1]),Number(e[2])-1,Number(e[3])):null}static#i(t){let e=String(t.getMonth()+1).padStart(2,"0"),r=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${e}-${r}`}static#s(t,e){let r=[];for(let s=t.getTime();s<=e.getTime();s+=te)r.push(c.#i(new Date(s)));return r}static#o(t,e,r){let s=d=>{let p=c.#r(d);if(!p)return!1;let u=p.getDay();return u===0||u===6},a=t.map((d,p)=>({d,i:p,weekend:s(d)})).filter(d=>r||!d.weekend),i=a.length>1?e/(a.length-1):0,o=new Array(t.length).fill(null),n=e,l=0;for(let d=0;d<t.length;d++){let p=s(t[d]);r||!p?(o[d]=Math.max(0,e-i*l),l++,n=o[d]):o[d]=n}return o}static#a(t,e){let r=new Map(e.map(s=>[s.date,s.remaining]));return t.map(s=>r.has(s)?r.get(s):null)}};x("burndown-chart",pt);var ut=class c extends C{setup(){let t=this.getAttribute("start"),e=this.getAttribute("end");if(!t||!e)return console.warn("product-roadmap: start and end attributes required"),!1;let r=c.#f(t,"start"),s=c.#f(e,"end");if(!r||!s||s<=r)return console.warn("product-roadmap: invalid start/end",t,e),!1;this.#l=r,this.#h=s,this.#y=s.getTime()-r.getTime(),this.#g=this.getAttribute("view")==="month"?"month":"quarter",this.#p=this.hasAttribute("editable");let a=[...this.querySelectorAll(":scope > section[data-lane]")];return a.length?(this.#x=a,this.#e(),!0):(console.warn("product-roadmap: no <section data-lane> children found"),!1)}attributeChangedCallback(){this.isConnected&&this.#x.length&&this.#e()}#e(){[...this.children].forEach(s=>{this.#x.includes(s)||s.remove()}),this.#x.forEach(s=>{s.hidden=!0});let t=document.createElement("div");t.className="rm-wrapper";let e=this.#t();t.appendChild(e);let r=document.createElement("div");r.className="rm-lanes";for(let s of this.#x){let a=s.getAttribute("data-lane")||"",i=document.createElement("section");i.className="rm-lane",i.dataset.lane=a;let o=document.createElement("header");o.className="rm-lane-label",o.textContent=a,i.appendChild(o);let n=document.createElement("div");n.className="rm-track",n.dataset.lane=a;let l=[...s.querySelectorAll(":scope > article[data-start][data-end]")];for(let d of l){let p=this.#r(d,a);p&&n.appendChild(p)}this.#p&&(n.addEventListener("dragover",this.#n),n.addEventListener("drop",this.#c)),i.appendChild(n),r.appendChild(i)}if(t.appendChild(r),this.hasAttribute("today-marker")&&this.#l&&this.#h){let s=new Date;if(s>=this.#l&&s<=this.#h){let a=document.createElement("div");a.className="rm-today",a.style.setProperty("--rm-x",this.#d(s).toFixed(4)),a.title=`Today: ${c.#v(s)}`,r.appendChild(a)}}this.appendChild(t),this.#k=t}#t(){let t=document.createElement("header");t.className="rm-axis";let e=this.#u();for(let r of e){let s=document.createElement("div");s.className="rm-tick",s.style.setProperty("--rm-x",r.startFraction.toFixed(4)),s.style.setProperty("--rm-w",(r.endFraction-r.startFraction).toFixed(4)),s.textContent=r.label,t.appendChild(s)}return t}#r(t,e){let r=c.#f(t.getAttribute("data-start"),"start"),s=c.#f(t.getAttribute("data-end"),"end");if(!r||!s||!this.#l||!this.#h)return null;let a=r<this.#l?this.#l:r,i=s>this.#h?this.#h:s;if(a>=i)return null;let o=this.#d(a),n=this.#d(i)-o,l=document.createElement("article");l.className="rm-bar",l.style.setProperty("--rm-x",o.toFixed(4)),l.style.setProperty("--rm-w",n.toFixed(4)),l.dataset.lane=e,l.dataset.start=c.#v(r),l.dataset.end=c.#v(s),t.dataset.status&&(l.dataset.status=t.dataset.status),t.id&&(l.dataset.sourceId=t.id),this.#p&&l.setAttribute("draggable","true");let d=t.querySelector("h1, h2, h3, h4, h5, h6"),p=document.createElement("span");if(p.className="rm-bar-title",p.textContent=d?d.textContent.trim():(t.textContent||"").trim().split(`
1780
- `)[0],l.appendChild(p),l.setAttribute("aria-label",`${p.textContent} \u2014 ${l.dataset.start} to ${l.dataset.end} in ${e}`),l.addEventListener("click",u=>{this.#w||this.dispatchEvent(new CustomEvent("product-roadmap:select",{bubbles:!0,detail:{initiative:t,lane:e,start:l.dataset.start,end:l.dataset.end,status:l.dataset.status||null}}))}),this.#p){let u=document.createElement("span");u.className="rm-bar-handle",u.setAttribute("aria-label","Resize end date"),l.appendChild(u),u.addEventListener("pointerdown",m=>this.#s(m,l,t)),l.addEventListener("pointerdown",m=>{m.target!==u&&this.#i(m,l,t)}),l.addEventListener("dragstart",m=>{m.dataTransfer&&(m.dataTransfer.effectAllowed="move",m.dataTransfer.setData("text/plain",t.id||l.dataset.sourceId||"")),this.#A=t,this.#_=e}),l.addEventListener("dragend",()=>{this.#A=null,this.#_=null})}return l}#i(t,e,r){if(t.button!==0)return;t.preventDefault();let s=e.parentElement.getBoundingClientRect(),a=t.clientX,i=parseFloat(e.style.getPropertyValue("--rm-x"))||0,o=parseFloat(e.style.getPropertyValue("--rm-w"))||0;this.#w={kind:"move",bar:e,initiative:r,trackRect:s,startX:a,startFraction:i,widthFraction:o},e.setPointerCapture(t.pointerId),e.addEventListener("pointermove",this.#o),e.addEventListener("pointerup",this.#a),e.addEventListener("pointercancel",this.#a)}#s(t,e,r){if(t.button!==0)return;t.preventDefault(),t.stopPropagation();let s=e.parentElement.getBoundingClientRect(),a=t.clientX,i=parseFloat(e.style.getPropertyValue("--rm-x"))||0,o=parseFloat(e.style.getPropertyValue("--rm-w"))||0;this.#w={kind:"resize",bar:e,initiative:r,trackRect:s,startX:a,startFraction:i,widthFraction:o},e.setPointerCapture(t.pointerId),e.addEventListener("pointermove",this.#o),e.addEventListener("pointerup",this.#a),e.addEventListener("pointercancel",this.#a)}#o=t=>{if(!this.#w)return;let{kind:e,bar:r,trackRect:s,startX:a,startFraction:i,widthFraction:o}=this.#w,n=(t.clientX-a)/s.width;if(e==="move"){let l=Math.max(0,Math.min(1-o,i+n));r.style.setProperty("--rm-x",l.toFixed(4))}else if(e==="resize"){let l=Math.max(.02,Math.min(1-i,o+n));r.style.setProperty("--rm-w",l.toFixed(4))}};#a=t=>{if(!this.#w)return;let{kind:e,bar:r,initiative:s}=this.#w;r.releasePointerCapture(t.pointerId),r.removeEventListener("pointermove",this.#o),r.removeEventListener("pointerup",this.#a),r.removeEventListener("pointercancel",this.#a);let a=parseFloat(r.style.getPropertyValue("--rm-x"))||0,i=parseFloat(r.style.getPropertyValue("--rm-w"))||0,o=this.#m(this.#b(a)),n=this.#m(this.#b(a+i));r.dataset.start=c.#v(o),r.dataset.end=c.#v(n);let l=this.#d(o),d=this.#d(n)-l;r.style.setProperty("--rm-x",l.toFixed(4)),r.style.setProperty("--rm-w",d.toFixed(4)),s&&(s.setAttribute("data-start",r.dataset.start??""),s.setAttribute("data-end",r.dataset.end??"")),this.dispatchEvent(new CustomEvent(e==="move"?"product-roadmap:reschedule":"product-roadmap:resize",{bubbles:!0,detail:{initiative:s,lane:r.dataset.lane,start:r.dataset.start,end:r.dataset.end}})),setTimeout(()=>{this.#w=null},0)};#n=t=>{this.#A&&(t.preventDefault(),t.dataTransfer.dropEffect="move")};#c=t=>{if(!this.#A)return;t.preventDefault();let e=t.currentTarget.dataset.lane,r=this.#A,s=this.#_;if(e===s)return;let a=this.#x.find(i=>i.getAttribute("data-lane")===e);a&&a.appendChild(r),this.dispatchEvent(new CustomEvent("product-roadmap:move",{bubbles:!0,detail:{initiative:r,fromLane:s,toLane:e,start:r.getAttribute("data-start"),end:r.getAttribute("data-end")}})),this.#e()};#d(t){if(!this.#l)return 0;let e=t.getTime()-this.#l.getTime();return Math.max(0,Math.min(1,e/this.#y))}#b(t){let e=this.#l??new Date;return new Date(e.getTime()+t*this.#y)}#m(t){if(this.#g==="month")return new Date(t.getFullYear(),t.getMonth(),1);let e=t.getMonth(),r=Math.floor(e/3)*3;return new Date(t.getFullYear(),r,1)}#u(){let t=[],e=this.#l,r=this.#h;if(!e||!r)return t;if(this.#g==="quarter"){let s=this.#m(e);for(;s<r;){let a=new Date(s.getFullYear(),s.getMonth()+3,1),i=this.#d(s<e?e:s),o=this.#d(a>r?r:a),n=Math.floor(s.getMonth()/3)+1;t.push({startFraction:i,endFraction:o,label:`Q${n} ${s.getFullYear()}`}),s=a}}else{let s=new Date(e.getFullYear(),e.getMonth(),1);for(;s<r;){let a=new Date(s.getFullYear(),s.getMonth()+1,1),i=this.#d(s<e?e:s),o=this.#d(a>r?r:a),n=s.toLocaleString(void 0,{month:"short"});t.push({startFraction:i,endFraction:o,label:`${n} ${s.getFullYear()}`}),s=a}}return t}static#f(t,e){if(!t)return null;let r=String(t).match(/^(\d{4})-Q([1-4])$/i);if(r){let i=Number(r[1]),n=(Number(r[2])-1)*3;return e==="end"?new Date(i,n+3,0):new Date(i,n,1)}let s=String(t).match(/^(\d{4})-(\d{2})-(\d{2})/);if(s)return new Date(Number(s[1]),Number(s[2])-1,Number(s[3]));let a=new Date(t);return isNaN(a.getTime())?null:a}static#v(t){let e=String(t.getMonth()+1).padStart(2,"0"),r=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${e}-${r}`}#l=null;#h=null;#y=0;#g="quarter";#p=!1;#x=[];#k=null;#w=null;#A=null;#_=null};x("product-roadmap",ut);function Tt(c){let t=c;return class extends t{static keyOf(e){return e.id}#e=[];#t=new Map;get items(){return this.#e}set items(e){let r=e||[],s=V({newItems:r,nodes:this.#t,keyOf:this.constructor.keyOf,renderItem:a=>this._renderItem(a),containerFor:(a,i)=>this._containerFor(a,i)});this.#e=r,this._postRender({...s,items:r}),this._emit("items-changed",{items:r},"api")}_renderItem(e){throw new Error(`${this.constructor.name}: must implement _renderItem(item)`)}_containerFor(e,r){return this}_postRender(e){}_emit(e,r,s="api"){this.dispatchEvent(new CustomEvent(`${this.localName}:${e}`,{detail:{...r,source:s},bubbles:!0}))}_nodeFor(e){return this.#t.get(e)||null}_seedCollection(e,r){this.#e=e,this.#t.clear();for(let[s,a]of r)this.#t.set(s,a)}_setItemsSilently(e){this.#e=e}}}var ht=class c extends Tt(C){static get observedAttributes(){return["src","compact","title"]}static keyOf(t){return t.id??t.storyId}static#e=0;#t=null;#r={};#i={};#s=null;#o="";#a=[];#n=null;setup(){this.#o=`kb-${++c.#e}`;let t=[...this.querySelectorAll(":scope > section[data-column]")];this.#a=t.map(a=>{let i=a.getAttribute("data-column")||"",n=a.getAttribute("data-column-label")||""||this.#y(i),l=a.getAttribute("data-wip"),d=l?parseInt(l,10):null,p=a.getAttribute("data-column-color")||null,u=[...a.children];return{id:i,label:n,wip:d,color:p,children:u}});for(let a of t)a.remove();this.#t=document.createElement("div"),this.#t.className="kb-columns",this.#t.setAttribute("role","region"),this.#t.setAttribute("aria-label","Kanban board");let e=0;for(let a of this.#a){let i=document.createElement("section");i.className="kb-column",i.setAttribute("data-column-id",a.id),a.color&&i.setAttribute("data-column-tint",a.color);let o=document.createElement("header");o.className="kb-column-header";let n=document.createElement("h3");n.textContent=a.label;let l=document.createElement("output");if(l.className="kb-count",l.textContent=String(a.children.length),n.appendChild(l),a.wip!==null&&!isNaN(a.wip)){let p=document.createElement("span");p.className="kb-wip",p.textContent=`/ ${a.wip}`,p.setAttribute("aria-label",`WIP limit ${a.wip}`),n.appendChild(p)}o.appendChild(n),i.appendChild(o);let d=document.createElement("drag-surface");if(d.setAttribute("group",this.#o),d.setAttribute("aria-label",`${a.label} items`),d.setAttribute("data-layout","stack"),d.setAttribute("data-layout-gap","xs"),a.children.length>0){for(let p of a.children)p.hasAttribute("draggable")||p.setAttribute("draggable","true"),p.hasAttribute("data-id")||(p.dataset.id=`kb-item-${e}`),d.appendChild(p);e+=a.children.length}else{let p=document.createElement("p");p.className="kb-empty",p.textContent="No items",d.appendChild(p)}i.appendChild(d),this.#t.appendChild(i),this.#r[a.id]=d,this.#i[a.id]=i,a.wip!==null&&a.children.length>a.wip&&i.setAttribute("data-wip-exceeded","")}let r=this.getAttribute("title");if(r){let a=document.createElement("h2");a.className="kb-title",a.textContent=r,this.appendChild(a)}this.appendChild(this.#t),this.#s=document.createElement("div"),this.#s.className="kb-live-region",this.#s.setAttribute("role","status"),this.#s.setAttribute("aria-live","polite"),this.#s.setAttribute("aria-atomic","true"),this.appendChild(this.#s),this.listen(this,"drag-surface:reorder",a=>{let i=a.detail,o=a.target.closest("drag-surface"),n=this.#u(o);n&&(this.#f(n),this.#d("drag"),this.dispatchEvent(new CustomEvent("kanban-board:reorder",{bubbles:!0,detail:{itemId:i.itemId,column:n,oldIndex:i.oldIndex,newIndex:i.newIndex}})))}),this.listen(this,"drag-surface:transfer",a=>{let i=a.detail,o=i.fromSurface,n=i.toSurface,l=this.#u(o),d=this.#u(n);if(!l||!d)return;i.item&&i.item.setAttribute("data-column",d),this.#f(l),this.#f(d);let p=n.querySelector(".kb-empty");if(p&&p.remove(),o.querySelectorAll(':scope > [draggable="true"]').length===0&&!o.querySelector(".kb-empty")){let _=document.createElement("p");_.className="kb-empty",_.textContent="No items",o.appendChild(_)}let m=this.#h(i.item),f=this.#v(l),g=this.#v(d);this.#l(`${m} moved from ${f} to ${g}`),this.#d("drag"),this.dispatchEvent(new CustomEvent("kanban-board:transfer",{bubbles:!0,detail:{itemId:i.itemId,fromColumn:l,toColumn:d,newIndex:i.newIndex,item:i.item}}));let v=n.querySelectorAll(':scope > [draggable="true"]').length,y=this.#a.find(_=>_.id===d);y?.wip!==null&&y?.wip!==void 0&&v>y.wip&&this.dispatchEvent(new CustomEvent("kanban-board:wip-exceeded",{bubbles:!0,detail:{column:d,limit:y.wip,count:v}}))}),this.#c();let s=this.getAttribute("src");if(s){this._loadSrc(s);return}this.dispatchEvent(new CustomEvent("kanban-board:ready",{bubbles:!0,detail:{columnCount:this.#a.length,itemCount:e}}))}#c(){let t=[],e=new Map;for(let[r,s]of Object.entries(this.#r)){let a=s.querySelectorAll(':scope > [draggable="true"]');for(let i of a){let o=i.getAttribute("data-id");o&&(t.push({id:o,column:r}),e.set(o,i))}}this._seedCollection(t,e)}#d(t){let e=[],r=new Map;for(let s of this.items){let a=String(s.id??s.storyId??"");a&&r.set(a,s)}for(let[s,a]of Object.entries(this.#r)){let i=a.querySelectorAll(':scope > [draggable="true"]');for(let o of i){let n=o.getAttribute("data-id");if(!n)continue;let l=r.get(n);e.push(l?{...l,column:s}:{id:n,column:s})}}this._setItemsSilently(e),this._emit("items-changed",{items:e},t)}teardown(){let t=this.querySelector(".kb-title");t&&t.remove(),this.#t&&(this.#t.remove(),this.#t=null),this.#s&&(this.#s.remove(),this.#s=null),this.#r={},this.#i={},this.#a=[]}get columns(){return this.#a.map(t=>({id:t.id,label:t.label,wip:t.wip??void 0,color:t.color??void 0}))}set columns(t){let e=(t||[]).map(i=>({id:i.id,label:i.label||this.#y(i.id),wip:i.wip??null,color:i.color??null,children:[]})),r=this.#t;this.#r={},this.#i={},this.#a=e;let s=this.#m();this.#t=s;let a=()=>{r&&r.remove(),this.appendChild(s)};this.hasAttribute("data-upgraded")&&r?S(this,a,"kb-vt"):a()}get renderItem(){return this.#n}set renderItem(t){this.#n=typeof t=="function"?t:null}_renderItem(t){let e;if(this.#n){let r=this.#n(t);if(!(r instanceof Element))throw new Error("kanban-board: renderItem must return an Element");e=r}else e=this.#b(t);return e.hasAttribute("draggable")||e.setAttribute("draggable","true"),e.hasAttribute("data-id")||e.setAttribute("data-id",String(c.keyOf(t))),e}_containerFor(t,e){let r=this.#r[t.column];if(!r)throw new Error(`kanban-board: no column "${t.column}" \u2014 set .columns first or include item.column matching an existing column id`);let s=r.querySelector(":scope > .kb-empty");return s&&s.remove(),r}_postRender(){for(let t of Object.keys(this.#r)){this.#f(t);let e=this.#r[t],r=e.querySelectorAll(':scope > [draggable="true"]'),s=e.querySelector(":scope > .kb-empty");if(r.length===0&&!s){let a=document.createElement("p");a.className="kb-empty",a.textContent="No items",e.appendChild(a)}else r.length>0&&s&&s.remove()}}#b(t){let e=customElements.get("work-item")?"work-item":"article",r=document.createElement(e);return e==="work-item"?r.data={itemId:t.id??t.storyId,type:t.type,priority:t.priority,status:t.status,estimate:t.estimate!=null?String(t.estimate):void 0,assignee:t.assignee,title:t.title,description:t.description,checklist:t.checklist,notes:t.notes,detail:t.detail}:(r.className="kb-card",r.textContent=t.title||t.label||t.id),r}#m(){let t=document.createElement("div");t.className="kb-columns",t.setAttribute("role","region"),t.setAttribute("aria-label","Kanban board");for(let e of this.#a){let r=document.createElement("section");r.className="kb-column",r.setAttribute("data-column-id",e.id),e.color&&r.setAttribute("data-column-tint",e.color);let s=document.createElement("header");s.className="kb-column-header";let a=document.createElement("h3");a.textContent=e.label;let i=document.createElement("output");if(i.className="kb-count",i.textContent="0",a.appendChild(i),e.wip!=null&&!isNaN(e.wip)){let l=document.createElement("span");l.className="kb-wip",l.textContent=`/ ${e.wip}`,l.setAttribute("aria-label",`WIP limit ${e.wip}`),a.appendChild(l)}s.appendChild(a),r.appendChild(s);let o=document.createElement("drag-surface");o.setAttribute("group",this.#o),o.setAttribute("aria-label",`${e.label} items`),o.setAttribute("data-layout","stack"),o.setAttribute("data-layout-gap","xs");let n=document.createElement("p");n.className="kb-empty",n.textContent="No items",o.appendChild(n),r.appendChild(o),t.appendChild(r),this.#r[e.id]=o,this.#i[e.id]=r}return t}attributeChangedCallback(t,e,r){e===r||!this.isConnected||t==="src"&&this._loadSrc(r)}async _loadSrc(t){if(t)try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();for(;this.firstChild;)this.firstChild.remove();for(let a of r.columns||[]){let i=document.createElement("section");i.setAttribute("data-column",a.id),a.label&&i.setAttribute("data-column-label",a.label),a.wip!=null&&i.setAttribute("data-wip",String(a.wip)),a.color&&i.setAttribute("data-column-color",a.color);for(let o of a.items||[]){let n;o.persona||o.action||o.storyId?(n=document.createElement("user-story"),n.setAttribute("detail",o.detail||"minimal"),o.storyId&&n.setAttribute("story-id",o.storyId),o.persona&&n.setAttribute("persona",o.persona),o.action&&n.setAttribute("action",o.action),o.benefit&&n.setAttribute("benefit",o.benefit),o.priority&&n.setAttribute("priority",o.priority),o.status&&n.setAttribute("status",o.status),o.points&&n.setAttribute("points",String(o.points))):(n=document.createElement("article"),n.className="kb-card",n.textContent=o.text||o.label||""),n.setAttribute("draggable","true"),n.dataset.id=o.id||o.storyId||"",i.appendChild(n)}this.appendChild(i)}let s=()=>{this.teardown(),this.removeAttribute("data-upgraded"),this.setup()};this.hasAttribute("data-upgraded")&&this.#t?S(this,s,"kb-vt"):s()}catch(e){console.warn(`[kanban-board] Failed to load src="${t}":`,e)}}#u(t){if(!t)return null;for(let[e,r]of Object.entries(this.#r))if(r===t)return e;return null}#f(t){let e=this.#r[t],r=this.#i[t];if(!e||!r)return;let s=e.querySelectorAll(':scope > [draggable="true"]').length,a=r.querySelector(".kb-count");a&&(a.textContent=String(s));let i=this.#a.find(o=>o.id===t);i?.wip!==null&&i?.wip!==void 0&&(s>i.wip?r.setAttribute("data-wip-exceeded",""):r.removeAttribute("data-wip-exceeded"))}#v(t){return this.#a.find(r=>r.id===t)?.label||this.#y(t)}#l(t){this.#s&&(this.#s.textContent="",requestAnimationFrame(()=>{this.#s&&(this.#s.textContent=t)}))}#h(t){return t.getAttribute("story-id")||t.getAttribute("data-id")||t.textContent?.trim().slice(0,40)||"item"}#y(t){return t.replace(/[-_]/g," ").replace(/\b\w/g,e=>e.toUpperCase())}};x("kanban-board",ht);var mt=class c extends C{static get observedAttributes(){return["src","compact","title"]}static#e=0;#t=null;#r=null;#i={};#s=null;#o="";#a=[];setup(){this.#o=`sm-${++c.#e}`;let t=[...this.querySelectorAll(":scope > section[data-activity]")];this.#a=t.map(a=>{let i=a.getAttribute("data-activity")||"",n=a.getAttribute("data-activity-label")||""||this.#m(i),l=a.getAttribute("data-journey-phase")||null,d=[...a.children];return{id:i,label:n,journeyPhase:l,children:d}});for(let a of t)a.remove();this.#t=document.createElement("div"),this.#t.className="sm-scroll",this.#t.setAttribute("role","region"),this.#t.setAttribute("aria-label","Story map"),this.#t.setAttribute("tabindex","0"),this.#r=document.createElement("div"),this.#r.className="sm-columns";let e=0;for(let a of this.#a){let i=document.createElement("section");i.className="sm-column",i.setAttribute("data-activity-column",a.id);let o=document.createElement("header");o.className="sm-activity-header";let n=document.createElement("h3");n.textContent=a.label;let l=document.createElement("span");l.className="sm-activity-count",l.textContent=String(a.children.length),n.appendChild(l),o.appendChild(n),i.appendChild(o);let d=document.createElement("drag-surface");if(d.setAttribute("group",this.#o),d.setAttribute("aria-label",`${a.label} stories`),d.setAttribute("data-layout","stack"),d.setAttribute("data-layout-gap","xs"),a.children.length>0){for(let p of a.children)d.appendChild(p);e+=a.children.length}else{let p=document.createElement("p");p.className="sm-empty",p.textContent="No stories yet",d.appendChild(p)}i.appendChild(d),this.#r.appendChild(i),this.#i[a.id]=d}let r=this.getAttribute("title");if(r){let a=document.createElement("h2");a.className="sm-title",a.textContent=r,this.appendChild(a)}this.#t.appendChild(this.#r),this.appendChild(this.#t),this.#s=document.createElement("div"),this.#s.className="sm-live-region",this.#s.setAttribute("role","status"),this.#s.setAttribute("aria-live","polite"),this.#s.setAttribute("aria-atomic","true"),this.appendChild(this.#s),this.listen(this,"drag-surface:reorder",a=>{let i=a.detail,o=a.target.closest("drag-surface"),n=this.#n(o);n&&(this.#c(n),this.dispatchEvent(new CustomEvent("story-map:reorder",{bubbles:!0,detail:{itemId:i.itemId,activity:n,oldIndex:i.oldIndex,newIndex:i.newIndex}})))}),this.listen(this,"drag-surface:transfer",a=>{let i=a.detail,o=i.fromSurface,n=i.toSurface,l=this.#n(o),d=this.#n(n);if(!l||!d)return;this.#c(l),this.#c(d);let p=n.querySelector(".sm-empty");if(p&&p.remove(),o.querySelectorAll(':scope > [draggable="true"]').length===0&&!o.querySelector(".sm-empty")){let f=document.createElement("p");f.className="sm-empty",f.textContent="No stories yet",o.appendChild(f)}let m=this.#b(i.item);this.#d(`${m} moved from ${l} to ${d}`),this.dispatchEvent(new CustomEvent("story-map:transfer",{bubbles:!0,detail:{itemId:i.itemId,fromActivity:l,toActivity:d,newIndex:i.newIndex}}))});let s=this.getAttribute("src");if(s){this._loadSrc(s);return}this.dispatchEvent(new CustomEvent("story-map:ready",{bubbles:!0,detail:{activityCount:this.#a.length,storyCount:e}}))}teardown(){this.#t&&(this.#t.remove(),this.#t=null),this.#s&&(this.#s.remove(),this.#s=null),this.#r=null,this.#i={},this.#a=[]}get activities(){return this.#a.map(t=>({id:t.id,label:t.label,journeyPhase:t.journeyPhase||void 0,stories:[...this.#i[t.id]?.querySelectorAll(':scope > [draggable="true"]')||[]].map(e=>({id:e.getAttribute("data-id")||void 0,storyId:e.getAttribute("story-id")||void 0,title:e.querySelector('[slot="title"]')?.textContent?.trim()||void 0}))}))}set activities(t){let e=Array.isArray(t)?t:[];for(;this.firstChild;)this.firstChild.remove();for(let s of e){let a=document.createElement("section");a.setAttribute("data-activity",s.id||""),s.label&&a.setAttribute("data-activity-label",s.label),s.journeyPhase&&a.setAttribute("data-journey-phase",s.journeyPhase);for(let i of s.stories||[]){let o,n=this;if(typeof n.renderStory=="function"){let l=n.renderStory(i);o=l instanceof Element?l:null}o||(customElements.get("user-story")?(o=document.createElement("user-story"),o.data=i):(o=document.createElement("article"),o.className="sm-card",o.textContent=i.title||i.id||"")),o.hasAttribute("draggable")||o.setAttribute("draggable","true"),i.id&&!o.hasAttribute("data-id")&&o.setAttribute("data-id",String(i.id)),a.appendChild(o)}this.appendChild(a)}let r=()=>{this.teardown(),this.removeAttribute("data-upgraded"),this.setup()};this.hasAttribute("data-upgraded")&&this.#t?S(this,r,"sm-vt"):r(),this.dispatchEvent(new CustomEvent("story-map:activities-changed",{detail:{activities:e,source:"property"},bubbles:!0}))}attributeChangedCallback(t,e,r){e===r||!this.isConnected||t==="src"&&this._loadSrc(r)}async _loadSrc(t){if(t)try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();for(;this.firstChild;)this.firstChild.remove();for(let a of r.activities||[]){let i=document.createElement("section");i.setAttribute("data-activity",a.id),i.setAttribute("data-activity-label",a.label||a.id),a.journeyPhase&&i.setAttribute("data-journey-phase",a.journeyPhase);for(let o of a.stories||[]){let n=document.createElement("user-story");n.setAttribute("draggable","true"),n.dataset.id=o.id||o.storyId,(o.storyId||o.id)&&n.setAttribute("story-id",o.storyId||o.id),o.title&&n.setAttribute("title",o.title),o.persona&&n.setAttribute("persona",o.persona),o.action&&n.setAttribute("action",o.action),o.benefit&&n.setAttribute("benefit",o.benefit),o.priority&&n.setAttribute("priority",o.priority),o.status&&n.setAttribute("status",o.status),o.points&&n.setAttribute("points",String(o.points)),n.setAttribute("detail",o.detail||"compact"),i.appendChild(n)}this.appendChild(i)}let s=()=>{this.teardown(),this.removeAttribute("data-upgraded"),this.setup()};this.hasAttribute("data-upgraded")&&this.#t?S(this,s,"sm-vt"):s()}catch(e){console.warn(`[story-map] Failed to load src="${t}":`,e)}}#n(t){if(!t)return null;for(let[e,r]of Object.entries(this.#i))if(r===t)return e;return null}#c(t){let e=this.#i[t];if(!e)return;let r=e.querySelectorAll(':scope > [draggable="true"]').length,s=e.closest("[data-activity-column]");if(!s)return;let a=s.querySelector(".sm-activity-count");a&&(a.textContent=String(r))}#d(t){this.#s&&(this.#s.textContent="",requestAnimationFrame(()=>{this.#s&&(this.#s.textContent=t)}))}#b(t){return t.getAttribute("story-id")||t.getAttribute("data-id")||t.textContent?.trim().slice(0,40)||"item"}#m(t){return t.replace(/[-_]/g," ").replace(/\b\w/g,e=>e.toUpperCase())}};x("story-map",mt);var Q=`
1781
- :host {
1782
- display: block;
1783
- position: relative;
1784
- font-family: var(--_font-sans);
1785
- line-height: 1.5;
1786
- color: var(--_text);
1787
- container-type: inline-size;
1788
-
1789
- --_bg: var(--review-surface-bg, var(--color-surface, #ffffff));
1790
- --_card: var(--review-surface-card, var(--color-surface-raised, #f8f9fa));
1791
- --_border: var(--review-surface-border, var(--color-border, #e0e0e0));
1792
- --_text: var(--review-surface-text, var(--color-text, #1a1a1a));
1793
- --_muted: var(--review-surface-muted, var(--color-text-muted, #666666));
1794
- --_accent: var(--review-surface-accent, var(--color-interactive, #0066cc));
1795
- --_pin-bg: var(--review-surface-pin-bg, var(--color-interactive, #0066cc));
1796
- --_pin-text: var(--review-surface-pin-text, #ffffff);
1797
- --_pin-size: var(--review-surface-pin-size, 28px);
1798
- --_resolved: var(--review-surface-resolved, var(--color-success, #16a34a));
1799
- --_radius: var(--review-surface-radius, var(--radius-xl, 1rem));
1800
- --_radius-m: var(--review-surface-radius-m, var(--radius-m, 0.5rem));
1801
- --_radius-full: var(--review-surface-radius-full, var(--radius-full, 9999px));
1802
- --_font-sans: var(--review-surface-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
1803
- --_font-xs: var(--review-surface-font-xs, var(--font-size-xs, 0.75rem));
1804
- --_font-sm: var(--review-surface-font-sm, var(--font-size-sm, 0.875rem));
1805
- --_font-md: var(--review-surface-font-md, var(--font-size-md, 1rem));
1806
- --_space-2xs: var(--review-surface-space-2xs, var(--size-2xs, 0.25rem));
1807
- --_space-xs: var(--review-surface-space-xs, var(--size-xs, 0.5rem));
1808
- --_space-s: var(--review-surface-space-s, var(--size-s, 0.75rem));
1809
- --_space-m: var(--review-surface-space-m, var(--size-m, 1rem));
1810
- --_space-l: var(--review-surface-space-l, var(--size-l, 1.5rem));
1811
- --_duration: var(--review-surface-duration, var(--duration-normal, 200ms));
1812
- --_duration-fast: var(--review-surface-duration-fast, var(--duration-fast, 100ms));
1813
- --_ease: var(--review-surface-ease, var(--ease-default, ease));
1814
- }
1815
-
1816
- *, *::before, *::after { box-sizing: border-box; margin: 0; }
1817
-
1818
- /* \u2500\u2500 Container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1819
- .rs-container {
1820
- position: relative;
1821
- display: grid;
1822
- }
1823
-
1824
- .rs-container > ::slotted(*),
1825
- .rs-container > .rs-overlay {
1826
- grid-area: 1 / 1;
1827
- }
1828
-
1829
- /* \u2500\u2500 Overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1830
- .rs-overlay {
1831
- position: relative;
1832
- z-index: 10;
1833
- pointer-events: none;
1834
- cursor: default;
1835
- }
1836
-
1837
- :host([data-annotating]) .rs-overlay {
1838
- pointer-events: auto;
1839
- cursor: crosshair;
1840
- }
1841
-
1842
- /* \u2500\u2500 Pin markers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1843
- .rs-pin {
1844
- position: absolute;
1845
- transform: translate(-50%, -50%);
1846
- width: var(--_pin-size);
1847
- height: var(--_pin-size);
1848
- border-radius: var(--_radius-full);
1849
- background: var(--_pin-bg);
1850
- color: var(--_pin-text);
1851
- border: 2px solid var(--_pin-text);
1852
- font-size: var(--_font-xs);
1853
- font-weight: 700;
1854
- font-family: inherit;
1855
- display: inline-flex;
1856
- align-items: center;
1857
- justify-content: center;
1858
- cursor: pointer;
1859
- pointer-events: auto;
1860
- padding: 0;
1861
- line-height: 1;
1862
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
1863
- transition: transform var(--_duration-fast) var(--_ease),
1864
- box-shadow var(--_duration-fast) var(--_ease);
1865
- z-index: 11;
1866
- }
1867
-
1868
- .rs-pin:hover {
1869
- transform: translate(-50%, -50%) scale(1.15);
1870
- box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
1871
- }
1872
-
1873
- .rs-pin:focus-visible {
1874
- outline: 2px solid var(--_accent);
1875
- outline-offset: 2px;
1876
- }
1877
-
1878
- .rs-pin[data-resolved] {
1879
- background: var(--_resolved);
1880
- }
1881
-
1882
- .rs-pin[data-active] {
1883
- transform: translate(-50%, -50%) scale(1.2);
1884
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--_pin-bg) 30%, transparent);
1885
- }
1886
-
1887
- /* \u2500\u2500 Popover \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1888
- .rs-popover {
1889
- position: absolute;
1890
- z-index: 20;
1891
- width: 300px;
1892
- max-height: 400px;
1893
- overflow-y: auto;
1894
- background: var(--_bg);
1895
- border: 1px solid var(--_border);
1896
- border-radius: var(--_radius-m);
1897
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08);
1898
- padding: 0;
1899
- opacity: 0;
1900
- transform: translateY(4px);
1901
- transition: opacity var(--_duration) var(--_ease), transform var(--_duration) var(--_ease);
1902
- pointer-events: none;
1903
- }
1904
-
1905
- .rs-popover[data-open] {
1906
- opacity: 1;
1907
- transform: translateY(0);
1908
- pointer-events: auto;
1909
- }
1910
-
1911
- .rs-popover__header {
1912
- display: flex;
1913
- align-items: center;
1914
- justify-content: space-between;
1915
- padding: 10px 12px 8px;
1916
- border-block-end: 1px solid var(--_border);
1917
- }
1918
-
1919
- .rs-popover__title {
1920
- font-size: var(--_font-sm);
1921
- font-weight: 700;
1922
- color: var(--_text);
1923
- }
1924
-
1925
- .rs-popover__actions {
1926
- display: flex;
1927
- gap: 4px;
1928
- }
1929
-
1930
- .rs-popover__btn {
1931
- display: inline-flex;
1932
- align-items: center;
1933
- justify-content: center;
1934
- width: 26px;
1935
- height: 26px;
1936
- border: none;
1937
- border-radius: 4px;
1938
- background: transparent;
1939
- color: var(--_muted);
1940
- cursor: pointer;
1941
- padding: 0;
1942
- transition: background var(--_duration-fast) var(--_ease), color var(--_duration-fast) var(--_ease);
1943
- }
1944
-
1945
- .rs-popover__btn svg {
1946
- width: 14px;
1947
- height: 14px;
1948
- }
1949
-
1950
- .rs-popover__btn:hover {
1951
- background: var(--_border);
1952
- color: var(--_text);
1953
- }
1954
-
1955
- .rs-popover__btn--resolve {
1956
- color: var(--_resolved);
1957
- }
1958
-
1959
- .rs-popover__btn--resolve:hover {
1960
- background: color-mix(in srgb, var(--_resolved) 15%, transparent);
1961
- }
1962
-
1963
- .rs-popover__btn--delete {
1964
- color: var(--color-error-text, var(--color-error, #dc2626));
1965
- }
1966
-
1967
- .rs-popover__btn--delete:hover {
1968
- background: color-mix(in oklch, var(--color-error, #dc2626) 8%, var(--_card));
1969
- color: var(--color-error-text, var(--color-error, #dc2626));
1970
- }
1971
-
1972
- /* \u2500\u2500 Comment thread \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
1973
- .rs-comment {
1974
- padding: 10px 12px;
1975
- }
1976
-
1977
- .rs-comment__meta {
1978
- display: flex;
1979
- align-items: center;
1980
- gap: 6px;
1981
- margin-block-end: 4px;
1982
- }
1983
-
1984
- .rs-comment__avatar {
1985
- width: 22px;
1986
- height: 22px;
1987
- border-radius: var(--_radius-full);
1988
- font-size: 10px;
1989
- font-weight: 700;
1990
- display: flex;
1991
- align-items: center;
1992
- justify-content: center;
1993
- color: var(--color-text-inverted, #fff);
1994
- flex-shrink: 0;
1995
- }
1996
-
1997
- .rs-comment__author {
1998
- font-size: var(--_font-xs);
1999
- font-weight: 600;
2000
- color: var(--_text);
2001
- }
2002
-
2003
- .rs-comment__time {
2004
- font-size: 11px;
2005
- color: var(--_muted);
2006
- }
2007
-
2008
- .rs-comment__text {
2009
- font-size: var(--_font-sm);
2010
- color: var(--_text);
2011
- line-height: 1.5;
2012
- white-space: pre-wrap;
2013
- word-break: break-word;
2014
- }
2015
-
2016
- /* Replies */
2017
- .rs-replies {
2018
- border-block-start: 1px solid var(--_border);
2019
- }
2020
-
2021
- .rs-reply {
2022
- padding: 8px 12px;
2023
- border-block-end: 1px solid color-mix(in srgb, var(--_border) 50%, transparent);
2024
- }
2025
-
2026
- .rs-reply:last-child {
2027
- border-block-end: none;
2028
- }
2029
-
2030
- /* \u2500\u2500 Input area \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2031
- .rs-input {
2032
- display: flex;
2033
- gap: 6px;
2034
- padding: 8px 12px;
2035
- border-block-start: 1px solid var(--_border);
2036
- background: var(--_card);
2037
- border-radius: 0 0 var(--_radius-m) var(--_radius-m);
2038
- }
2039
-
2040
- .rs-input__field {
2041
- flex: 1;
2042
- min-height: 32px;
2043
- max-height: 80px;
2044
- padding: 6px 10px;
2045
- border: 1px solid var(--_border);
2046
- border-radius: 6px;
2047
- font-family: inherit;
2048
- font-size: var(--_font-xs);
2049
- line-height: 1.4;
2050
- color: var(--_text);
2051
- background: var(--_bg);
2052
- resize: none;
2053
- }
2054
-
2055
- .rs-input__field:focus {
2056
- outline: 2px solid var(--_accent);
2057
- outline-offset: -1px;
2058
- border-color: var(--_accent);
2059
- }
2060
-
2061
- .rs-input__field::placeholder {
2062
- color: var(--_muted);
2063
- }
2064
-
2065
- .rs-input__submit {
2066
- align-self: flex-end;
2067
- display: inline-flex;
2068
- align-items: center;
2069
- justify-content: center;
2070
- width: 32px;
2071
- height: 32px;
2072
- border: none;
2073
- border-radius: 6px;
2074
- background: var(--_accent);
2075
- color: var(--color-text-inverted, #fff);
2076
- cursor: pointer;
2077
- padding: 0;
2078
- flex-shrink: 0;
2079
- transition: background var(--_duration-fast) var(--_ease);
2080
- }
2081
-
2082
- .rs-input__submit svg {
2083
- width: 14px;
2084
- height: 14px;
2085
- }
2086
-
2087
- .rs-input__submit:hover {
2088
- background: color-mix(in srgb, var(--_accent) 85%, #000);
2089
- }
2090
-
2091
- .rs-input__submit:disabled {
2092
- opacity: 0.4;
2093
- cursor: not-allowed;
2094
- }
2095
-
2096
- /* \u2500\u2500 Toolbar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2097
- .rs-toolbar {
2098
- display: flex;
2099
- align-items: center;
2100
- gap: var(--_space-xs);
2101
- padding: var(--_space-xs) var(--_space-s);
2102
- background: var(--_card);
2103
- border: 1px solid var(--_border);
2104
- border-radius: var(--_radius-m);
2105
- margin-block-start: var(--_space-xs);
2106
- }
2107
-
2108
- .rs-toolbar__btn {
2109
- display: inline-flex;
2110
- align-items: center;
2111
- gap: 5px;
2112
- padding: 4px 10px;
2113
- border: 1px solid var(--_border);
2114
- border-radius: 6px;
2115
- background: var(--_bg);
2116
- color: var(--_text);
2117
- font-family: inherit;
2118
- font-size: var(--_font-xs);
2119
- font-weight: 600;
2120
- cursor: pointer;
2121
- line-height: 1;
2122
- transition: background var(--_duration-fast) var(--_ease),
2123
- border-color var(--_duration-fast) var(--_ease);
2124
- }
2125
-
2126
- .rs-toolbar__btn svg {
2127
- width: 14px;
2128
- height: 14px;
2129
- }
2130
-
2131
- .rs-toolbar__btn:hover {
2132
- background: var(--_border);
2133
- }
2134
-
2135
- .rs-toolbar__btn[aria-pressed="true"] {
2136
- background: var(--_accent);
2137
- color: var(--color-text-inverted, #fff);
2138
- border-color: var(--_accent);
2139
- }
2140
-
2141
- .rs-toolbar__count {
2142
- font-size: var(--_font-xs);
2143
- color: var(--_muted);
2144
- margin-inline-start: auto;
2145
- }
2146
-
2147
- /* \u2500\u2500 Resolved badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2148
- .rs-resolved-badge {
2149
- display: inline-flex;
2150
- align-items: center;
2151
- gap: 4px;
2152
- font-size: 11px;
2153
- font-weight: 600;
2154
- color: var(--_resolved);
2155
- padding: 2px 8px;
2156
- border-radius: var(--_radius-full);
2157
- background: color-mix(in srgb, var(--_resolved) 12%, transparent);
2158
- }
2159
-
2160
- .rs-resolved-badge svg {
2161
- width: 12px;
2162
- height: 12px;
2163
- }
2164
-
2165
- /* \u2500\u2500 Live region \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2166
- .rs-live {
2167
- position: absolute;
2168
- width: 1px;
2169
- height: 1px;
2170
- overflow: hidden;
2171
- clip: rect(0, 0, 0, 0);
2172
- white-space: nowrap;
2173
- }
2174
-
2175
- /* \u2500\u2500 Compact \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2176
- :host([compact]) {
2177
- --_pin-size: 22px;
2178
- }
2179
-
2180
- :host([compact]) .rs-popover {
2181
- width: 250px;
2182
- max-height: 300px;
2183
- }
2184
-
2185
- :host([compact]) .rs-toolbar {
2186
- padding: 3px var(--_space-xs);
2187
- }
2188
-
2189
- :host([compact]) .rs-toolbar__btn {
2190
- font-size: 11px;
2191
- padding: 3px 8px;
2192
- }
2193
-
2194
- /* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2195
- @container (max-width: 400px) {
2196
- .rs-popover {
2197
- width: 240px;
2198
- }
2199
-
2200
- .rs-toolbar {
2201
- flex-wrap: wrap;
2202
- }
2203
- }
2204
-
2205
- /* \u2500\u2500 Motion \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2206
- @media (prefers-reduced-motion: reduce) {
2207
- .rs-pin,
2208
- .rs-popover,
2209
- .rs-toolbar__btn,
2210
- .rs-popover__btn,
2211
- .rs-input__submit {
2212
- transition: none;
2213
- }
2214
- }
2215
-
2216
- /* \u2500\u2500 Print \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2217
- @media print {
2218
- .rs-overlay,
2219
- .rs-toolbar,
2220
- .rs-popover {
2221
- display: none;
2222
- }
2223
- }
2224
-
2225
- /* \u2500\u2500 Utility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2226
- .state-msg { padding: var(--_space-l); font-size: var(--_font-sm); color: var(--_muted); font-style: italic; }
2227
- .state-msg--error { color: var(--color-error-text, var(--color-error, #dc2626)); }
2228
- `;function ee(){let c=globalThis.localStorage;if(!c)throw new Error("VBStore: localStorage is not available in this environment");return{async getRaw(t){return c.getItem(t)},async setRaw(t,e){c.setItem(t,e)},async removeRaw(t){c.removeItem(t)},async keys(t){let e=[];for(let r=0;r<c.length;r++){let s=c.key(r);s&&s.startsWith(t)&&e.push(s)}return e}}}var X=null;function I(){return X||(X=ee()),X}function ft(c,t){if(typeof c!="string"||!c)throw new TypeError("VBStore: namespace must be a non-empty string");if(typeof t!="string"||!t)throw new TypeError("VBStore: key must be a non-empty string");return`vb:${c}:${t}`}function Mt(c){if(typeof c!="string"||!c)throw new TypeError("VBStore: namespace must be a non-empty string");return`vb:${c}:`}function zt(c){try{let t=JSON.parse(c);if(t&&typeof t=="object"&&typeof t.timestamp=="number")return t}catch{}return null}var Y={configure(c={}){X=c.backend??null},async set(c,t,e){let r={data:e,timestamp:Date.now()};await I().setRaw(ft(c,t),JSON.stringify(r))},async get(c,t,e){let r=await I().getRaw(ft(c,t));if(r==null)return null;let s=zt(r);return!s||e?.maxAge!=null&&Date.now()-s.timestamp>e.maxAge?null:s.data},async remove(c,t){await I().removeRaw(ft(c,t))},async list(c){let t=Mt(c),e=await I().keys(t),r=[];for(let s of e){let a=await I().getRaw(s);if(a==null)continue;let i=zt(a);i&&r.push({key:s.slice(t.length),data:i.data,timestamp:i.timestamp})}return r},async clear(c){let t=Mt(c),e=await I().keys(t);for(let r of e)await I().removeRaw(r)},async clearAll(){let c=await I().keys("vb:");for(let t of c)await I().removeRaw(t)},async setMany(c,t){for(let[e,r]of t)await Y.set(c,e,r)}};var bt="[data-copy], [data-copy-target], [data-paste-target]",re="Copied to clipboard",se="Pasted from clipboard",gt=new WeakMap;async function yt(c,t={}){if(c==null||c==="")return!1;let{button:e,announceMessage:r=re,duration:s=1500}=t;try{await navigator.clipboard.writeText(c)}catch{return!1}return Nt({button:e,duration:s,announceMessage:r,eventDetail:{text:c}}),!0}function Nt({button:c,duration:t,announceMessage:e,eventDetail:r,state:s="copied",eventName:a="copy"}){if(c){c.dataset.state=s;let i=gt.get(c);i&&clearTimeout(i),gt.set(c,setTimeout(()=>{delete c.dataset.state,gt.delete(c)},t)),c.dispatchEvent(new CustomEvent(a,{bubbles:!0,detail:r}))}oe(e,c??document.body)}async function ae(c,t={}){let{button:e,announceMessage:r=se,duration:s=1500}=t,a;try{a=await navigator.clipboard.readText()}catch{return null}return c&&("value"in c&&(c instanceof HTMLInputElement||c instanceof HTMLTextAreaElement||c instanceof HTMLSelectElement)?c.value=a:c.textContent=a,c.dispatchEvent(new Event("input",{bubbles:!0}))),Nt({button:e,duration:s,announceMessage:r,eventDetail:{text:a},state:"pasted",eventName:"paste"}),a}function Lt(c=document){c.querySelectorAll(bt).forEach(vt)}function vt(c){c.hasAttribute("data-copy-init")||(c.setAttribute("data-copy-init",""),c.addEventListener("click",()=>{if(c.dataset.pasteTarget){let e=document.querySelector(c.dataset.pasteTarget);if(!e)return;ae(e,{button:c});return}let t=ie(c);t&&yt(t,{button:c})}))}function ie(c){if(c.dataset.copy)return c.dataset.copy;if(c.dataset.copyTarget){let t=document.querySelector(c.dataset.copyTarget);if(!t)return"";let e=c.dataset.copyAttr;return e?t.getAttribute(e)??"":t.textContent??""}return""}function oe(c,t){let e=document.createElement("div");e.setAttribute("role","status"),e.setAttribute("aria-live","polite"),e.className="visually-hidden",e.textContent=c,t.appendChild(e),setTimeout(()=>e.remove(),1e3)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>Lt()):Lt();var ne=new MutationObserver(c=>{for(let t of c)for(let e of t.addedNodes){if(e.nodeType!==Node.ELEMENT_NODE)continue;let r=e;r.matches(bt)&&vt(r),r.querySelectorAll(bt).forEach(s=>vt(s))}});ne.observe(document.documentElement,{childList:!0,subtree:!0});var P=class{#e=new Map;async load(){return[...this.#e.values()]}async save(t){return t.id||(t.id=crypto.randomUUID()),this.#e.set(t.id,t),t}async update(t,e){let r=this.#e.get(t);if(!r)throw new Error(`Pin ${t} not found`);return Object.assign(r,e),r}async remove(t){this.#e.delete(t)}},K=class{#e;constructor(t="default"){this.#e=t}async#t(){let t=await Y.get("reviews",this.#e);return Array.isArray(t)?t:[]}async#r(t){await Y.set("reviews",this.#e,t)}async load(){return this.#t()}async save(t){t.id||(t.id=crypto.randomUUID());let e=await this.#t();return e.push(t),await this.#r(e),t}async update(t,e){let r=await this.#t(),s=r.findIndex(a=>a.id===t);if(s===-1)throw new Error(`Pin ${t} not found`);return Object.assign(r[s],e),await this.#r(r),r[s]}async remove(t){let e=(await this.#t()).filter(r=>r.id!==t);await this.#r(e)}},W=class{#e;constructor(t){if(!t)throw new Error("RestAdapter requires an endpoint URL");this.#e=t.replace(/\/$/,"")}async load(){let t=await fetch(this.#e);if(!t.ok)throw new Error(`HTTP ${t.status}`);let e=await t.json();return Array.isArray(e)?e:e.pins||[]}async save(t){let e=await fetch(this.#e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.json()}async update(t,e){let r=await fetch(`${this.#e}/${encodeURIComponent(t)}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()}async remove(t){let e=await fetch(`${this.#e}/${encodeURIComponent(t)}`,{method:"DELETE"});if(!e.ok)throw new Error(`HTTP ${e.status}`)}},xt=class extends HTMLElement{static get observedAttributes(){return["src","editable","adapter","endpoint","storage-key","author","compact","show-resolved"]}#e=new Map;constructor(){super(),this.attachShadow({mode:"open"}),this.__pins=[],this.__adapter=null,this._activePin=null,this._annotating=!1}get pins(){return this.__pins}set pins(t){let e=Array.isArray(t)?t:[];this.__pins!==e&&(this.__pins=e,this.isConnected&&this._render(),this.dispatchEvent(new CustomEvent("review-surface:pins-changed",{detail:{pins:e,source:"property"},bubbles:!0,composed:!0})))}get adapter(){return this.__adapter}set adapter(t){this.__adapter=t,this.isConnected&&this._loadFromAdapter()}#t(){for(let t of this.children){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}connectedCallback(){this.#t(),this.setAttribute("data-upgraded",""),this.#r(),this.hasAttribute("src")?this._loadSrc(this.getAttribute("src")):this._loadFromAdapter()}disconnectedCallback(){this.removeAttribute("data-upgraded"),this.removeAttribute("data-annotating")}attributeChangedCallback(t){this.isConnected&&(t==="src"?this._loadSrc(this.getAttribute("src")):t==="adapter"||t==="endpoint"||t==="storage-key"?(this.#r(),this._loadFromAdapter()):this._render())}#r(){if(this.__adapter&&!(this.__adapter instanceof P)&&!(this.__adapter instanceof K)&&!(this.__adapter instanceof W))return;switch(this.getAttribute("adapter")||"memory"){case"local":this.__adapter=new K(this.getAttribute("storage-key")||"default");break;case"rest":try{this.__adapter=new W(this.getAttribute("endpoint")??"")}catch{this.__adapter=new P}break;default:this.__adapter=new P}}async _loadSrc(t){if(!(!t||!this.shadowRoot)){this.shadowRoot.innerHTML=`<style>${Q}</style><div class="state-msg">Loading\u2026</div>`;try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();this.__pins=Array.isArray(r)?r:r.pins||[],this._render()}catch(e){let r=e instanceof Error?e.message:String(e);this.shadowRoot.innerHTML=`<style>${Q}</style><div class="state-msg state-msg--error">Could not load pins: ${h(r)}</div>`}}}async _loadFromAdapter(){if(this.__adapter){try{this.__pins=await this.__adapter.load()}catch{this.__pins=[]}this._render()}}async addPin(t){let e={id:crypto.randomUUID(),x:Math.max(0,Math.min(100,t.x)),y:Math.max(0,Math.min(100,t.y)),text:t.text||"",author:t.author||this.getAttribute("author")||"Anonymous",createdAt:new Date().toISOString(),resolved:!1,resolvedBy:null,resolvedAt:null,replies:[]};return this.__adapter&&await this.__adapter.save(e),this.__pins.push(e),this._render(),this.#c(`Pin ${this.#i().length} added`),this.dispatchEvent(new CustomEvent("review-surface:add",{bubbles:!0,composed:!0,detail:{pin:e}})),e}async removePin(t){let e=this.__pins.find(r=>r.id===t);e&&(this.__adapter&&await this.__adapter.remove(t),this.__pins=this.__pins.filter(r=>r.id!==t),this._activePin===t&&(this._activePin=null),this._render(),this.#c("Pin removed"),this.dispatchEvent(new CustomEvent("review-surface:remove",{bubbles:!0,composed:!0,detail:{pin:e}})))}async resolvePin(t){let e=this.__pins.find(s=>s.id===t);if(!e)return;let r={resolved:!0,resolvedBy:this.getAttribute("author")||"Anonymous",resolvedAt:new Date().toISOString()};this.__adapter&&await this.__adapter.update(t,r),Object.assign(e,r),this._render(),this.#c("Pin resolved"),this.dispatchEvent(new CustomEvent("review-surface:resolve",{bubbles:!0,composed:!0,detail:{pin:e}}))}async unresolvePin(t){let e=this.__pins.find(s=>s.id===t);if(!e)return;let r={resolved:!1,resolvedBy:null,resolvedAt:null};this.__adapter&&await this.__adapter.update(t,r),Object.assign(e,r),this._render(),this.#c("Pin re-opened"),this.dispatchEvent(new CustomEvent("review-surface:update",{bubbles:!0,composed:!0,detail:{pin:e,changes:r}}))}exportPins(){return structuredClone(this.__pins)}importPins(t){this.__pins=Array.isArray(t)?structuredClone(t):[],this._activePin=null,this._render()}#i(){let t=this.hasAttribute("show-resolved");return this.__pins.filter(e=>t||!e.resolved).sort((e,r)=>new Date(e.createdAt??0).getTime()-new Date(r.createdAt??0).getTime())}_render(){if(!this.shadowRoot)return;let t=this.hasAttribute("editable"),e=this.#i(),r=this._activePin?this.__pins.find(s=>s.id===this._activePin):null;this.setAttribute("pin-count",String(e.length)),this.shadowRoot.innerHTML=`<style>${Q}</style>
2229
- <div class="rs-container">
2230
- <slot></slot>
2231
- <div class="rs-overlay" role="img" aria-label="Review annotation surface">
2232
- ${e.map((s,a)=>this._renderPin(s,a+1)).join("")}
2233
- </div>
2234
- ${r?this._renderPopover(r,t):""}
2235
- </div>
2236
- ${t?this._renderToolbar(e.length):""}
2237
- <div class="rs-live" aria-live="polite" aria-atomic="true"></div>`,this._bindListeners(t),this.dispatchEvent(new CustomEvent("review-surface:ready",{bubbles:!0,composed:!0,detail:{pinCount:e.length}}))}_renderPin(t,e){let r=t.text?t.text.slice(0,50):"Empty pin";return`<button class="rs-pin"
2238
- data-pin-id="${h(t.id)}"
2239
- ${t.resolved?"data-resolved":""}
2240
- ${this._activePin===t.id?"data-active":""}
2241
- style="left:${t.x}%;top:${t.y}%"
2242
- aria-label="Pin ${e}: ${h(r)}"
2243
- aria-expanded="${this._activePin===t.id}"
2244
- aria-haspopup="dialog">
2245
- <span class="rs-pin__number">${e}</span>
2246
- </button>`}_renderPopover(t,e){let r=this.#i().findIndex(s=>s.id===t.id)+1;return`<div class="rs-popover" data-open
2247
- style="left:${Math.min(t.x,70)}%;top:${t.y}%"
2248
- role="dialog"
2249
- aria-labelledby="rs-popover-title-${h(t.id)}">
2250
-
2251
- <div class="rs-popover__header">
2252
- <span class="rs-popover__title" id="rs-popover-title-${h(t.id)}">
2253
- Pin ${r}
2254
- ${t.resolved?`<span class="rs-resolved-badge">${A(k.checkCircle)} Resolved</span>`:""}
2255
- </span>
2256
- <div class="rs-popover__actions">
2257
- ${e&&!t.resolved?`
2258
- <button class="rs-popover__btn rs-popover__btn--resolve" data-action="resolve" data-pin-id="${h(t.id)}"
2259
- aria-label="Resolve pin" title="Resolve">${A(k.checkCircle)}</button>`:""}
2260
- ${e&&t.resolved?`
2261
- <button class="rs-popover__btn" data-action="unresolve" data-pin-id="${h(t.id)}"
2262
- aria-label="Re-open pin" title="Re-open">${A(k.messageCircle)}</button>`:""}
2263
- ${e?`
2264
- <button class="rs-popover__btn rs-popover__btn--delete" data-action="delete" data-pin-id="${h(t.id)}"
2265
- aria-label="Delete pin" title="Delete">${A(k.x)}</button>`:""}
2266
- <button class="rs-popover__btn" data-action="close"
2267
- aria-label="Close">${A(k.x)}</button>
2268
- </div>
2269
- </div>
2270
-
2271
- <div class="rs-comment">
2272
- <div class="rs-comment__meta">
2273
- <span class="rs-comment__avatar" style="background:${L(t.author||"Anonymous")}">${z(t.author||"Anonymous")}</span>
2274
- <span class="rs-comment__author">${h(t.author||"Anonymous")}</span>
2275
- <span class="rs-comment__time">${this.#n(t.createdAt)}</span>
2276
- </div>
2277
- <div class="rs-comment__text">${h(t.text)}</div>
2278
- </div>
2279
-
2280
- ${t.replies?.length?`
2281
- <div class="rs-replies">
2282
- ${t.replies.map(s=>`
2283
- <div class="rs-reply">
2284
- <div class="rs-comment__meta">
2285
- <span class="rs-comment__avatar" style="background:${L(s.author||"Anonymous")}">${z(s.author||"Anonymous")}</span>
2286
- <span class="rs-comment__author">${h(s.author||"Anonymous")}</span>
2287
- <span class="rs-comment__time">${this.#n(s.createdAt)}</span>
2288
- </div>
2289
- <div class="rs-comment__text">${h(s.text)}</div>
2290
- </div>
2291
- `).join("")}
2292
- </div>`:""}
2293
-
2294
- ${e?`
2295
- <div class="rs-input">
2296
- <textarea class="rs-input__field" placeholder="Reply\u2026" rows="1"
2297
- aria-label="Reply to pin ${r}"></textarea>
2298
- <button class="rs-input__submit" data-action="reply" data-pin-id="${h(t.id)}"
2299
- aria-label="Send reply">${A(k.send)}</button>
2300
- </div>`:""}
2301
-
2302
- </div>`}_renderToolbar(t){return`<div class="rs-toolbar" role="toolbar" aria-label="Review tools">
2303
- <button class="rs-toolbar__btn" data-action="toggle-mode"
2304
- aria-pressed="${this._annotating}"
2305
- title="Toggle annotate mode">
2306
- ${A(k.mapPin)} Annotate
2307
- </button>
2308
- <button class="rs-toolbar__btn" data-action="export"
2309
- title="Export pins as JSON">
2310
- ${A(k.download)} Export
2311
- </button>
2312
- <output class="rs-toolbar__count">${t} pin${t!==1?"s":""}</output>
2313
- </div>`}_bindListeners(t){let e=this.shadowRoot;if(!e)return;e.querySelectorAll(".rs-pin").forEach(a=>{a.addEventListener("click",i=>{i.stopPropagation();let o=a.dataset.pinId??null;this._activePin=this._activePin===o?null:o,this._render(),this._activePin&&this.dispatchEvent(new CustomEvent("review-surface:select",{bubbles:!0,composed:!0,detail:{pin:this.__pins.find(n=>n.id===o)}}))})});let r=e.querySelector(".rs-overlay");r&&t&&r.addEventListener("click",a=>{if(!this._annotating)return;let i=a;if(i.target?.closest(".rs-pin"))return;let n=r.getBoundingClientRect(),l=(i.clientX-n.left)/n.width*100,d=(i.clientY-n.top)/n.height*100;this.#s(l,d)}),e.querySelectorAll("[data-action]").forEach(a=>{a.addEventListener("click",i=>{i.stopPropagation();let o=a.dataset.action,n=a.dataset.pinId;switch(o){case"close":this._activePin=null,this._render();break;case"resolve":n&&this.resolvePin(n);break;case"unresolve":n&&this.unresolvePin(n);break;case"delete":n&&this.removePin(n);break;case"toggle-mode":this._annotating=!this._annotating,this._annotating?this.setAttribute("data-annotating",""):this.removeAttribute("data-annotating"),this._render(),this.dispatchEvent(new CustomEvent("review-surface:mode",{bubbles:!0,composed:!0,detail:{mode:this._annotating?"annotate":"view"}}));break;case"export":this.#a();break;case"reply":this.#o(n);break}})});let s=e.querySelector(".rs-input__field");s&&s.addEventListener("keydown",a=>{let i=a;if(i.key==="Enter"&&!i.shiftKey){i.preventDefault();let n=e.querySelector('[data-action="reply"]')?.dataset.pinId;n&&this.#o(n)}}),e.addEventListener("keydown",a=>{a.key==="Escape"&&(this._activePin?(this._activePin=null,this._render()):this._annotating&&(this._annotating=!1,this.removeAttribute("data-annotating"),this._render(),this.dispatchEvent(new CustomEvent("review-surface:mode",{bubbles:!0,composed:!0,detail:{mode:"view"}}))))})}async#s(t,e){let r=this.getAttribute("author")||"Anonymous",s=await this.addPin({x:t,y:e,text:"",author:r});this._activePin=s.id,this._render(),requestAnimationFrame(()=>{(this.shadowRoot?.querySelector(".rs-input__field")??null)?.focus()})}async#o(t){let e=this.shadowRoot?.querySelector(".rs-input__field")??null;if(!e)return;let r=e.value.trim();if(!r)return;let s=this.__pins.find(i=>i.id===t);if(!s)return;let a={id:crypto.randomUUID(),text:r,author:this.getAttribute("author")||"Anonymous",createdAt:new Date().toISOString()};s.replies||(s.replies=[]),s.text?(s.replies.push(a),this.__adapter&&await this.__adapter.update(t,{replies:s.replies})):(s.text=r,this.__adapter&&await this.__adapter.update(t,{text:r})),this._render(),this.#c("Reply added"),requestAnimationFrame(()=>{(this.shadowRoot?.querySelector(".rs-input__field")??null)?.focus()}),this.dispatchEvent(new CustomEvent("review-surface:update",{bubbles:!0,composed:!0,detail:{pin:s,changes:{replies:s.replies}}}))}async#a(){let t=JSON.stringify(this.exportPins(),null,2);if(await yt(t,{announceMessage:"Pins copied to clipboard"}))return;let r=new Blob([t],{type:"application/json"}),s=URL.createObjectURL(r),a=document.createElement("a");a.href=s,a.download="review-pins.json",a.click(),URL.revokeObjectURL(s),this.#c("Pins exported as file")}#n(t){if(!t)return"";try{let e=new Date(t),s=new Date().getTime()-e.getTime(),a=Math.floor(s/6e4);if(a<1)return"just now";if(a<60)return`${a}m ago`;let i=Math.floor(a/60);if(i<24)return`${i}h ago`;let o=Math.floor(i/24);return o<7?`${o}d ago`:e.toLocaleDateString()}catch{return""}}#c(t){let e=this.shadowRoot?.querySelector(".rs-live");e&&(e.textContent=t)}};x("review-surface",xt);var N=864e5,wt=N*7,G=N*30,ce=N*91,Pt=N*365;function j(c){return typeof c=="number"?c:new Date(c).getTime()}function de(c){return c<=wt*3?t=>t.toLocaleDateString(void 0,{month:"short",day:"numeric"}):c<=G*3?t=>t.toLocaleDateString(void 0,{month:"short",day:"numeric"}):c<=Pt?t=>t.toLocaleDateString(void 0,{month:"short",year:"2-digit"}):t=>t.toLocaleDateString(void 0,{year:"numeric"})}function le(c){return c<=wt*3?"day":c<=G*3?"week":c<=Pt?"month":"quarter"}function Dt(c){return String(c).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}var _t=class c extends C{static get observedAttributes(){return["src","title","view","show-today","show-progress","show-dependencies","compact"]}#e=null;#t=null;#r=null;#i=[];#s=0;#o=0;#a=0;setup(){let t=this.querySelector(":scope > table");return!t||(this.#i=this.#d(t),this.#i.length===0)?!1:(this.#s=Math.min(...this.#i.map(e=>e.start)),this.#o=Math.max(...this.#i.map(e=>e.end)),this.#a=this.#o-this.#s,this.#a<=0&&(this.#a=N),this.#b(t),this.dispatchEvent(new CustomEvent("gantt-chart:ready",{bubbles:!0,detail:{taskCount:this.#i.length,dateRange:{start:new Date(this.#s).toISOString(),end:new Date(this.#o).toISOString()}}})),!0)}teardown(){this.#r&&(this.#r.remove(),this.#r=null),this.#e&&(this.#e.remove(),this.#e=null),this.#t&&(this.#t.remove(),this.#t=null);let t=this.querySelector("table.gc-sr-only");t&&t.classList.remove("gc-sr-only"),this.#i=[]}static#n=0;attributeChangedCallback(t,e,r){e===r||!this.isConnected||(t==="src"?this._loadSrc(r):this.hasAttribute("data-upgraded")&&this.#c())}#c(){let t=()=>{this.teardown(),this.removeAttribute("data-upgraded"),this.setup()};if(this.hasAttribute("data-upgraded")&&"startViewTransition"in document&&!matchMedia("(prefers-reduced-motion: reduce)").matches){let e=`gc-vt-${++c.#n}`;this.style.viewTransitionName=e,document.startViewTransition(t).finished.finally(()=>{this.style.viewTransitionName=""})}else t()}get tasks(){return this.#i}set tasks(t){let e=(t||[]).map((r,s)=>({id:r.id??`gc-task-${s}`,name:r.name??`Task ${s+1}`,start:typeof r.start=="number"?r.start:j(r.start),end:typeof r.end=="number"?r.end:r.end!=null?j(r.end):typeof r.start=="number"?r.start:j(r.start),progress:r.progress??0,group:r.group??null,depends:Array.isArray(r.depends)?r.depends:r.depends?String(r.depends).split(",").map(a=>a.trim()):[],status:r.status??null,assignee:r.assignee??null,milestone:!!r.milestone,color:r.color??null,storyIds:r.storyIds??[],itemIds:r.itemIds??[]}));if((this.#e||this.#r||this.#t)&&(this.#r&&(this.#r.remove(),this.#r=null),this.#e&&(this.#e.remove(),this.#e=null),this.#t&&(this.#t.remove(),this.#t=null)),this.#i=e,e.length>0){this.#s=Math.min(...e.map(s=>s.start)),this.#o=Math.max(...e.map(s=>s.end)),this.#a=this.#o-this.#s,this.#a<=0&&(this.#a=N);let r=this.querySelector(":scope > table");r||(r=document.createElement("table"),r.classList.add("gc-sr-only"),this.appendChild(r)),this.#b(r)}this.dispatchEvent(new CustomEvent("gantt-chart:tasks-changed",{detail:{tasks:e,source:"property"},bubbles:!0}))}#d(t){let e=t.querySelectorAll("tbody tr"),r=[];for(let s=0;s<e.length;s++){let a=e[s],i=a.querySelectorAll("time[datetime]");if(i.length<2&&!a.hasAttribute("data-milestone"))continue;let o=i[0]?.getAttribute("datetime"),n=i.length>1?i[1].getAttribute("datetime"):o;if(!o)continue;let l=a.querySelector("progress"),d=l?l.value/(l.max||100):0,p=a.cells[0]?.textContent?.trim()||`Task ${s+1}`;r.push({id:a.dataset.taskId||`gc-task-${s}`,name:p,start:j(o),end:j(n),progress:d,group:a.dataset.group||null,depends:a.dataset.depends?a.dataset.depends.split(",").map(u=>u.trim()):[],status:a.dataset.status||null,assignee:a.dataset.assignee||null,milestone:a.hasAttribute("data-milestone"),color:a.dataset.color||null,storyIds:a.dataset.storyIds?a.dataset.storyIds.split(",").map(u=>u.trim()):[],itemIds:a.dataset.itemIds?a.dataset.itemIds.split(",").map(u=>u.trim()):[]})}return r}#b(t){let e=this.getAttribute("title"),r=this.hasAttribute("show-today"),s=this.hasAttribute("show-progress"),a=this.hasAttribute("show-dependencies");e&&(this.#r=document.createElement("h2"),this.#r.className="gc-title",this.#r.textContent=e,this.insertBefore(this.#r,t)),this.#e=document.createElement("div"),this.#e.className="gc-container",this.#e.setAttribute("role","region"),this.#e.setAttribute("aria-label",`Gantt chart${e?": "+e:""}`);let i=this.#m();this.#e.appendChild(i);let o=document.createElement("div");o.className="gc-body";let n=document.createElement("div");n.className="gc-task-list";let l=document.createElement("div");l.className="gc-bars";let d=this.#f();l.appendChild(d);let p=this.#v();for(let[u,m]of p){if(p.size>1&&u){let f=document.createElement("div");f.className="gc-group-header";let g=document.createElement("span");g.className="gc-group-label",g.textContent=u,f.appendChild(g),n.appendChild(f);let v=document.createElement("div");v.className="gc-group-spacer",l.appendChild(v)}for(let f of m){let g=document.createElement("div");g.className="gc-task-row",g.setAttribute("data-task-id",f.id);let v=document.createElement("span");v.className="gc-task-name",v.textContent=f.name,g.appendChild(v);let y=document.createElement("span");y.className="gc-task-dates",y.textContent=`${new Date(f.start).toLocaleDateString()} to ${new Date(f.end).toLocaleDateString()}`,g.appendChild(y),n.appendChild(g);let _=document.createElement("div");_.className="gc-bar-row",f.milestone?_.appendChild(this.#h(f)):_.appendChild(this.#l(f,s)),l.appendChild(_)}}if(r){let u=this.#y();u&&l.appendChild(u)}a&&requestAnimationFrame(()=>{let u=this.#g(l);u&&l.appendChild(u)}),o.appendChild(n),o.appendChild(l),this.#e.appendChild(o),this.insertBefore(this.#e,t),t.classList.add("gc-sr-only"),this.#t=document.createElement("div"),this.#t.className="gc-sr-only",this.#t.setAttribute("role","status"),this.#t.setAttribute("aria-live","polite"),this.#t.setAttribute("aria-atomic","true"),this.appendChild(this.#t),this.listen(this.#e,"click",u=>{let m=u.target.closest(".gc-bar, .gc-milestone");if(!m)return;let f=m.dataset.taskId,g=this.#i.find(v=>v.id===f);g&&(this.#x(`Selected: ${g.name}`),this.dispatchEvent(new CustomEvent("gantt-chart:task-click",{bubbles:!0,detail:{task:g}})))}),this.listen(this.#e,"keydown",u=>{let m=u;if(m.key==="Enter"||m.key===" "){let f=m.target.closest(".gc-bar, .gc-milestone");f&&(m.preventDefault(),f.click())}})}#m(){let t=document.createElement("div");t.className="gc-timeline-header";let e=document.createElement("div");e.className="gc-timeline-spacer",t.appendChild(e);let r=document.createElement("div");r.className="gc-timeline-dates";let s=this.#u();for(let{position:a,text:i}of s){let o=document.createElement("span");o.className="gc-date-label",o.style.left=`${a}%`,o.textContent=i,r.appendChild(o)}return t.appendChild(r),t}#u(){let t=this.getAttribute("view")||"auto",e=t==="auto"?le(this.#a):t,r=de(this.#a),s=[],a;switch(e){case"day":a=N;break;case"week":a=wt;break;case"month":a=G;break;case"quarter":a=ce;break;default:a=G}let i=new Date(this.#s);if(e==="week"){let l=i.getDay(),d=l===0?1:l===1?0:8-l;i.setDate(i.getDate()+d)}else if(e==="month")i.setDate(1),i.getTime()<this.#s&&i.setMonth(i.getMonth()+1);else if(e==="quarter"){let l=i.getMonth(),d=Math.ceil((l+1)/3)*3;i.setMonth(d),i.setDate(1)}let o=i.getTime();o>this.#s+a*.5&&s.push({position:0,text:r(new Date(this.#s))});let n=o;for(;n<=this.#o;){let l=(n-this.#s)/this.#a*100;if(l>=0&&l<=100&&s.push({position:l,text:r(new Date(n))}),e==="month"){let d=new Date(n);d.setMonth(d.getMonth()+1),n=d.getTime()}else if(e==="quarter"){let d=new Date(n);d.setMonth(d.getMonth()+3),n=d.getTime()}else n+=a}return s}#f(){let t=document.createElement("div");t.className="gc-grid-lines";let e=this.#u();for(let{position:r}of e){if(r<=0)continue;let s=document.createElement("div");s.className="gc-grid-line",s.style.left=`${r}%`,t.appendChild(s)}return t}#v(){let t=new Map;for(let e of this.#i){let r=e.group||"";t.has(r)||t.set(r,[]),t.get(r)?.push(e)}return t}#l(t,e){let r=(t.start-this.#s)/this.#a*100,s=(t.end-t.start)/this.#a*100,a=document.createElement("div");if(a.className="gc-bar",a.setAttribute("data-task-id",t.id),a.setAttribute("role","img"),a.setAttribute("tabindex","0"),a.setAttribute("aria-label",`${Dt(t.name)}: ${new Date(t.start).toLocaleDateString()} to ${new Date(t.end).toLocaleDateString()}`+(t.progress>0?`, ${Math.round(t.progress*100)}% complete`:"")),a.style.left=`${r}%`,a.style.width=`${Math.max(s,.5)}%`,t.status&&a.setAttribute("data-status",t.status),t.color&&a.style.setProperty("--gc-bar-color",t.color),e&&t.progress>0){let i=document.createElement("div");i.className="gc-bar-fill",i.style.width=`${Math.round(t.progress*100)}%`,a.appendChild(i)}if(s>8){let i=document.createElement("span");i.className="gc-bar-label",i.textContent=t.name,a.appendChild(i)}return a}#h(t){let e=(t.start-this.#s)/this.#a*100,r=document.createElement("div");return r.className="gc-milestone",r.setAttribute("data-task-id",t.id),r.setAttribute("role","img"),r.setAttribute("tabindex","0"),r.setAttribute("aria-label",`Milestone: ${Dt(t.name)}, ${new Date(t.start).toLocaleDateString()}`),r.style.left=`${e}%`,t.status&&r.setAttribute("data-status",t.status),t.color&&r.style.setProperty("--gc-bar-color",t.color),r}#y(){let t=Date.now();if(t<this.#s||t>this.#o)return null;let e=(t-this.#s)/this.#a*100,r=document.createElement("div");r.className="gc-today-line",r.style.left=`${e}%`;let s=document.createElement("span");return s.className="gc-today-label",s.textContent="Today",r.appendChild(s),r}#g(t){if(!this.#i.some(n=>n.depends.length>0))return null;let r="http://www.w3.org/2000/svg",s=document.createElementNS(r,"svg");s.setAttribute("class","gc-deps"),s.style.width="100%",s.style.height="100%";let a=document.createElementNS(r,"defs"),i=document.createElementNS(r,"marker");i.setAttribute("id","gc-arrowhead"),i.setAttribute("markerWidth","8"),i.setAttribute("markerHeight","6"),i.setAttribute("refX","8"),i.setAttribute("refY","3"),i.setAttribute("orient","auto");let o=document.createElementNS(r,"polygon");o.setAttribute("points","0 0, 8 3, 0 6"),o.setAttribute("fill","var(--color-text-muted, #666666)"),i.appendChild(o),a.appendChild(i),s.appendChild(a);for(let n of this.#i)for(let l of n.depends){let d=this.#i.find(w=>w.id===l);if(!d)continue;let p=(d.end-this.#s)/this.#a*100,u=(n.start-this.#s)/this.#a*100,m=this.#p(d.id,t),f=this.#p(n.id,t);if(m===-1||f===-1)continue;let g=36,v=m*g+g/2,y=f*g+g/2,_=document.createElementNS(r,"path"),b=p+(u-p)/2;_.setAttribute("d",`M ${p}% ${v} C ${b}% ${v}, ${b}% ${y}, ${u}% ${y}`),_.setAttribute("class","gc-dep-line"),s.appendChild(_)}return s}#p(t,e){let r=e.querySelectorAll(".gc-bar-row");for(let s=0;s<r.length;s++){let a=r[s].querySelector("[data-task-id]");if(a&&a.dataset.taskId===t)return s}return-1}async _loadSrc(t){if(t)try{let e=await fetch(t);if(!e.ok)throw new Error(`HTTP ${e.status}`);let r=await e.json();for(;this.firstChild;)this.firstChild.remove();let s=document.createElement("table"),a=document.createElement("thead"),i=document.createElement("tr");for(let n of["Task","Start","End","Progress"]){let l=document.createElement("th");l.textContent=n,i.appendChild(l)}a.appendChild(i),s.appendChild(a);let o=document.createElement("tbody");for(let n of r.tasks||[]){let l=document.createElement("tr");n.id&&(l.dataset.taskId=n.id),n.group&&(l.dataset.group=n.group),n.depends&&(l.dataset.depends=Array.isArray(n.depends)?n.depends.join(","):n.depends),n.status&&(l.dataset.status=n.status),n.assignee&&(l.dataset.assignee=n.assignee),n.milestone&&l.setAttribute("data-milestone",""),n.color&&(l.dataset.color=n.color),n.storyIds&&(l.dataset.storyIds=Array.isArray(n.storyIds)?n.storyIds.join(","):n.storyIds),n.itemIds&&(l.dataset.itemIds=Array.isArray(n.itemIds)?n.itemIds.join(","):n.itemIds);let d=document.createElement("td");d.textContent=n.name||"",l.appendChild(d);let p=document.createElement("td"),u=document.createElement("time");u.setAttribute("datetime",n.start),u.textContent=new Date(n.start).toLocaleDateString(void 0,{month:"short",day:"numeric"}),p.appendChild(u),l.appendChild(p);let m=document.createElement("td"),f=document.createElement("time");f.setAttribute("datetime",n.end||n.start),f.textContent=new Date(n.end||n.start).toLocaleDateString(void 0,{month:"short",day:"numeric"}),m.appendChild(f),l.appendChild(m);let g=document.createElement("td"),v=document.createElement("progress");v.value=n.progress||0,v.max=100,v.textContent=`${n.progress||0}%`,g.appendChild(v),l.appendChild(g),o.appendChild(l)}s.appendChild(o),this.appendChild(s),r.title&&this.setAttribute("title",r.title),this.#c()}catch(e){console.warn(`[gantt-chart] Failed to load src="${t}":`,e)}}#x(t){this.#t&&(this.#t.textContent="",requestAnimationFrame(()=>{this.#t&&(this.#t.textContent=t)}))}};x("gantt-chart",_t);var R=`
2314
- :host {
2315
- --_bg: var(--work-item-bg, var(--color-surface, #ffffff));
2316
- --_text: var(--work-item-text, var(--color-text, #1a1a1a));
2317
- --_muted: var(--work-item-muted, var(--color-text-muted, #666));
2318
- --_border: var(--work-item-border, var(--color-border, #e0e0e0));
2319
- --_accent: var(--work-item-accent, var(--color-interactive, #0066cc));
2320
- --_card-bg: var(--work-item-card-bg, var(--color-surface-raised, #f8f9fa));
2321
- --_highlight: var(--work-item-highlight, color-mix(in srgb, var(--_accent) 8%, transparent));
2322
- --_radius: var(--work-item-radius, var(--radius-l, 0.75rem));
2323
- --_shadow: var(--work-item-shadow, var(--shadow-sm));
2324
- --_shadow-hover: var(--work-item-shadow-hover, var(--shadow-md));
2325
- --_duration: var(--work-item-duration, var(--duration-normal, 200ms));
2326
- --_ease: var(--work-item-ease, var(--ease-default, ease));
2327
- --_space-2xs: var(--work-item-space-2xs, var(--size-2xs, 0.25rem));
2328
- --_space-xs: var(--work-item-space-xs, var(--size-xs, 0.5rem));
2329
- --_space-s: var(--work-item-space-s, var(--size-s, 0.75rem));
2330
- --_space-m: var(--work-item-space-m, var(--size-m, 1rem));
2331
- --_font-xs: var(--work-item-font-xs, var(--font-size-xs, 0.75rem));
2332
- --_font-sm: var(--work-item-font-sm, var(--font-size-sm, 0.875rem));
2333
- --_font-md: var(--work-item-font-md, var(--font-size-md, 1rem));
2334
- --_font-lg: var(--work-item-font-lg, var(--font-size-lg, 1.125rem));
2335
- --_font-mono: var(--work-item-font-mono, var(--font-mono, ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace));
2336
- --_radius-s: var(--work-item-radius-s, var(--radius-s, 0.25rem));
2337
- --_radius-full: var(--work-item-radius-full, var(--radius-full, 9999px));
2338
-
2339
- display: block;
2340
- font-family: var(--work-item-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
2341
- }
2342
-
2343
- *, *::before, *::after { box-sizing: border-box; margin: 0; }
2344
-
2345
- /* \u2500\u2500 Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2346
- .wi-card {
2347
- background: var(--_bg);
2348
- border: 1px solid var(--_border);
2349
- border-radius: var(--_radius);
2350
- overflow: hidden;
2351
- box-shadow: var(--_shadow);
2352
- transition: box-shadow var(--_duration) var(--_ease);
2353
- }
2354
-
2355
- .wi-card:hover {
2356
- box-shadow: var(--_shadow-hover);
2357
- }
2358
-
2359
- /* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2360
- .wi-header {
2361
- display: flex;
2362
- align-items: center;
2363
- justify-content: space-between;
2364
- padding: var(--_space-s) var(--_space-m);
2365
- background: var(--_card-bg);
2366
- border-block-end: 1px solid var(--_border);
2367
- gap: var(--_space-s);
2368
- flex-wrap: wrap;
2369
- }
2370
-
2371
- .wi-meta {
2372
- display: flex;
2373
- align-items: center;
2374
- gap: var(--_space-xs);
2375
- flex-wrap: wrap;
2376
- min-width: 0;
2377
- }
2378
-
2379
- .wi-id {
2380
- font-size: var(--_font-xs);
2381
- font-weight: 600;
2382
- color: var(--_muted);
2383
- font-family: var(--_font-mono);
2384
- }
2385
-
2386
- /* \u2500\u2500 Type badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2387
- .wi-type {
2388
- display: inline-flex;
2389
- align-items: center;
2390
- gap: 4px;
2391
- font-size: 11px;
2392
- font-weight: 600;
2393
- padding: 3px 8px;
2394
- border-radius: var(--_radius-s);
2395
- text-transform: capitalize;
2396
- }
2397
-
2398
- .wi-type svg {
2399
- width: 12px;
2400
- height: 12px;
2401
- }
2402
-
2403
- /* Type colors \u2014 driven by VB theme tokens, with color-mix surfaces so the
2404
- pill background shifts with the active theme. */
2405
- .wi-type[data-type="task"] { color: var(--color-info, #3b82f6); background: color-mix(in oklch, var(--color-info, #3b82f6) 12%, transparent); }
2406
- .wi-type[data-type="bug"] { color: var(--color-error, #dc2626); background: color-mix(in oklch, var(--color-error, #dc2626) 12%, transparent); }
2407
- .wi-type[data-type="chore"] { color: var(--color-text-muted, #6b7280); background: color-mix(in oklch, var(--color-text-muted, #6b7280) 12%, transparent); }
2408
- .wi-type[data-type="spike"] { color: var(--color-accent, #8b5cf6); background: color-mix(in oklch, var(--color-accent, #8b5cf6) 12%, transparent); }
2409
- .wi-type[data-type="feature"] { color: var(--color-success, #059669); background: color-mix(in oklch, var(--color-success, #059669) 12%, transparent); }
2410
-
2411
- /* \u2500\u2500 Badges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2412
- .wi-badges {
2413
- display: flex;
2414
- align-items: center;
2415
- gap: var(--_space-xs);
2416
- }
2417
-
2418
- .wi-priority,
2419
- .wi-status {
2420
- font-size: 11px;
2421
- padding: 4px 10px;
2422
- border-radius: var(--_radius-full);
2423
- font-weight: 600;
2424
- text-transform: uppercase;
2425
- letter-spacing: 0.3px;
2426
- }
2427
-
2428
- .wi-estimate {
2429
- width: 28px;
2430
- height: 28px;
2431
- border-radius: var(--_radius-full);
2432
- background: var(--_accent);
2433
- color: white;
2434
- font-size: var(--_font-xs);
2435
- font-weight: 700;
2436
- display: flex;
2437
- align-items: center;
2438
- justify-content: center;
2439
- }
2440
-
2441
- /* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2442
- .wi-body {
2443
- padding: 16px 20px;
2444
- }
2445
-
2446
- .wi-title-wrap {
2447
- margin-block-end: var(--_space-xs);
2448
- }
2449
-
2450
- .wi-title-wrap:last-child {
2451
- margin-block-end: 0;
2452
- }
2453
-
2454
- ::slotted([slot="title"]) {
2455
- font-size: var(--_font-lg) !important;
2456
- font-weight: 700 !important;
2457
- color: var(--_text) !important;
2458
- line-height: 1.4 !important;
2459
- margin: 0 !important;
2460
- }
2461
-
2462
- .wi-title-fallback {
2463
- font-size: var(--_font-lg);
2464
- font-weight: 700;
2465
- color: var(--_text);
2466
- line-height: 1.4;
2467
- }
2468
-
2469
- .wi-title:last-child {
2470
- margin-block-end: 0;
2471
- }
2472
-
2473
- /* \u2500\u2500 Assignee \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2474
- .wi-assignee {
2475
- display: inline-flex;
2476
- align-items: center;
2477
- gap: 5px;
2478
- font-size: var(--_font-xs);
2479
- color: var(--_muted);
2480
- margin-block-start: var(--_space-xs);
2481
- }
2482
-
2483
- .wi-assignee__avatar {
2484
- width: 20px;
2485
- height: 20px;
2486
- border-radius: var(--_radius-full);
2487
- font-size: 9px;
2488
- font-weight: 700;
2489
- display: flex;
2490
- align-items: center;
2491
- justify-content: center;
2492
- color: var(--color-text-inverted, #fff);
2493
- flex-shrink: 0;
2494
- }
2495
-
2496
- /* \u2500\u2500 Linked stories \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2497
- .wi-links {
2498
- display: flex;
2499
- flex-wrap: wrap;
2500
- gap: 4px;
2501
- margin-block-start: var(--_space-s);
2502
- }
2503
-
2504
- .wi-link {
2505
- display: inline-flex;
2506
- align-items: center;
2507
- gap: 3px;
2508
- font-size: 11px;
2509
- font-weight: 500;
2510
- padding: 2px 8px;
2511
- border-radius: var(--_radius-s);
2512
- background: var(--_highlight);
2513
- color: var(--_accent);
2514
- text-decoration: none;
2515
- }
2516
-
2517
- .wi-link:hover {
2518
- text-decoration: underline;
2519
- }
2520
-
2521
- .wi-link svg {
2522
- width: 11px;
2523
- height: 11px;
2524
- }
2525
-
2526
- /* \u2500\u2500 Sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2527
- .wi-sections {
2528
- border-block-start: 1px solid var(--_border);
2529
- }
2530
-
2531
- .wi-section {
2532
- padding: 14px 20px;
2533
- border-block-end: 1px solid var(--_border);
2534
- }
2535
-
2536
- .wi-section:last-child {
2537
- border-block-end: none;
2538
- }
2539
-
2540
- .wi-section-header {
2541
- display: flex;
2542
- align-items: center;
2543
- gap: var(--_space-xs);
2544
- margin-block-end: var(--_space-s);
2545
- }
2546
-
2547
- .wi-section-icon {
2548
- width: 22px;
2549
- height: 22px;
2550
- border-radius: 5px;
2551
- display: flex;
2552
- align-items: center;
2553
- justify-content: center;
2554
- }
2555
-
2556
- .wi-section-icon svg {
2557
- width: 13px;
2558
- height: 13px;
2559
- fill: var(--color-text-inverted, #fff);
2560
- }
2561
-
2562
- .wi-section-icon.description { background: var(--color-info, #3b82f6); }
2563
- .wi-section-icon.checklist { background: var(--color-success, #22c55e); }
2564
- .wi-section-icon.notes { background: var(--color-warning, #f59e0b); }
2565
-
2566
- .wi-section-title {
2567
- font-size: var(--_font-xs);
2568
- font-weight: 600;
2569
- color: var(--_muted);
2570
- text-transform: uppercase;
2571
- letter-spacing: 0.5px;
2572
- }
2573
-
2574
- .wi-section-content {
2575
- color: var(--_text);
2576
- font-size: var(--_font-sm);
2577
- line-height: 1.6;
2578
- }
2579
-
2580
- .wi-section-content ::slotted(ul),
2581
- .wi-section-content ::slotted(ol) {
2582
- margin: 0;
2583
- padding-inline-start: 20px;
2584
- }
2585
-
2586
- .wi-section-content ::slotted(p) {
2587
- margin: 0;
2588
- }
2589
-
2590
- .slot-fallback {
2591
- color: var(--_muted);
2592
- font-style: italic;
2593
- }
2594
-
2595
- /* \u2500\u2500 Minimal detail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2596
- .wi-card--minimal {
2597
- padding: var(--_space-xs);
2598
- cursor: pointer;
2599
- }
2600
-
2601
- .wi-card--minimal:hover {
2602
- box-shadow: var(--_shadow-hover);
2603
- }
2604
-
2605
- .wi-card--minimal:focus-visible {
2606
- outline: 2px solid var(--_accent);
2607
- outline-offset: 2px;
2608
- }
2609
-
2610
- .wi-card--minimal .wi-header { display: none; }
2611
- .wi-card--minimal .wi-sections { display: none; }
2612
- .wi-card--minimal .wi-links { display: none; }
2613
- .wi-card--minimal .wi-assignee { display: none; }
2614
-
2615
- .wi-card--minimal .wi-body {
2616
- padding: var(--_space-xs) var(--_space-s);
2617
- }
2618
-
2619
- .wi-card--minimal .wi-title-fallback,
2620
- .wi-card--minimal ::slotted([slot="title"]) {
2621
- font-size: var(--_font-sm) !important;
2622
- font-weight: 600 !important;
2623
- }
2624
-
2625
- .wi-card--minimal .wi-id {
2626
- display: block;
2627
- margin-block-end: var(--_space-2xs);
2628
- }
2629
-
2630
- .wi-card--minimal .wi-type {
2631
- font-size: 10px;
2632
- padding: 2px 6px;
2633
- }
2634
-
2635
- /* \u2500\u2500 Compact detail \u2014 hide empty sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2636
- .wi-card--compact .wi-section[data-empty] {
2637
- display: none;
2638
- }
2639
-
2640
- .wi-card--compact .slot-fallback {
2641
- display: none;
2642
- }
2643
-
2644
- .wi-card--compact .wi-body {
2645
- padding: var(--_space-s) var(--_space-m);
2646
- }
2647
-
2648
- /* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2649
- @media (max-width: 480px) {
2650
- .wi-header {
2651
- flex-direction: column;
2652
- align-items: flex-start;
2653
- }
2654
-
2655
- .wi-badges {
2656
- width: 100%;
2657
- justify-content: flex-start;
2658
- }
2659
- }
2660
-
2661
- @media (prefers-reduced-motion: reduce) {
2662
- .wi-card {
2663
- transition: none;
2664
- }
2665
- }
2666
-
2667
- @media print {
2668
- .wi-card {
2669
- box-shadow: none;
2670
- break-inside: avoid;
2671
- }
2672
- }
2673
-
2674
- .state-msg { padding: var(--_space-m); font-size: var(--_font-sm); color: var(--_muted); font-style: italic; }
2675
- .state-msg--error { color: var(--color-error-text, var(--color-error, #dc2626)); }
2676
- `;var jt={task:'<rect x="3" y="3" width="18" height="18" rx="2"/><path d="m9 12 2 2 4-4"/>',bug:'<path d="m8 2 1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/>',chore:'<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/>',spike:'<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/>',feature:'<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>'},At={critical:{label:"Critical",color:"#dc2626",bg:"rgba(220, 38, 38, 0.1)"},high:{label:"High",color:"#ea580c",bg:"rgba(234, 88, 12, 0.1)"},medium:{label:"Medium",color:"#ca8a04",bg:"rgba(202, 138, 4, 0.1)"},low:{label:"Low",color:"#16a34a",bg:"rgba(22, 163, 74, 0.1)"}},kt={backlog:{label:"Backlog",color:"#6b7280",bg:"rgba(107, 114, 128, 0.1)"},"to-do":{label:"To Do",color:"#3b82f6",bg:"rgba(59, 130, 246, 0.1)"},"in-progress":{label:"In Progress",color:"#8b5cf6",bg:"rgba(139, 92, 246, 0.1)"},review:{label:"Review",color:"#f59e0b",bg:"rgba(245, 158, 11, 0.1)"},done:{label:"Done",color:"#22c55e",bg:"rgba(34, 197, 94, 0.1)"},blocked:{label:"Blocked",color:"#dc2626",bg:"rgba(220, 38, 38, 0.1)"}},Ct=class extends HTMLElement{static get observedAttributes(){return["item-id","type","priority","status","estimate","assignee","story-ids","detail","compact","src"]}#e=new Map;constructor(){super(),this.attachShadow({mode:"open"})}#t(){for(let t of[...this.children]){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}_resolve(t){return this.getAttribute(t)||this.#e.get(t)||""}connectedCallback(){this.#t(),this.itemId&&!this.id&&(this.id=this.itemId),this.hasAttribute("src")&&this._loadSrc(this.getAttribute("src")),this.#r(),this.setAttribute("data-upgraded","")}disconnectedCallback(){this.removeAttribute("data-upgraded")}attributeChangedCallback(t,e,r){e!==r&&this.shadowRoot&&(t==="src"&&this.isConnected?this._loadSrc(r):this.#r())}get itemId(){return this.getAttribute("item-id")||""}get itemTitle(){return this.querySelector('[slot="title"]')?.textContent?.trim()||this.#e.get("title")||""}get itemType(){return this.getAttribute("type")||"task"}get priority(){return this.getAttribute("priority")||"medium"}get status(){return this.getAttribute("status")||"backlog"}get estimate(){return this.getAttribute("estimate")||""}get assignee(){return this.getAttribute("assignee")||""}get storyIds(){let t=this.getAttribute("story-ids")||"";return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}get _detailLevel(){return this.getAttribute("detail")?this.getAttribute("detail"):this.hasAttribute("compact")?"compact":"full"}get _minimalLabel(){return this.itemTitle||this.itemId||"Work item"}updateStatus(t){kt[t]&&(this.setAttribute("status",t),this.dispatchEvent(new CustomEvent("work-item:status",{detail:{status:t,itemId:this.itemId},bubbles:!0,composed:!0})))}updatePriority(t){At[t]&&(this.setAttribute("priority",t),this.dispatchEvent(new CustomEvent("work-item:priority",{detail:{priority:t,itemId:this.itemId},bubbles:!0,composed:!0})))}get data(){return{itemId:this.itemId||void 0,type:this.itemType,priority:this.priority,status:this.status,estimate:this.estimate||void 0,assignee:this.assignee||void 0,storyIds:this.storyIds.length?this.storyIds:void 0,detail:this.getAttribute("detail")||void 0,title:this.itemTitle||void 0}}set data(t){!t||typeof t!="object"||(this._applyData(t),this.shadowRoot&&this.#r(),this.dispatchEvent(new CustomEvent("work-item:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0})))}_applyData(t){for(let[e,r]of[["itemId","item-id"],["type","type"],["priority","priority"],["status","status"],["estimate","estimate"],["assignee","assignee"],["detail","detail"]])t[e]!=null&&this.setAttribute(r,String(t[e]));if(t.storyIds&&this.setAttribute("story-ids",Array.isArray(t.storyIds)?t.storyIds.join(","):String(t.storyIds)),t.title&&!this.querySelector('[slot="title"]')){let e=document.createElement("h3");e.slot="title",e.textContent=String(t.title),this.appendChild(e)}for(let e of["description","notes"])if(t[e]&&!this.querySelector(`[slot="${e}"]`)){let r=document.createElement("p");r.slot=e,r.textContent=String(t[e]),this.appendChild(r)}if(t.checklist&&!this.querySelector('[slot="checklist"]')){let e=document.createElement("ul");e.slot="checklist";let r=Array.isArray(t.checklist)?t.checklist:[t.checklist];for(let s of r){let a=document.createElement("li");a.textContent=String(s),e.appendChild(a)}this.appendChild(e)}}async _loadSrc(t){if(!t)return;let e=this.shadowRoot;e.innerHTML=`<style>${R}</style><div class="state-msg">Loading\u2026</div>`;try{let r=await fetch(t);if(!r.ok)throw new Error(`HTTP ${r.status}`);let s=await r.json();this._applyData(s),this.#r()}catch(r){e.innerHTML=`<style>${R}</style><div class="state-msg state-msg--error">Could not load: ${h(r.message)}</div>`}}#r(){let t=this.shadowRoot,e=At[this.priority]||At.medium,r=kt[this.status]||kt.backlog,s=this.itemType,a=jt[s]||jt.task,i=this._detailLevel,o=this.itemId?`Work item: ${h(this.itemId)}`:"Work item";if(i==="minimal"){t.innerHTML=`<style>${R}</style>
2677
- <article class="wi-card wi-card--minimal" role="article" aria-label="${o}"
2678
- tabindex="0">
2679
- <div class="wi-body">
2680
- <div class="wi-meta">
2681
- ${this.itemId?`<span class="wi-id">${h(this.itemId)}</span>`:""}
2682
- <span class="wi-type" data-type="${h(s)}">${A(a)} ${h(s)}</span>
2683
- </div>
2684
- <div class="wi-title-wrap">
2685
- <slot name="title"><span class="wi-title-fallback">${h(this._minimalLabel)}</span></slot>
2686
- </div>
2687
- </div>
2688
- </article>`;return}if(t.innerHTML=`<style>${R}</style>
2689
- <article class="wi-card wi-card--${i}" role="article" aria-label="${o}">
2690
-
2691
- <header class="wi-header">
2692
- <div class="wi-meta">
2693
- ${this.itemId?`<span class="wi-id">${h(this.itemId)}</span>`:""}
2694
- <span class="wi-type" data-type="${h(s)}">${A(a)} ${h(s)}</span>
2695
- </div>
2696
- <div class="wi-badges">
2697
- <span class="wi-priority" style="color:${e.color};background:${e.bg}">${h(e.label)}</span>
2698
- <span class="wi-status" style="color:${r.color};background:${r.bg}">${h(r.label)}</span>
2699
- ${this.estimate?`<span class="wi-estimate" title="Estimate">${h(this.estimate)}</span>`:""}
2700
- </div>
2701
- </header>
2702
-
2703
- <div class="wi-body">
2704
- <div class="wi-title-wrap">
2705
- <slot name="title"><span class="wi-title-fallback">[Untitled work item]</span></slot>
2706
- </div>
2707
-
2708
- ${this.assignee?`
2709
- <div class="wi-assignee">
2710
- <span class="wi-assignee__avatar" style="background:${L(this.assignee)}">${z(this.assignee)}</span>
2711
- ${h(this.assignee)}
2712
- </div>`:""}
2713
-
2714
- ${this.storyIds.length?`
2715
- <div class="wi-links">
2716
- ${this.storyIds.map(n=>`<a class="wi-link" href="#${h(n)}">${A('<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7 7h10"/><path d="M7 12h10"/><path d="M7 17h10"/>')} ${h(n)}</a>`).join("")}
2717
- </div>`:""}
2718
- </div>
2719
-
2720
- <div class="wi-sections">
2721
- <div class="wi-section">
2722
- <div class="wi-section-header">
2723
- <div class="wi-section-icon description">
2724
- <svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
2725
- </div>
2726
- <span class="wi-section-title">Description</span>
2727
- </div>
2728
- <div class="wi-section-content">
2729
- <slot name="description"><em class="slot-fallback">No description.</em></slot>
2730
- </div>
2731
- </div>
2732
-
2733
- <div class="wi-section">
2734
- <div class="wi-section-header">
2735
- <div class="wi-section-icon checklist">
2736
- <svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
2737
- </div>
2738
- <span class="wi-section-title">Checklist</span>
2739
- </div>
2740
- <div class="wi-section-content">
2741
- <slot name="checklist"><em class="slot-fallback">No checklist items.</em></slot>
2742
- </div>
2743
- </div>
2744
-
2745
- <div class="wi-section">
2746
- <div class="wi-section-header">
2747
- <div class="wi-section-icon notes">
2748
- <svg viewBox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
2749
- </div>
2750
- <span class="wi-section-title">Notes</span>
2751
- </div>
2752
- <div class="wi-section-content">
2753
- <slot name="notes"><em class="slot-fallback">No notes.</em></slot>
2754
- </div>
2755
- </div>
2756
- </div>
2757
-
2758
- </article>`,i==="compact")for(let n of t.querySelectorAll(".wi-section")){let l=n.querySelector("slot");l&&l.assignedNodes().length===0&&n.setAttribute("data-empty","")}this.dispatchEvent(new CustomEvent("work-item:ready",{detail:{itemId:this.itemId,title:this.itemTitle,type:s,priority:this.priority,status:this.status},bubbles:!0,composed:!0}))}};x("work-item",Ct);var O=`
2759
- :host {
2760
- --_bg: var(--adr-wc-bg, var(--color-surface, #ffffff));
2761
- --_text: var(--adr-wc-text, var(--color-text, #1a1a1a));
2762
- --_muted: var(--adr-wc-muted, var(--color-text-muted, #666));
2763
- --_border: var(--adr-wc-border, var(--color-border, #e0e0e0));
2764
- --_accent: var(--adr-wc-accent, var(--color-interactive, #0066cc));
2765
- --_card-bg: var(--adr-wc-card-bg, var(--color-surface-raised, #f8f9fa));
2766
- --_highlight: var(--adr-wc-highlight, color-mix(in srgb, var(--_accent) 8%, transparent));
2767
- --_radius: var(--adr-wc-radius, var(--radius-l, 0.75rem));
2768
- --_shadow: var(--adr-wc-shadow, var(--shadow-sm));
2769
- --_shadow-hover: var(--adr-wc-shadow-hover, var(--shadow-md));
2770
- --_duration: var(--adr-wc-duration, var(--duration-normal, 200ms));
2771
- --_ease: var(--adr-wc-ease, var(--ease-default, ease));
2772
- --_space-2xs: var(--adr-wc-space-2xs, var(--size-2xs, 0.25rem));
2773
- --_space-xs: var(--adr-wc-space-xs, var(--size-xs, 0.5rem));
2774
- --_space-s: var(--adr-wc-space-s, var(--size-s, 0.75rem));
2775
- --_space-m: var(--adr-wc-space-m, var(--size-m, 1rem));
2776
- --_font-xs: var(--adr-wc-font-xs, var(--font-size-xs, 0.75rem));
2777
- --_font-sm: var(--adr-wc-font-sm, var(--font-size-sm, 0.875rem));
2778
- --_font-md: var(--adr-wc-font-md, var(--font-size-md, 1rem));
2779
- --_font-lg: var(--adr-wc-font-lg, var(--font-size-lg, 1.125rem));
2780
- --_font-mono: var(--adr-wc-font-mono, var(--font-mono, ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace));
2781
- --_radius-s: var(--adr-wc-radius-s, var(--radius-s, 0.25rem));
2782
- --_radius-full: var(--adr-wc-radius-full, var(--radius-full, 9999px));
2783
-
2784
- display: block;
2785
- font-family: var(--adr-wc-font, var(--font-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif));
2786
- }
2787
-
2788
- *, *::before, *::after { box-sizing: border-box; margin: 0; }
2789
-
2790
- /* \u2500\u2500 Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2791
- .adr-card {
2792
- background: var(--_bg);
2793
- border: 1px solid var(--_border);
2794
- border-radius: var(--_radius);
2795
- overflow: hidden;
2796
- box-shadow: var(--_shadow);
2797
- transition: box-shadow var(--_duration) var(--_ease);
2798
- }
2799
-
2800
- .adr-card:hover {
2801
- box-shadow: var(--_shadow-hover);
2802
- }
2803
-
2804
- /* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2805
- .adr-header {
2806
- display: flex;
2807
- align-items: center;
2808
- justify-content: space-between;
2809
- padding: var(--_space-s) var(--_space-m);
2810
- background: var(--_card-bg);
2811
- border-block-end: 1px solid var(--_border);
2812
- gap: var(--_space-s);
2813
- flex-wrap: wrap;
2814
- }
2815
-
2816
- .adr-meta {
2817
- display: flex;
2818
- align-items: center;
2819
- gap: var(--_space-xs);
2820
- flex-wrap: wrap;
2821
- min-width: 0;
2822
- }
2823
-
2824
- .adr-id {
2825
- font-size: var(--_font-xs);
2826
- font-weight: 600;
2827
- color: var(--_muted);
2828
- font-family: var(--_font-mono);
2829
- }
2830
-
2831
- /* \u2500\u2500 Status badge \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2832
- .adr-badges {
2833
- display: flex;
2834
- align-items: center;
2835
- gap: var(--_space-xs);
2836
- }
2837
-
2838
- .adr-status {
2839
- font-size: 11px;
2840
- padding: 4px 10px;
2841
- border-radius: var(--_radius-full);
2842
- font-weight: 600;
2843
- text-transform: uppercase;
2844
- letter-spacing: 0.3px;
2845
- }
2846
-
2847
- /* \u2500\u2500 Date (slotted <time>) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2848
- .adr-date-wrap {
2849
- display: inline-flex;
2850
- align-items: center;
2851
- gap: 4px;
2852
- font-size: var(--_font-xs);
2853
- color: var(--_muted);
2854
- }
2855
-
2856
- .adr-date-wrap svg {
2857
- width: 12px;
2858
- height: 12px;
2859
- flex-shrink: 0;
2860
- }
2861
-
2862
- ::slotted([slot="date"]) {
2863
- font-size: var(--_font-xs);
2864
- font-family: var(--_font-mono);
2865
- color: var(--_muted);
2866
- }
2867
-
2868
- /* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2869
- .adr-body {
2870
- padding: 16px 20px;
2871
- }
2872
-
2873
- /* \u2500\u2500 Title (slotted heading) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2874
- .adr-title-wrap {
2875
- margin-block-end: 0;
2876
- }
2877
-
2878
- ::slotted([slot="title"]) {
2879
- font-size: var(--_font-lg) !important;
2880
- font-weight: 700 !important;
2881
- color: var(--_text) !important;
2882
- line-height: 1.4 !important;
2883
- margin: 0 !important;
2884
- }
2885
-
2886
- /* Fallback title when no slot content */
2887
- .adr-title-fallback {
2888
- font-size: var(--_font-lg);
2889
- font-weight: 700;
2890
- color: var(--_text);
2891
- line-height: 1.4;
2892
- }
2893
-
2894
- /* \u2500\u2500 Supersedes / Superseded-by links \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2895
- .adr-links {
2896
- display: flex;
2897
- flex-wrap: wrap;
2898
- gap: 4px;
2899
- margin-block-start: var(--_space-s);
2900
- }
2901
-
2902
- .adr-links-label {
2903
- font-size: 11px;
2904
- font-weight: 600;
2905
- color: var(--_muted);
2906
- text-transform: uppercase;
2907
- letter-spacing: 0.3px;
2908
- margin-inline-end: var(--_space-2xs);
2909
- align-self: center;
2910
- }
2911
-
2912
- .adr-link {
2913
- display: inline-flex;
2914
- align-items: center;
2915
- gap: 3px;
2916
- font-size: 11px;
2917
- font-weight: 500;
2918
- padding: 2px 8px;
2919
- border-radius: var(--_radius-s);
2920
- background: var(--_highlight);
2921
- color: var(--_accent);
2922
- text-decoration: none;
2923
- }
2924
-
2925
- .adr-link:hover {
2926
- text-decoration: underline;
2927
- }
2928
-
2929
- .adr-link svg {
2930
- width: 11px;
2931
- height: 11px;
2932
- }
2933
-
2934
- /* \u2500\u2500 Sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2935
- .adr-sections {
2936
- border-block-start: 1px solid var(--_border);
2937
- }
2938
-
2939
- .adr-section {
2940
- padding: 14px 20px;
2941
- border-block-end: 1px solid var(--_border);
2942
- }
2943
-
2944
- .adr-section:last-child {
2945
- border-block-end: none;
2946
- }
2947
-
2948
- .adr-section-header {
2949
- display: flex;
2950
- align-items: center;
2951
- gap: var(--_space-xs);
2952
- margin-block-end: var(--_space-s);
2953
- }
2954
-
2955
- .adr-section-icon {
2956
- width: 22px;
2957
- height: 22px;
2958
- border-radius: 5px;
2959
- display: flex;
2960
- align-items: center;
2961
- justify-content: center;
2962
- }
2963
-
2964
- .adr-section-icon svg {
2965
- width: 13px;
2966
- height: 13px;
2967
- fill: var(--color-text-inverted, #fff);
2968
- }
2969
-
2970
- .adr-section-icon.context { background: var(--color-accent, #8b5cf6); }
2971
- .adr-section-icon.decision { background: var(--color-success, #22c55e); }
2972
- .adr-section-icon.consequences { background: var(--color-warning, #f59e0b); }
2973
-
2974
- .adr-section-title {
2975
- font-size: var(--_font-xs);
2976
- font-weight: 600;
2977
- color: var(--_muted);
2978
- text-transform: uppercase;
2979
- letter-spacing: 0.5px;
2980
- }
2981
-
2982
- .adr-section-content {
2983
- color: var(--_text);
2984
- font-size: var(--_font-sm);
2985
- line-height: 1.6;
2986
- }
2987
-
2988
- .adr-section-content ::slotted(ul),
2989
- .adr-section-content ::slotted(ol) {
2990
- margin: 0;
2991
- padding-inline-start: 20px;
2992
- }
2993
-
2994
- .adr-section-content ::slotted(p) {
2995
- margin: 0;
2996
- }
2997
-
2998
- .slot-fallback {
2999
- color: var(--_muted);
3000
- font-style: italic;
3001
- }
3002
-
3003
- /* \u2500\u2500 Minimal detail \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3004
- .adr-card--minimal {
3005
- padding: var(--_space-xs);
3006
- cursor: pointer;
3007
- }
3008
-
3009
- .adr-card--minimal:hover {
3010
- box-shadow: var(--_shadow-hover);
3011
- }
3012
-
3013
- .adr-card--minimal:focus-visible {
3014
- outline: 2px solid var(--_accent);
3015
- outline-offset: 2px;
3016
- }
3017
-
3018
- .adr-card--minimal .adr-header { display: none; }
3019
- .adr-card--minimal .adr-sections { display: none; }
3020
- .adr-card--minimal .adr-links { display: none; }
3021
- .adr-card--minimal .adr-date-wrap { display: none; }
3022
-
3023
- .adr-card--minimal .adr-body {
3024
- padding: var(--_space-xs) var(--_space-s);
3025
- }
3026
-
3027
- .adr-card--minimal .adr-title-fallback,
3028
- .adr-card--minimal ::slotted([slot="title"]) {
3029
- font-size: var(--_font-sm) !important;
3030
- font-weight: 600 !important;
3031
- }
3032
-
3033
- .adr-card--minimal .adr-id {
3034
- display: block;
3035
- margin-block-end: var(--_space-2xs);
3036
- }
3037
-
3038
- .adr-card--minimal .adr-status {
3039
- font-size: 10px;
3040
- padding: 2px 6px;
3041
- }
3042
-
3043
- /* \u2500\u2500 Compact detail \u2014 hide empty sections \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3044
- .adr-card--compact .adr-section[data-empty] {
3045
- display: none;
3046
- }
3047
-
3048
- .adr-card--compact .slot-fallback {
3049
- display: none;
3050
- }
3051
-
3052
- .adr-card--compact .adr-body {
3053
- padding: var(--_space-s) var(--_space-m);
3054
- }
3055
-
3056
- /* \u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
3057
- @media (max-width: 480px) {
3058
- .adr-header {
3059
- flex-direction: column;
3060
- align-items: flex-start;
3061
- }
3062
-
3063
- .adr-badges {
3064
- width: 100%;
3065
- justify-content: flex-start;
3066
- }
3067
- }
3068
-
3069
- @media (prefers-reduced-motion: reduce) {
3070
- .adr-card {
3071
- transition: none;
3072
- }
3073
- }
3074
-
3075
- @media print {
3076
- .adr-card {
3077
- box-shadow: none;
3078
- break-inside: avoid;
3079
- }
3080
- }
3081
-
3082
- .state-msg { padding: var(--_space-m); font-size: var(--_font-sm); color: var(--_muted); font-style: italic; }
3083
- .state-msg--error { color: var(--color-error-text, var(--color-error, #dc2626)); }
3084
- `;var Rt={proposed:{label:"Proposed",color:"#3b82f6",bg:"rgba(59, 130, 246, 0.1)"},accepted:{label:"Accepted",color:"#22c55e",bg:"rgba(34, 197, 94, 0.1)"},deprecated:{label:"Deprecated",color:"#f59e0b",bg:"rgba(245, 158, 11, 0.1)"},superseded:{label:"Superseded",color:"#6b7280",bg:"rgba(107, 114, 128, 0.1)"}},D={calendar:'<rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" x2="16" y1="2" y2="6"/><line x1="8" x2="8" y1="2" y2="6"/><line x1="3" x2="21" y1="10" y2="10"/>',context:'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" x2="8" y1="13" y2="13"/><line x1="16" x2="8" y1="17" y2="17"/><line x1="10" x2="8" y1="9" y2="9"/>',decision:'<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/>',consequences:'<path d="m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"/><path d="m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"/><path d="M7 21h10"/><path d="M12 3v18"/><path d="M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2"/>',arrowRight:'<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>'},Et=class extends HTMLElement{static get observedAttributes(){return["adr-id","status","supersedes","superseded-by","detail","compact","src"]}#e=new Map;constructor(){super(),this.attachShadow({mode:"open"})}#t(){for(let t of[...this.children]){let e=t.getAttribute("slot");e&&this.#e.set(e,t.textContent.trim())}}connectedCallback(){this.#t(),this.adrId&&!this.id&&(this.id=this.adrId),this.hasAttribute("src")&&this._loadSrc(this.getAttribute("src")),this.#r(),this.setAttribute("data-upgraded","")}disconnectedCallback(){this.removeAttribute("data-upgraded")}attributeChangedCallback(t,e,r){e!==r&&this.shadowRoot&&(t==="src"&&this.isConnected?this._loadSrc(r):this.#r())}get adrId(){return this.getAttribute("adr-id")||""}get status(){return this.getAttribute("status")||"proposed"}get adrTitle(){return this.querySelector('[slot="title"]')?.textContent?.trim()||this.#e.get("title")||""}get adrDate(){let t=this.querySelector('[slot="date"]');return t?.getAttribute("datetime")||t?.textContent?.trim()||this.#e.get("date")||""}get supersedes(){let t=this.getAttribute("supersedes")||"";return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}get supersededBy(){let t=this.getAttribute("superseded-by")||"";return t?t.split(",").map(e=>e.trim()).filter(Boolean):[]}get _detailLevel(){return this.getAttribute("detail")?this.getAttribute("detail"):this.hasAttribute("compact")?"compact":"full"}get _minimalLabel(){return this.adrTitle||this.adrId||"ADR"}get data(){return{adrId:this.adrId||void 0,status:this.status,detail:this.getAttribute("detail")||void 0,supersedes:this.supersedes.length?this.supersedes:void 0,supersededBy:this.supersededBy.length?this.supersededBy:void 0,title:this.adrTitle||void 0,date:this.adrDate||void 0}}set data(t){!t||typeof t!="object"||(this._applyData(t),this.#t(),this.shadowRoot&&this.#r(),this.dispatchEvent(new CustomEvent("adr-wc:data-changed",{detail:{data:this.data,source:"property"},bubbles:!0,composed:!0})))}_applyData(t){if(t.adrId!=null&&this.setAttribute("adr-id",String(t.adrId)),t.status!=null&&this.setAttribute("status",String(t.status)),t.detail!=null&&this.setAttribute("detail",String(t.detail)),t.supersedes&&this.setAttribute("supersedes",Array.isArray(t.supersedes)?t.supersedes.join(","):String(t.supersedes)),t.supersededBy&&this.setAttribute("superseded-by",Array.isArray(t.supersededBy)?t.supersededBy.join(","):String(t.supersededBy)),t.title&&!this.querySelector('[slot="title"]')){let e=document.createElement("h3");e.slot="title",e.textContent=String(t.title),this.appendChild(e)}if(t.date&&!this.querySelector('[slot="date"]')){let e=document.createElement("time");e.slot="date",e.setAttribute("datetime",String(t.date)),e.textContent=new Date(String(t.date)).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"}),this.appendChild(e)}for(let e of["context","decision"])if(t[e]&&!this.querySelector(`[slot="${e}"]`)){let r=document.createElement("p");r.slot=e,r.textContent=String(t[e]),this.appendChild(r)}if(t.consequences&&!this.querySelector('[slot="consequences"]')){let e=document.createElement("ul");e.slot="consequences";let r=Array.isArray(t.consequences)?t.consequences:[t.consequences];for(let s of r){let a=document.createElement("li");a.textContent=String(s),e.appendChild(a)}this.appendChild(e)}}async _loadSrc(t){if(!t)return;let e=this.shadowRoot;e.innerHTML=`<style>${O}</style><div class="state-msg">Loading\u2026</div>`;try{let r=await fetch(t);if(!r.ok)throw new Error(`HTTP ${r.status}`);let s=await r.json();this._applyData(s),this.#t(),this.#r()}catch(r){e.innerHTML=`<style>${O}</style><div class="state-msg state-msg--error">Could not load: ${h(r.message)}</div>`}}#r(){let t=this.shadowRoot,e=Rt[this.status]||Rt.proposed,r=this._detailLevel,s=this.adrId?`ADR: ${h(this.adrId)}`:"Architectural Decision Record",a=!!this.querySelector('[slot="date"]')||this.#e.has("date");if(r==="minimal"){t.innerHTML=`<style>${O}</style>
3085
- <article class="adr-card adr-card--minimal" role="article" aria-label="${s}"
3086
- tabindex="0">
3087
- <div class="adr-body">
3088
- <div class="adr-meta">
3089
- ${this.adrId?`<span class="adr-id">${h(this.adrId)}</span>`:""}
3090
- <span class="adr-status" style="color:${e.color};background:${e.bg}">${h(e.label)}</span>
3091
- </div>
3092
- <div class="adr-title-wrap">
3093
- <slot name="title"><span class="adr-title-fallback">${h(this._minimalLabel)}</span></slot>
3094
- </div>
3095
- </div>
3096
- </article>`;return}if(t.innerHTML=`<style>${O}</style>
3097
- <article class="adr-card adr-card--${r}" role="article" aria-label="${s}">
3098
-
3099
- <header class="adr-header">
3100
- <div class="adr-meta">
3101
- ${this.adrId?`<span class="adr-id">${h(this.adrId)}</span>`:""}
3102
- ${a?`<span class="adr-date-wrap">${A(D.calendar)} <slot name="date"></slot></span>`:""}
3103
- </div>
3104
- <div class="adr-badges">
3105
- <span class="adr-status" style="color:${e.color};background:${e.bg}">${h(e.label)}</span>
3106
- </div>
3107
- </header>
3108
-
3109
- <div class="adr-body">
3110
- <div class="adr-title-wrap">
3111
- <slot name="title"><span class="adr-title-fallback">[Untitled ADR]</span></slot>
3112
- </div>
3113
-
3114
- ${this.supersedes.length?`
3115
- <div class="adr-links">
3116
- <span class="adr-links-label">Supersedes</span>
3117
- ${this.supersedes.map(i=>`<a class="adr-link" href="#${h(i)}">${A(D.arrowRight)} ${h(i)}</a>`).join("")}
3118
- </div>`:""}
3119
-
3120
- ${this.supersededBy.length?`
3121
- <div class="adr-links">
3122
- <span class="adr-links-label">Superseded by</span>
3123
- ${this.supersededBy.map(i=>`<a class="adr-link" href="#${h(i)}">${A(D.arrowRight)} ${h(i)}</a>`).join("")}
3124
- </div>`:""}
3125
- </div>
3126
-
3127
- <div class="adr-sections">
3128
- <div class="adr-section">
3129
- <div class="adr-section-header">
3130
- <div class="adr-section-icon context">${A(D.context)}</div>
3131
- <span class="adr-section-title">Context</span>
3132
- </div>
3133
- <div class="adr-section-content">
3134
- <slot name="context"><em class="slot-fallback">No context provided.</em></slot>
3135
- </div>
3136
- </div>
3137
-
3138
- <div class="adr-section">
3139
- <div class="adr-section-header">
3140
- <div class="adr-section-icon decision">${A(D.decision)}</div>
3141
- <span class="adr-section-title">Decision</span>
3142
- </div>
3143
- <div class="adr-section-content">
3144
- <slot name="decision"><em class="slot-fallback">No decision recorded.</em></slot>
3145
- </div>
3146
- </div>
3147
-
3148
- <div class="adr-section">
3149
- <div class="adr-section-header">
3150
- <div class="adr-section-icon consequences">${A(D.consequences)}</div>
3151
- <span class="adr-section-title">Consequences</span>
3152
- </div>
3153
- <div class="adr-section-content">
3154
- <slot name="consequences"><em class="slot-fallback">No consequences documented.</em></slot>
3155
- </div>
3156
- </div>
3157
- </div>
3158
-
3159
- </article>`,r==="compact")for(let i of t.querySelectorAll(".adr-section")){let o=i.querySelector("slot");o&&o.assignedNodes().length===0&&i.setAttribute("data-empty","")}this.dispatchEvent(new CustomEvent("adr-wc:ready",{detail:{adrId:this.adrId,title:this.adrTitle,status:this.status},bubbles:!0,composed:!0}))}};x("adr-wc",Et);
3160
- //# sourceMappingURL=ux-planning.full.js.map