loop-canvas 0.1.5 → 0.1.6

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.
package/public/app.js CHANGED
@@ -1,113 +1,122 @@
1
- const m=e=>document.querySelector(e),q=m("#viewport"),ct=m("#world"),fr=m("#frames"),dt=m("#ink"),ns=m("#cursors"),Y=m("#hover-box"),z=m("#composer"),U=m("#composer-input"),D=m("#thread"),L=e=>String(e??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),Qn=()=>Math.random().toString(36).slice(2,10),Jn=()=>(Qn()+Qn()).slice(0,8),$e={get(e,t){try{const n=localStorage.getItem(e);return n==null?t:JSON.parse(n)}catch{return t}},set(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch{}}},ur={select:'<path d="M9.80282 4.62973L15.8364 6.99069C19.3164 8.35243 21.0564 9.03329 20.9987 10.1133C20.941 11.1934 19.1251 11.6886 15.4933 12.6791C14.412 12.974 13.8713 13.1215 13.4964 13.4963C13.1215 13.8712 12.9741 14.4119 12.6791 15.4933C11.6887 19.125 11.1934 20.9409 10.1134 20.9986C9.03335 21.0563 8.35249 19.3163 6.99075 15.8363L4.62979 9.80276C3.20411 6.15934 2.49127 4.33764 3.41448 3.41442C4.3377 2.49121 6.15941 3.20405 9.80282 4.62973Z"/>',pen:'<path d="M3.49977 18.9853V20.5H5.01449C6.24074 20.5 6.85387 20.5 7.40518 20.2716C7.9565 20.0433 8.39004 19.6097 9.25713 18.7426L19.1211 8.87868C20.0037 7.99612 20.4449 7.55483 20.4937 7.01325C20.5018 6.92372 20.5018 6.83364 20.4937 6.74411C20.4449 6.20253 20.0037 5.76124 19.1211 4.87868C18.2385 3.99612 17.7972 3.55483 17.2557 3.50605C17.1661 3.49798 17.0761 3.49798 16.9865 3.50605C16.4449 3.55483 16.0037 3.99612 15.1211 4.87868L5.25713 14.7426C4.39004 15.6097 3.9565 16.0433 3.72813 16.5946C3.49977 17.1459 3.49977 17.759 3.49977 18.9853Z"/><path d="M13.5 6.5L17.5 10.5"/>',erase:'<path d="M8.73792 7.78021L4.84693 11.7574C3.67722 12.953 3.09236 13.5508 3.01263 14.2802C2.99579 14.4343 2.99579 14.5899 3.01263 14.744C3.09236 15.4733 3.67722 16.0711 4.84693 17.2668L4.99601 17.4191C5.62049 18.0575 5.93274 18.3766 6.30638 18.5911C6.5236 18.7157 6.75482 18.8134 6.99505 18.882C7.40827 19 7.85149 19 8.73792 19C9.62436 19 10.0676 19 10.4808 18.882C10.721 18.8134 10.9522 18.7157 11.1695 18.5911C11.5431 18.3766 11.8554 18.0575 12.4798 17.4191L15.3239 14.5121M8.73792 7.78021L12.3199 4.12313C13.7065 2.70754 14.3997 1.99974 15.2627 2C16.1256 2.00026 16.8185 2.70846 18.2042 4.12487L18.9473 4.8845C20.3159 6.28342 21.0002 6.98288 21 7.85008C20.9997 8.71728 20.315 9.41633 18.9456 10.8144L15.3239 14.5121M8.73792 7.78021L15.3239 14.5121"/><path d="M10 22L21 22"/>',comment:'<path d="M12 18.0012H15C18.2998 18.0012 19.9497 18.0012 20.9749 16.9761C22 15.951 22 14.3011 22 11.0012V9.50122C22 6.20139 22 4.55147 20.9749 3.52635C19.9497 2.50122 18.2998 2.50122 15 2.50122H9C5.70017 2.50122 4.05025 2.50122 3.02513 3.52635C2 4.55147 2 6.20139 2 9.50122V14.0012C2 14.4656 2 14.6978 2.02201 14.8931C2.20484 16.5158 3.48545 17.7964 5.10812 17.9792C5.30344 18.0012 5.53563 18.0012 6 18.0012V20.0819C6 20.9044 6 21.3157 6.26407 21.457C6.52814 21.5983 6.87033 21.3702 7.5547 20.914L12 18.0012Z"/>',frame:'<path d="M2 6H22M2 18H22"/><path d="M6 22L6 2M18 22V2"/>',comments:'<path d="M8 13.0012H16M8 8.00122H12"/><path d="M12 18.0012H15C18.2998 18.0012 19.9497 18.0012 20.9749 16.9761C22 15.951 22 14.3011 22 11.0012V9.50122C22 6.20139 22 4.55147 20.9749 3.52635C19.9497 2.50122 18.2998 2.50122 15 2.50122H9C5.70017 2.50122 4.05025 2.50122 3.02513 3.52635C2 4.55147 2 6.20139 2 9.50122V14.0012C2 14.4656 2 14.6978 2.02201 14.8931C2.20484 16.5158 3.48545 17.7964 5.10812 17.9792C5.30344 18.0012 5.53563 18.0012 6 18.0012V20.0819C6 20.9044 6 21.3157 6.26407 21.457C6.52814 21.5983 6.87033 21.3702 7.5547 20.914L12 18.0012Z"/>',undo:'<path d="M3 8H15C18.3137 8 21 10.6863 21 14C21 17.3137 18.3137 20 15 20H11"/><path d="M7 4L5.8462 4.87652C3.94873 6.31801 3 7.03875 3 8C3 8.96125 3.94873 9.68199 5.8462 11.1235L7 12"/>',redo:'<path d="M21 8H9C5.68629 8 3 10.6863 3 14C3 17.3137 5.68629 20 9 20H13"/><path d="M17 4L18.1538 4.87652C20.0513 6.31801 21 7.03875 21 8C21 8.96125 20.0513 9.68199 18.1538 11.1235L17 12"/>',before:'<path d="M3.49902 14.9656C4.72475 18.4791 8.06749 21 11.999 21C16.9696 21 20.999 16.9706 20.999 12C20.999 7.02944 16.9696 3 11.999 3C8.29827 3 4.8984 5.6756 3.68943 8.5"/><path d="M11.999 7V12L14.999 14"/><path d="M7.49751 8.74363C7.49751 8.74363 3.81388 9.3026 3.25487 8.7436C2.69585 8.1846 3.25488 4.50098 3.25488 4.50098"/>',copy:'<path d="M7.5 14.5C7.5 11.2002 7.5 9.55025 8.52513 8.52513C9.55025 7.5 11.2002 7.5 14.5 7.5C17.7998 7.5 19.4497 7.5 20.4749 8.52513C21.5 9.55025 21.5 11.2002 21.5 14.5C21.5 17.7998 21.5 19.4497 20.4749 20.4749C19.4497 21.5 17.7998 21.5 14.5 21.5C11.2002 21.5 9.55025 21.5 8.52513 20.4749C7.5 19.4497 7.5 17.7998 7.5 14.5Z"/><path d="M7.5 16.5C6.10355 16.5 5.40533 16.5 4.84402 16.3036C3.83866 15.9518 3.0482 15.1613 2.69641 14.156C2.5 13.5947 2.5 12.8964 2.5 11.5V9.5C2.5 6.20017 2.5 4.55025 3.52513 3.52513C4.55025 2.5 6.20017 2.5 9.5 2.5H11.5C12.8964 2.5 13.5947 2.5 14.156 2.69641C15.1613 3.0482 15.9518 3.83866 16.3036 4.84402C16.5 5.40533 16.5 6.10355 16.5 7.5"/>',check:'<path d="M5 14L8.5 17.5L19 6.5"/>',stop:'<path d="M4 12C4 8.72077 4 7.08116 4.81382 5.91891C5.1149 5.48891 5.48891 5.1149 5.91891 4.81382C7.08116 4 8.72077 4 12 4C15.2792 4 16.9188 4 18.0811 4.81382C18.5111 5.1149 18.8851 5.48891 19.1862 5.91891C20 7.08116 20 8.72077 20 12C20 15.2792 20 16.9188 19.1862 18.0811C18.8851 18.5111 18.5111 18.8851 18.0811 19.1862C16.9188 20 15.2792 20 12 20C8.72077 20 7.08116 20 5.91891 19.1862C5.48891 18.8851 5.1149 18.5111 4.81382 18.0811C4 16.9188 4 15.2792 4 12Z"/>',up:'<path d="M12 5.5V19"/><path d="M18 11C18 11 13.5811 5.00001 12 5C10.4188 4.99999 6 11 6 11"/>',retry:'<path d="M20.4879 15C19.2524 18.4956 15.9187 21 12 21C7.02943 21 3 16.9706 3 12C3 7.02943 7.02943 3 12 3C15.7292 3 18.9286 5.26806 20.2941 8.5"/><path d="M15 9H18C19.4142 9 20.1213 9 20.5607 8.56066C21 8.12132 21 7.41421 21 6V3"/>',steer:'<path d="M13 6H8.5C6.01472 6 4 8.01472 4 10.5C4 12.9853 6.01472 15 8.5 15H20"/><path d="M17 12C17 12 20 14.2095 20 15C20 15.7906 17 18 17 18"/>',play:'<path d="M18.8906 12.846C18.5371 14.189 16.8667 15.138 13.5257 17.0361C10.296 18.8709 8.6812 19.7884 7.37983 19.4196C6.8418 19.2671 6.35159 18.9776 5.95624 18.5787C5 17.6139 5 15.7426 5 12C5 8.2574 5 6.3861 5.95624 5.42132C6.35159 5.02245 6.8418 4.73288 7.37983 4.58042C8.6812 4.21165 10.296 5.12907 13.5257 6.96393C16.8667 8.86197 18.5371 9.811 18.8906 11.154C19.0365 11.7084 19.0365 12.2916 18.8906 12.846Z"/>',x:'<path d="M18.9991 19L5 5.00098"/><path d="M19 5L5.00092 18.999"/>',plus:'<path d="M12.001 4.00101V20.001"/><path d="M20.001 12.001L4.00098 12.001"/>',mic:'<path d="M7 6.5C7 4.01472 9.01472 2 11.5 2C13.9853 2 16 4.01472 16 6.5V11.5C16 13.9853 13.9853 16 11.5 16C9.01472 16 7 13.9853 7 11.5V6.5Z"/><path d="M11.5 19H11.0828C7.57267 19 4.57706 16.4623 4 13M11.5 19H11.9172C15.4273 19 18.4229 16.4623 19 13M11.5 19V22"/>',file:'<path d="M8 17H16"/><path d="M8 13H12"/><path d="M13 2.5V3C13 5.82843 13 7.24264 13.8787 8.12132C14.7574 9 16.1716 9 19 9H19.5M20 10.6569V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V9.45584C4 6.21082 4 4.58831 4.88607 3.48933C5.06508 3.26731 5.26731 3.06508 5.48933 2.88607C6.58831 2 8.21082 2 11.4558 2C12.1614 2 12.5141 2 12.8372 2.11401C12.9044 2.13772 12.9702 2.165 13.0345 2.19575C13.3436 2.34355 13.593 2.593 14.0919 3.09188L18.8284 7.82843C19.4065 8.40649 19.6955 8.69552 19.8478 9.06306C20 9.4306 20 9.83935 20 10.6569Z"/>',clip:'<path d="M9.5 8V14.5C9.5 15.8807 10.6193 17 12 17C13.3807 17 14.5 15.8807 14.5 14.5V6.5C14.5 4.01472 12.4853 2 10 2C7.51472 2 5.5 4.01472 5.5 6.5V15.5C5.5 19.0899 8.41015 22 12 22C15.5899 22 18.5 19.0899 18.5 15.5V6"/>',read:'<path d="M8 17H16"/><path d="M8 13H12"/><path d="M13 2.5V3C13 5.82843 13 7.24264 13.8787 8.12132C14.7574 9 16.1716 9 19 9H19.5M20 10.6569V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V9.45584C4 6.21082 4 4.58831 4.88607 3.48933C5.06508 3.26731 5.26731 3.06508 5.48933 2.88607C6.58831 2 8.21082 2 11.4558 2C12.1614 2 12.5141 2 12.8372 2.11401C12.9044 2.13772 12.9702 2.165 13.0345 2.19575C13.3436 2.34355 13.593 2.593 14.0919 3.09188L18.8284 7.82843C19.4065 8.40649 19.6955 8.69552 19.8478 9.06306C20 9.4306 20 9.83935 20 10.6569Z"/>',edit:'<path d="M16.4249 4.60509L17.4149 3.6151C18.2351 2.79497 19.5648 2.79497 20.3849 3.6151C21.205 4.43524 21.205 5.76493 20.3849 6.58507L19.3949 7.57506M16.4249 4.60509L9.76558 11.2644C9.25807 11.772 8.89804 12.4078 8.72397 13.1041L8 16L10.8959 15.276C11.5922 15.102 12.228 14.7419 12.7356 14.2344L19.3949 7.57506M16.4249 4.60509L19.3949 7.57506"/><path d="M18.9999 13.5C18.9999 16.7875 18.9999 18.4312 18.092 19.5376C17.9258 19.7401 17.7401 19.9258 17.5375 20.092C16.4312 21 14.7874 21 11.4999 21H11C7.22876 21 5.34316 21 4.17159 19.8284C3.00003 18.6569 3 16.7712 3 13V12.5C3 9.21252 3 7.56879 3.90794 6.46244C4.07417 6.2599 4.2599 6.07417 4.46244 5.90794C5.56879 5 7.21252 5 10.5 5"/>',find:'<path d="M17 17L21 21"/><path d="M19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19C15.4183 19 19 15.4183 19 11Z"/>',look:'<path d="M21.544 11.045C21.848 11.4713 22 11.6845 22 12C22 12.3155 21.848 12.5287 21.544 12.955C20.1779 14.8706 16.6892 19 12 19C7.31078 19 3.8221 14.8706 2.45604 12.955C2.15201 12.5287 2 12.3155 2 12C2 11.6845 2.15201 11.4713 2.45604 11.045C3.8221 9.12944 7.31078 5 12 5C16.6892 5 20.1779 9.12944 21.544 11.045Z"/><path d="M15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12Z"/>',run:'<path d="M14 4H10C6.22876 4 4.34315 4 3.17157 5.17157C2 6.34315 2 8.22876 2 12C2 15.7712 2 17.6569 3.17157 18.8284C4.34315 20 6.22876 20 10 20H14C17.7712 20 19.6569 20 20.8284 18.8284C22 17.6569 22 15.7712 22 12C22 8.22876 22 6.34315 20.8284 5.17157C19.6569 4 17.7712 4 14 4Z"/><path d="M7 9L8.83981 10.5858C9.61327 11.2525 10 11.5858 10 12C10 12.4142 9.61327 12.7475 8.83981 13.4142L7 15"/><path d="M13 16H17"/>',think:'<path d="M8 16.4998C6.7725 15.4011 6 13.7768 6 11.9998C6 8.68605 8.68629 5.99976 12 5.99976C15.3137 5.99976 18 8.68605 18 11.9998C18 13.7768 17.2275 15.4011 16 16.4998"/><path d="M12 11.9998V16.4998"/><path d="M9.5 18.9998H14.5"/><path d="M10.5 21.4998H13.5"/><path d="M3.5 11.9998H2.5M5.98438 5.97632L5.23438 5.23022M18.0195 5.97632L18.7695 5.23022M21.5 11.9998H20.5M12 2.49976V3.49976"/>',add:'<path d="M12 3.00005C16.2426 3.00005 18.364 3.00005 19.682 4.31807C21 5.63609 21 7.75741 21 12.0001C21 16.2427 21 18.364 19.682 19.682C18.364 21.0001 16.2426 21.0001 12 21.0001C7.75736 21.0001 5.63604 21.0001 4.31802 19.682C3 18.364 3 16.2427 3 12.0001C3 7.75741 3 5.63609 4.31802 4.31807C5.63604 3.00005 7.75736 3.00005 12 3.00005Z"/><path d="M12.0001 8.00005V12.0001M12.0001 12.0001V16.0001M12.0001 12.0001H16.0001M12.0001 12.0001H8.00006"/>',expand:'<path d="M16.4999 3.26621C17.3443 3.25421 20.1408 2.67328 20.7337 3.26621C21.3266 3.85913 20.7457 6.65559 20.7337 7.5M20.5059 3.49097L13.5021 10.4961"/><path d="M3.26636 16.5001C3.25436 17.3445 2.67343 20.141 3.26636 20.7339C3.85928 21.3268 6.65574 20.7459 7.50015 20.7339M10.502 13.4976L3.49824 20.5027"/>',collapse:'<path d="M6.5023 10.7365C7.34671 10.7485 10.1432 11.3294 10.7361 10.7365C11.329 10.1436 10.7481 7.34708 10.7361 6.50267M13.2685 17.5027C13.2565 16.6583 12.6756 13.8618 13.2685 13.2689C13.8614 12.676 16.6579 13.2569 17.5023 13.2689M20.9991 21.001L13.6102 13.6188M10.3691 10.3763L2.99998 2.99902"/>',resolve:'<path d="M22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12Z"/><path d="M8 12.5L10.5 15L16 9"/>',reopen:'<path d="M11 6H15.5C17.9853 6 20 8.01472 20 10.5C20 12.9853 17.9853 15 15.5 15H4"/><path d="M6.99998 12C6.99998 12 4.00001 14.2095 4 15C3.99999 15.7906 7 18 7 18"/>',more:'<path d="M6.00449 12.5V12M18.0045 12.5V12M12.0045 12.5V12M7.00449 12.5C7.00449 11.9477 6.55677 11.5 6.00449 11.5C5.4522 11.5 5.00449 11.9477 5.00449 12.5C5.00449 13.0523 5.4522 13.5 6.00449 13.5C6.55677 13.5 7.00449 13.0523 7.00449 12.5ZM19.0045 12.5C19.0045 11.9477 18.5568 11.5 18.0045 11.5C17.4522 11.5 17.0045 11.9477 17.0045 12.5C17.0045 13.0523 17.4522 13.5 18.0045 13.5C18.5568 13.5 19.0045 13.0523 19.0045 12.5ZM13.0045 12.5C13.0045 11.9477 12.5568 11.5 12.0045 11.5C11.4522 11.5 11.0045 11.9477 11.0045 12.5C11.0045 13.0523 11.4522 13.5 12.0045 13.5C12.5568 13.5 13.0045 13.0523 13.0045 12.5Z"/>',reply:'<path d="M3.99219 10H11.9922C13.8521 10 14.7821 10 15.5451 10.2044C17.6157 10.7592 19.2329 12.3765 19.7877 14.4471C19.9922 15.2101 19.9922 16.1401 19.9922 18"/><path d="M7.99219 6L6.83839 6.87652C4.94092 8.31801 3.99219 9.03875 3.99219 10C3.99219 10.9612 4.94092 11.682 6.83839 13.1235L7.99219 14"/>',trash:'<path d="M18.8516 16.3743L19.5 6H4.5L5.14839 16.3743C5.315 19.0401 5.39831 20.373 6.26426 21.1865C7.13021 22 8.46571 22 11.1367 22H12.8633C15.5343 22 16.8698 22 17.7357 21.1865C18.6017 20.373 18.685 19.0401 18.8516 16.3743Z"/><path d="M16 6H21M16 6L15.3778 4.34082C15.0007 3.33524 14.8122 2.83245 14.4402 2.50292C14.3213 2.39765 14.1904 2.3069 14.0501 2.2326C13.6109 2 13.074 2 12 2C10.926 2 10.3891 2 9.9499 2.2326C9.8096 2.3069 9.67865 2.39765 9.55982 2.50292C9.18783 2.83245 8.99928 3.33524 8.62219 4.34082L8 6M16 6H8M3 6H8"/><path d="M9.5 11V17M14.5 11V17"/>',phone:'<path d="M13.5 2H10.5C8.14298 2 6.96447 2 6.23223 2.73223C5.5 3.46447 5.5 4.64298 5.5 7V17C5.5 19.357 5.5 20.5355 6.23223 21.2678C6.96447 22 8.14298 22 10.5 22H13.5C15.857 22 17.0355 22 17.7678 21.2678C18.5 20.5355 18.5 19.357 18.5 17V7C18.5 4.64298 18.5 3.46447 17.7678 2.73223C17.0355 2 15.857 2 13.5 2Z"/><path d="M12.125 19H12M12.25 19C12.25 19.1381 12.1381 19.25 12 19.25C11.8619 19.25 11.75 19.1381 11.75 19C11.75 18.8619 11.8619 18.75 12 18.75C12.1381 18.75 12.25 18.8619 12.25 19Z"/>',tablet:'<path d="M14.5 2H9.5C6.67157 2 5.25736 2 4.37868 2.87868C3.5 3.75736 3.5 5.17157 3.5 8V16C3.5 18.8284 3.5 20.2426 4.37868 21.1213C5.25736 22 6.67157 22 9.5 22H14.5C17.3284 22 18.7426 22 19.6213 21.1213C20.5 20.2426 20.5 18.8284 20.5 16V8C20.5 5.17157 20.5 3.75736 19.6213 2.87868C18.7426 2 17.3284 2 14.5 2Z"/><path d="M12.125 19H12M12.25 19C12.25 19.1381 12.1381 19.25 12 19.25C11.8619 19.25 11.75 19.1381 11.75 19C11.75 18.8619 11.8619 18.75 12 18.75C12.1381 18.75 12.25 18.8619 12.25 19Z"/>',desktop:'<path d="M14 21H16M14 21C13.1716 21 12.5 20.3284 12.5 19.5V17L12 17M14 21H10M10 21H8M10 21C10.8284 21 11.5 20.3284 11.5 19.5V17L12 17M12 17V21"/><path d="M16 3H8C5.17157 3 3.75736 3 2.87868 3.87868C2 4.75736 2 6.17157 2 9V11C2 13.8284 2 15.2426 2.87868 16.1213C3.75736 17 5.17157 17 8 17H16C18.8284 17 20.2426 17 21.1213 16.1213C22 15.2426 22 13.8284 22 11V9C22 6.17157 22 4.75736 21.1213 3.87868C20.2426 3 18.8284 3 16 3Z"/>',keyboard:'<path d="M14.5 7H9.5C6.21252 7 4.56878 7 3.46243 7.90796C3.25989 8.07418 3.07418 8.25989 2.90796 8.46243C2 9.56878 2 11.2125 2 14.5C2 17.7875 2 19.4312 2.90796 20.5376C3.07418 20.7401 3.25989 20.9258 3.46243 21.092C4.56878 22 6.21252 22 9.5 22H14.5C17.7875 22 19.4312 22 20.5376 21.092C20.7401 20.9258 20.9258 20.7401 21.092 20.5376C22 19.4312 22 17.7875 22 14.5C22 11.2125 22 9.56878 21.092 8.46243C20.9258 8.25989 20.7401 8.07418 20.5376 7.90796C19.4312 7 17.7875 7 14.5 7Z"/><path d="M12 7V5C12 4.44772 12.4477 4 13 4C13.5523 4 14 3.55228 14 3V2"/><path d="M7 12L8 12"/><path d="M11.5 12L12.5 12"/><path d="M16 12L17 12"/><path d="M7 17L17 17"/>',freeze:'<path d="M14.244 3.00632C13.801 3.40963 12.6212 5.00086 11.991 5C11.3608 4.99909 10.1858 3.40451 9.744 3"/><path d="M14.244 20.9937C13.801 20.5904 12.6212 18.9991 11.991 19C11.3608 19.0009 10.1858 20.5955 9.744 21"/><path d="M20.9077 9.45191C20.337 9.26993 18.3691 9.04383 18.0547 8.4976C17.7404 7.9514 18.5338 6.13651 18.6632 5.55164"/><path d="M5.33024 18.4456C5.45802 17.8603 6.24618 16.043 5.93032 15.4976C5.61445 14.9523 3.64599 14.732 3.07477 14.5516"/><path d="M3.07602 9.45203C3.64679 9.27005 5.61472 9.04395 5.9291 8.49772C6.2434 7.95152 5.44996 6.13663 5.32055 5.55176"/><path d="M18.6529 18.4457C18.5252 17.8604 17.737 16.0431 18.0529 15.4977C18.3687 14.9524 20.3372 14.7321 20.9084 14.5518"/><path d="M15.4581 9.97911L17.994 8.49982M11.9937 8.02071L11.9937 4.99982M17.9937 15.4998L15.458 14.0206M5.99424 15.4998L8.56579 13.9997M11.9937 18.9998L11.9937 15.9789M8.56579 10.0001L5.994 8.49982"/><path d="M15.4957 11.7313C15.4955 10.8861 15.4955 10.4635 15.2945 10.1155C15.0935 9.76744 14.7275 9.55617 13.9955 9.13361L13.5316 8.86583C12.7996 8.44326 12.4336 8.23198 12.0317 8.23199C11.6298 8.23201 11.2638 8.44332 10.5318 8.86593L10.0679 9.13379C9.33581 9.55644 8.96978 9.76777 8.76882 10.1158C8.56786 10.4639 8.56786 10.8866 8.56786 11.7319L8.56786 12.2677C8.56786 13.113 8.56786 13.5356 8.76881 13.8837C8.96976 14.2318 9.33578 14.4431 10.0678 14.8658L10.5319 15.1337C11.264 15.5564 11.63 15.7678 12.032 15.7678C12.4339 15.7678 12.7999 15.5564 13.532 15.1338L13.9958 14.866C14.728 14.4433 15.0941 14.2319 15.295 13.8838C15.496 13.5356 15.4959 13.1129 15.4958 12.2674L15.4957 11.7313Z"/>',stage:'<path d="M15.5 21C16.8956 21 17.5933 21 18.1611 20.8278C19.4395 20.44 20.44 19.4395 20.8278 18.1611C21 17.5933 21 16.8956 21 15.5M21 8.5C21 7.10444 21 6.40666 20.8278 5.83886C20.44 4.56046 19.4395 3.56004 18.1611 3.17224C17.5933 3 16.8956 3 15.5 3M8.5 21C7.10444 21 6.40666 21 5.83886 20.8278C4.56046 20.44 3.56004 19.4395 3.17224 18.1611C3 17.5933 3 16.8956 3 15.5M3 8.5C3 7.10444 3 6.40666 3.17224 5.83886C3.56004 4.56046 4.56046 3.56004 5.83886 3.17224C6.40666 3 7.10444 3 8.5 3"/>',layers:'<path d="M8.64298 3.14559L6.93816 3.93362C4.31272 5.14719 3 5.75397 3 6.75C3 7.74603 4.31272 8.35281 6.93817 9.56638L8.64298 10.3544C10.2952 11.1181 11.1214 11.5 12 11.5C12.8786 11.5 13.7048 11.1181 15.357 10.3544L17.0618 9.56638C19.6873 8.35281 21 7.74603 21 6.75C21 5.75397 19.6873 5.14719 17.0618 3.93362L15.357 3.14559C13.7048 2.38186 12.8786 2 12 2C11.1214 2 10.2952 2.38186 8.64298 3.14559Z"/><path d="M20.788 11.0972C20.9293 11.2959 21 11.5031 21 11.7309C21 12.7127 19.6873 13.3109 17.0618 14.5072L15.357 15.284C13.7048 16.0368 12.8786 16.4133 12 16.4133C11.1214 16.4133 10.2952 16.0368 8.64298 15.284L6.93817 14.5072C4.31272 13.3109 3 12.7127 3 11.7309C3 11.5031 3.07067 11.2959 3.212 11.0972"/><path d="M20.3767 16.2661C20.7922 16.5971 21 16.927 21 17.3176C21 18.2995 19.6873 18.8976 17.0618 20.0939L15.357 20.8707C13.7048 21.6236 12.8786 22 12 22C11.1214 22 10.2952 21.6236 8.64298 20.8707L6.93817 20.0939C4.31272 18.8976 3 18.2995 3 17.3176C3 16.927 3.20778 16.5971 3.62334 16.2661"/>',sun:'<path d="M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z"/><path d="M12 2V3.5M12 20.5V22M19.0708 19.0713L18.0101 18.0106M5.98926 5.98926L4.9286 4.9286M22 12H20.5M3.5 12H2M19.0713 4.92871L18.0106 5.98937M5.98975 18.0107L4.92909 19.0714"/>',moon:'<path d="M21.5 14.0784C20.3003 14.7189 18.9301 15.0821 17.4751 15.0821C12.7491 15.0821 8.91792 11.2509 8.91792 6.52485C8.91792 5.06986 9.28105 3.69968 9.92163 2.5C5.66765 3.49698 2.5 7.31513 2.5 11.8731C2.5 17.1899 6.8101 21.5 12.1269 21.5C16.6849 21.5 20.503 18.3324 21.5 14.0784Z"/>',left:'<path d="M15 6C15 6 9.00001 10.4189 9 12C8.99999 13.5812 15 18 15 18"/>',right:'<path d="M9.00005 6C9.00005 6 15 10.4189 15 12C15 13.5812 9 18 9 18"/>',down:'<path d="M18 9.00005C18 9.00005 13.5811 15 12 15C10.4188 15 6 9 6 9"/>',point:'<path d="M9 14.5V4.5a1.5 1.5 0 0 1 3 0v6"/><path d="M12 10a1.5 1.5 0 0 1 3 0v1.5"/><path d="M15 11a1.5 1.5 0 0 1 3 0v1"/><path d="M18 12a1.5 1.5 0 0 1 3 0v3.5a6.5 6.5 0 0 1-6.5 6.5h-1.6a6 6 0 0 1-4.7-2.3l-3.4-4.4a1.7 1.7 0 0 1 2.6-2.2L9 14.5"/>',hand:'<path d="M18 11V6a2 2 0 0 0-4 0"/><path d="M14 10V4a2 2 0 0 0-4 0v2"/><path d="M10 10.5V6a2 2 0 0 0-4 0v8"/><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-6-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.83L7 15"/>'},T=(e,t="")=>`<svg class="hi${t?" "+t:""}" viewBox="0 0 24 24" aria-hidden="true">${ur[e]||""}</svg>`;document.querySelectorAll("i[data-i]").forEach(e=>{e.outerHTML=T(e.dataset.i)});function is(e){e?document.documentElement.dataset.theme=e:delete document.documentElement.dataset.theme;const t=e?e==="dark":matchMedia("(prefers-color-scheme: dark)").matches,n=document.getElementById("theme-btn");n&&(n.innerHTML=T(t?"sun":"moon"),n.title=t?"Light mode (\u21E7D)":"Dark mode (\u21E7D)")}function sa(){const t=(document.documentElement.dataset.theme?document.documentElement.dataset.theme==="dark":matchMedia("(prefers-color-scheme: dark)").matches)?"light":"dark";try{localStorage.setItem("loop.theme",t)}catch{}is(t)}is((()=>{try{return localStorage.getItem("loop.theme")}catch{return null}})()),matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>is(document.documentElement.dataset.theme)),document.getElementById("theme-btn").addEventListener("click",sa);const ss=["#5B6AD0","#D2575C","#3B9A6C","#B98A2C","#8A63C4","#2E93A6","#CC6E3C"],pr=["#2F5BFF","#E5484D","#1F9D55","#D9A100","#8E4EC6","#0E9AA7","#E8590C"],mr=e=>{const t=pr.indexOf(String(e||"").toUpperCase());return t>=0?ss[t]:/^#[0-9a-f]{6}$/i.test(e||"")?e:"#88888F"},aa=(e,t,n="",i="")=>`<span class="av${n?" "+n:""}" style="--c:${mr(t)}">${i?`<img src="${L(i)}" alt="" referrerpolicy="no-referrer">`:L($a(e).slice(0,1))}</span>`,as="#E5484D";let u=null,y={x:120,y:140,z:.5},os=!1,j="select",Bt=!1,I=null,W=null,F=null,Ze=null;const K=new Set;let ei=null,Ne=null;const oa=new Set,H=new Map,_e=new Map,en=new Map,X=window.LOOP_ADAPTER||null,V=$e.get("loop.me",null)||{id:Qn(),name:"",color:ss[Math.floor(Math.random()*ss.length)]};X?.me&&Object.assign(V,X.me),V.id=V.id||Qn();async function w(e,t,n){if(X)return X.api(e,t,n);const i=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:n?JSON.stringify(n):void 0}),s=await i.json().catch(()=>({}));if(!i.ok)throw new Error(s.error||`HTTP ${i.status}`);return s}function b(e,t=2200){const n=m("#toast");n.textContent=e,n.hidden=!1,clearTimeout(b.t),b.t=setTimeout(()=>n.hidden=!0,t)}const k=()=>u?.role==="owner";function hr(){if(X)return X.connect(ti);const e=new EventSource("/__loop/api/events");e.onmessage=t=>ti(JSON.parse(t.data)),e.onerror=()=>{m("#agent-pill").classList.add("offline")},e.onopen=()=>{m("#agent-pill").classList.remove("offline")}}function ra(){if(!Et()&&!ae)return location.reload();setTimeout(ra,1500)}function ti(e){if(e.type==="state"){if(u?.version&&e.state.version&&e.state.version!==u.version){location.reload();return}u?.codeId&&e.state.codeId&&e.state.codeId!==u.codeId&&ra();const t=!u;u=e.state,t&&xr(),ii()}else if(e.type==="patch"){if(!u)return;Object.assign(u,e.set||{}),!ae&&(e.lists?.frames?.up?.length>1||e.lists?.sections?.up?.length)&&(ct.classList.add("gliding"),clearTimeout(ti.glide),ti.glide=setTimeout(()=>ct.classList.remove("gliding"),520));const t=k()&&(e.lists?.sections?.up||[]).find(n=>n.optionsFor&&!(u.sections||[]).some(i=>i.id===n.id));for(const[n,i]of Object.entries(e.lists||{})){const s=new Map((u[n]||[]).map(a=>[a.id,a]));for(const a of i.up||[])s.set(a.id,a);u[n]=i.order?i.order.map(a=>s.get(a)).filter(Boolean):(u[n]||[]).map(a=>s.get(a.id))}ii(),t&&Qo(t.id)}else if(e.type==="activity"){if(!u)return;const t=u.live[e.frameId];t&&(t.step=e.step,t.partial=e.partial||"");const n=e.partial==null&&u.comments.find(s=>s.id===e.commentId);if(n&&e.step&&!/^(Writing…|Reading your comment…|Your chat picked this up|Working…)$/.test(e.step)){const s=n.steps||=[],a=s[s.length-1];!/^(Reading the code|Editing|Writing|Setting up an option)$/.test(e.step)&&(!a||a.s!==e.step)&&s.push({t:Date.now(),s:e.step}),Ka(e.commentId)}const i=H.get(e.frameId);i&&t&&Le(i.step,e.step),document.querySelectorAll(`[data-step-for="${e.commentId}"]`).forEach(s=>Le(s,e.step)),Ia(e.commentId,e.partial||""),Wr(e.frameId)}else if(e.type==="frame-changed"){{const t=H.get(e.frameId);if(t?.quietN>0&&Date.now()<t.quietT&&!e.done&&!e.live){t.quietN--;return}t&&(t.quietN=0)}Ar(e.frameId),e.done&&qr(e.frameId,e.status==="done"?u.frames.find(t=>t.id===e.frameId)?.kind==="frozen"?"Changed in the app":"Updated":e.status==="error"?"Failed":"",e.status!=="done"),e.done&&e.status==="done"&&Sl(e.frameId),e.done&&(e.status==="done"||e.status==="error")&&Pr(e.frameId,e.commentId,e.status)}else if(e.type==="presence"){if(e.id===V.id)return;e.leave?en.delete(e.id):en.set(e.id,{...e,t:Date.now()}),La(),ri()}}function Le(e,t){e&&e.textContent!==t&&(e.textContent=t)}const ft={at:0,ids:new Set};function gr(){const e=$e.get(`loop.seen.${u.name}`,null);e?(ft.at=e.at,ft.ids=new Set(e.ids)):(ft.at=Date.now(),la())}function la(){$e.set(`loop.seen.${u.name}`,{at:ft.at,ids:[...ft.ids].slice(-400)})}function yr(e){const t=Wt(e).filter(i=>i.kind!=="note"),n=t[t.length-1];return!!n&&n.status==="done"&&(n.finishedAt||0)>ft.at&&!ft.ids.has(n.id)}function ca(e){let t=!1;for(const n of Wt(e))n.finishedAt&&!ft.ids.has(n.id)&&(ft.ids.add(n.id),t=!0);return t&&la(),t}const vr=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5],rs=[64,148,255];let ni=0,da=0;const fa=matchMedia("(prefers-reduced-motion: reduce)");function br(){ni||(ni=requestAnimationFrame(ua))}function ua(e){ni=0;const t=[...document.querySelectorAll(".area.working")];if(!t.length||(fa.matches||(ni=requestAnimationFrame(ua)),e-da<33))return;da=e;const n=fa.matches?.35:e%5200/5200,i=Math.min(1,n/.8),a=-.2+i*i*(3-2*i)*1.45,o=1,r=.119;for(const l of t){const c=l.getBoundingClientRect();if(c.right<0||c.bottom<0||c.left>innerWidth||c.top>innerHeight||c.width<12||c.height<12)continue;let f=3;for(;c.width/f*(c.height/f)>6e4;)f++;const d=Math.ceil(c.width/f),p=Math.ceil(c.height/f);let h=l.querySelector(":scope > canvas.dz");h||(h=document.createElement("canvas"),h.className="dz",l.appendChild(h)),(h.width!==d||h.height!==p)&&(h.width=d,h.height=p,h.style.setProperty("--cols",d),h.style.setProperty("--rows",p));const g=h.getContext("2d"),v=g.createImageData(d,p),S=v.data,A=Math.hypot(d,p),x=Math.min(d,p),M=Math.max(2.4,x*.05+Math.max(0,x-40)*.03)*(l.classList.contains("whole")?1.5:1),C=M*4.5;for(let B=0;B<p;B++)for(let P=0;P<d;P++){const ee=Math.min(P,B,d-1-P,p-1-B);if(ee>C)continue;const R=Math.hypot(P,B)/A-a,oe=o*Math.exp(-R*R/r)*Math.exp(-ee/M);if(oe>(vr[(B&3)*4+(P&3)]+.5)/16){const Jt=(B*d+P)*4;S[Jt]=rs[0],S[Jt+1]=rs[1],S[Jt+2]=rs[2],S[Jt+3]=255*(.3+.7*oe)|0}}g.putImageData(v,0,0)}}const wr='<svg viewBox="0 0 24 24" aria-hidden="true"><path pathLength="14" d="M5 14L8.5 17.5L19 6.5"/></svg>';function xr(){gr();const e=$e.get(`loop.view.${u.name}`,null);e?(y=e,se()):Ge(!1),os=!0,k()?V.name=u.hostName||V.name||"You":V.name||fo(),$e.set("loop.me",V),document.body.classList.toggle("guest",!k()),m("#new-frame-btn").hidden=!k(),m("#section-btn").hidden=!k(),document.querySelector("#toolbar .tb-sep").hidden=!k()}function se(){y.z>=.02||(y.z=.04),ha=performance.now(),ct.style.transform=`translate(${y.x}px, ${y.y}px) scale(${y.z})`,ct.style.setProperty("--z",y.z),se.lastZ!==y.z&&(se.lastZ=y.z,ct.style.willChange!=="transform"&&(ct.style.willChange="transform"),clearTimeout(se.crisp),se.crisp=setTimeout(()=>{ct.style.willChange="auto"},160));const e=Math.min(1.5,Math.max(1,Math.pow(y.z,.42)));document.documentElement.style.setProperty("--lz",e.toFixed(3)),document.body.classList.toggle("zoom-tiny",y.z<.12);const t=`${Math.round(y.z*100)}%`,n=m("#zoom-level");if(n.textContent!==t){n.textContent=t;const i=m("#zoom");i.classList.add("awake"),clearTimeout(se.zt),se.zt=setTimeout(()=>i.classList.remove("awake"),1200)}Ln(),tn(),Ce(),Vn(),he&&Pe(),Y.hidden=!0,os&&u&&(clearTimeout(se.t),se.t=setTimeout(()=>$e.set(`loop.view.${u.name}`,y),300)),u&&se.z!==y.z&&(se.z=y.z,se.lq||(se.lq=requestAnimationFrame(()=>{se.lq=0,er()})),clearTimeout(se.pt),se.pt=setTimeout(()=>{for(const i of u.frames)it(i.id)},120))}function ut(e,t,n){const i=Math.min(4,Math.max(.04,y.z*n));y.x=e-(e-y.x)*(i/y.z),y.y=t-(t-y.y)*(i/y.z),y.z=i,cs()}let ls=!1;function cs(){ls||(ls=!0,requestAnimationFrame(()=>{ls=!1,se()}))}function pa(e,t,n){e.preventDefault();const i=Math.max(-30,Math.min(30,e.deltaMode===1?e.deltaY*16:e.deltaY));ut(t,n,Math.exp(-i*(e.ctrlKey&&!e.metaKey?.01:.004)))}const re=(e,t)=>({x:(e-y.x)/y.z,y:(t-y.y)/y.z});function Ge(e=!0,t){const n=(u?.frames||[]).filter(v=>!t||t.includes(v.id));if(!n.length)return y={x:innerWidth/2,y:innerHeight/2,z:.5},se();const i=Math.min(...n.map(v=>v.x)),s=Math.min(...n.map(v=>v.y)),a=Math.max(...n.map(v=>v.x+v.w)),o=Math.max(...n.map(v=>v.y+v.h)),r=80,l=110,c=110,f=Math.max(.04,Math.min(1,(innerWidth-r*2)/(a-i),(innerHeight-l-c)/(o-s))),d={z:f,x:(innerWidth-(a-i)*f)/2-i*f,y:l+(innerHeight-l-c-(o-s)*f)/2-s*f};if(!e)return y=d,se();const p={...y},h=performance.now(),g=v=>{const S=Math.min(1,(v-h)/280),A=1-Math.pow(1-S,3);y={x:p.x+(d.x-p.x)*A,y:p.y+(d.y-p.y)*A,z:p.z+(d.z-p.z)*A},se(),S<1&&requestAnimationFrame(g)};requestAnimationFrame(g)}function ii(){if(!u)return;m("#canvas-name").querySelector("input")||(m("#canvas-name").textContent=u.name),m("#canvas-name").classList.toggle("editable",k()&&!X),m("#history-btn").hidden=!k()||!!X,document.title=`${u.name} \u2014 Loop`,m("#empty").hidden=u.frames.length>0,m("#empty").classList.toggle("guest",!k()),k()&&!X&&u.hostName&&V.name!==u.hostName&&os&&(V.name=u.hostName,$e.set("loop.me",V)),Ir(),ri();const e=new Set(u.frames.map(t=>t.id));for(const[t,n]of H)e.has(t)||(n.el.contains(z)&&ne(),n.el.remove(),H.delete(t));for(const t of u.frames)Q(t);u.sections||=[],Nt(),I&&!e.has(I)&&(I=null),xt(),Sn(),W&&bi(),he&&Br(),F&&F.frameId!==ce&&!e.has(F.frameId)&&ne();for(const t of[...K])e.has(t)||K.delete(t);He(),Wn(),dl(),ol(),E&&Kn(),N&&or(),_&&(kn(),Zn()),Ln(),Vi()}function si(e){try{const t=e.iframe.contentWindow.location;return t.href==="about:blank"?null:t.pathname+t.search+t.hash}catch{return null}}let ds=0,fs=0,$n=null;const kr=/[?&]nosleep\b/.test(location.search);let ma=new Set;function $r(e){const t=Ot(e),n=Math.max(0,Math.min(t.l+t.w,innerWidth)-Math.max(t.l,0)),i=Math.max(0,Math.min(t.t+t.h,innerHeight)-Math.max(t.t,0));return{shown:n*i,of:t.w*t.h,r:t}}function Lr(){const e=new Set;if(!u)return e;if(E)return e.add(E.fid),e;const t=[];for(const n of u.frames){const{shown:i,of:s,r:a}=$r(n);if(!(i<400||i<s*.1)){if(kr||n.id===$n||n.id===I||n.id===de||$?.frameId===n.id||ve?.fid===n.id||K.has(n.id)){e.add(n.id);continue}(i>=innerWidth*innerHeight*.25||i>=s*.5&&(a.h>=innerHeight*.55||a.w>=innerWidth*.55))&&t.push([n.id,i])}}return t.sort((n,i)=>i[1]-n[1]).slice(0,2).forEach(([n])=>e.add(n)),e}const Cr=e=>ma.has(e);function Mr(e,t,n){const i=e.requestAnimationFrame.bind(e),s=new Map;let a=0;t.waking=Date.now(),e.requestAnimationFrame=r=>{if(!t.asleep)return i(r);const l=-++a;return s.set(l,r),l};const o=e.cancelAnimationFrame.bind(e);e.cancelAnimationFrame=r=>r<0?s.delete(r):o(r),t.sleepTo=r=>{if(t.asleep!==r){t.asleep=r;try{const l=e.document;let c=l.getElementById("__loop-sleep");r&&!c&&(c=l.createElement("style"),c.id="__loop-sleep",c.textContent="*, *::before, *::after { animation-play-state: paused !important; }",(l.head||l.documentElement).appendChild(c)),!r&&c&&c.remove(),l.querySelectorAll("video").forEach(f=>{try{r?(f._loopPlay=!f.paused,f.pause()):f._loopPlay&&f.play()}catch{}})}catch{}if(!r){const l=[...s.values()];s.clear(),l.forEach(c=>i(c))}}},t.asleep=!1,tn()}function tn(){fs||!u||(fs=setTimeout(()=>{fs=0,ma=Lr();for(const[e,t]of H){if(!t.sleepTo)continue;const n=Date.now()-(t.waking||0)<700;t.sleepTo(!n&&!Cr(e))}},120))}setInterval(()=>tn(),1500);function Ln(){ds||!u||(ds=requestAnimationFrame(()=>{ds=0;const e=innerWidth,t=innerHeight,n=u.frames.length>6,i=[];for(const s of u.frames){const a=H.get(s.id);if(!a?.iframe)continue;const o=Oe(s),r=y.z,l=y.x+o.x*r,c=y.y+o.y*r,f=o.w*r,d=o.h*r,p=g=>Math.max(0,l-e-g,-(l+f)-g,c-t-g,-(c+d)-g),h=!n||u.live[o.id]||I===o.id||de===o.id||E?.fid===o.id||K.has(o.id);if(a.el.classList.toggle("narrow",f<200),a.el.classList.toggle("far",wn(s)),u.live[o.id]){const g=Math.max(0,Math.min(l+f,e)-Math.max(l,0)),v=Math.max(0,Math.min(c+d,t)-Math.max(c,0)),S=g*v>=e*t*.2&&g*v>=f*d*.5;a.wedge||(a.wedge=document.createElement("i"),a.wedge.className="work-edge",a.el.appendChild(a.wedge)),a.el.classList.toggle("work-far",!S)}else a.el.classList.contains("work-far")&&a.el.classList.remove("work-far");a.parked?(h||p(e*.5)===0&&Math.max(f,d)>160)&&i.push({fe:a,keep:h,on:p(0)===0,d:Math.hypot(l+f/2-e/2,c+d/2-t/2)}):!h&&(p(e)>0||Math.max(f,d)<110)&&(a.resume=si(a),a.parked=!0,a.el.classList.add("parked"),a.iframe.src="about:blank"),a.parked&&ya(a)}if(i.length){const s=performance.now()-ha>140;i.sort((o,r)=>r.keep-o.keep||r.on-o.on||o.d-r.d);const a=s?i.slice(0,2):i.filter(o=>o.keep).slice(0,2);for(const{fe:o}of a)o.parked=!1,o.el.classList.remove("parked"),o.el.classList.add("waking"),clearTimeout(o.wakeT),o.wakeT=setTimeout(()=>ga(o),8e3),o.iframe.src=o.resume||o.iframe.dataset.src||"about:blank",o.resume=null;i.length>a.length&&setTimeout(Ln,s?90:160)}}))}let ha=0;function ga(e){clearTimeout(e.wakeT),requestAnimationFrame(()=>requestAnimationFrame(()=>e.el.classList.remove("waking")))}function ya(e){if(X)return;const t=e.hint.querySelector("img"),n=`/__loop/poster/${e.id}?v=${e.rev||0}`;if(t.dataset.src===n)return;t.dataset.src=n;const i=new Image;i.onload=()=>{t.dataset.src===n&&(t.src=n,t.hidden=!1)},i.src=n}function Oe(e){return{...e,..._e.get(e.id)||{}}}function Er(e){const t=document.createElement("div");t.className="frame",t.dataset.id=e.id,t.innerHTML=`
1
+ const m=e=>document.querySelector(e),I=m("#viewport"),xt=m("#world"),Vr=m("#frames"),kt=m("#ink"),xi=m("#cursors"),V=m("#hover-box"),H=m("#composer"),W=m("#composer-input"),z=m("#thread"),L=e=>String(e??"").replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t]),ha=()=>Math.random().toString(36).slice(2,10),ga=()=>(ha()+ha()).slice(0,8),Ae={get(e,t){try{const n=localStorage.getItem(e);return n==null?t:JSON.parse(n)}catch{return t}},set(e,t){try{localStorage.setItem(e,JSON.stringify(t))}catch{}}},Xr={select:'<path d="M9.80282 4.62973L15.8364 6.99069C19.3164 8.35243 21.0564 9.03329 20.9987 10.1133C20.941 11.1934 19.1251 11.6886 15.4933 12.6791C14.412 12.974 13.8713 13.1215 13.4964 13.4963C13.1215 13.8712 12.9741 14.4119 12.6791 15.4933C11.6887 19.125 11.1934 20.9409 10.1134 20.9986C9.03335 21.0563 8.35249 19.3163 6.99075 15.8363L4.62979 9.80276C3.20411 6.15934 2.49127 4.33764 3.41448 3.41442C4.3377 2.49121 6.15941 3.20405 9.80282 4.62973Z"/>',pen:'<path d="M3.49977 18.9853V20.5H5.01449C6.24074 20.5 6.85387 20.5 7.40518 20.2716C7.9565 20.0433 8.39004 19.6097 9.25713 18.7426L19.1211 8.87868C20.0037 7.99612 20.4449 7.55483 20.4937 7.01325C20.5018 6.92372 20.5018 6.83364 20.4937 6.74411C20.4449 6.20253 20.0037 5.76124 19.1211 4.87868C18.2385 3.99612 17.7972 3.55483 17.2557 3.50605C17.1661 3.49798 17.0761 3.49798 16.9865 3.50605C16.4449 3.55483 16.0037 3.99612 15.1211 4.87868L5.25713 14.7426C4.39004 15.6097 3.9565 16.0433 3.72813 16.5946C3.49977 17.1459 3.49977 17.759 3.49977 18.9853Z"/><path d="M13.5 6.5L17.5 10.5"/>',erase:'<path d="M8.73792 7.78021L4.84693 11.7574C3.67722 12.953 3.09236 13.5508 3.01263 14.2802C2.99579 14.4343 2.99579 14.5899 3.01263 14.744C3.09236 15.4733 3.67722 16.0711 4.84693 17.2668L4.99601 17.4191C5.62049 18.0575 5.93274 18.3766 6.30638 18.5911C6.5236 18.7157 6.75482 18.8134 6.99505 18.882C7.40827 19 7.85149 19 8.73792 19C9.62436 19 10.0676 19 10.4808 18.882C10.721 18.8134 10.9522 18.7157 11.1695 18.5911C11.5431 18.3766 11.8554 18.0575 12.4798 17.4191L15.3239 14.5121M8.73792 7.78021L12.3199 4.12313C13.7065 2.70754 14.3997 1.99974 15.2627 2C16.1256 2.00026 16.8185 2.70846 18.2042 4.12487L18.9473 4.8845C20.3159 6.28342 21.0002 6.98288 21 7.85008C20.9997 8.71728 20.315 9.41633 18.9456 10.8144L15.3239 14.5121M8.73792 7.78021L15.3239 14.5121"/><path d="M10 22L21 22"/>',comment:'<path d="M12 18.0012H15C18.2998 18.0012 19.9497 18.0012 20.9749 16.9761C22 15.951 22 14.3011 22 11.0012V9.50122C22 6.20139 22 4.55147 20.9749 3.52635C19.9497 2.50122 18.2998 2.50122 15 2.50122H9C5.70017 2.50122 4.05025 2.50122 3.02513 3.52635C2 4.55147 2 6.20139 2 9.50122V14.0012C2 14.4656 2 14.6978 2.02201 14.8931C2.20484 16.5158 3.48545 17.7964 5.10812 17.9792C5.30344 18.0012 5.53563 18.0012 6 18.0012V20.0819C6 20.9044 6 21.3157 6.26407 21.457C6.52814 21.5983 6.87033 21.3702 7.5547 20.914L12 18.0012Z"/>',frame:'<path d="M2 6H22M2 18H22"/><path d="M6 22L6 2M18 22V2"/>',comments:'<path d="M8 13.0012H16M8 8.00122H12"/><path d="M12 18.0012H15C18.2998 18.0012 19.9497 18.0012 20.9749 16.9761C22 15.951 22 14.3011 22 11.0012V9.50122C22 6.20139 22 4.55147 20.9749 3.52635C19.9497 2.50122 18.2998 2.50122 15 2.50122H9C5.70017 2.50122 4.05025 2.50122 3.02513 3.52635C2 4.55147 2 6.20139 2 9.50122V14.0012C2 14.4656 2 14.6978 2.02201 14.8931C2.20484 16.5158 3.48545 17.7964 5.10812 17.9792C5.30344 18.0012 5.53563 18.0012 6 18.0012V20.0819C6 20.9044 6 21.3157 6.26407 21.457C6.52814 21.5983 6.87033 21.3702 7.5547 20.914L12 18.0012Z"/>',undo:'<path d="M3 8H15C18.3137 8 21 10.6863 21 14C21 17.3137 18.3137 20 15 20H11"/><path d="M7 4L5.8462 4.87652C3.94873 6.31801 3 7.03875 3 8C3 8.96125 3.94873 9.68199 5.8462 11.1235L7 12"/>',redo:'<path d="M21 8H9C5.68629 8 3 10.6863 3 14C3 17.3137 5.68629 20 9 20H13"/><path d="M17 4L18.1538 4.87652C20.0513 6.31801 21 7.03875 21 8C21 8.96125 20.0513 9.68199 18.1538 11.1235L17 12"/>',before:'<path d="M3.49902 14.9656C4.72475 18.4791 8.06749 21 11.999 21C16.9696 21 20.999 16.9706 20.999 12C20.999 7.02944 16.9696 3 11.999 3C8.29827 3 4.8984 5.6756 3.68943 8.5"/><path d="M11.999 7V12L14.999 14"/><path d="M7.49751 8.74363C7.49751 8.74363 3.81388 9.3026 3.25487 8.7436C2.69585 8.1846 3.25488 4.50098 3.25488 4.50098"/>',copy:'<path d="M7.5 14.5C7.5 11.2002 7.5 9.55025 8.52513 8.52513C9.55025 7.5 11.2002 7.5 14.5 7.5C17.7998 7.5 19.4497 7.5 20.4749 8.52513C21.5 9.55025 21.5 11.2002 21.5 14.5C21.5 17.7998 21.5 19.4497 20.4749 20.4749C19.4497 21.5 17.7998 21.5 14.5 21.5C11.2002 21.5 9.55025 21.5 8.52513 20.4749C7.5 19.4497 7.5 17.7998 7.5 14.5Z"/><path d="M7.5 16.5C6.10355 16.5 5.40533 16.5 4.84402 16.3036C3.83866 15.9518 3.0482 15.1613 2.69641 14.156C2.5 13.5947 2.5 12.8964 2.5 11.5V9.5C2.5 6.20017 2.5 4.55025 3.52513 3.52513C4.55025 2.5 6.20017 2.5 9.5 2.5H11.5C12.8964 2.5 13.5947 2.5 14.156 2.69641C15.1613 3.0482 15.9518 3.83866 16.3036 4.84402C16.5 5.40533 16.5 6.10355 16.5 7.5"/>',check:'<path d="M5 14L8.5 17.5L19 6.5"/>',stop:'<path d="M4 12C4 8.72077 4 7.08116 4.81382 5.91891C5.1149 5.48891 5.48891 5.1149 5.91891 4.81382C7.08116 4 8.72077 4 12 4C15.2792 4 16.9188 4 18.0811 4.81382C18.5111 5.1149 18.8851 5.48891 19.1862 5.91891C20 7.08116 20 8.72077 20 12C20 15.2792 20 16.9188 19.1862 18.0811C18.8851 18.5111 18.5111 18.8851 18.0811 19.1862C16.9188 20 15.2792 20 12 20C8.72077 20 7.08116 20 5.91891 19.1862C5.48891 18.8851 5.1149 18.5111 4.81382 18.0811C4 16.9188 4 15.2792 4 12Z"/>',up:'<path d="M12 5.5V19"/><path d="M18 11C18 11 13.5811 5.00001 12 5C10.4188 4.99999 6 11 6 11"/>',retry:'<path d="M20.4879 15C19.2524 18.4956 15.9187 21 12 21C7.02943 21 3 16.9706 3 12C3 7.02943 7.02943 3 12 3C15.7292 3 18.9286 5.26806 20.2941 8.5"/><path d="M15 9H18C19.4142 9 20.1213 9 20.5607 8.56066C21 8.12132 21 7.41421 21 6V3"/>',steer:'<path d="M13 6H8.5C6.01472 6 4 8.01472 4 10.5C4 12.9853 6.01472 15 8.5 15H20"/><path d="M17 12C17 12 20 14.2095 20 15C20 15.7906 17 18 17 18"/>',play:'<path d="M18.8906 12.846C18.5371 14.189 16.8667 15.138 13.5257 17.0361C10.296 18.8709 8.6812 19.7884 7.37983 19.4196C6.8418 19.2671 6.35159 18.9776 5.95624 18.5787C5 17.6139 5 15.7426 5 12C5 8.2574 5 6.3861 5.95624 5.42132C6.35159 5.02245 6.8418 4.73288 7.37983 4.58042C8.6812 4.21165 10.296 5.12907 13.5257 6.96393C16.8667 8.86197 18.5371 9.811 18.8906 11.154C19.0365 11.7084 19.0365 12.2916 18.8906 12.846Z"/>',x:'<path d="M18.9991 19L5 5.00098"/><path d="M19 5L5.00092 18.999"/>',plus:'<path d="M12.001 4.00101V20.001"/><path d="M20.001 12.001L4.00098 12.001"/>',mic:'<path d="M7 6.5C7 4.01472 9.01472 2 11.5 2C13.9853 2 16 4.01472 16 6.5V11.5C16 13.9853 13.9853 16 11.5 16C9.01472 16 7 13.9853 7 11.5V6.5Z"/><path d="M11.5 19H11.0828C7.57267 19 4.57706 16.4623 4 13M11.5 19H11.9172C15.4273 19 18.4229 16.4623 19 13M11.5 19V22"/>',file:'<path d="M8 17H16"/><path d="M8 13H12"/><path d="M13 2.5V3C13 5.82843 13 7.24264 13.8787 8.12132C14.7574 9 16.1716 9 19 9H19.5M20 10.6569V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V9.45584C4 6.21082 4 4.58831 4.88607 3.48933C5.06508 3.26731 5.26731 3.06508 5.48933 2.88607C6.58831 2 8.21082 2 11.4558 2C12.1614 2 12.5141 2 12.8372 2.11401C12.9044 2.13772 12.9702 2.165 13.0345 2.19575C13.3436 2.34355 13.593 2.593 14.0919 3.09188L18.8284 7.82843C19.4065 8.40649 19.6955 8.69552 19.8478 9.06306C20 9.4306 20 9.83935 20 10.6569Z"/>',clip:'<path d="M9.5 8V14.5C9.5 15.8807 10.6193 17 12 17C13.3807 17 14.5 15.8807 14.5 14.5V6.5C14.5 4.01472 12.4853 2 10 2C7.51472 2 5.5 4.01472 5.5 6.5V15.5C5.5 19.0899 8.41015 22 12 22C15.5899 22 18.5 19.0899 18.5 15.5V6"/>',read:'<path d="M8 17H16"/><path d="M8 13H12"/><path d="M13 2.5V3C13 5.82843 13 7.24264 13.8787 8.12132C14.7574 9 16.1716 9 19 9H19.5M20 10.6569V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V9.45584C4 6.21082 4 4.58831 4.88607 3.48933C5.06508 3.26731 5.26731 3.06508 5.48933 2.88607C6.58831 2 8.21082 2 11.4558 2C12.1614 2 12.5141 2 12.8372 2.11401C12.9044 2.13772 12.9702 2.165 13.0345 2.19575C13.3436 2.34355 13.593 2.593 14.0919 3.09188L18.8284 7.82843C19.4065 8.40649 19.6955 8.69552 19.8478 9.06306C20 9.4306 20 9.83935 20 10.6569Z"/>',edit:'<path d="M16.4249 4.60509L17.4149 3.6151C18.2351 2.79497 19.5648 2.79497 20.3849 3.6151C21.205 4.43524 21.205 5.76493 20.3849 6.58507L19.3949 7.57506M16.4249 4.60509L9.76558 11.2644C9.25807 11.772 8.89804 12.4078 8.72397 13.1041L8 16L10.8959 15.276C11.5922 15.102 12.228 14.7419 12.7356 14.2344L19.3949 7.57506M16.4249 4.60509L19.3949 7.57506"/><path d="M18.9999 13.5C18.9999 16.7875 18.9999 18.4312 18.092 19.5376C17.9258 19.7401 17.7401 19.9258 17.5375 20.092C16.4312 21 14.7874 21 11.4999 21H11C7.22876 21 5.34316 21 4.17159 19.8284C3.00003 18.6569 3 16.7712 3 13V12.5C3 9.21252 3 7.56879 3.90794 6.46244C4.07417 6.2599 4.2599 6.07417 4.46244 5.90794C5.56879 5 7.21252 5 10.5 5"/>',find:'<path d="M17 17L21 21"/><path d="M19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19C15.4183 19 19 15.4183 19 11Z"/>',look:'<path d="M21.544 11.045C21.848 11.4713 22 11.6845 22 12C22 12.3155 21.848 12.5287 21.544 12.955C20.1779 14.8706 16.6892 19 12 19C7.31078 19 3.8221 14.8706 2.45604 12.955C2.15201 12.5287 2 12.3155 2 12C2 11.6845 2.15201 11.4713 2.45604 11.045C3.8221 9.12944 7.31078 5 12 5C16.6892 5 20.1779 9.12944 21.544 11.045Z"/><path d="M15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12Z"/>',run:'<path d="M14 4H10C6.22876 4 4.34315 4 3.17157 5.17157C2 6.34315 2 8.22876 2 12C2 15.7712 2 17.6569 3.17157 18.8284C4.34315 20 6.22876 20 10 20H14C17.7712 20 19.6569 20 20.8284 18.8284C22 17.6569 22 15.7712 22 12C22 8.22876 22 6.34315 20.8284 5.17157C19.6569 4 17.7712 4 14 4Z"/><path d="M7 9L8.83981 10.5858C9.61327 11.2525 10 11.5858 10 12C10 12.4142 9.61327 12.7475 8.83981 13.4142L7 15"/><path d="M13 16H17"/>',think:'<path d="M8 16.4998C6.7725 15.4011 6 13.7768 6 11.9998C6 8.68605 8.68629 5.99976 12 5.99976C15.3137 5.99976 18 8.68605 18 11.9998C18 13.7768 17.2275 15.4011 16 16.4998"/><path d="M12 11.9998V16.4998"/><path d="M9.5 18.9998H14.5"/><path d="M10.5 21.4998H13.5"/><path d="M3.5 11.9998H2.5M5.98438 5.97632L5.23438 5.23022M18.0195 5.97632L18.7695 5.23022M21.5 11.9998H20.5M12 2.49976V3.49976"/>',add:'<path d="M12 3.00005C16.2426 3.00005 18.364 3.00005 19.682 4.31807C21 5.63609 21 7.75741 21 12.0001C21 16.2427 21 18.364 19.682 19.682C18.364 21.0001 16.2426 21.0001 12 21.0001C7.75736 21.0001 5.63604 21.0001 4.31802 19.682C3 18.364 3 16.2427 3 12.0001C3 7.75741 3 5.63609 4.31802 4.31807C5.63604 3.00005 7.75736 3.00005 12 3.00005Z"/><path d="M12.0001 8.00005V12.0001M12.0001 12.0001V16.0001M12.0001 12.0001H16.0001M12.0001 12.0001H8.00006"/>',expand:'<path d="M16.4999 3.26621C17.3443 3.25421 20.1408 2.67328 20.7337 3.26621C21.3266 3.85913 20.7457 6.65559 20.7337 7.5M20.5059 3.49097L13.5021 10.4961"/><path d="M3.26636 16.5001C3.25436 17.3445 2.67343 20.141 3.26636 20.7339C3.85928 21.3268 6.65574 20.7459 7.50015 20.7339M10.502 13.4976L3.49824 20.5027"/>',collapse:'<path d="M6.5023 10.7365C7.34671 10.7485 10.1432 11.3294 10.7361 10.7365C11.329 10.1436 10.7481 7.34708 10.7361 6.50267M13.2685 17.5027C13.2565 16.6583 12.6756 13.8618 13.2685 13.2689C13.8614 12.676 16.6579 13.2569 17.5023 13.2689M20.9991 21.001L13.6102 13.6188M10.3691 10.3763L2.99998 2.99902"/>',resolve:'<path d="M22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12Z"/><path d="M8 12.5L10.5 15L16 9"/>',reopen:'<path d="M11 6H15.5C17.9853 6 20 8.01472 20 10.5C20 12.9853 17.9853 15 15.5 15H4"/><path d="M6.99998 12C6.99998 12 4.00001 14.2095 4 15C3.99999 15.7906 7 18 7 18"/>',more:'<path d="M6.00449 12.5V12M18.0045 12.5V12M12.0045 12.5V12M7.00449 12.5C7.00449 11.9477 6.55677 11.5 6.00449 11.5C5.4522 11.5 5.00449 11.9477 5.00449 12.5C5.00449 13.0523 5.4522 13.5 6.00449 13.5C6.55677 13.5 7.00449 13.0523 7.00449 12.5ZM19.0045 12.5C19.0045 11.9477 18.5568 11.5 18.0045 11.5C17.4522 11.5 17.0045 11.9477 17.0045 12.5C17.0045 13.0523 17.4522 13.5 18.0045 13.5C18.5568 13.5 19.0045 13.0523 19.0045 12.5ZM13.0045 12.5C13.0045 11.9477 12.5568 11.5 12.0045 11.5C11.4522 11.5 11.0045 11.9477 11.0045 12.5C11.0045 13.0523 11.4522 13.5 12.0045 13.5C12.5568 13.5 13.0045 13.0523 13.0045 12.5Z"/>',reply:'<path d="M3.99219 10H11.9922C13.8521 10 14.7821 10 15.5451 10.2044C17.6157 10.7592 19.2329 12.3765 19.7877 14.4471C19.9922 15.2101 19.9922 16.1401 19.9922 18"/><path d="M7.99219 6L6.83839 6.87652C4.94092 8.31801 3.99219 9.03875 3.99219 10C3.99219 10.9612 4.94092 11.682 6.83839 13.1235L7.99219 14"/>',trash:'<path d="M18.8516 16.3743L19.5 6H4.5L5.14839 16.3743C5.315 19.0401 5.39831 20.373 6.26426 21.1865C7.13021 22 8.46571 22 11.1367 22H12.8633C15.5343 22 16.8698 22 17.7357 21.1865C18.6017 20.373 18.685 19.0401 18.8516 16.3743Z"/><path d="M16 6H21M16 6L15.3778 4.34082C15.0007 3.33524 14.8122 2.83245 14.4402 2.50292C14.3213 2.39765 14.1904 2.3069 14.0501 2.2326C13.6109 2 13.074 2 12 2C10.926 2 10.3891 2 9.9499 2.2326C9.8096 2.3069 9.67865 2.39765 9.55982 2.50292C9.18783 2.83245 8.99928 3.33524 8.62219 4.34082L8 6M16 6H8M3 6H8"/><path d="M9.5 11V17M14.5 11V17"/>',phone:'<path d="M13.5 2H10.5C8.14298 2 6.96447 2 6.23223 2.73223C5.5 3.46447 5.5 4.64298 5.5 7V17C5.5 19.357 5.5 20.5355 6.23223 21.2678C6.96447 22 8.14298 22 10.5 22H13.5C15.857 22 17.0355 22 17.7678 21.2678C18.5 20.5355 18.5 19.357 18.5 17V7C18.5 4.64298 18.5 3.46447 17.7678 2.73223C17.0355 2 15.857 2 13.5 2Z"/><path d="M12.125 19H12M12.25 19C12.25 19.1381 12.1381 19.25 12 19.25C11.8619 19.25 11.75 19.1381 11.75 19C11.75 18.8619 11.8619 18.75 12 18.75C12.1381 18.75 12.25 18.8619 12.25 19Z"/>',tablet:'<path d="M14.5 2H9.5C6.67157 2 5.25736 2 4.37868 2.87868C3.5 3.75736 3.5 5.17157 3.5 8V16C3.5 18.8284 3.5 20.2426 4.37868 21.1213C5.25736 22 6.67157 22 9.5 22H14.5C17.3284 22 18.7426 22 19.6213 21.1213C20.5 20.2426 20.5 18.8284 20.5 16V8C20.5 5.17157 20.5 3.75736 19.6213 2.87868C18.7426 2 17.3284 2 14.5 2Z"/><path d="M12.125 19H12M12.25 19C12.25 19.1381 12.1381 19.25 12 19.25C11.8619 19.25 11.75 19.1381 11.75 19C11.75 18.8619 11.8619 18.75 12 18.75C12.1381 18.75 12.25 18.8619 12.25 19Z"/>',desktop:'<path d="M14 21H16M14 21C13.1716 21 12.5 20.3284 12.5 19.5V17L12 17M14 21H10M10 21H8M10 21C10.8284 21 11.5 20.3284 11.5 19.5V17L12 17M12 17V21"/><path d="M16 3H8C5.17157 3 3.75736 3 2.87868 3.87868C2 4.75736 2 6.17157 2 9V11C2 13.8284 2 15.2426 2.87868 16.1213C3.75736 17 5.17157 17 8 17H16C18.8284 17 20.2426 17 21.1213 16.1213C22 15.2426 22 13.8284 22 11V9C22 6.17157 22 4.75736 21.1213 3.87868C20.2426 3 18.8284 3 16 3Z"/>',keyboard:'<path d="M14.5 7H9.5C6.21252 7 4.56878 7 3.46243 7.90796C3.25989 8.07418 3.07418 8.25989 2.90796 8.46243C2 9.56878 2 11.2125 2 14.5C2 17.7875 2 19.4312 2.90796 20.5376C3.07418 20.7401 3.25989 20.9258 3.46243 21.092C4.56878 22 6.21252 22 9.5 22H14.5C17.7875 22 19.4312 22 20.5376 21.092C20.7401 20.9258 20.9258 20.7401 21.092 20.5376C22 19.4312 22 17.7875 22 14.5C22 11.2125 22 9.56878 21.092 8.46243C20.9258 8.25989 20.7401 8.07418 20.5376 7.90796C19.4312 7 17.7875 7 14.5 7Z"/><path d="M12 7V5C12 4.44772 12.4477 4 13 4C13.5523 4 14 3.55228 14 3V2"/><path d="M7 12L8 12"/><path d="M11.5 12L12.5 12"/><path d="M16 12L17 12"/><path d="M7 17L17 17"/>',freeze:'<path d="M14.244 3.00632C13.801 3.40963 12.6212 5.00086 11.991 5C11.3608 4.99909 10.1858 3.40451 9.744 3"/><path d="M14.244 20.9937C13.801 20.5904 12.6212 18.9991 11.991 19C11.3608 19.0009 10.1858 20.5955 9.744 21"/><path d="M20.9077 9.45191C20.337 9.26993 18.3691 9.04383 18.0547 8.4976C17.7404 7.9514 18.5338 6.13651 18.6632 5.55164"/><path d="M5.33024 18.4456C5.45802 17.8603 6.24618 16.043 5.93032 15.4976C5.61445 14.9523 3.64599 14.732 3.07477 14.5516"/><path d="M3.07602 9.45203C3.64679 9.27005 5.61472 9.04395 5.9291 8.49772C6.2434 7.95152 5.44996 6.13663 5.32055 5.55176"/><path d="M18.6529 18.4457C18.5252 17.8604 17.737 16.0431 18.0529 15.4977C18.3687 14.9524 20.3372 14.7321 20.9084 14.5518"/><path d="M15.4581 9.97911L17.994 8.49982M11.9937 8.02071L11.9937 4.99982M17.9937 15.4998L15.458 14.0206M5.99424 15.4998L8.56579 13.9997M11.9937 18.9998L11.9937 15.9789M8.56579 10.0001L5.994 8.49982"/><path d="M15.4957 11.7313C15.4955 10.8861 15.4955 10.4635 15.2945 10.1155C15.0935 9.76744 14.7275 9.55617 13.9955 9.13361L13.5316 8.86583C12.7996 8.44326 12.4336 8.23198 12.0317 8.23199C11.6298 8.23201 11.2638 8.44332 10.5318 8.86593L10.0679 9.13379C9.33581 9.55644 8.96978 9.76777 8.76882 10.1158C8.56786 10.4639 8.56786 10.8866 8.56786 11.7319L8.56786 12.2677C8.56786 13.113 8.56786 13.5356 8.76881 13.8837C8.96976 14.2318 9.33578 14.4431 10.0678 14.8658L10.5319 15.1337C11.264 15.5564 11.63 15.7678 12.032 15.7678C12.4339 15.7678 12.7999 15.5564 13.532 15.1338L13.9958 14.866C14.728 14.4433 15.0941 14.2319 15.295 13.8838C15.496 13.5356 15.4959 13.1129 15.4958 12.2674L15.4957 11.7313Z"/>',stage:'<path d="M15.5 21C16.8956 21 17.5933 21 18.1611 20.8278C19.4395 20.44 20.44 19.4395 20.8278 18.1611C21 17.5933 21 16.8956 21 15.5M21 8.5C21 7.10444 21 6.40666 20.8278 5.83886C20.44 4.56046 19.4395 3.56004 18.1611 3.17224C17.5933 3 16.8956 3 15.5 3M8.5 21C7.10444 21 6.40666 21 5.83886 20.8278C4.56046 20.44 3.56004 19.4395 3.17224 18.1611C3 17.5933 3 16.8956 3 15.5M3 8.5C3 7.10444 3 6.40666 3.17224 5.83886C3.56004 4.56046 4.56046 3.56004 5.83886 3.17224C6.40666 3 7.10444 3 8.5 3"/>',layers:'<path d="M8.64298 3.14559L6.93816 3.93362C4.31272 5.14719 3 5.75397 3 6.75C3 7.74603 4.31272 8.35281 6.93817 9.56638L8.64298 10.3544C10.2952 11.1181 11.1214 11.5 12 11.5C12.8786 11.5 13.7048 11.1181 15.357 10.3544L17.0618 9.56638C19.6873 8.35281 21 7.74603 21 6.75C21 5.75397 19.6873 5.14719 17.0618 3.93362L15.357 3.14559C13.7048 2.38186 12.8786 2 12 2C11.1214 2 10.2952 2.38186 8.64298 3.14559Z"/><path d="M20.788 11.0972C20.9293 11.2959 21 11.5031 21 11.7309C21 12.7127 19.6873 13.3109 17.0618 14.5072L15.357 15.284C13.7048 16.0368 12.8786 16.4133 12 16.4133C11.1214 16.4133 10.2952 16.0368 8.64298 15.284L6.93817 14.5072C4.31272 13.3109 3 12.7127 3 11.7309C3 11.5031 3.07067 11.2959 3.212 11.0972"/><path d="M20.3767 16.2661C20.7922 16.5971 21 16.927 21 17.3176C21 18.2995 19.6873 18.8976 17.0618 20.0939L15.357 20.8707C13.7048 21.6236 12.8786 22 12 22C11.1214 22 10.2952 21.6236 8.64298 20.8707L6.93817 20.0939C4.31272 18.8976 3 18.2995 3 17.3176C3 16.927 3.20778 16.5971 3.62334 16.2661"/>',sun:'<path d="M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z"/><path d="M12 2V3.5M12 20.5V22M19.0708 19.0713L18.0101 18.0106M5.98926 5.98926L4.9286 4.9286M22 12H20.5M3.5 12H2M19.0713 4.92871L18.0106 5.98937M5.98975 18.0107L4.92909 19.0714"/>',moon:'<path d="M21.5 14.0784C20.3003 14.7189 18.9301 15.0821 17.4751 15.0821C12.7491 15.0821 8.91792 11.2509 8.91792 6.52485C8.91792 5.06986 9.28105 3.69968 9.92163 2.5C5.66765 3.49698 2.5 7.31513 2.5 11.8731C2.5 17.1899 6.8101 21.5 12.1269 21.5C16.6849 21.5 20.503 18.3324 21.5 14.0784Z"/>',left:'<path d="M15 6C15 6 9.00001 10.4189 9 12C8.99999 13.5812 15 18 15 18"/>',right:'<path d="M9.00005 6C9.00005 6 15 10.4189 15 12C15 13.5812 9 18 9 18"/>',down:'<path d="M18 9.00005C18 9.00005 13.5811 15 12 15C10.4188 15 6 9 6 9"/>',point:'<path d="M9 14.5V4.5a1.5 1.5 0 0 1 3 0v6"/><path d="M12 10a1.5 1.5 0 0 1 3 0v1.5"/><path d="M15 11a1.5 1.5 0 0 1 3 0v1"/><path d="M18 12a1.5 1.5 0 0 1 3 0v3.5a6.5 6.5 0 0 1-6.5 6.5h-1.6a6 6 0 0 1-4.7-2.3l-3.4-4.4a1.7 1.7 0 0 1 2.6-2.2L9 14.5"/>',hand:'<path d="M18 11V6a2 2 0 0 0-4 0"/><path d="M14 10V4a2 2 0 0 0-4 0v2"/><path d="M10 10.5V6a2 2 0 0 0-4 0v8"/><path d="M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-6-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.83L7 15"/>'},A=(e,t="")=>`<svg class="hi${t?" "+t:""}" viewBox="0 0 24 24" aria-hidden="true">${Xr[e]||""}</svg>`;document.querySelectorAll("i[data-i]").forEach(e=>{e.outerHTML=A(e.dataset.i)});function ki(e){e?document.documentElement.dataset.theme=e:delete document.documentElement.dataset.theme;const t=e?e==="dark":matchMedia("(prefers-color-scheme: dark)").matches,n=document.getElementById("theme-btn");n&&(n.innerHTML=A(t?"sun":"moon"),n.title=t?"Light mode (\u21E7D)":"Dark mode (\u21E7D)")}function Ts(){const t=(document.documentElement.dataset.theme?document.documentElement.dataset.theme==="dark":matchMedia("(prefers-color-scheme: dark)").matches)?"light":"dark";try{localStorage.setItem("loop.theme",t)}catch{}ki(t)}ki((()=>{try{return localStorage.getItem("loop.theme")}catch{return null}})()),matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>ki(document.documentElement.dataset.theme)),document.getElementById("theme-btn").addEventListener("click",Ts);const $i=["#5B6AD0","#D2575C","#3B9A6C","#B98A2C","#8A63C4","#2E93A6","#CC6E3C"],Ur=["#2F5BFF","#E5484D","#1F9D55","#D9A100","#8E4EC6","#0E9AA7","#E8590C"],Zr=e=>{const t=Ur.indexOf(String(e||"").toUpperCase());return t>=0?$i[t]:/^#[0-9a-f]{6}$/i.test(e||"")?e:"#88888F"},As=(e,t,n="",a="")=>`<span class="av${n?" "+n:""}" style="--c:${Zr(t)}">${a?`<img src="${L(a)}" alt="" referrerpolicy="no-referrer">`:L(Zs(e).slice(0,1))}</span>`,Li="#E5484D";let f=null,b={x:120,y:140,z:.5},Ci=!1,K="select",Yt=!1,_=null,j=null,B=null,Ue=null;const Y=new Set;let ya=null,Ze=null;const _s=new Set,D=new Map,ze=new Map,ln=new Map,X=window.LOOP_ADAPTER||null,U=Ae.get("loop.me",null)||{id:ha(),name:"",color:$i[Math.floor(Math.random()*$i.length)]};X?.me&&Object.assign(U,X.me),U.id=U.id||ha();async function w(e,t,n){if(X)return X.api(e,t,n);const a=await fetch(t,{method:e,headers:{"content-type":"application/json"},body:n?JSON.stringify(n):void 0}),i=await a.json().catch(()=>({}));if(!a.ok)throw new Error(i.error||`HTTP ${a.status}`);return i}function y(e,t=2200){const n=m("#toast");n.textContent=e,n.hidden=!1,clearTimeout(y.t),y.t=setTimeout(()=>n.hidden=!0,t)}const $=()=>f?.role==="owner";function Gr(){if(X)return X.connect(ba);const e=new EventSource("/__loop/api/events");e.onmessage=t=>ba(JSON.parse(t.data)),e.onerror=()=>{m("#agent-pill").classList.add("offline")},e.onopen=()=>{m("#agent-pill").classList.remove("offline")}}function Ps(){if(!Ot()&&!se)return location.reload();setTimeout(Ps,1500)}function ba(e){if(e.type==="state"){if(f?.version&&e.state.version&&e.state.version!==f.version){location.reload();return}f?.codeId&&e.state.codeId&&e.state.codeId!==f.codeId&&Ps();const t=!f;f=e.state,t&&al(),wa()}else if(e.type==="patch"){if(!f)return;Object.assign(f,e.set||{}),!se&&(e.lists?.frames?.up?.length>1||e.lists?.sections?.up?.length)&&(xt.classList.add("gliding"),clearTimeout(ba.glide),ba.glide=setTimeout(()=>xt.classList.remove("gliding"),520));const t=$()&&(e.lists?.sections?.up||[]).find(n=>n.optionsFor&&!(f.sections||[]).some(a=>a.id===n.id));for(const[n,a]of Object.entries(e.lists||{})){const i=new Map((f[n]||[]).map(s=>[s.id,s]));for(const s of a.up||[])i.set(s.id,s);f[n]=a.order?a.order.map(s=>i.get(s)).filter(Boolean):(f[n]||[]).map(s=>i.get(s.id))}wa(),t&&Dr(t.id)}else if(e.type==="activity"){if(!f)return;const t=f.live[e.frameId];t&&(t.step=e.step,t.partial=e.partial||"");const n=e.partial==null&&f.comments.find(i=>i.id===e.commentId);if(n&&e.step&&!/^(Writing…|Reading your comment…|Your chat picked this up|Working…)$/.test(e.step)){const i=n.steps||=[],s=i[i.length-1];!/^(Reading the code|Editing|Writing|Setting up an option)$/.test(e.step)&&(!s||s.s!==e.step)&&i.push({t:Date.now(),s:e.step}),wo(e.commentId)}const a=D.get(e.frameId);a&&t&&$e(a.step,e.step),document.querySelectorAll(`[data-step-for="${e.commentId}"]`).forEach(i=>$e(i,e.step)),ro(e.commentId,e.partial||""),Sl(e.frameId)}else if(e.type==="frame-changed"){{const t=D.get(e.frameId);if(t?.quietN>0&&Date.now()<t.quietT&&!e.done&&!e.live){t.quietN--;return}t&&(t.quietN=0)}ul(e.frameId),e.done&&hl(e.frameId,e.status==="done"?f.frames.find(t=>t.id===e.frameId)?.kind==="frozen"?"Changed in the app":"Updated":e.status==="error"?"Failed":"",e.status!=="done"),e.done&&e.status==="done"&&hc(e.frameId),e.done&&(e.status==="done"||e.status==="error")&&ml(e.frameId,e.commentId,e.status)}else if(e.type==="presence"){if(e.id===U.id)return;e.leave?ln.delete(e.id):ln.set(e.id,{...e,t:Date.now()}),Gs(),$a()}}function $e(e,t){e&&e.textContent!==t&&(e.textContent=t)}const $t={at:0,ids:new Set};function Qr(){const e=Ae.get(`loop.seen.${f.name}`,null);e?($t.at=e.at,$t.ids=new Set(e.ids)):($t.at=Date.now(),qs())}function qs(){Ae.set(`loop.seen.${f.name}`,{at:$t.at,ids:[...$t.ids].slice(-400)})}function Jr(e){const t=Xt(e).filter(a=>a.kind!=="note"),n=t[t.length-1];return!!n&&n.status==="done"&&(n.finishedAt||0)>$t.at&&!$t.ids.has(n.id)}function Ds(e){let t=!1;for(const n of Xt(e))n.finishedAt&&!$t.ids.has(n.id)&&($t.ids.add(n.id),t=!0);return t&&qs(),t}const el=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5],Mi=[64,148,255];let va=0,Is=0;const Hs=matchMedia("(prefers-reduced-motion: reduce)");function tl(){va||(va=requestAnimationFrame(zs))}function zs(e){va=0;const t=[...document.querySelectorAll(".area.working")];if(!t.length||(Hs.matches||(va=requestAnimationFrame(zs)),e-Is<33))return;Is=e;const n=Hs.matches?.35:e%5200/5200,a=Math.min(1,n/.8),s=-.2+a*a*(3-2*a)*1.45,o=1,r=.119;for(const c of t){const l=c.getBoundingClientRect();if(l.right<0||l.bottom<0||l.left>innerWidth||l.top>innerHeight||l.width<12||l.height<12)continue;let d=3;for(;l.width/d*(l.height/d)>6e4;)d++;const u=Math.ceil(l.width/d),p=Math.ceil(l.height/d);let h=c.querySelector(":scope > canvas.dz");h||(h=document.createElement("canvas"),h.className="dz",c.appendChild(h)),(h.width!==u||h.height!==p)&&(h.width=u,h.height=p,h.style.setProperty("--cols",u),h.style.setProperty("--rows",p));const g=h.getContext("2d"),v=g.createImageData(u,p),T=v.data,C=Math.hypot(u,p),k=Math.min(u,p),M=Math.max(2.4,k*.05+Math.max(0,k-40)*.03)*(c.classList.contains("whole")?1.5:1),E=M*4.5;for(let N=0;N<p;N++)for(let q=0;q<u;q++){const ne=Math.min(q,N,u-1-q,p-1-N);if(ne>E)continue;const R=Math.hypot(q,N)/C-s,ce=o*Math.exp(-R*R/r)*Math.exp(-ne/M);if(ce>(el[(N&3)*4+(q&3)]+.5)/16){const rn=(N*u+q)*4;T[rn]=Mi[0],T[rn+1]=Mi[1],T[rn+2]=Mi[2],T[rn+3]=255*(.3+.7*ce)|0}}g.putImageData(v,0,0)}}const nl='<svg viewBox="0 0 24 24" aria-hidden="true"><path pathLength="14" d="M5 14L8.5 17.5L19 6.5"/></svg>';function al(){setTimeout(sr,400),Qr();const e=Ae.get(`loop.view.${f.name}`,null);e?(b=e,ie()):Oe(!1),Ci=!0,$()?U.name=f.hostName||U.name||"You":U.name||Ro(),Ae.set("loop.me",U),document.body.classList.toggle("guest",!$()),m("#new-frame-btn").hidden=!$(),m("#section-btn").hidden=!$(),document.querySelector("#toolbar .tb-sep").hidden=!$()}function ie(){b.z>=.02||(b.z=.04),Bs=performance.now(),xt.style.transform=`translate(${b.x}px, ${b.y}px) scale(${b.z})`,xt.style.setProperty("--z",b.z),ie.lastZ!==b.z&&(ie.lastZ=b.z,xt.style.willChange!=="transform"&&(xt.style.willChange="transform"),clearTimeout(ie.crisp),ie.crisp=setTimeout(()=>{xt.style.willChange="auto"},160));const e=Math.min(1.5,Math.max(1,Math.pow(b.z,.42)));document.documentElement.style.setProperty("--lz",e.toFixed(3)),document.body.classList.toggle("zoom-tiny",b.z<.12);const t=`${Math.round(b.z*100)}%`,n=m("#zoom-level");if(n.textContent!==t){n.textContent=t;const a=m("#zoom");a.classList.add("awake"),clearTimeout(ie.zt),ie.zt=setTimeout(()=>a.classList.remove("awake"),1200)}Hn(),cn(),_e(),fa(),ye&&Re(),V.hidden=!0,Ci&&f&&(clearTimeout(ie.t),ie.t=setTimeout(()=>Ae.set(`loop.view.${f.name}`,b),300)),f&&ie.z!==b.z&&(ie.z=b.z,ie.lq||(ie.lq=requestAnimationFrame(()=>{ie.lq=0,Hr()})),clearTimeout(ie.pt),ie.pt=setTimeout(()=>{for(const a of f.frames)ut(a.id)},120))}function Lt(e,t,n){const a=Math.min(4,Math.max(.04,b.z*n));b.x=e-(e-b.x)*(a/b.z),b.y=t-(t-b.y)*(a/b.z),b.z=a,Si()}let Ei=!1;function Si(){Ei||(Ei=!0,requestAnimationFrame(()=>{Ei=!1,ie()}))}function Os(e,t,n){e.preventDefault();const a=Math.max(-30,Math.min(30,e.deltaMode===1?e.deltaY*16:e.deltaY));Lt(t,n,Math.exp(-a*(e.ctrlKey&&!e.metaKey?.01:.004)))}const re=(e,t)=>({x:(e-b.x)/b.z,y:(t-b.y)/b.z});function Oe(e=!0,t){const n=(f?.frames||[]).filter(r=>!t||t.includes(r.id));if(!n.length)return b={x:innerWidth/2,y:innerHeight/2,z:.5},ie();const a=Math.min(...n.map(r=>r.x)),i=Math.min(...n.map(r=>r.y)),s=Math.max(...n.map(r=>r.x+r.w)),o=Math.max(...n.map(r=>r.y+r.h));return Rs({x:a,y:i,w:s-a,h:o-i},1,e)}function Rs(e,t=1,n=!0){const a=e.x,i=e.y,s=e.x+Math.max(1,e.w),o=e.y+Math.max(1,e.h),r=80,c=110,l=110,d=Math.max(.04,Math.min(t,(innerWidth-r*2)/(s-a),(innerHeight-c-l)/(o-i))),u={z:d,x:(innerWidth-(s-a)*d)/2-a*d,y:c+(innerHeight-c-l-(o-i)*d)/2-i*d};if(!n)return b=u,ie();const p={...b},h=performance.now(),g=v=>{const T=Math.min(1,(v-h)/280),C=1-Math.pow(1-T,3);b={x:p.x+(u.x-p.x)*C,y:p.y+(u.y-p.y)*C,z:p.z+(u.z-p.z)*C},ie(),T<1&&requestAnimationFrame(g)};requestAnimationFrame(g)}function wa(){if(!f)return;m("#canvas-name").querySelector("input")||(m("#canvas-name").textContent=f.name),m("#canvas-name").classList.toggle("editable",$()&&!X),m("#history-btn").hidden=!$()||!!X,document.title=`${f.name} \u2014 Loop`,m("#empty").hidden=f.frames.length>0,m("#empty").classList.toggle("guest",!$()),$()&&!X&&f.hostName&&U.name!==f.hostName&&Ci&&(U.name=f.hostName,Ae.set("loop.me",U)),vl(),$a();const e=new Set(f.frames.map(t=>t.id));for(const[t,n]of D)e.has(t)||(n.el.contains(H)&&te(),n.el.remove(),D.delete(t));for(const t of f.frames)J(t);f.sections||=[],wt(),_&&!e.has(_)&&(_=null),qt(),Nn(),j&&Ia(),ye&&Ml(),B&&B.frameId!==le&&!e.has(B.frameId)&&te();for(const t of[...Y])e.has(t)||Y.delete(t);Fe(),oa(),Ul(),Kl(),S&&da(),F&&Fr(),P&&(Pn(),pa()),Hn(),ui()}function Dn(e){try{const t=e.iframe.contentWindow.location;return t.href==="about:blank"?null:t.pathname+t.search+t.hash}catch{return null}}let Ti=0,Ai=0,In=null;const il=/[?&]nosleep\b/.test(location.search);let Ns=new Set;function sl(e){const t=jt(e),n=Math.max(0,Math.min(t.l+t.w,innerWidth)-Math.max(t.l,0)),a=Math.max(0,Math.min(t.t+t.h,innerHeight)-Math.max(t.t,0));return{shown:n*a,of:t.w*t.h,r:t}}function ol(){const e=new Set;if(!f)return e;if(S)return e.add(S.fid),e;const t=[];for(const n of f.frames){const{shown:a,of:i,r:s}=sl(n);if(!(a<400||a<i*.1)){if(il||n.id===In||n.id===_||n.id===fe||x?.frameId===n.id||xe?.fid===n.id||Y.has(n.id)){e.add(n.id);continue}(a>=innerWidth*innerHeight*.25||a>=i*.5&&(s.h>=innerHeight*.55||s.w>=innerWidth*.55))&&t.push([n.id,a])}}return t.sort((n,a)=>a[1]-n[1]).slice(0,2).forEach(([n])=>e.add(n)),e}const rl=e=>Ns.has(e);function ll(e,t,n){const a=e.requestAnimationFrame.bind(e),i=new Map;let s=0;t.waking=Date.now(),e.requestAnimationFrame=r=>{if(!t.asleep)return a(r);const c=-++s;return i.set(c,r),c};const o=e.cancelAnimationFrame.bind(e);e.cancelAnimationFrame=r=>r<0?i.delete(r):o(r),t.sleepTo=r=>{if(t.asleep!==r){t.asleep=r;try{const c=e.document;let l=c.getElementById("__loop-sleep");r&&!l&&(l=c.createElement("style"),l.id="__loop-sleep",l.textContent="*, *::before, *::after { animation-play-state: paused !important; }",(c.head||c.documentElement).appendChild(l)),!r&&l&&l.remove(),c.querySelectorAll("video").forEach(d=>{try{r?(d._loopPlay=!d.paused,d.pause()):d._loopPlay&&d.play()}catch{}})}catch{}if(!r){const c=[...i.values()];i.clear(),c.forEach(l=>a(l))}}},t.asleep=!1,cn()}function cn(){Ai||!f||(Ai=setTimeout(()=>{Ai=0,Ns=ol();for(const[e,t]of D){if(!t.sleepTo)continue;const n=Date.now()-(t.waking||0)<700;t.sleepTo(!n&&!rl(e))}},120))}setInterval(()=>cn(),1500);function Hn(){Ti||!f||(Ti=requestAnimationFrame(()=>{Ti=0;const e=innerWidth,t=innerHeight,n=f.frames.length>6,a=[];for(const i of f.frames){const s=D.get(i.id);if(!s?.iframe)continue;const o=De(i),r=b.z,c=b.x+o.x*r,l=b.y+o.y*r,d=o.w*r,u=o.h*r,p=g=>Math.max(0,c-e-g,-(c+d)-g,l-t-g,-(l+u)-g),h=!n||f.live[o.id]||_===o.id||fe===o.id||S?.fid===o.id||Y.has(o.id);if(s.el.classList.toggle("narrow",d<200),s.el.classList.toggle("far",Tn(i)),f.live[o.id]){const g=Math.max(0,Math.min(c+d,e)-Math.max(c,0)),v=Math.max(0,Math.min(l+u,t)-Math.max(l,0)),T=g*v>=e*t*.2&&g*v>=d*u*.5;s.wedge||(s.wedge=document.createElement("i"),s.wedge.className="work-edge",s.el.appendChild(s.wedge)),s.el.classList.toggle("work-far",!T)}else s.el.classList.contains("work-far")&&s.el.classList.remove("work-far");s.parked?(h||p(e*.5)===0&&Math.max(d,u)>160)&&a.push({fe:s,keep:h,on:p(0)===0,d:Math.hypot(c+d/2-e/2,l+u/2-t/2)}):!h&&(p(e)>0||Math.max(d,u)<110)&&(s.resume=Dn(s),s.parked=!0,s.el.classList.add("parked"),s.iframe.src="about:blank"),s.parked&&Ws(s)}if(a.length){const i=performance.now()-Bs>140;a.sort((o,r)=>r.keep-o.keep||r.on-o.on||o.d-r.d);const s=i?a.slice(0,2):a.filter(o=>o.keep).slice(0,2);for(const{fe:o}of s)o.parked=!1,o.el.classList.remove("parked"),o.el.classList.add("waking"),clearTimeout(o.wakeT),o.wakeT=setTimeout(()=>Fs(o),8e3),o.iframe.src=o.resume||o.iframe.dataset.src||"about:blank",o.resume=null;a.length>s.length&&setTimeout(Hn,i?90:160)}}))}let Bs=0;function Fs(e){clearTimeout(e.wakeT),requestAnimationFrame(()=>requestAnimationFrame(()=>e.el.classList.remove("waking")))}function Ws(e){if(X)return;const t=e.hint.querySelector("img"),n=`/__loop/poster/${e.id}?v=${e.rev||0}`;if(t.dataset.src===n)return;t.dataset.src=n;const a=new Image;a.onload=()=>{t.dataset.src===n&&(t.src=n,t.hidden=!1,e.hint.classList.add("has-pic"))},a.src=n}function De(e){return{...e,...ze.get(e.id)||{}}}function cl(e){const t=document.createElement("div");t.className="frame",t.dataset.id=e.id,t.innerHTML=`
2
2
  <div class="frame-label">
3
- <span class="spinner"></span><span class="ic"></span><span class="name"></span><span class="kind" hidden></span><button class="count" title="Versions: look back through this frame's changes" hidden>${T("layers")}<span></span></button>
3
+ <span class="spinner"></span><span class="ic"></span><span class="name"></span><span class="kind" hidden></span><button class="count" title="Versions: look back through this frame's changes" hidden>${A("layers")}<span></span></button>
4
4
  <span class="step"></span><span class="elapsed"></span><span class="updated"></span>
5
- <button class="stop" title="Stop the agent">Stop</button><button class="use" title="Make this the real screen. The other options go away." hidden>Use this</button>
5
+ <button class="stop" title="Stop the agent">Stop</button>
6
6
  </div>
7
7
  <div class="frame-body"><iframe title="${L(e.name)}"></iframe><div class="parked-hint"><span></span><img alt="" draggable="false" hidden></div><div class="empty-hint"><b>Describe this screen</b></div><div class="down-hint"><b></b><span>Start it again and this frame comes back by itself.</span></div><div class="shield"></div><div class="areas"></div><div class="progress"></div></div><div class="edge-zone"></div><div class="pins"></div><button class="dims" tabindex="-1"></button>
8
- ${["n","s","e","w","ne","nw","se","sw"].map(i=>`<div class="resize rz-${i}" data-dir="${i}"></div>`).join("")}`,fr.appendChild(t);const n={id:e.id,el:t,iframe:t.querySelector("iframe"),label:t.querySelector(".frame-label"),name:t.querySelector(".name"),dims:t.querySelector(".dims"),kind:t.querySelector(".kind"),count:t.querySelector(".count"),step:t.querySelector(".step"),elapsed:t.querySelector(".elapsed"),updated:t.querySelector(".updated"),ic:t.querySelector(".ic"),pins:t.querySelector(".pins"),restore:null,parked:!0,hint:t.querySelector(".parked-hint")};return t.classList.add("parked"),va(n,e,n.iframe),t.querySelector(".stop").addEventListener("pointerdown",i=>i.stopPropagation()),t.querySelector(".stop").addEventListener("click",()=>{const i=Object.values(u.live),s=u.live[e.id];for(const a of i.length>1?i:s?[s]:[])w("POST",`/__loop/api/comments/${a.commentId}/cancel`).catch(o=>b(o.message))}),t.querySelector(".use").addEventListener("pointerdown",i=>i.stopPropagation()),t.querySelector(".use").addEventListener("click",async i=>{i.stopPropagation();const s=u.frames.find(a=>a.id===e.id)?.optionOf;if(s)try{await w("POST",`/__loop/api/comments/${s.cid}/choose`,{option:s.oid}),b("Now the real screen. The other options are gone.")}catch(a){b(a.message)}}),n.label.addEventListener("dblclick",i=>{!i.target.closest(".count")&&!i.target.closest(".use")&&k()&&!n.renaming&&ka(e.id)}),n.dims.addEventListener("pointerdown",i=>i.stopPropagation()),n.dims.innerHTML='<button class="fill-dot" data-pick="frame-fill" title="Fill"><i></i></button><span class="dz"></span>',n.dims.addEventListener("click",i=>{if(i.stopPropagation(),!k())return;const s=i.target.closest(".fill-dot");if(s){const a=u.frames.find(o=>o.id===e.id);return s.dataset.val=a?.fill&&a.fill!=="none"?a.fill:"#ffffff",Oi(s)}Re=Re===e.id?null:e.id,He()}),n.count.addEventListener("pointerdown",i=>i.stopPropagation()),n.count.addEventListener("click",i=>{i.stopPropagation(),ir(e.id)}),H.set(e.id,n),n}function va(e,t,n){n.addEventListener("load",()=>{if(e.el.classList.contains("waking")&&n.src!=="about:blank"&&ga(e),n._incoming){const i=e.iframe,s=document.activeElement===i;n._incoming=!1,e.iframe=n;try{e.restore&&n.contentWindow.scrollTo(e.restore.sx,e.restore.sy)}catch{}requestAnimationFrame(()=>requestAnimationFrame(()=>{if(n.classList.remove("incoming"),i.remove(),s)try{n.focus()}catch{}if(e.swapping=!1,clearTimeout(e.swapT),e.swapNext){const a=e.swapNext;e.swapNext=null,ba(e,t,a)}}))}if(n===e.iframe){try{const i=n.contentWindow;if(e.parked)return;const s=()=>{e.cur=si(e);const c=u?.frames.find(f=>f.id===t.id);c?.kind==="route"&&!c.optionOf&&(e.kind.textContent=(e.cur||c.src).split("?")[0])};s();for(const c of["pushState","replaceState"]){const f=i.history[c];i.history[c]=function(...d){const p=f.apply(this,d);return setTimeout(s),p}}i.addEventListener("popstate",s),i.addEventListener("hashchange",s),e.restore&&(i.scrollTo(e.restore.sx,e.restore.sy),e.restore=null),e.el.classList.toggle("empty",!!i.document.querySelector('meta[name="loop-empty"]'));let a=0;i.addEventListener("scroll",()=>{a||(a=requestAnimationFrame(()=>{a=0,it(t.id)}))},{passive:!0,capture:!0}),i.addEventListener("resize",()=>it(t.id));const o=c=>{const f=n.getBoundingClientRect(),d=f.width/(n.offsetWidth||1);return[f.left+c.clientX*d,f.top+c.clientY*d]};ac(i,t.id,o),pc(t.id),Mr(i,e,t.id);let r=null,l=0;i.addEventListener("wheel",c=>{if(E){(c.ctrlKey||c.metaKey)&&c.preventDefault();return}if(c.ctrlKey||c.metaKey)return pa(c,...o(c));const f=performance.now();if(!r||f-l>140){const p=Math.abs(c.deltaX)>Math.abs(c.deltaY);r=no(c.target,p?"x":"y",p?c.deltaX:c.deltaY)?"page":"canvas"}if(l=f,r==="page")return;c.preventDefault();const d=c.deltaMode===1?16:1;y.x-=c.deltaX*d,y.y-=c.deltaY*d,cs()},{passive:!1}),Sr(i,t.id),i.addEventListener("pointerdown",()=>{Ie&&!E&&de!==t.id&&Ts(t.id)},!0),e.autoKb=null,$c(i,e,t.id),i.addEventListener("gesturestart",c=>{c.preventDefault(),ki=y.z}),i.addEventListener("gesturechange",c=>{if(c.preventDefault(),E)return;const[f,d]=o(c);ut(f,d,ki*c.scale/y.z)}),i.addEventListener("keydown",c=>{if(c.key==="Escape"){de=null,ot(),ie(null);for(const g of u.frames)Q(g);return}const f=c.target;!(f&&(f.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(f.tagName)))&&!c.metaKey&&!c.ctrlKey&&/^[vhpecdfnk?]$/i.test(c.key)&&setTimeout(()=>{c.defaultPrevented||(ot(),window.dispatchEvent(new KeyboardEvent("keydown",{key:c.key,code:c.code,shiftKey:c.shiftKey,altKey:c.altKey})))},0);const p=c.target,h=p&&(p.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(p.tagName));(c.metaKey||c.ctrlKey)&&!h&&(c.key.toLowerCase()==="z"||c.ctrlKey&&c.key.toLowerCase()==="y")&&(c.preventDefault(),c.shiftKey||c.key.toLowerCase()==="y"?Nn():_i())})}catch{}setTimeout(()=>it(t.id),60)}})}function Sr(e,t){const n=e.document;let i=null,s=0;const a=()=>{const f=u?.frames.find(d=>d.id===t);return Xo(f)};try{const f=n.createElement("style");f.dataset.loop="touch";const d=`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Ccircle cx='14' cy='14' r='11' fill='rgba(120,120,128,.38)' stroke='rgba(255,255,255,.75)' stroke-width='1.5'/%3E%3C/svg%3E") 14 14, default`;f.textContent=`html.loop-touch, html.loop-touch * { -webkit-user-select: none !important; user-select: none !important; -webkit-touch-callout: none; cursor: ${d} !important; }
8
+ ${["n","s","e","w","ne","nw","se","sw"].map(a=>`<div class="resize rz-${a}" data-dir="${a}"></div>`).join("")}`,Vr.appendChild(t);const n={id:e.id,el:t,iframe:t.querySelector("iframe"),label:t.querySelector(".frame-label"),name:t.querySelector(".name"),dims:t.querySelector(".dims"),kind:t.querySelector(".kind"),count:t.querySelector(".count"),step:t.querySelector(".step"),elapsed:t.querySelector(".elapsed"),updated:t.querySelector(".updated"),ic:t.querySelector(".ic"),pins:t.querySelector(".pins"),restore:null,parked:!0,hint:t.querySelector(".parked-hint")};return t.classList.add("parked"),js(n,e,n.iframe),t.querySelector(".stop").addEventListener("pointerdown",a=>a.stopPropagation()),t.querySelector(".stop").addEventListener("click",()=>{const a=Object.values(f.live),i=f.live[e.id];for(const s of a.length>1?a:i?[i]:[])w("POST",`/__loop/api/comments/${s.commentId}/cancel`).catch(o=>y(o.message))}),n.label.addEventListener("dblclick",a=>{!a.target.closest(".count")&&$()&&!n.renaming&&_i(e.id)}),n.dims.addEventListener("pointerdown",a=>a.stopPropagation()),n.dims.innerHTML='<button class="fill-dot" data-pick="frame-fill" title="Fill"><i></i></button><span class="dz"></span>',n.dims.addEventListener("click",a=>{if(a.stopPropagation(),!$())return;const i=a.target.closest(".fill-dot");if(i){const s=f.frames.find(o=>o.id===e.id);return i.dataset.val=s?.fill&&s.fill!=="none"?s.fill:"#ffffff",ii(i)}Ke=Ke===e.id?null:e.id,Fe()}),n.count.addEventListener("pointerdown",a=>a.stopPropagation()),n.count.addEventListener("click",a=>{a.stopPropagation(),Ls(e.id)}),D.set(e.id,n),n}function js(e,t,n){n.addEventListener("load",()=>{if(setTimeout(()=>{const a=f?.frames.find(i=>i.id===t.id);a&&(Us(e,a,f.live[t.id]),yl(e,a))},30),e.el.classList.contains("waking")&&n.src!=="about:blank"&&Fs(e),n._incoming){const a=e.iframe,i=document.activeElement===a;n._incoming=!1,e.iframe=n;try{e.restore&&n.contentWindow.scrollTo(e.restore.sx,e.restore.sy)}catch{}requestAnimationFrame(()=>requestAnimationFrame(()=>{if(n.classList.remove("incoming"),a.remove(),i)try{n.focus()}catch{}if(e.swapping=!1,clearTimeout(e.swapT),e.swapNext){const s=e.swapNext;e.swapNext=null,Ks(e,t,s)}}))}if(n===e.iframe){try{const a=n.contentWindow;if(e.parked)return;const i=()=>{e.cur=Dn(e);const l=f?.frames.find(d=>d.id===t.id);l?.kind==="route"&&!l.optionOf&&(e.kind.textContent=(e.cur||l.src).split("?")[0])};i();for(const l of["pushState","replaceState"]){const d=a.history[l];a.history[l]=function(...u){const p=d.apply(this,u);return setTimeout(i),p}}a.addEventListener("popstate",i),a.addEventListener("hashchange",i),e.restore&&(a.scrollTo(e.restore.sx,e.restore.sy),e.restore=null),e.el.classList.toggle("empty",!!a.document.querySelector('meta[name="loop-empty"]')&&!Pi(f.frames.find(l=>l.id===t.id)||t));let s=0;a.addEventListener("scroll",()=>{s||(s=requestAnimationFrame(()=>{s=0,ut(t.id)}))},{passive:!0,capture:!0}),a.addEventListener("resize",()=>ut(t.id));const o=l=>{const d=n.getBoundingClientRect(),u=d.width/(n.offsetWidth||1);return[d.left+l.clientX*u,d.top+l.clientY*u]};Gc(a,t.id,o),sd(t.id),ll(a,e,t.id);let r=null,c=0;a.addEventListener("wheel",l=>{if(S){(l.ctrlKey||l.metaKey)&&l.preventDefault();return}if(l.ctrlKey||l.metaKey)return Os(l,...o(l));const d=performance.now();if(!r||d-c>140){const p=Math.abs(l.deltaX)>Math.abs(l.deltaY);r=Ao(l.target,p?"x":"y",p?l.deltaX:l.deltaY)?"page":"canvas"}if(c=d,r==="page")return;l.preventDefault();const u=l.deltaMode===1?16:1;b.x-=l.deltaX*u,b.y-=l.deltaY*u,Si()},{passive:!1}),dl(a,t.id),a.addEventListener("pointerdown",()=>{Be&&!S&&fe!==t.id&&Gi(t.id)},!0),a.addEventListener("contextmenu",l=>{if(l.shiftKey)return;l.preventDefault();const[d,u]=o(l);lr(d,u,e.el.querySelector(".frame-body"))}),e.autoKb=null,md(a,e,t.id),a.addEventListener("gesturestart",l=>{l.preventDefault(),Oa=b.z}),a.addEventListener("gesturechange",l=>{if(l.preventDefault(),S)return;const[d,u]=o(l);Lt(d,u,Oa*l.scale/b.z)}),a.addEventListener("keydown",l=>{if(l.key==="Escape"){fe=null,ht(),Z(null);for(const g of f.frames)J(g);return}const d=l.target;!(d&&(d.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(d.tagName)))&&!l.metaKey&&!l.ctrlKey&&/^[vhpecdfnksx?]$/i.test(l.key)&&setTimeout(()=>{l.defaultPrevented||(ht(),window.dispatchEvent(new KeyboardEvent("keydown",{key:l.key,code:l.code,shiftKey:l.shiftKey,altKey:l.altKey})))},0);const p=l.target,h=p&&(p.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(p.tagName));(l.metaKey||l.ctrlKey)&&!h&&(l.key.toLowerCase()==="z"||l.ctrlKey&&l.key.toLowerCase()==="y")&&(l.preventDefault(),l.shiftKey||l.key.toLowerCase()==="y"?Qn():Va())})}catch{}setTimeout(()=>ut(t.id),60)}})}function dl(e,t){const n=e.document;let a=null,i=0;const s=()=>{const d=f?.frames.find(u=>u.id===t);return Tr(d)};try{const d=n.createElement("style");d.dataset.loop="touch";const u=`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Ccircle cx='14' cy='14' r='11' fill='rgba(120,120,128,.38)' stroke='rgba(255,255,255,.75)' stroke-width='1.5'/%3E%3C/svg%3E") 14 14, default`;d.textContent=`html.loop-touch, html.loop-touch * { -webkit-user-select: none !important; user-select: none !important; -webkit-touch-callout: none; cursor: ${u} !important; }
9
9
  html.loop-touch input, html.loop-touch textarea, html.loop-touch [contenteditable] { -webkit-user-select: text !important; user-select: text !important; }
10
- html.loop-touch img, html.loop-touch a { -webkit-user-drag: none; }`,(n.head||n.documentElement).appendChild(f),n.documentElement.classList.toggle("loop-touch",a())}catch{}const o=(f,d)=>{const p=n.scrollingElement||n.documentElement;for(let h=f?.nodeType===1?f:f?.parentElement;h&&h!==p&&h!==n.body;h=h.parentElement){const g=e.getComputedStyle(h),v=d==="x"?g.overflowX:g.overflowY;if(/(auto|scroll|overlay)/.test(v)&&(d==="x"?h.scrollWidth-h.clientWidth:h.scrollHeight-h.clientHeight)>1)return h}return p},r=(f,d,p)=>{f&&(d||p)&&f.scrollTo({left:f.scrollLeft+d,top:f.scrollTop+p,behavior:"instant"})},l=f=>{try{return e.getComputedStyle(f).scrollSnapType!=="none"}catch{return!1}};e.addEventListener("pointerdown",f=>{cancelAnimationFrame(s),!(!a()||f.pointerType!=="mouse"||f.button!==0)&&(f.target.closest?.('input, textarea, select, [contenteditable=""], [contenteditable="true"], [draggable="true"]')||(i={x:f.clientX,y:f.clientY,lx:f.clientX,ly:f.clientY,lt:performance.now(),vx:0,vy:0,moved:!1,target:f.target,sx:null,sy:null}))},!0),e.addEventListener("pointermove",f=>{if(!i)return;if(!(f.buttons&1))return c();if(!i.moved){if(Math.hypot(f.clientX-i.x,f.clientY-i.y)<6)return;i.moved=!0,i.sx=o(i.target,"x"),i.sy=o(i.target,"y"),e.getSelection?.()?.removeAllRanges()}const d=f.clientX-i.lx,p=f.clientY-i.ly,h=performance.now(),g=Math.max(1,h-i.lt);i.sx===i.sy?r(i.sx,-d,-p):(r(i.sx,-d,0),r(i.sy,0,-p)),i.vx=.7*(d/g*16)+.3*i.vx,i.vy=.7*(p/g*16)+.3*i.vy,i.lx=f.clientX,i.ly=f.clientY,i.lt=h,f.preventDefault()},!0);const c=()=>{const f=i;if(i=null,!f?.moved)return;const d=v=>{v.stopPropagation(),v.preventDefault()};if(e.addEventListener("click",d,{capture:!0,once:!0}),setTimeout(()=>e.removeEventListener("click",d,!0),80),performance.now()-f.lt>90)return;let p=l(f.sx)?0:f.vx,h=l(f.sy)?0:f.vy;const g=()=>{p*=.95,h*=.95,!(Math.abs(p)<.4&&Math.abs(h)<.4)&&(f.sx===f.sy?r(f.sx,-p,-h):(r(f.sx,-p,0),r(f.sy,0,-h)),s=requestAnimationFrame(g))};s=requestAnimationFrame(g)};e.addEventListener("pointerup",c,!0),e.addEventListener("pointercancel",c,!0),e.addEventListener("blur",c),n.addEventListener("selectstart",f=>{i&&a()&&f.preventDefault()},!0),n.addEventListener("dragstart",f=>{a()&&!f.target.closest?.('[draggable="true"]')&&f.preventDefault()},!0)}function ba(e,t,n){if(e.swapping){e.swapNext=n;return}e.swapping=!0;const i=document.createElement("iframe");i.title=e.iframe.title,i.dataset.src=e.iframe.dataset.src,i.className="incoming",i._incoming=!0,va(e,t,i),e.iframe.after(i),i.src=n,e.swapT=setTimeout(()=>{i._incoming&&i.dispatchEvent(new Event("load"))},5e3)}function Tr(e){try{const t=e.iframe.contentWindow;return!!(t.document.querySelector('script[src*="/@vite/client"], nextjs-portal, script[src*="webpack-dev-server"], script[src*="hot-update"]')||t.__vite_plugin_react_preamble_installed__||t.$RefreshReg$||t.__webpack_hmr||t.parcelHotUpdate||Object.keys(t).some(i=>i.startsWith("webpackHotUpdate")))}catch{return!1}}function Q(e){if(!e)return;const t=Oe(e),n=H.get(t.id)||Er(t),i=n.el.style,s=t.fill==="none"?"transparent":t.fill||"";(i.getPropertyValue("--fill")||"")!==s&&(s?i.setProperty("--fill",s):i.removeProperty("--fill")),n.el.classList.toggle("nofill",t.fill==="none"),i.left=`${t.x}px`,i.top=`${t.y}px`,i.width=`${t.w}px`,i.height=`${t.h}px`,i.setProperty("--fw",`${t.w}px`);{const c=ys(t),f=`Describe this ${c.what}`;i.setProperty("--pfs",`${c.fs}px`),i.setProperty("--pk",(c.fs/27).toFixed(3)),i.setProperty("--plx",`${c.lx*100}%`),i.setProperty("--pty",`${c.ty*100}%`),n.el.dataset.on!==c.on&&(n.el.dataset.on=c.on),n.hintB||=n.el.querySelector(".empty-hint b"),n.hintB&&n.hintB.textContent!==f&&(n.hintB.textContent=f)}n.inkAt!==`${t.x},${t.y}`&&(n.inkAt=`${t.x},${t.y}`,Ea(t.id));const a=X?.frameSrc?.(t)||(t.kind==="folder"||t.kind==="frozen"?`/__loop/f/${t.id}/${encodeURIComponent(t.entry||"index.html")}`:t.src);n.iframe.dataset.src!==a&&(n.iframe.dataset.src=a,n.resume=null,n.parked||(n.iframe.src=a)),Le(n.hint.firstChild,t.name),n.el.classList.toggle("narrow",t.w*y.z<200),n.renaming||(n.name.textContent=t.name),n.kind.hidden=t.kind==="folder"||t.kind==="static"||t.kind==="frozen";const o=t.kind==="frozen";n.ic.dataset.k!==(o?"frozen":"live")&&(n.ic.dataset.k=o?"frozen":"live",n.ic.innerHTML=o?Wi:""),n.ic.dataset.tip=o?`Frozen ${new Date(t.frozenAt||t.createdAt).toLocaleString([],{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"})}${t.from?` \xB7 from ${t.from.split("?")[0]}`:""}`:"Live",n.el.classList.toggle("is-frozen",o),Yo(n,t),n.kind.textContent=t.kind==="route"&&!t.optionOf?(n.cur||t.src).split("?")[0]:"Live";{let c=null;if(t.kind==="url")try{c=new URL(t.src).origin}catch{}const f=!!c&&!!u.down?.includes(c);f!==!!n.down&&(n.down=f,n.el.classList.toggle("down",f),f?(n.downB||=n.el.querySelector(".down-hint b"),n.downB.textContent=`${c.replace(/^https?:\/\//,"")} isn\u2019t running`):!n.parked&&n.iframe.dataset.src&&(n.iframe.src=n.iframe.dataset.src))}const r=u.live[t.id],l=t.kind==="folder"&&!X?Ji(t.id).length:0;if(Le(n.count.lastChild,l&&!r?String(l+1):""),n.count.hidden=!l||!!r,n.el.classList.toggle("working",!!r),r){n.stopB||=n.el.querySelector(".frame-label .stop");const c=Object.keys(u.live).length>1;Le(n.stopB,c?"Stop all agents":"Stop"),n.stopB.title=c?"Stop every agent that is working":"Stop the agent"}n.el.classList.toggle("building",!!t.building);{const c=k()&&!X&&u.agent.mode==="inbox"&&!u.chatListening&&u.comments.find(d=>d.frameId===t.id&&d.kind==="create"&&d.status==="queued"&&!d.background);let f=n.el.querySelector(":scope > .frame-body > .wait-pill");c&&!f&&(f=document.createElement("div"),f.className="wait-pill",n.el.querySelector(".frame-body").appendChild(f),f.addEventListener("pointerdown",d=>d.stopPropagation()),f.addEventListener("click",async d=>{const p=d.target.closest("button");if(p){p.disabled=!0,p.textContent="Starting\u2026";try{await w("POST",`/__loop/api/comments/${f.dataset.cid}/background`)}catch(h){b(h.message)}}})),f&&!c?f.remove():f&&f.dataset.cid!==c.id&&(f.dataset.cid=c.id,f.innerHTML=`<span>Chat isn\u2019t listening</span><button class="pin-act" title="Build it now in the background${u.chatHistory?", carrying on from a copy of that chat":" in a new session"}">${u.chatHistory?"Carry on here":"Run in new chat"}<kbd>${lt==="metaKey"?"\u2318":"Ctrl"}\u21B5</kbd></button>`)}if(n.useB||=n.el.querySelector(".frame-label .use"),n.useB&&(n.useB.hidden=!(t.optionOf?.live&&!t.building&&!r&&k())),n.el.classList.toggle("filling",t.building==="filling"),n.el.classList.toggle("in-section",(u.sections||[]).some(c=>Gi(ea(c),t))),r){const c=u.comments.find(f=>f.id===r.commentId);Le(n.step,r.step||(c?.kind==="create"?"Building the frame\u2026":"Working\u2026")),Le(n.elapsed,ai(r.startedAt))}n.el.classList.toggle("selected",I===t.id||K.has(t.id)),n.el.classList.toggle("live",ve?.fid===t.id||j==="select"&&Ie&&!Bt&&$?.frameId!==t.id),Le(n.dims.querySelector(".dz"),`${Math.round(t.w)} \xD7 ${Math.round(t.h)}`),n.dims.dataset.tip="Fill \xB7 size & device presets";{const c=n.dims.querySelector(".fill-dot i");c&&(c.style.background=t.fill&&t.fill!=="none"?t.fill:"",c.parentElement.classList.toggle("is-none",t.fill==="none"))}if(Ze===t.id){const c=ei===t.id;Ze=ei=null,queueMicrotask(()=>{E||(ie(t.id),Tt(t.id),c&&setTimeout(()=>hi(t.id),340))})}}function ai(e){const t=Math.max(0,Math.round((Date.now()-e)/1e3));return t<60?`${t}s`:`${Math.floor(t/60)}m ${String(t%60).padStart(2,"0")}s`}setInterval(()=>{if(!u)return;for(const[n,i]of Object.entries(u.live)){const s=H.get(n);s&&(s.elapsed.textContent=ai(i.startedAt))}document.querySelectorAll("[data-elapsed-from]").forEach(n=>Le(n,ai(+n.dataset.elapsedFrom)));const e=Date.now();let t=!1;for(const[n,i]of en)e-i.t>15e3&&(en.delete(n),t=!0);t&&(La(),ri())},1e3);function Ar(e){const t=H.get(e);if(!t)return;try{const s=t.iframe.contentWindow;t.restore={sx:s.scrollX,sy:s.scrollY}}catch{t.restore=null}if(t.rev=(t.rev||0)+1,t.parked){t.resume=null,ya(t);return}const n=t.iframe.dataset.src,i=u.frames.find(s=>s.id===e);if(!(i?.kind==="static"||i?.kind==="frozen"))if(i?.kind==="folder")ba(t,i,`${n}?_m=${Date.now()}`);else if(i?.kind==="route"){if(Tr(t))return;try{t.iframe.contentWindow.location.reload()}catch{t.iframe.src=n}}else try{t.iframe.contentWindow.location.reload()}catch{t.iframe.src=n}}const pe=document.createElement("div");pe.id="done",pe.hidden=!0,document.body.appendChild(pe);let oi=0;const wa=document.title;function xa(e){try{const t=xa.ac||=new(window.AudioContext||window.webkitAudioContext),n=t.currentTime;for(const[i,s]of(e?[440,330]:[660,990]).entries()){const a=t.createOscillator(),o=t.createGain();a.type="sine",a.frequency.value=s,a.connect(o),o.connect(t.destination),o.gain.setValueAtTime(0,n+i*.11),o.gain.linearRampToValueAtTime(.06,n+i*.11+.02),o.gain.exponentialRampToValueAtTime(1e-4,n+i*.11+.5),a.start(n+i*.11),a.stop(n+i*.11+.55)}}catch{}}function _r(e){const t=u.frames.find(s=>s.id===e);if(!t)return!1;const n=Ot(t);return Math.max(0,Math.min(n.l+n.w,innerWidth)-Math.max(n.l,0))*Math.max(0,Math.min(n.t+n.h,innerHeight)-Math.max(n.t,0))>n.w*n.h*.4&&n.w>120}function Pr(e,t,n){if(!k()||X||!u)return;const i=document.hidden;if(!i&&_r(e))return;const a=u.frames.find(c=>c.id===e),o=u.comments.find(c=>c.id===t),r=n==="error",l=e===ce?"the canvas":a?.name||"a frame";xa(r),i&&(oi++,document.title=`(${oi}) ${wa}`),pe.innerHTML=`<span class="dn-ic${r?" err":""}">${T(r?"x":"check","s")}</span><span class="dn-text"><b>${r?"Failed":"Done"}</b> \xB7 ${L(l)}</span><button class="dn-go">Go there</button><button class="dn-x" title="Dismiss">${T("x","s")}</button>`,pe.dataset.fid=e,pe.dataset.cid=t||"",pe.hidden=!1,pe.classList.remove("in"),pe.offsetWidth,pe.classList.add("in"),clearTimeout(pe._t),pe._t=setTimeout(()=>{pe.hidden=!0},9e3)}pe.addEventListener("click",e=>{if(e.target.closest(".dn-x")){pe.hidden=!0;return}if(!e.target.closest(".dn-go"))return;pe.hidden=!0;const t=u.comments.find(n=>n.id===pe.dataset.cid);t?Ls(u.comments.find(n=>n.id===(t.parentId||t.id))||t,!0):pe.dataset.fid&&pe.dataset.fid!==ce&&(ie(pe.dataset.fid),Ge(!0,[pe.dataset.fid]))}),document.addEventListener("visibilitychange",()=>{!document.hidden&&oi&&(oi=0,document.title=wa)});function qr(e,t,n){const i=H.get(e);!i||!t||(i.updated.textContent=t,i.el.classList.remove("updated","failed"),i.el.offsetWidth,i.el.classList.add(n?"failed":"updated"),clearTimeout(i.flashT),i.flashT=setTimeout(()=>i.el.classList.remove("updated","failed"),4200))}function ka(e){const t=H.get(e),n=u.frames.find(a=>a.id===e);t.renaming=!0;const i=document.createElement("input");i.className="rename",i.value=n.name,t.name.replaceChildren(i),i.focus(),i.select(),i.addEventListener("pointerdown",a=>a.stopPropagation());const s=a=>{if(!t.renaming)return;t.renaming=!1;const o=i.value.trim();if(t.name.textContent=a&&o?o:n.name,a&&o&&o!==n.name){const r=n.name;w("PATCH",`/__loop/api/frames/${e}`,{name:o}),Z("Rename frame",()=>At(e,{name:r}),()=>At(e,{name:o}))}};i.addEventListener("keydown",a=>{a.stopPropagation(),a.key==="Enter"&&s(!0),a.key==="Escape"&&s(!1)}),i.addEventListener("blur",()=>s(!0))}function Ir(){const e=m("#agent-pill"),t=Object.keys(u.live).length,n=u.comments.filter(d=>d.status==="queued").length,i=u.comments.filter(d=>d.status==="waiting").length,s=u.agent.lastModel&&(u.agentBin==="codex"?!/^claude/.test(u.agent.lastModel):/^claude/.test(u.agent.lastModel));let o=u.agent.mode==="inbox"?u.chatListening?`Your chat \xB7 ${u.agentLabel||"agent"}`:"Your chat isn\u2019t listening \xB7 comments run in the background":(u.agentLabel||"Claude Code")+(s?` \xB7 ${_n(u.agent.lastModel)}`:"");u.hostOnline===!1&&(o=`${u.hostName||"Host"} is offline \xB7 comments wait`),t?o+=` \xB7 ${t} working`:n&&(o+=` \xB7 ${n} queued`),i&&k()&&(o+=` \xB7 ${i} to review`),m("#agent-label").textContent=o,e.classList.toggle("busy",t>0),e.classList.toggle("say",t>0||n>0||i>0&&k()||u.hostOnline===!1||u.agent.mode==="inbox"&&!u.chatListening),e.dataset.tip=e.classList.contains("say")?"Where comments go":o,e.classList.toggle("inbox",u.agent.mode==="inbox"&&!t&&!u.chatListening);{let d=m("#agent-wake");d||(d=document.createElement("div"),d.id="agent-wake",m("#agent-menu").prepend(d),d.addEventListener("click",g=>{g.target.closest("button")&&navigator.clipboard?.writeText(Aa).then(()=>b("Copied. Paste it into your chat.",2200),()=>b("Select the line and copy it"))}));const p=u.agent.mode==="inbox"&&!u.chatListening&&k()&&!X,h=p?`<b>Your chat isn\u2019t listening</b><span>${u.chatHistory?"Comments carry on in the background from a copy of that chat, with everything it knows.":"Comments run in the background in a new session."} To bring the chat itself back, paste this into it:</span><code>${L(Aa)}</code><button>Copy</button>`:"";d._h!==h&&(d._h=h,d.innerHTML=h),d.hidden=!p}document.querySelectorAll("#agent-menu .menu-item").forEach(d=>{d.classList.toggle("on",d.dataset.mode===u.agent.mode&&(!d.dataset.runner||d.dataset.runner===u.agentBin)),d.dataset.runner&&(d.hidden=u.runners&&!u.runners[d.dataset.runner])}),Es(),Hr();const r=m("#agent-allowed"),l=u.agent.allow||[],c=d=>d.startsWith("dir:")?`Files in ${d.slice(4)}`:/^Bash\((.*):\*\)$/.exec(d)?.[1]??d.replace(/^mcp__/,"").replace(/__/g," \xB7 "),f=l.length?`<div class="menu-title">Allowed on this canvas</div><div class="al-note">Looking at files, copying them and making folders are always allowed.</div>${l.map(d=>`<div class="al-row"><code title="${L(d)}">${L(c(d))}</code><button data-disallow="${L(d)}" title="Stop allowing this">${Pn.x}</button></div>`).join("")}`:"";r._h!==f&&(r._h=f,r.innerHTML=f,r.hidden=!l.length),m("#share-menu").hidden||$i()}function Hr(){const e=m("#update-pill"),t=u.update;if(e.hidden=!t||!k()||!!X,e.hidden)return;const n=t.state==="updating"?'<span class="up-spin"></span>Updating\u2026':t.state==="queued"?"Updates when the agent finishes":t.state==="failed"?"Update failed \xB7 Retry":t.how==="next-start"?`Loop ${L(t.latest)} is ready next start`:`${T("up")}Update to ${L(t.latest)}`;e._h!==n&&(e._h=n,e.innerHTML=n),e.disabled=t.state==="updating"||t.state==="queued"||t.how==="next-start",e.classList.toggle("failed",t.state==="failed"),e.title=t.state==="failed"?`Couldn\u2019t update: ${t.error||"unknown error"}`:t.how==="next-start"?"Loop runs through npx here, so the new version is used the next time it starts":`Loop ${t.latest} is out (you have ${u.version}). Installs it and restarts Loop; your canvas stays exactly as it is.`}m("#update-pill").addEventListener("click",async()=>{try{await w("POST","/__loop/api/update")}catch(e){b(e.message)}});function $a(e){return(e||"?").trim().split(/\s+/).map(t=>t[0]).join("").slice(0,2).toUpperCase()}function ri(){const e=[{name:V.name||"You",color:V.color},...en.values()];m("#presence").innerHTML=e.length>1?e.slice(0,6).map((t,n)=>`<span class="avatar${n?"":" me"}" title="${L(n?t.name:`${t.name} (you) \xB7 click to change your name`)}">${aa(t.name,t.color,"",t.avatar)}</span>`).join(""):""}function La(){const e=new Set;for(const t of en.values()){e.add(t.id);let n=ns.querySelector(`[data-id="${CSS.escape(t.id)}"]`);n||(n=document.createElement("div"),n.className="cursor",n.dataset.id=t.id,n.innerHTML=`<div class="cursor-inner"><svg viewBox="0 0 18 18"><path d="M2 1.5l13 6.2-5.6 1.5-2.4 5.6z" fill="${L(t.color)}" stroke="#fff" stroke-width="1.4" stroke-linejoin="round"/></svg><span style="background:${L(t.color)}">${L(t.name)}</span></div>`,ns.appendChild(n)),n.style.transform=`translate(${t.x}px, ${t.y}px)`}ns.querySelectorAll(".cursor").forEach(t=>{e.has(t.dataset.id)||t.remove()})}let Ca=0;function zr(e,t){const n=Date.now();if(n-Ca<70||!u)return;Ca=n;const i=re(e,t);w("POST","/__loop/api/presence",{id:V.id,name:V.name||"Guest",color:V.color,avatar:V.avatar,x:i.x,y:i.y}).catch(()=>{})}addEventListener("beforeunload",()=>!X&&navigator.sendBeacon?.("/__loop/api/presence",new Blob([JSON.stringify({id:V.id,leave:!0})],{type:"application/json"})));function us(e){if(e.length<4)return`M${e[0]} ${e[1]}l.01 0`;let t=`M${e[0]} ${e[1]}`;for(let n=2;n<e.length-2;n+=2)t+=`Q${e[n]} ${e[n+1]} ${(e[n]+e[n+2])/2} ${(e[n+1]+e[n+3])/2}`;return t+`L${e[e.length-2]} ${e[e.length-1]}`}const Ft=new Set;let nn=null;function ps(e){const t=new Set(u.comments.find(n=>n.id===e)?.inkStrokes||[]);for(const n of Object.values(u.live||{})){const i=u.comments.find(s=>s.id===n.commentId);if(i&&(i.parentId||i.id)===e)for(const s of i.inkStrokes||[])t.add(s)}return[...t].filter(n=>u.strokes.some(i=>i.id===n))}function Dr(){const e=new Set(F?.inkStrokes||[]);for(const t of Object.values(u.live||{}))for(const n of u.comments.find(i=>i.id===t.commentId)?.inkStrokes||[])e.add(n);for(const t of Object.values(u.live||{})){const n=u.comments.find(s=>s.id===t.commentId),i=n&&u.comments.find(s=>s.id===n.parentId);for(const s of i?.inkStrokes||[])e.add(s)}return e}function Ma(e){if(e.fx==null||!e.frameId)return{dx:0,dy:0};const t=u.frames.find(i=>i.id===e.frameId);if(!t)return{dx:0,dy:0};const n=Oe(t);return{dx:n.x-e.fx,dy:n.y-e.fy}}const sn=e=>{const{dx:t,dy:n}=Ma(e);return t||n?e.points.map((i,s)=>i+(s%2?n:t)):e.points};function Ea(e){for(const t of u.strokes){if(e&&t.frameId!==e)continue;const{dx:n,dy:i}=Ma(t),s=n||i?`translate(${n} ${i})`:"";dt.querySelectorAll(`path[data-id="${t.id}"], path[data-for="${t.id}"]`).forEach(a=>{(a.getAttribute("transform")||"")!==s&&(s?a.setAttribute("transform",s):a.removeAttribute("transform"))})}}function xt(){dt.querySelector("defs")||dt.insertAdjacentHTML("afterbegin",`<defs>
10
+ html.loop-touch img, html.loop-touch a { -webkit-user-drag: none; }`,(n.head||n.documentElement).appendChild(d),n.documentElement.classList.toggle("loop-touch",s())}catch{}const o=(d,u)=>{const p=n.scrollingElement||n.documentElement;for(let h=d?.nodeType===1?d:d?.parentElement;h&&h!==p&&h!==n.body;h=h.parentElement){const g=e.getComputedStyle(h),v=u==="x"?g.overflowX:g.overflowY;if(/(auto|scroll|overlay)/.test(v)&&(u==="x"?h.scrollWidth-h.clientWidth:h.scrollHeight-h.clientHeight)>1)return h}return p},r=(d,u,p)=>{d&&(u||p)&&d.scrollTo({left:d.scrollLeft+u,top:d.scrollTop+p,behavior:"instant"})},c=d=>{try{return e.getComputedStyle(d).scrollSnapType!=="none"}catch{return!1}};e.addEventListener("pointerdown",d=>{if(cancelAnimationFrame(i),!s()||d.pointerType!=="mouse"||d.button!==0||d.target.closest?.('input, textarea, select, [contenteditable=""], [contenteditable="true"], [draggable="true"]'))return;let u="auto";for(let p=d.target;p&&p.nodeType===1;p=p.parentElement){const h=e.getComputedStyle(p).touchAction;if(h&&h!=="auto"){u=h;break}}u!=="none"&&(a={x:d.clientX,y:d.clientY,lx:d.clientX,ly:d.clientY,lt:performance.now(),vx:0,vy:0,moved:!1,target:d.target,sx:null,sy:null,ax:!/pan-y/.test(u)||/pan-x/.test(u),ay:!/pan-x/.test(u)||/pan-y/.test(u)})},!0),e.addEventListener("pointermove",d=>{if(!a)return;if(!(d.buttons&1))return l();if(!a.moved){if(Math.hypot(d.clientX-a.x,d.clientY-a.y)<6)return;a.moved=!0,a.sx=o(a.target,"x"),a.sy=o(a.target,"y"),e.getSelection?.()?.removeAllRanges()}const u=a.ax?d.clientX-a.lx:0,p=a.ay?d.clientY-a.ly:0,h=performance.now(),g=Math.max(1,h-a.lt);a.sx===a.sy?r(a.sx,-u,-p):(r(a.sx,-u,0),r(a.sy,0,-p)),a.vx=.7*(u/g*16)+.3*a.vx,a.vy=.7*(p/g*16)+.3*a.vy,a.lx=d.clientX,a.ly=d.clientY,a.lt=h,(u||p)&&d.preventDefault()},!0);const l=()=>{const d=a;if(a=null,!d?.moved)return;const u=v=>{v.stopPropagation(),v.preventDefault()};if(e.addEventListener("click",u,{capture:!0,once:!0}),setTimeout(()=>e.removeEventListener("click",u,!0),80),performance.now()-d.lt>90)return;let p=c(d.sx)?0:d.vx,h=c(d.sy)?0:d.vy;const g=()=>{p*=.95,h*=.95,!(Math.abs(p)<.4&&Math.abs(h)<.4)&&(d.sx===d.sy?r(d.sx,-p,-h):(r(d.sx,-p,0),r(d.sy,0,-h)),i=requestAnimationFrame(g))};i=requestAnimationFrame(g)};e.addEventListener("pointerup",l,!0),e.addEventListener("pointercancel",l,!0),e.addEventListener("blur",l),n.addEventListener("selectstart",d=>{a&&s()&&d.preventDefault()},!0),n.addEventListener("dragstart",d=>{s()&&!d.target.closest?.('[draggable="true"]')&&d.preventDefault()},!0)}function Ks(e,t,n){if(e.swapping){e.swapNext=n;return}e.swapping=!0;const a=document.createElement("iframe");a.title=e.iframe.title,a.dataset.src=e.iframe.dataset.src,a.className="incoming",a._incoming=!0,js(e,t,a),e.iframe.after(a),a.src=n,e.swapT=setTimeout(()=>{a._incoming&&a.dispatchEvent(new Event("load"))},5e3)}function fl(e){try{const t=e.iframe.contentWindow;return!!(t.document.querySelector('script[src*="/@vite/client"], nextjs-portal, script[src*="webpack-dev-server"], script[src*="hot-update"]')||t.__vite_plugin_react_preamble_installed__||t.$RefreshReg$||t.__webpack_hmr||t.parcelHotUpdate||Object.keys(t).some(a=>a.startsWith("webpackHotUpdate")))}catch{return!1}}function J(e){if(!e)return;const t=De(e),n=D.get(t.id)||cl(t),a=n.el.style,i=t.fill==="none"?"transparent":t.fill||"";(a.getPropertyValue("--fill")||"")!==i&&(i?a.setProperty("--fill",i):a.removeProperty("--fill")),n.el.classList.toggle("nofill",t.fill==="none"),a.left=`${t.x}px`,a.top=`${t.y}px`,a.width=`${t.w}px`,a.height=`${t.h}px`,a.setProperty("--fw",`${t.w}px`);{const l=Ri(t),d=`Describe this ${l.what}`;a.setProperty("--pfs",`${l.fs}px`),a.setProperty("--pk",(l.fs/27).toFixed(3)),a.setProperty("--plx",`${l.lx*100}%`),a.setProperty("--pty",`${l.ty*100}%`),n.el.dataset.on!==l.on&&(n.el.dataset.on=l.on),n.hintB||=n.el.querySelector(".empty-hint b"),n.hintB&&n.hintB.textContent!==d&&(n.hintB.textContent=d)}n.inkAt!==`${t.x},${t.y}`&&(n.inkAt=`${t.x},${t.y}`,eo(t.id));const s=X?.frameSrc?.(t)||(t.kind==="folder"||t.kind==="frozen"?`/__loop/f/${t.id}/${encodeURIComponent(t.entry||"index.html")}`:t.src);n.iframe.dataset.src!==s&&(n.iframe.dataset.src=s,n.resume=null,n.parked||(n.iframe.src=s)),$e(n.hint.firstChild,t.name),n.el.classList.toggle("narrow",t.w*b.z<200),n.renaming||(n.name.textContent=t.name),n.kind.hidden=t.kind==="folder"||t.kind==="static"||t.kind==="frozen";const o=t.kind==="frozen";n.ic.dataset.k!==(o?"frozen":"live")&&(n.ic.dataset.k=o?"frozen":"live",n.ic.innerHTML=o?ci:""),n.ic.dataset.tip=o?`Frozen ${new Date(t.frozenAt||t.createdAt).toLocaleString([],{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"})}${t.from?` \xB7 from ${t.from.split("?")[0]}`:""}`:"Live",n.el.classList.toggle("is-frozen",o),Mr(n,t),n.kind.textContent=t.kind==="route"&&!t.optionOf?(n.cur||t.src).split("?")[0]:"Live";{let l=null;if(t.kind==="url")try{l=new URL(t.src).origin}catch{}const d=!!l&&!!f.down?.includes(l);d!==!!n.down&&(n.down=d,n.el.classList.toggle("down",d),d?(n.downB||=n.el.querySelector(".down-hint b"),n.downB.textContent=`${l.replace(/^https?:\/\//,"")} isn\u2019t running`):!n.parked&&n.iframe.dataset.src&&(n.iframe.src=n.iframe.dataset.src))}const r=f.live[t.id],c=t.kind==="folder"&&!X?vi(t.id).length:0;if($e(n.count.lastChild,c&&!r?String(c+1):""),n.count.hidden=!c||!!r,n.el.classList.toggle("working",!!r),r){n.stopB||=n.el.querySelector(".frame-label .stop");const l=Object.keys(f.live).length>1;$e(n.stopB,l?"Stop all agents":"Stop"),n.stopB.title=l?"Stop every agent that is working":"Stop the agent"}n.el.classList.toggle("building",!!t.building),Us(n,t,r);{const l=$()&&!X&&f.agent.mode==="inbox"&&!f.chatListening&&f.comments.find(u=>u.frameId===t.id&&u.kind==="create"&&u.status==="queued"&&!u.background);let d=n.el.querySelector(":scope > .frame-body > .wait-pill");l&&!d&&(d=document.createElement("div"),d.className="wait-pill",n.el.querySelector(".frame-body").appendChild(d),d.addEventListener("pointerdown",u=>u.stopPropagation()),d.addEventListener("click",async u=>{const p=u.target.closest("button");if(p){p.disabled=!0,p.textContent="Starting\u2026";try{await w("POST",`/__loop/api/comments/${d.dataset.cid}/background`)}catch(h){y(h.message)}}})),d&&!l?d.remove():d&&d.dataset.cid!==l.id&&(d.dataset.cid=l.id,d.innerHTML=`<span>Chat isn\u2019t listening</span><button class="pin-act" title="Build it now in the background${f.chatHistory?", carrying on from a copy of that chat":" in a new session"}">${f.chatHistory?"Carry on here":"Run in new chat"}<kbd>${rt==="metaKey"?"\u2318":"Ctrl"}\u21B5</kbd></button>`)}if(n.el.classList.toggle("filling",t.building==="filling"),n.el.classList.toggle("in-section",(f.sections||[]).some(l=>An($s(l),t))),r){const l=f.comments.find(d=>d.id===r.commentId);$e(n.step,r.step||(l?.kind==="create"?"Building the frame\u2026":"Working\u2026")),$e(n.elapsed,xa(r.startedAt))}n.el.classList.toggle("selected",_===t.id||Y.has(t.id)),n.el.classList.toggle("live",xe?.fid===t.id||K==="select"&&Be&&!Yt&&x?.frameId!==t.id),$e(n.dims.querySelector(".dz"),`${Math.round(t.w)} \xD7 ${Math.round(t.h)}`),n.dims.dataset.tip="Fill \xB7 size & device presets";{const l=n.dims.querySelector(".fill-dot i");l&&(l.style.background=t.fill&&t.fill!=="none"?t.fill:"",l.parentElement.classList.toggle("is-none",t.fill==="none"))}if(Ue===t.id){const l=ya===t.id;Ue=ya=null,queueMicrotask(()=>{S||(Z(t.id),St(t.id),l&&setTimeout(()=>_a(t.id),340))})}}function xa(e){const t=Math.max(0,Math.round((Date.now()-e)/1e3));return t<60?`${t}s`:`${Math.floor(t/60)}m ${String(t%60).padStart(2,"0")}s`}setInterval(()=>{if(!f)return;for(const[n,a]of Object.entries(f.live)){const i=D.get(n);i&&(i.elapsed.textContent=xa(a.startedAt))}document.querySelectorAll("[data-elapsed-from]").forEach(n=>$e(n,xa(+n.dataset.elapsedFrom)));const e=Date.now();let t=!1;for(const[n,a]of ln)e-a.t>15e3&&(ln.delete(n),t=!0);t&&(Gs(),$a())},1e3);function ul(e){const t=D.get(e);if(!t)return;try{const i=t.iframe.contentWindow;t.restore={sx:i.scrollX,sy:i.scrollY}}catch{t.restore=null}if(t.rev=(t.rev||0)+1,t.parked){t.resume=null,Ws(t);return}const n=t.iframe.dataset.src,a=f.frames.find(i=>i.id===e);if(!(a?.kind==="static"||a?.kind==="frozen"))if(a?.kind==="folder")Ks(t,a,`${n}?_m=${Date.now()}`);else if(a?.kind==="route"){if(fl(t))return;try{t.iframe.contentWindow.location.reload()}catch{t.iframe.src=n}}else try{t.iframe.contentWindow.location.reload()}catch{t.iframe.src=n}}const he=document.createElement("div");he.id="done",he.hidden=!0,document.body.appendChild(he);let ka=0;const Ys=document.title;function Vs(e){try{const t=Vs.ac||=new(window.AudioContext||window.webkitAudioContext),n=t.currentTime;for(const[a,i]of(e?[440,330]:[660,990]).entries()){const s=t.createOscillator(),o=t.createGain();s.type="sine",s.frequency.value=i,s.connect(o),o.connect(t.destination),o.gain.setValueAtTime(0,n+a*.11),o.gain.linearRampToValueAtTime(.06,n+a*.11+.02),o.gain.exponentialRampToValueAtTime(1e-4,n+a*.11+.5),s.start(n+a*.11),s.stop(n+a*.11+.55)}}catch{}}function pl(e){const t=f.frames.find(i=>i.id===e);if(!t)return!1;const n=jt(t);return Math.max(0,Math.min(n.l+n.w,innerWidth)-Math.max(n.l,0))*Math.max(0,Math.min(n.t+n.h,innerHeight)-Math.max(n.t,0))>n.w*n.h*.4&&n.w>120}function ml(e,t,n){if(!$()||X||!f)return;const a=document.hidden;if(!a&&pl(e))return;const s=f.frames.find(l=>l.id===e),o=f.comments.find(l=>l.id===t),r=n==="error",c=e===le?"the canvas":s?.name||"a frame";Vs(r),a&&(ka++,document.title=`(${ka}) ${Ys}`),he.innerHTML=`<span class="dn-ic${r?" err":""}">${A(r?"x":"check","s")}</span><span class="dn-text"><b>${r?"Failed":"Done"}</b> \xB7 ${L(c)}</span><button class="dn-go">Go there</button><button class="dn-x" title="Dismiss">${A("x","s")}</button>`,he.dataset.fid=e,he.dataset.cid=t||"",he.hidden=!1,he.classList.remove("in"),he.offsetWidth,he.classList.add("in"),clearTimeout(he._t),he._t=setTimeout(()=>{he.hidden=!0},9e3)}he.addEventListener("click",e=>{if(e.target.closest(".dn-x")){he.hidden=!0;return}if(!e.target.closest(".dn-go"))return;he.hidden=!0;const t=f.comments.find(n=>n.id===he.dataset.cid);t?Yi(f.comments.find(n=>n.id===(t.parentId||t.id))||t,!0):he.dataset.fid&&he.dataset.fid!==le&&(Z(he.dataset.fid),Oe(!0,[he.dataset.fid]))}),document.addEventListener("visibilitychange",()=>{!document.hidden&&ka&&(ka=0,document.title=Ys)});function hl(e,t,n){const a=D.get(e);!a||!t||(a.updated.textContent=t,a.el.classList.remove("updated","failed"),a.el.offsetWidth,a.el.classList.add(n?"failed":"updated"),clearTimeout(a.flashT),a.flashT=setTimeout(()=>a.el.classList.remove("updated","failed"),4200))}function Xs(e,t,n){e.textContent=t;try{e.contentEditable="plaintext-only"}catch{}e.contentEditable!=="plaintext-only"&&(e.contentEditable="true"),e.classList.add("editing-name"),e.spellcheck=!1,e.focus();const a=document.createRange();a.selectNodeContents(e);const i=getSelection();i.removeAllRanges(),i.addRange(a);let s=!1;const o=c=>{if(s)return;s=!0;const l=e.textContent.replace(/\s+/g," ").trim();e.contentEditable="false",e.removeAttribute("contenteditable"),e.classList.remove("editing-name"),e.textContent=c&&l?l:t,getSelection().removeAllRanges(),n(c&&l&&l!==t?l:null)},r=c=>c.stopPropagation();e.addEventListener("pointerdown",r),e.addEventListener("dblclick",r),e.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"&&(c.preventDefault(),o(!0)),c.key==="Escape"&&(c.preventDefault(),o(!1))}),e.addEventListener("paste",c=>{c.preventDefault(),document.execCommand("insertText",!1,(c.clipboardData?.getData("text/plain")||"").replace(/\s+/g," "))}),e.addEventListener("blur",()=>{o(!0),e.removeEventListener("pointerdown",r),e.removeEventListener("dblclick",r)},{once:!0})}function _i(e){const t=D.get(e),n=f.frames.find(a=>a.id===e);!t||!n||(t.renaming=!0,Xs(t.name,n.name,a=>{if(t.renaming=!1,a){const i=n.name;w("PATCH",`/__loop/api/frames/${e}`,{name:a}),G("Rename frame",()=>Rt(e,{name:i}),()=>Rt(e,{name:a}))}}))}function gl(e){try{const t=e.iframe.contentDocument;return!!t?.querySelector('meta[name="loop-placeholder"], meta[name="loop-empty"]')||!!t&&t.readyState==="complete"&&!t.body?.children.length&&/waiting for the agent/.test(t.body?.textContent||"")}catch{return!1}}const Pi=e=>f.comments.find(t=>t.frameId===e.id&&(t.status==="working"||t.status==="queued")&&!t.inBatch);function Us(e,t,n){const a=Pi(t),i=t.kind==="folder"&&gl(e),s=!!a&&i;e.el.classList.toggle("empty",i&&!a&&!!(()=>{try{return e.iframe.contentDocument?.querySelector('meta[name="loop-empty"]')}catch{return null}})()),s&&(e.fromEmpty=!0,B?.prompt&&B.frameId===t.id&&te()),a||(e.fromEmpty=!1);let o=e.el.querySelector(":scope > .frame-body > .making");if(!s){o&&!o.classList.contains("out")&&(o.classList.add("out"),setTimeout(()=>o.remove(),400));return}if(!o){o=document.createElement("div"),o.className="making";const r=t.source?`/__loop/api/site-icon?u=${encodeURIComponent(t.source)}`:null;o.innerHTML=`<div class="mk-mid"><span class="mk-icon">${r?`<img src="${r}" alt="" onerror="this.replaceWith(Object.assign(document.createElement('i'),{className:'mk-spark'}))">`:'<i class="mk-spark"></i>'}</span><span class="mk-step"></span>${t.source?`<span class="mk-from">${L(cs(t.source))}</span>`:""}</div>`,e.el.querySelector(".frame-body").appendChild(o)}$e(o.querySelector(".mk-step"),n?.step&&!/^(Working…|Reading your comment…|Your chat picked this up)$/.test(n.step)?n.step:a.status==="queued"?"Waiting to start":t.source?"Reading the design":"Designing the screen")}function yl(e,t){if(t.kind!=="folder")return;if(!e.fromEmpty||!Pi(t)){e.seen=null;return}let n;try{n=e.iframe.contentDocument}catch{return}if(!n?.body)return;e.seen||=new Set;const a=r=>{const c=[];for(let l=r;l&&l!==n.body;l=l.parentElement)c.unshift(l.tagName+[...l.parentElement?.children||[]].indexOf(l));return c.join("/")},i=[];for(const r of n.body.querySelectorAll("body > *, body > * > *, body > * > * > *")){if(/^(SCRIPT|STYLE|LINK|META)$/.test(r.tagName))continue;const c=a(r);e.seen.has(c)||(e.seen.add(c),i.push(r))}const s=i.filter(r=>!i.includes(r.parentElement)).slice(0,40);if(!s.length)return;const o=n.createElement("style");o.textContent="@keyframes loopIn{from{opacity:0;transform:translateY(6px)}}.loop-in{animation:loopIn .45s cubic-bezier(.2,.8,.2,1) both}",n.head?.appendChild(o),s.forEach((r,c)=>{r.classList.add("loop-in"),r.style.animationDelay=`${Math.min(c*70,1400)}ms`,setTimeout(()=>{r.classList.remove("loop-in"),r.style.animationDelay="",r.getAttribute("style")||r.removeAttribute("style"),r.getAttribute("class")||r.removeAttribute("class")},600+Math.min(c*70,1400))})}const qi={claude:'<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#D97757" d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z"/></svg>',codex:'<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>'};function bl(){return f.hostOnline===!1?"offline":f.agent.mode==="inbox"&&!f.chatListening?"away":"on"}function vl(){const e=m("#agent-pill"),t=Object.keys(f.live).length,n=f.agentBin==="codex"?"codex":"claude",a=f.comments.filter(C=>C.status==="queued").length,i=f.comments.filter(C=>C.status==="waiting").length,s=bl(),o=$()&&!X,r=f.agent.lastModel&&(n==="codex"?!/^claude/.test(f.agent.lastModel):/^claude/.test(f.agent.lastModel)),c=f.agentLabel||(n==="codex"?"Codex":"Claude Code"),l=e.querySelector(".agent-logo");l._r!==n&&(l._r=n,l.innerHTML=qi[n]);let d=s==="offline"?`${f.hostName||"Host"} is offline`:s==="away"?"Disconnected":t?`Working${t>1?` \xB7 ${t}`:""}`:a?`${a} queued`:f.agent.mode==="inbox"?"Connected":c;i&&$()&&!t&&(d=`${i} to review`),$e(m("#agent-label"),d),e.classList.toggle("busy",t>0),e.classList.toggle("away",s==="away"),e.classList.toggle("offline",s==="offline"),e.classList.toggle("say",s!=="on"||t>0||a>0||i>0&&$()),e._info={state:s,n:t,queued:a,waiting:i,who:c,runner:n,model:r?Zt(f.agent.lastModel):f.agent.chat?.model?Zt(f.agent.chat.model):null},delete e.dataset.tip;const u=s==="away"?`Your chat isn\u2019t listening. Comments run in the background meanwhile${t?` (${t} working)`:""}.`:s==="offline"?"Comments wait until the host is back":f.agent.mode==="inbox"?`Comments go to your chat \xB7 ${c}`:`${c} runs your comments${r?` \xB7 ${Zt(f.agent.lastModel)}`:""}`;e.classList.remove("inbox");{const C=f.agent.mode==="inbox"&&$()?f.chatContext:null,k=e.querySelector(".ctx-ring");if(k.toggleAttribute("hidden",!C),!C&&e._info&&delete e._info.ctx,C){const M=Math.max(0,Math.min(100,Math.round(C.used/C.window*100))),E=N=>N>=1e6?`${(N/1e6).toFixed(N%1e6?1:0)}M`:`${Math.round(N/1e3)}k`;k.querySelector(".cr-fill").style.strokeDasharray=`${M} 100`,e.classList.toggle("ctx-high",M>=80),e.classList.toggle("ctx-full",M>=95),e._info.ctx={pct:M,used:E(C.used),window:E(C.window)}}}const p=m("#reconnect-btn");p.hidden=!(s==="away"&&o),cc(s),Le&&!Le.hidden&&Ra(),document.querySelectorAll("#agent-menu .am-opt").forEach(C=>{C.classList.toggle("on",C.dataset.mode===f.agent.mode&&(!C.dataset.runner||C.dataset.runner===f.agentBin)),C.dataset.runner&&(C.hidden=f.runners&&!f.runners[C.dataset.runner]);const k=C.querySelector("[data-logo]");k&&!k.innerHTML&&(k.innerHTML=qi[k.dataset.logo])}),m("#agent-menu").hidden||Ra(),Ui(),wl();const h=m("#agent-allowed"),g=f.agent.allow||[],v=C=>C.startsWith("dir:")?`Files in ${C.slice(4)}`:/^Bash\((.*):\*\)$/.exec(C)?.[1]??C.replace(/^mcp__/,"").replace(/__/g," \xB7 "),T=g.length?`<button class="al-head" aria-expanded="${gn}"><span>Allowed on this canvas</span><span class="al-count">${g.length}</span><svg class="al-chev" viewBox="0 0 16 16" aria-hidden="true"><path d="M6 4l4 4-4 4"/></svg></button><div class="al-body"${gn?"":" hidden"}><div class="al-note">Reading files, copying them and making folders are always allowed.</div>${g.map(C=>`<div class="al-row"><code title="${L(C)}">${L(v(C))}</code><button data-disallow="${L(C)}" title="Stop allowing this">${Wn.x}</button></div>`).join("")}</div>`:"";h._h!==T&&(h._h=T,h.innerHTML=T,h.hidden=!g.length),m("#share-menu").hidden||Na()}function wl(){const e=m("#update-pill"),t=f.update;if(e.hidden=!t||!$()||!!X,e.hidden)return;const n=t.state==="updating"?'<span class="up-spin"></span>Updating\u2026':t.state==="queued"?"Updates when the agent finishes":t.state==="failed"?"Update failed \xB7 Retry":t.how==="next-start"?`Loop ${L(t.latest)} is ready next start`:`${A("up")}Update to ${L(t.latest)}`;e._h!==n&&(e._h=n,e.innerHTML=n),e.disabled=t.state==="updating"||t.state==="queued"||t.how==="next-start",e.classList.toggle("failed",t.state==="failed"),e.title=t.state==="failed"?`Couldn\u2019t update: ${t.error||"unknown error"}`:t.how==="next-start"?"Loop runs through npx here, so the new version is used the next time it starts":`Loop ${t.latest} is out (you have ${f.version}). Installs it and restarts Loop; your canvas stays exactly as it is.`}m("#update-pill").addEventListener("click",async()=>{try{await w("POST","/__loop/api/update")}catch(e){y(e.message)}});function Zs(e){return(e||"?").trim().split(/\s+/).map(t=>t[0]).join("").slice(0,2).toUpperCase()}function $a(){const e=[{name:U.name||"You",color:U.color},...ln.values()];m("#presence").innerHTML=e.length>1?e.slice(0,6).map((t,n)=>`<span class="avatar${n?"":" me"}" title="${L(n?t.name:`${t.name} (you) \xB7 click to change your name`)}">${As(t.name,t.color,"",t.avatar)}</span>`).join(""):""}function Gs(){const e=new Set;for(const t of ln.values()){e.add(t.id);let n=xi.querySelector(`[data-id="${CSS.escape(t.id)}"]`);n||(n=document.createElement("div"),n.className="cursor",n.dataset.id=t.id,n.innerHTML=`<div class="cursor-inner"><svg viewBox="0 0 18 18"><path d="M2 1.5l13 6.2-5.6 1.5-2.4 5.6z" fill="${L(t.color)}" stroke="#fff" stroke-width="1.4" stroke-linejoin="round"/></svg><span style="background:${L(t.color)}">${L(t.name)}</span></div>`,xi.appendChild(n)),n.style.transform=`translate(${t.x}px, ${t.y}px)`}xi.querySelectorAll(".cursor").forEach(t=>{e.has(t.dataset.id)||t.remove()})}let Qs=0;function xl(e,t){const n=Date.now();if(n-Qs<70||!f)return;Qs=n;const a=re(e,t);w("POST","/__loop/api/presence",{id:U.id,name:U.name||"Guest",color:U.color,avatar:U.avatar,x:a.x,y:a.y}).catch(()=>{})}addEventListener("beforeunload",()=>!X&&navigator.sendBeacon?.("/__loop/api/presence",new Blob([JSON.stringify({id:U.id,leave:!0})],{type:"application/json"})));function Di(e){if(e.length<4)return`M${e[0]} ${e[1]}l.01 0`;let t=`M${e[0]} ${e[1]}`;for(let n=2;n<e.length-2;n+=2)t+=`Q${e[n]} ${e[n+1]} ${(e[n]+e[n+2])/2} ${(e[n+1]+e[n+3])/2}`;return t+`L${e[e.length-2]} ${e[e.length-1]}`}const Vt=new Set;let dn=null;function Ii(e){const t=new Set(f.comments.find(n=>n.id===e)?.inkStrokes||[]);for(const n of Object.values(f.live||{})){const a=f.comments.find(i=>i.id===n.commentId);if(a&&(a.parentId||a.id)===e)for(const i of a.inkStrokes||[])t.add(i)}return[...t].filter(n=>f.strokes.some(a=>a.id===n))}function kl(){const e=new Set(B?.inkStrokes||[]);for(const t of Object.values(f.live||{}))for(const n of f.comments.find(a=>a.id===t.commentId)?.inkStrokes||[])e.add(n);for(const t of Object.values(f.live||{})){const n=f.comments.find(i=>i.id===t.commentId),a=n&&f.comments.find(i=>i.id===n.parentId);for(const i of a?.inkStrokes||[])e.add(i)}return e}function Js(e){if(e.fx==null||!e.frameId)return{dx:0,dy:0};const t=f.frames.find(a=>a.id===e.frameId);if(!t)return{dx:0,dy:0};const n=De(t);return{dx:n.x-e.fx,dy:n.y-e.fy}}const fn=e=>{const{dx:t,dy:n}=Js(e);return t||n?e.points.map((a,i)=>a+(i%2?n:t)):e.points};function eo(e){for(const t of f.strokes){if(e&&t.frameId!==e)continue;const{dx:n,dy:a}=Js(t),i=n||a?`translate(${n} ${a})`:"";kt.querySelectorAll(`path[data-id="${t.id}"], path[data-for="${t.id}"]`).forEach(s=>{(s.getAttribute("transform")||"")!==i&&(i?s.setAttribute("transform",i):s.removeAttribute("transform"))})}}function qt(){kt.querySelector("defs")||kt.insertAdjacentHTML("afterbegin",`<defs>
11
11
  <filter id="aura-blur" x="-60%" y="-60%" width="220%" height="220%"><feGaussianBlur stdDeviation="10"/></filter>
12
12
  <linearGradient id="aura-grad" x1="0" y1="0" x2="1" y2="0" spreadMethod="reflect">
13
13
  <stop offset="0" stop-color="#7c98ff"/><stop offset=".45" stop-color="#c58bff"/><stop offset=".55" stop-color="#ffffff"/><stop offset="1" stop-color="#7cd4ff"/>
14
14
  <animateTransform attributeName="gradientTransform" type="translate" from="-1 0" to="1 0" dur="2.4s" repeatCount="indefinite"/>
15
- </linearGradient></defs><g class="auras"></g>`);const e=new Set([...Dr()].filter(s=>!(F?.inkStrokes||[]).includes(s))),t=new Set,n=dt.querySelector("g.auras");n.querySelectorAll("path").forEach(s=>{t.has(s.dataset.for)||s.remove()});for(const s of u.strokes){if(!t.has(s.id)||n.querySelector(`path[data-for="${s.id}"]`))continue;const a=document.createElementNS("http://www.w3.org/2000/svg","path");a.dataset.for=s.id,a.setAttribute("d",us(s.points)),a.setAttribute("class","aura-stroke"),a.setAttribute("stroke","url(#aura-grad)"),a.setAttribute("filter","url(#aura-blur)"),n.appendChild(a)}const i=new Set(u.strokes.map(s=>s.id));dt.querySelectorAll("path[data-id]").forEach(s=>{i.has(s.dataset.id)||s.remove()});for(const s of u.strokes){let a=dt.querySelector(`path[data-id="${s.id}"]`);a||(a=document.createElementNS("http://www.w3.org/2000/svg","path"),a.dataset.id=s.id,a.setAttribute("d",us(s.points)),dt.appendChild(a)),a.setAttribute("stroke",s.color),a.setAttribute("stroke-width",s.width),a.classList.toggle("used",!!s.commentId),a.classList.toggle("working",e.has(s.id)),a.style.display=s.commentId&&!e.has(s.id)&&!Ft.has(s.commentId)&&nn!==s.commentId?"none":""}Ea()}function Cn(e,t){for(let n=u.frames.length-1;n>=0;n--){const i=u.frames[n];if(e>=i.x&&e<=i.x+i.w&&t>=i.y&&t<=i.y+i.h)return i}return null}function le(e){try{return H.get(e)?.iframe.contentDocument||null}catch{return null}}function tt(e,t,n){const i=H.get(e).iframe.getBoundingClientRect();return{lx:(t-i.left)/y.z,ly:(n-i.top)/y.z}}function Me(e,t,n){const i=le(e);if(!i)return null;try{return i.elementFromPoint(t,n)}catch{return null}}function kt(e){if(!e||!e.ownerDocument)return"";const t=e.ownerDocument,n=[];for(let i=e;i&&i.nodeType===1&&i!==t.documentElement;i=i.parentElement){if(i.id&&/^[A-Za-z][\w-]*$/.test(i.id)){n.unshift(`#${i.id}`);break}let s=i.tagName.toLowerCase();const a=i.parentElement?[...i.parentElement.children].filter(o=>o.tagName===i.tagName):[];if(a.length>1&&(s+=`:nth-of-type(${a.indexOf(i)+1})`),n.unshift(s),i.tagName==="BODY"||n.length>7)break}return n.join(" > ")}function Sa(e){const t=typeof e.className=="string"&&e.className.trim()?"."+e.className.trim().split(/\s+/)[0]:"";return e.tagName.toLowerCase()+t}function ms(e,t,n){const i=Me(e,t,n),s=le(e);let a=0,o=0;try{a=s.defaultView.scrollX,o=s.defaultView.scrollY}catch{}const r={x:t,y:n,sx:a,sy:o};if(i&&i!==s.documentElement){const l=i.getBoundingClientRect();Object.assign(r,{selector:kt(i),tag:i.tagName.toLowerCase(),label:Sa(i),text:(i.innerText||i.getAttribute?.("aria-label")||i.getAttribute?.("alt")||"").replace(/\s+/g," ").trim().slice(0,140),html:i.outerHTML.length>1500?i.outerHTML.slice(0,1500)+"\u2026":i.outerHTML,fx:l.width?(t-l.left)/l.width:0,fy:l.height?(n-l.top)/l.height:0})}return r}const ce="__canvas";function hs(e,t){const n=le(e);if(!n?.defaultView)return null;const i=n.defaultView,s=n.scrollingElement||n.documentElement;let a=i.scrollX,o=i.scrollY;const r=t.selector||t.container?.selector||t.elements?.[0]?.selector;try{for(let l=r&&n.querySelector(r)?.parentElement;l&&l!==s&&l!==n.documentElement;l=l.parentElement)a+=l.scrollLeft,o+=l.scrollTop}catch{}return{x:a,y:o}}function Mn(e,t){const n=e!==ce&&t&&hs(e,t);return n&&(t.sx=n.x,t.sy=n.y),t}function En(e,t){if(e===ce)return{x:t.wx,y:t.wy};if(t.scope==="frame"||t.scope==="point"||t.scope==="area"||t.scope==="elements"){if(t.scope==="frame")return{x:t.x,y:t.y};const s=hs(e,t)||{x:t.sx||0,y:t.sy||0};return{x:t.x-(s.x-(t.sx||0)),y:t.y-(s.y-(t.sy||0))}}const n=le(e);if(n&&t.selector)try{const s=n.querySelector(t.selector);if(s){const a=s.getBoundingClientRect();if(a.width||a.height)return{x:a.left+t.fx*a.width,y:a.top+t.fy*a.height}}}catch{}const i=hs(e,t)||{x:t.sx||0,y:t.sy||0};return{x:t.x-(i.x-(t.sx||0)),y:t.y-(i.y-(t.sy||0))}}function li(e,t,n,i="deep"){const{lx:s,ly:a}=tt(e,t,n),o=le(e),r=Pi(e,Me(e,s,a),i==="drill"?"level":i);if(!r||r===o?.documentElement){Y.hidden=!0;return}const l=H.get(e).iframe.getBoundingClientRect(),c=r.getBoundingClientRect(),f=y.z,d=Math.max(l.left,l.left+c.left*f),p=Math.max(l.top,l.top+c.top*f),h=Math.min(l.right,l.left+c.right*f),g=Math.min(l.bottom,l.top+c.bottom*f);Object.assign(Y.style,{left:`${d}px`,top:`${p}px`,width:`${Math.max(0,h-d)}px`,height:`${Math.max(0,g-p)}px`}),Y.dataset.tag=rt(r),Y.classList.toggle("sel",!!$?.els.includes(r));const v=[...r.children].filter(A=>!/^(SCRIPT|STYLE|BR)$/.test(A.tagName)).slice(0,30).map(A=>A.getBoundingClientRect()).filter(A=>A.width>3&&A.height>3),S=`${c.left},${c.top},${c.width},${c.height},${f},${v.length}`;Y._k!==S&&(Y._k=S,Y.innerHTML=v.map(A=>`<i style="left:${(A.left-c.left)*f-1.5}px;top:${(A.top-c.top)*f-1.5}px;width:${A.width*f}px;height:${A.height*f}px"></i>`).join("")),Y.hidden=!1}function Wt(e){return u.comments.filter(t=>t.id===e||t.parentId===e).sort((t,n)=>t.createdAt-n.createdAt)}function ci(e){const t=Wt(e).filter(n=>n.kind!=="note");return t.some(n=>n.status==="working")?"working":t[t.length-1]?.status||"done"}function Ta(e){return u.comments.filter(t=>t.frameId===e&&!t.parentId&&t.kind!=="create").sort((t,n)=>t.createdAt-n.createdAt)}const me=document.createElement("div");me.id="peek",me.className="pop",me.hidden=!0,document.body.appendChild(me);let he=null,di=null,fi=null,nt=null,an=null;const Aa="Start listening to the Loop canvas again: run `loop watch` with the Monitor tool and keep it running.",pt=(e,t)=>!!e&&De.x>=e.left-t&&De.x<=e.right+t&&De.y>=e.top-t&&De.y<=e.bottom+t,mt=e=>document.querySelector(`.pin[data-key="${e}"] .pin-dot`)?.getBoundingClientRect()||null;function Or(e,t){if(!t||matchMedia("(prefers-reduced-motion: reduce)").matches)return;const n=e.getBoundingClientRect();if(!n.width||!n.height)return;const i=(l,c)=>Math.max(0,Math.min(c,l)),s=i(t.left-n.left,n.width-24),a=i(t.top-n.top,n.height-24),o=i(n.right-t.right,n.width-s-24),r=i(n.bottom-t.bottom,n.height-a-24);e._growing?.cancel(),e._growing=e.animate([{clipPath:`inset(${a}px ${o}px ${r}px ${s}px round 14px)`,opacity:.7},{clipPath:"inset(0px 0px 0px 0px round 18px)",opacity:1}],{duration:190,easing:"cubic-bezier(.2, .8, .2, 1)"})}function Rr(e){clearTimeout(di),!(he===e||an===e)&&(document.querySelector(`.pin[data-key="${e}"]`)?.dataset.act||he&&pt(me.getBoundingClientRect(),0)||(di=setTimeout(()=>{W===e||ae||!u?.comments.some(t=>t.id===e)||!pt(mt(e),6)||W&&!$t||F&&!z.hidden||An(e,null,!0)},W?30:80)))}let $t=!1,Qe=null;function Nr(){an&&!pt(mt(an),4)&&(an=null),$t&&W&&(D.contains(document.activeElement)||!!D.querySelector(".thread-reply textarea")?.value.trim()||vi.length?($t=!1,clearTimeout(Qe),Qe=null):pt(D.getBoundingClientRect(),12)||pt(mt(W),8)?(clearTimeout(Qe),Qe=null):Qe||(Qe=setTimeout(()=>{Qe=null,$t&&J()},180))),he&&(pt(me.getBoundingClientRect(),10)||pt(fi,8)?(clearTimeout(nt),nt=null):nt||(nt=setTimeout(()=>{nt=null,Pe()},150)))}function Pe(){if(clearTimeout(di),clearTimeout(nt),nt=null,!he)return;pt(fi,4)&&(an=he);const e=u?.comments.find(t=>t.id===he);e&&Lt(e.frameId)?.querySelector(`.area[data-key="${he}"]`)?.classList.remove("hover"),he=null,me.hidden=!0,mi()}function _a(e){const t=Ta(e.frameId).findIndex(n=>n.id===e.id)+1;return t?`<span class="pin-n" title="Comment ${t}">${t}</span>`:""}function Br(){const e=u.comments.find(o=>o.id===he);if(!e||W===he)return Pe();const t=Wt(e.id),n=t[t.length-1],i=t.length-(n===e?1:2),s=[[e.id,ks(e,n!==e)]];i>0&&s.push(["__more",`<div class="pk-gap">${i} more ${i===1?"message":"messages"}</div>`]),n!==e&&s.push([n.id,ks(n)]),me.firstChild||(me.innerHTML='<div class="thread-body"></div><div class="pk-bar"></div>'),Pa(me.querySelector(".thread-body"),s);const a=`${_a(e)}<span class="pk-who">${L(e.author?.name||"You")} \xB7 ${jt(e.createdAt)}</span>
16
- <button class="t-btn" data-pk="open" title="Open and reply">${Fe.reply}</button>${k()?`<button class="t-btn" data-pk="resolve" title="${e.resolved?"Reopen":"Resolve"}">${e.resolved?Fe.reopen:Fe.resolve}</button>`:""}`;me._bar!==a&&(me._bar=a,me.querySelector(".pk-bar").innerHTML=a),qa(me),Fr()}function Fr(){if(!he)return;const e=u.comments.find(i=>i.id===he);if(!e?.anchor)return;const t=En(e.frameId,e.anchor),n=pi(e.frameId,t.x,t.y);Oa(me,n.x,n.y,!1,mt(he)),fi=mt(he)||fi,mi()}document.documentElement.addEventListener("pointerleave",()=>{he&&!nt&&(nt=setTimeout(()=>{nt=null,Pe()},150))}),me.addEventListener("pointerdown",e=>e.stopPropagation()),me.addEventListener("wheel",e=>e.stopPropagation()),me.addEventListener("click",async e=>{const t=he;if(!t)return;if(e.target.closest('[data-pk="resolve"]')){Pe();try{await w("POST",`/__loop/api/comments/${t}/resolve`)}catch(i){b(i.message)}return}if(e.target.closest("a"))return;const n=me.dataset.o;Pe(),An(t,n)});function Pa(e,t){const n=e._cache||=new Map,i=new Set(t.map(a=>a[0]));for(const a of[...e.children])i.has(a.dataset.mid)||(n.delete(a.dataset.mid),a.remove());let s=null;for(const[a,o]of t){let r=[...e.children].find(c=>c.dataset.mid===a);r||(r=document.createElement("div"),r.className="m",r.dataset.mid=a),n.get(a)!==o&&(n.set(a,o),r.innerHTML=o);const l=s?s.nextSibling:e.firstChild;l!==r&&e.insertBefore(r,l),s=r}}function qa(e){e.querySelectorAll("[data-step-for]").forEach(t=>{const n=u.comments.find(s=>s.id===t.dataset.stepFor),i=n&&u.live[n.frameId];Le(t,i?.commentId===n?.id&&i.step||"Working\u2026"),n&&Ka(n.id,e),i?.commentId===n?.id&&Ia(n.id,i.partial||"",e)}),e.querySelectorAll("[data-elapsed-from]").forEach(t=>Le(t,ai(+t.dataset.elapsedFrom)))}function Ia(e,t,n=document){n.querySelectorAll(`[data-partial-for="${e}"]`).forEach(i=>{if(i._src===t)return;i._src=t,i.hidden=!t,i.innerHTML=t?yi(t):"";const s=i.closest(".thread-body");s&&s.scrollHeight-s.scrollTop-s.clientHeight<80&&(s.scrollTop=s.scrollHeight)})}const Ha=new Map;function za(e){const t=u.live[e];return t?(t.partial||"").trim().split(`
17
- `)[0].replace(/[*_`#>]/g,"").trim()||t.step||"Working\u2026":""}function Wr(e){const t=u.live[e],n=ui(e);if(!t||!n)return;const i=u.comments.find(o=>o.id===t.commentId)?.parentId||t.commentId,s=n.querySelector(`.pin[data-key="${i}"] .pl`);if(!s)return;const a=za(e);s.textContent!==a&&(s.textContent=a,(t.partial||"").trim()||(s.classList.remove("tick"),s.offsetWidth,s.classList.add("tick")))}async function jr(e){const t=e.dataset.act,n=e.dataset.cid;if(!t||!n)return;if(t==="see")return An(e.dataset.key||n);delete e.dataset.act;const i=e.querySelector(".pl");i._h=null,i.textContent=t==="send"?"Sending\u2026":t==="allow"?"Allowed":"Starting\u2026";try{await w("POST",`/__loop/api/comments/${n}/${t}`,t==="allow"?{all:!0,i:u.comments.find(s=>s.id===n)?.blocked?.findIndex(s=>!s.allowed)}:void 0)}catch(s){b(s.message);const a=u.comments.find(o=>o.id===n)?.frameId;a&&ht(a)}}function Sn(){for(const e of u.frames)ht(e.id);ht(ce)}function ui(e){return e===ce?m("#canvas-pins"):H.get(e)?.pins}function Lt(e){return e===ce?m("#canvas-pins"):H.get(e)?.el.querySelector(".areas")}function ht(e){const t=ui(e);if(!t)return;const n={pins:t},i=Ta(e),s=i.map((d,p)=>({key:d.id,n:p+1,c:d})).filter(d=>!d.c.resolved||W===d.key);F?.frameId===e&&!F.prompt&&s.push({key:"__draft",n:i.length+1,draft:!0});const a=new Set(s.map(d=>d.key));n.pins.querySelectorAll(".pin").forEach(d=>{a.has(d.dataset.key)||d.remove()});for(const d of s){let p=n.pins.querySelector(`.pin[data-key="${d.key}"]`);p||(p=document.createElement("div"),p.className="pin",p.dataset.key=d.key,p.innerHTML='<div class="pin-dot"><b class="pn"></b><svg class="pw" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="5.5"/></svg><span class="pl"></span></div>',p.addEventListener("pointerdown",P=>P.stopPropagation()),d.draft||p.addEventListener("click",P=>{if(P.stopPropagation(),p.dataset.act&&P.target.closest(".pin-act"))return jr(p);if(p.classList.contains("making")&&P.target.closest(".pl")){const ee=u.comments.find(R=>R.id===d.key);if(ee?.optionSection)return Xi.delete(ee.optionSection),Jo(ee.optionSection)}An(d.key)}),p.addEventListener("pointerenter",()=>{Lt(e)?.querySelector(`.area[data-key="${d.key}"]`)?.classList.add("hover"),d.draft||Rr(d.key)}),p.addEventListener("pointerleave",()=>{he!==d.key&&(Lt(e)?.querySelector(`.area[data-key="${d.key}"]`)?.classList.remove("hover"),clearTimeout(di))}),n.pins.appendChild(p));const h=p.querySelector(".pn"),g=!!d.c&&(d.c.author?.guest||!!d.c.author?.name&&d.c.author.name!==V.name);let v=d.draft?"draft":ci(d.key);!d.draft&&v==="done"&&W===d.key&&ca(d.key);const S=!d.draft&&v==="done"&&yr(d.key);S?h._ck!==1&&(h._ck=1,h.innerHTML=wr):(h._ck&&(h._ck=0,h.textContent=""),Le(h,String(d.n)));const A=!d.draft&&u.frames.some(P=>P.building&&P.optionOf?.cid===d.key)&&!(v==="queued"&&u.agent.mode==="inbox"&&!u.chatListening);A&&v!=="working"&&(v="working");const x=Ha.get(d.key);Ha.set(d.key,v),x==="working"&&v!=="working"&&v!=="queued"&&(p._ended=v==="done"?S?null:"Done":v==="error"?"Failed":"Stopped",clearTimeout(p._endT),p._endT=setTimeout(()=>{p._ended=null,u&&ht(e)},2400));const M=p.querySelector(".pl"),C=!d.draft&&Wt(d.key).filter(P=>P.kind!=="note").pop(),B=!d.draft&&k()&&!X&&C&&(v==="queued"&&!C.local&&!C.background&&u.agent.mode==="inbox"&&!u.chatListening?u.chatHistory?{act:"background",say:"Chat isn\u2019t listening",btn:"Carry on here",tip:"The chat this was sent to isn\u2019t listening. Carry on in the background from a copy of that chat, with everything it knows. It also starts by itself in a moment."}:{act:"background",say:"Chat isn\u2019t listening",btn:"Run in new chat",tip:"The chat this was sent to isn\u2019t listening. Run it in a new session instead (without that chat\u2019s history). It also starts by itself in a moment."}:v==="waiting"?{act:"send",say:"Waiting for you",btn:"Send",tip:"Send this comment to the agent"}:(v==="done"||v==="error")&&xs(C).length?nl(C):null);if(B){p.dataset.act=B.act,p.dataset.cid=C.id;const P=`<span>${L(B.say)}</span><button class="pin-act" title="${L(B.tip)}">${L(B.btn)}${B.act==="background"?`<kbd>${lt==="metaKey"?"\u2318":"Ctrl"}\u21B5</kbd>`:""}</button>`;M._h!==P&&(M._h=P,M.innerHTML=P)}else p.dataset.act&&(delete p.dataset.act,M._h=null,M.textContent="");if(v==="working"){const P=u.live[e],ee=P&&(u.comments.find(R=>R.id===P.commentId)?.parentId||P.commentId)===d.key;Le(M,A?"Making options \u2192":ee?za(e):"Working\u2026")}else S&&!B?Le(M,"Done"):p._ended&&Le(M,p._ended);p.className=`pin ${v}${d.c?.resolved?" resolved":""}${W===d.key||d.draft?" active":""}${v==="working"?" talking":B?" talking needs":S?" talking done-new":p._ended?" talking ended":""}${p.classList.contains("carded")?" carded":""}${p.classList.contains("ping")?" ping":""}${p.classList.contains("low")?" low":""}${g?" theirs":""}${A?" making":""}`}const o=u.live[e]?.commentId,r=o&&(u.comments.find(d=>d.id===o)?.parentId||o),l=s.filter(d=>d.draft?F?.area:d.c?.anchor?.scope==="area"||d.c?.anchor?.area||d.key===r&&(d.c?.anchor?.scope==="elements"||d.c?.anchor?.scope==="frame"||ps(d.key).length)),c=new Set(l.map(d=>d.key)),f=Lt(e);f.querySelectorAll(".area:not(.picking)").forEach(d=>{c.has(d.dataset.key)||d.remove()});for(const d of l){let p=f.querySelector(`.area[data-key="${d.key}"]`);p||(p=document.createElement("div"),p.dataset.key=d.key,f.prepend(p));const h=!d.draft&&d.key!==r&&ci(d.key)==="queued";p.className=`area${d.draft?" draft show":""}${W===d.key?" show":""}${d.key===r?" show working":""}${h?" show queued":""}${d.c?.anchor?.scope==="frame"?" whole":""}${d.key===r&&ps(d.key).length&&d.c?.anchor?.scope!=="area"&&!d.c?.anchor?.area?" inkbox":""}`}it(e),l.some(d=>d.key===r)&&br(),Ln()}function it(e){const t=ui(e);!t||!u||($?.frameId===e&&Ae(),Lt(e)?.querySelectorAll(".area[data-key]").forEach(n=>{const i=n.dataset.key==="__draft"?F?.anchor:u.comments.find(l=>l.id===n.dataset.key)?.anchor;if(!i)return;if(i.scope==="frame"){const l=u.frames.find(c=>c.id===e);if(!l)return;Object.assign(n.style,{left:"0px",top:"0px",width:`${l.w}px`,height:`${l.h}px`});return}if(n.classList.contains("inkbox")){const l=ps(n.dataset.key),c=u.frames.find(M=>M.id===e),f=c&&Oe(c),d=u.strokes.filter(M=>l.includes(M.id)).flatMap(M=>sn(M));if(!f||d.length<2){n.style.width="0";return}const p=d.filter((M,C)=>C%2===0).map(M=>M-f.x),h=d.filter((M,C)=>C%2).map(M=>M-f.y),g=12,v=Math.max(0,Math.min(...p)-g),S=Math.max(0,Math.min(...h)-g),A=Math.min(f.w,Math.max(...p)+g),x=Math.min(f.h,Math.max(...h)+g);Object.assign(n.style,{left:`${v}px`,top:`${S}px`,width:`${Math.max(0,A-v)}px`,height:`${Math.max(0,x-S)}px`});return}if(i.scope==="elements"){const l=le(e),c=(i.elements||[]).map(g=>{try{return l?.querySelector(g.selector)?.getBoundingClientRect()}catch{return null}}).filter(g=>g&&(g.width||g.height));if(!c.length){n.style.width="0";return}const f=Math.min(...c.map(g=>g.left)),d=Math.min(...c.map(g=>g.top)),p=Math.max(...c.map(g=>g.right)),h=Math.max(...c.map(g=>g.bottom));Object.assign(n.style,{left:`${f}px`,top:`${d}px`,width:`${p-f}px`,height:`${h-d}px`});return}const{x:s,y:a}=En(e,i),o=i.area?i.area.w:i.w,r=i.area?i.area.h:i.h;Object.assign(n.style,{left:`${s}px`,top:`${a}px`,width:`${o}px`,height:`${r}px`})}),t.querySelectorAll(".pin").forEach(n=>{const i=n.dataset.key==="__draft"?F?.anchor:u.comments.find(r=>r.id===n.dataset.key)?.anchor;if(!i){n.hidden=!0;return}const{x:s,y:a}=En(e,i);n.style.left=`${s}px`,n.style.top=`${a}px`;const o=u.frames.find(r=>r.id===e);n.hidden=!!o&&(s<-4||a<-4||s>o.w+4||a>o.h+4),n.classList.toggle("low",e!==ce&&a*y.z<34*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1))}),(F?.frameId===e||W&&u.comments.find(n=>n.id===W)?.frameId===e)&&Ce())}function pi(e,t,n){if(e===ce)return{x:y.x+t*y.z,y:y.y+n*y.z};const i=Oe(u.frames.find(s=>s.id===e));return{x:y.x+(i.x+t)*y.z,y:y.y+(i.y+n)*y.z}}function Da(e,t,n,i){const s=e.offsetWidth||340,a=e.offsetHeight||140,o=28*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1);let r=i?t+o+10:t+18,l=i?Math.min(i.top,n)-4:n-18;r+s>innerWidth-12&&(r=t-s-10),r=Math.max(12,Math.min(r,innerWidth-s-12)),l=Math.max(60,Math.min(l,innerHeight-a-76)),e.style.left=`${r}px`,e.style.top=`${l}px`}let Ct=28;function Oa(e,t,n,i,s){Ct=28*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1),s&&s.height>4&&(t=s.left,n=s.bottom,Ct=s.height),i&&(e.style.maxHeight="");const a=e.offsetWidth||340;let o=e.offsetHeight||140;const r=n-56,l=innerHeight-12-(n-Ct),c=innerWidth-12-t,f=t+Ct-12;let d=i&&e._side;d&&(d[0]==="b"?o>r&&l>r:o>l&&r>l)&&(d=(d[0]==="b"?"t":"b")+d[1]);const p=i?o:Math.max(o,380);if(d||(d=(p<=r||r>=l?"b":"t")+(a<=c||c>=f?"l":"r")),i){e._side=d;const A=d[0]==="b"?r:l;o>A&&(e.style.maxHeight=`${Math.max(180,Math.floor(A))}px`,o=e.offsetHeight)}const h=d[1]==="l"?t:t+Ct-a,g=d[0]==="b"?n-o:n-Ct,v=Math.max(12,Math.min(h,innerWidth-a-12)),S=Math.max(56,Math.min(g,innerHeight-o-12));e.style.left=`${Math.round(v)}px`,e.style.top=`${Math.round(S)}px`,e.dataset.o=d,e.style.transformOrigin=`${Math.max(0,Math.min(a,t+Ct/2-v))}px ${Math.max(0,Math.min(o,n-Ct/2-S))}px`,e.classList.toggle("at-pin",d==="bl"&&v===h&&S===g),e._covers=v===h&&S===g}function mi(){const e=new Set;W&&!D.hidden&&!D.classList.contains("docked")&&D._covers&&e.add(W),he&&!me.hidden&&me._covers&&e.add(he),document.querySelectorAll(".pin").forEach(t=>t.classList.toggle("carded",e.has(t.dataset.key)))}function Ce(){if(u){if(It(),ko(),F?.prompt&&!z.hidden){const e=Oe(u.frames.find(t=>t.id===F.frameId));if(e){const t=ys(e),n=y.z,i=e.w*(1-2*t.lx)*n,s=Math.min(44,t.fs*n),a=H.get(e.id)?.el.querySelector(".frame-body"),o=!!a;if(z.classList.toggle("onpage",o),o)z.dataset.on=t.on,z.parentElement!==a&&(vs(a),z.style.left=z.style.top=z.style.width=""),(z._pz!==n||z._pw!==e.w)&&(z._pz=n,z._pw=e.w,gt(U));else{vs(document.body),z._pz=z._pw=null;const r=z.offsetWidth||380,l=z.offsetHeight||200,c=y.y+(e.y+e.h/2)*n;Da(z,y.x+(e.x+e.w)*n,c-l/2+18)}}}else if(F&&!z.hidden){const e=En(F.frameId,F.anchor),t=pi(F.frameId,e.x,e.y);Da(z,t.x,t.y,mt("__draft"))}if(W&&!D.hidden&&!D.classList.contains("docked")){const e=u.comments.find(t=>t.id===W);if(e?.anchor){const t=En(e.frameId,e.anchor),n=pi(e.frameId,t.x,t.y);Oa(D,n.x,n.y,!0,mt(W)),D._grow&&(D._grow=!1,Or(D,mt(W)))}}if(mi(),gn(),Ne){const e=pi(Ne.frameId,Ne.lx,Ne.ly),t=m("#ink-chip");t.style.left=`${e.x+10}px`,t.style.top=`${e.y+10}px`}}}function gs(e){return u.strokes.filter(t=>t.frameId===e&&!t.commentId&&oa.has(t.id))}function Mt(e,t,n,i,s){qe&&qn(!0),J(),Tn(),z.classList.remove("prompt"),bs();const a=e===ce?null:s?ms(e,s.x+s.w/2,s.y+s.h/2):ms(e,t,n),o=gs(e);F={frameId:e,picked:a,lx:t,ly:n,area:s||null,inkStrokes:o.map(c=>c.id)},Xr(e===ce?"canvas":s?"area":"point");const r=m("#composer-area");r.classList.remove("chip-frame"),r.hidden=!s,s&&(r.textContent=e===ce?`Area \xB7 ${F.anchor.near.length||"no"} frame${F.anchor.near.length===1?"":"s"}`:`Area \xB7 ${F.anchor.elements.length} element${F.anchor.elements.length===1?"":"s"}`);const l=m("#composer-ink");l.hidden=!o.length,l.innerHTML=`${Ga}<span>${o.length} mark${o.length===1?"":"s"}</span>`,U.placeholder=k()?"Ask for a change":"Add a comment",In.length=0,z.hidden=!1,U.value="",gt(U),Ss.paint(),ht(e),Ce(),xt(),setTimeout(()=>U.focus({preventScroll:!0}),0),ws(e)}function Ra(e,t){return u.frames.map(n=>({f:n,d:Math.hypot(Math.max(n.x-e,0,e-n.x-n.w),Math.max(n.y-t,0,t-n.y-n.h))})).sort((n,i)=>n.d-i.d).slice(0,2).filter(n=>n.d<1200).map(n=>n.f.name)}function Yr(e){const t=u.frames.filter(n=>n.x<e.x+e.w&&n.x+n.w>e.x&&n.y<e.y+e.h&&n.y+n.h>e.y).map(n=>n.name);return t.length?t:Ra(e.x+e.w/2,e.y+e.h/2)}function Kr(e,t){const n=le(e);if(!n?.body)return[];const i=Math.max(12,Math.min(t.w,t.h)*.08),s=t.x-i,a=t.y-i,o=t.x+t.w+i,r=t.y+t.h+i,l=[];for(const d of n.body.querySelectorAll("*")){if(l.length>600)break;const p=d.getBoundingClientRect();!p.width||!p.height||["SCRIPT","STYLE","LINK","META"].includes(d.tagName)||p.left>=s&&p.top>=a&&p.right<=o&&p.bottom<=r&&l.push(d)}const c=new Set(l);let f=l.filter(d=>{for(let p=d.parentElement;p;p=p.parentElement)if(c.has(p))return!1;return!0});if(!f.length){const d=Me(e,t.x+t.w/2,t.y+t.h/2);d&&d!==n.documentElement&&(f=[d])}return f.slice(0,14).map(d=>({selector:kt(d),tag:d.tagName.toLowerCase(),text:(d.innerText||d.getAttribute("aria-label")||d.getAttribute("alt")||"").replace(/\s+/g," ").trim().slice(0,80)}))}function Vr(e,t){const n=le(e);let i=Me(e,t.x+t.w/2,t.y+t.h/2);for(;i&&i!==n?.body;){const s=i.getBoundingClientRect();if(s.left<=t.x+2&&s.top<=t.y+2&&s.right>=t.x+t.w-2&&s.bottom>=t.y+t.h-2)break;i=i.parentElement}return i&&i!==n?.documentElement?{selector:kt(i),tag:i.tagName.toLowerCase(),text:(i.innerText||"").replace(/\s+/g," ").trim().slice(0,80)}:null}function Xr(e){const t=F;if(!t)return;const n=u.frames.find(i=>i.id===t.frameId);t.scope=e,e==="canvas"&&t.area?t.anchor={scope:e,wx:t.area.x,wy:t.area.y,area:{w:t.area.w,h:t.area.h},near:Yr(t.area)}:e==="canvas"?t.anchor={scope:e,wx:t.lx,wy:t.ly,near:Ra(t.lx,t.ly)}:e==="area"?t.anchor={scope:e,x:t.area.x,y:t.area.y,w:t.area.w,h:t.area.h,sx:t.picked?.sx||0,sy:t.picked?.sy||0,elements:Kr(t.frameId,t.area),container:Vr(t.frameId,t.area)}:t.anchor={...t.picked||{},scope:"point",x:t.lx,y:t.ly,fx:void 0,fy:void 0},Mn(t.frameId,t.anchor),ht(t.frameId),Ce()}function ys(e){const t=e.w<=480;let n="light";if(e.fill==="none")n="canvas";else if(/^#[0-9a-f]{6}$/i.test(e.fill||"")){const i=parseInt(e.fill.slice(1),16);.299*(i>>16)+.587*(i>>8&255)+.114*(i&255)<140&&(n="dark")}return{fs:Math.max(e.w*.037,Math.min(30,e.w*.077)),lx:t?.09:.11,ty:t?.15:.27,on:n,what:e.w<=1024?"screen":"page"}}function vs(e){if(z.parentElement===e)return;const t=document.activeElement===U;e.appendChild(z),t&&U.focus({preventScroll:!0})}function bs(){z.classList.remove("onpage"),vs(document.body),z._pz=z._pw=null,document.querySelectorAll(".frame.prompting").forEach(e=>e.classList.remove("prompting"))}const Ur={Mobile:["Login","Onboarding","Home feed","Profile","Settings","Checkout"],Tablet:["Dashboard","Reader","Calendar","Settings","Kanban board"],Desktop:["Landing page","Dashboard","Pricing","Sign up","Settings","Blog post"]};function hi(e){const t=u?.frames.find(i=>i.id===e);if(!t)return;J(),Tn(),bs();const n=t.w<=480?"Mobile":t.w<=1024?"Tablet":"Desktop";F={frameId:e,picked:null,lx:24,ly:24,area:null,inkStrokes:[],prompt:!0,scope:"frame",anchor:{scope:"frame",x:24,y:24}},z.classList.add("prompt"),H.get(e)?.el.classList.add("prompting"),m("#prompt-title").textContent=`What should \u201C${t.name}\u201D be?`,m("#prompt-ideas").innerHTML=Ur[n].map(i=>`<button>${L(i)}</button>`).join(""),m("#composer-area").hidden=!0,m("#composer-ink").hidden=!0,U.placeholder=`Describe this ${ys(t).what}`,In.length=0,z.hidden=!1,U.value="",gt(U),Ss.paint(),Ce(),setTimeout(()=>U.focus({preventScroll:!0}),0),ws(e)}m("#prompt-ideas").addEventListener("click",e=>{const t=e.target.closest("button");t&&(U.value=`${t.textContent} `,gt(U),Ss.paint(),U.focus(),U.setSelectionRange(U.value.length,U.value.length))});function ne(){z.classList.contains("soft")&&(z.querySelector(".hint").innerHTML="<kbd>\u21B5</kbd> send \xB7 <kbd>\u21E7\u21B5</kbd> new line \xB7 <kbd>esc</kbd>"),z.classList.remove("prompt","soft"),bs(),Fa=null,to(),F?.deep&&Ye(),document.querySelectorAll(".frame.whole").forEach(t=>t.classList.remove("whole"));const e=F?.frameId;F=null,z.hidden=!0,e&&ht(e),u&&xt()}function gt(e){e.style.height="auto",e.style.height=`${Math.min(e===U&&z.classList.contains("onpage")?innerHeight*.45/y.z:180,e.scrollHeight)}px`}U.addEventListener("input",()=>gt(U)),U.addEventListener("keydown",e=>{if(e.stopPropagation(),e.key==="Enter"&&!e.shiftKey&&!e.isComposing){if(e.preventDefault(),F?.deep&&!U.value.trim()&&!In.length&&$?.els.length===1&&un($.els[0],!0)&&k()){const{frameId:t,els:n}=$;ne(),pn(t,n[0]);return}Na()}e.key==="Escape"&&ne()});async function Na(){const e=In.splice(0),t=U.value.trim()||(e.length?"See the attached reference.":"");if(!t||!F)return;const n=F;ne(),we("select");const i=u.strokes.filter(o=>n.inkStrokes.includes(o.id)),s={id:Jn(),frameId:n.frameId,text:t,anchor:n.anchor,author:{name:V.name,color:V.color},inkStrokes:n.inkStrokes,attachments:e};i.length&&n.frameId!==ce&&Object.assign(s,Zr(n.frameId,i));const a=gi(s);try{const o=await w("POST","/__loop/api/comments",s);o?.id&&o.id!==s.id&&a(),k()||b("Comment added \u2014 the host will send it to the agent")}catch(o){a(),b(o.message)}}function gi(e){if(X)return()=>{};const t={id:e.id,frameId:e.frameId,parentId:e.parentId||null,text:e.text,anchor:e.anchor||u.comments.find(n=>n.id===e.parentId)?.anchor||null,author:{...e.author,guest:!k()},inkStrokes:e.inkStrokes||[],status:k()?"queued":"waiting",reply:null,createdAt:Date.now(),local:!0,...e.attachments?.length?{attachments:e.attachments.map(n=>({name:n.name,type:n.type,url:n.data}))}:{}};u.comments.push(t);for(const n of u.strokes)t.inkStrokes.includes(n.id)&&(n.commentId=t.id);return ii(),()=>{u.comments=u.comments.filter(n=>n!==t),ii()}}const Ba=new Map;function ws(e){!u||X||!k()||!e||Date.now()-(Ba.get(e)||0)<6e4||(Ba.set(e,Date.now()),w("POST",`/__loop/api/frames/${e}/warm`).catch(()=>{}))}function Zr(e,t){const n=u.frames.find(c=>c.id===e),i=le(e),s=new Map;for(const c of t){const f=c.points.length/2,d=Math.max(1,Math.floor(f/14));for(let p=0;p<f;p+=d){const h=c.points[p*2]-(c.fx??n.x),g=c.points[p*2+1]-(c.fy??n.y),v=Me(e,h,g);if(!v||v===i?.documentElement||v===i?.body)continue;const S=kt(v);s.has(S)||s.set(S,{selector:S,tag:v.tagName.toLowerCase(),text:(v.innerText||"").replace(/\s+/g," ").trim().slice(0,60),el:v})}}const a=[...s.values()].slice(0,10),o=Math.min(1,1280/Math.max(n.w,n.h)),r=document.createElement("canvas");r.width=Math.round(n.w*o),r.height=Math.round(n.h*o);const l=r.getContext("2d");l.scale(o,o),l.fillStyle="#fff",l.fillRect(0,0,n.w,n.h),l.strokeStyle="#C8C8CE",l.lineWidth=2,l.strokeRect(1,1,n.w-2,n.h-2),l.font="14px ui-monospace, Menlo, monospace";for(const c of a)try{const f=c.el.getBoundingClientRect();l.strokeStyle="#2F5BFF",l.setLineDash([6,4]),l.lineWidth=1.5,l.strokeRect(f.left,f.top,f.width,f.height),l.setLineDash([]),l.fillStyle="#2F5BFF",l.fillText(c.tag+(c.text?` "${c.text.slice(0,30)}"`:""),f.left+4,Math.max(14,f.top-4))}catch{}l.strokeStyle=as,l.lineWidth=4,l.lineCap="round",l.lineJoin="round";for(const c of t){l.beginPath();for(let f=0;f<c.points.length;f+=2){const d=c.points[f]-(c.fx??n.x),p=c.points[f+1]-(c.fy??n.y);f?l.lineTo(d,p):l.moveTo(d,p)}l.stroke()}return{ink:a.map(({el:c,...f})=>f),annotationPng:r.toDataURL("image/png")}}function jc(e,t,n){Ne={frameId:e,lx:t,ly:n},m("#ink-chip").hidden=!1,Ce()}function Tn(){Ne=null,m("#ink-chip").hidden=!0}let Fa=null;function Gr(e,t,n){if(!(!z.hidden&&U.value.trim())){if(e){const i=u.frames.find(c=>c.id===e),s=gs(e),a=s.flatMap(c=>sn(c).filter((f,d)=>d%2===0)),o=s.flatMap(c=>sn(c).filter((f,d)=>d%2===1)),r=(a.length?(Math.min(...a)+Math.max(...a))/2:t[t.length-2])-i.x,l=(o.length?(Math.min(...o)+Math.max(...o))/2:t[t.length-1])-i.y;Mt(e,r,l)}else Mt(ce,t[t.length-2],t[t.length-1],"canvas");F&&(F.soft=!0,z.classList.add("soft"),U.placeholder="What should change here?",z.querySelector(".hint").innerHTML="<kbd>\u21B5</kbd> send \xB7 <kbd>esc</kbd> skip",Fa={x:n.clientX,y:n.clientY,t:Date.now()})}}addEventListener("pointerdown",e=>{!F?.soft||z.hidden||z.contains(e.target)||U.value.trim()||j==="pen"&&e.target.closest("#viewport")||ne()},!0),U.addEventListener("input",()=>{F?.soft&&U.value.trim()&&(F.soft=!1,z.classList.remove("soft"))}),m("#ink-chip button").addEventListener("click",()=>{if(!Ne)return;const e=gs(Ne.frameId),t=u.frames.find(o=>o.id===Ne.frameId),n=e.flatMap(o=>sn(o).filter((r,l)=>l%2===0)),i=e.flatMap(o=>sn(o).filter((r,l)=>l%2===1)),s=n.length?(Math.min(...n)+Math.max(...n))/2-t.x:Ne.lx,a=i.length?(Math.min(...i)+Math.max(...i))/2-t.y:Ne.ly;Mt(Ne.frameId,s,a)});function An(e,t,n){qe&&qn(!0),clearTimeout(Qe),Qe=null,$t=!!n,e!==W&&(st=!1),ne(),Tn(),e!==W&&(vi.length=0),Pe(),e!==W&&(D.dataset.tid="",D._side=t||null,D.classList.remove("in","grow"),D.offsetWidth,D.classList.add(t?"grow":"in"),D._grow=!t),W=e,D.hidden=!1;{const i=u.comments.find(s=>s.id===e);ca(e)&&i&&ht(i.frameId)}D.classList.toggle("docked",st),st&&(D.style.left=D.style.top=D.style.maxHeight=""),bi(),Sn(),Ce()}function J(){W&&(to(),(Ft.size||nn)&&(Ft.clear(),nn=null,xt()),pt(mt(W),4)&&(an=W),clearTimeout(Qe),Qe=null,$t=!1,st=!1,W=null,D.hidden=!0,D.dataset.tid="",Sn(),mi())}const jt=e=>{const t=(Date.now()-e)/1e3;return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:new Date(e).toLocaleDateString()};function _n(e){if(!e)return"";const t=/claude-([a-z]+)-(\d+)(?:-(\d+))?/i.exec(e);if(t)return`${t[1][0].toUpperCase()}${t[1].slice(1)} ${t[2]}${t[3]&&t[3].length<=2?"."+t[3]:""}`;const n=/^gpt-([\d.]+)(?:-([a-z]+))?/i.exec(e);return n?`GPT-${n[1]}${n[2]?" "+n[2][0].toUpperCase()+n[2].slice(1):""}`:e}function Yc(e){const t=[];if(e.model&&t.push(_n(e.model)),e.startedAt&&e.finishedAt){const n=Math.round((e.finishedAt-e.startedAt)/1e3);t.push(n<60?`${n}s`:`${Math.floor(n/60)}m ${n%60}s`)}return t.length?`<div class="a-meta">${L(t.join(" \xB7 "))}</div>`:""}const Kc=T("check","s"),Qr={claude:'<svg class="lg claude" viewBox="0 0 24 24"><path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z"/></svg>',codex:'<svg class="lg" viewBox="0 0 24 24"><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>',loop:'<svg class="lg ring" viewBox="0 0 24 24"><circle cx="12" cy="12" r="6.5"/></svg>'};function Jr(e){const t=String(e?.model||"").toLowerCase();return/claude|opus|sonnet|haiku|fable|mythos/.test(t)?"claude":/gpt|codex|^o\d/.test(t)||u?.agentBin==="codex"?"codex":u?.agentBin==="claude"?"claude":"loop"}const el={claude:"Claude",codex:"Codex",loop:"Agent"},Wa=e=>{const t=Jr(e);return`<span class="m-mark" title="${el[t]}">${Qr[t]}</span>`};function Vc(e){if(!(e.startedAt&&e.finishedAt))return"";const t=Math.round((e.finishedAt-e.startedAt)/1e3);return`<span title="${L(e.model?_n(e.model):"")}">Worked ${t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`}</span>`}const Pn={undo:T("undo"),before:T("before"),redo:T("redo"),copy:T("copy"),check:T("check"),stop:T("stop"),send:T("up"),retry:T("retry"),steer:T("steer"),bg:T("play"),x:T("x")},Be=(e,t,n,i,s="")=>`<button class="a-btn${i?" lbl":""}${s?" "+s:""}" ${t} title="${L(n)}" aria-label="${L(n)}">${Pn[e]}${i?`<span>${L(i)}</span>`:""}</button>`;function tl(e){const t=k(),n=(s,a,o,r)=>`<div class="m-agent ${s}">${Wa(e)}<div class="m-body">${a}${o?`<div class="m-acts${r?" show":""}">${o}</div>`:""}</div></div>`,i=`data-id="${e.id}"`;switch(e.status){case"waiting":return n("quiet",'<div class="m-text">Waiting for the host to send this to the agent.</div>',t?Be("send",`data-act="send" ${i}`,"Send to the agent","Send","primary"):"",!0);case"queued":{if(e.local)return n("quiet",'<div class="m-work"><span class="a-text">Sending\u2026</span></div>',"");const s=e.parentId||e.id,a=t&&Wt(s).some(c=>c.status==="working"),o=u.agent.mode==="inbox"&&!e.background,r=o&&!u.chatListening,l=a?"Queued \xB7 runs after the current change":r?u.chatHistory?"Your chat isn\u2019t listening, so this carries on in the background in a moment, with what that chat knows.":"Your chat isn\u2019t listening, so this starts in a new session in a moment.":o?"Sent to your chat":"Queued";return n("quiet",`<div class="m-work"><span class="a-text">${l}</span></div>`,t?`${a?Be("steer",`data-act="steer" ${i}`,"Steer: stop the current run and include this message in it","Steer","primary"):""}${r?Be("bg",`data-act="background" ${i}`,u.chatHistory?"Carry on now in the background, from a copy of your chat":"Run it now in the background, without your chat\u2019s context","Run now"):""}${Be("x",`data-act="cancel" ${i}`,"Cancel")}`:"",!0)}case"working":return n("",`<ol class="m-steps" data-steps-for="${e.id}"></ol><div class="m-work"><span class="a-text" data-step-for="${e.id}"></span><span class="m-time" data-elapsed-from="${u.live[e.frameId]?.startedAt||e.startedAt||e.createdAt}"></span>${t?Be("stop",`data-act="cancel" ${i}`,"Stop"):""}</div><div class="m-text md m-stream" data-partial-for="${e.id}" hidden></div>`,"");case"done":return n("",`${al(e)}<div class="m-text md">${e.undone?"Reverted.":yi(e.reply||"Done.")}</div>${rl(e)}${ja(e)}`,`${e.snapshot&&!X&&u.frames.find(s=>s.id===e.frameId)?.kind==="folder"?Be("before",`data-act="before" ${i}`,"See the frame before this change"):""}${t&&e.snapshot&&!e.undone?Be("undo",`data-act="undo" ${i}`,"Undo this change"):""}${t&&e.undone&&e.redoSnap?Be("redo",`data-act="redo" ${i}`,"Redo this change"):""}${Be("copy",`data-copy="${e.id}"`,"Copy the reply")}<time>${jt(e.finishedAt||e.createdAt)}</time>`);case"error":return n("error",`<div class="m-text">${L(e.reply||"Something went wrong.")}</div>${ja(e)}`,t?Be("retry",`data-act="send" ${i}`,"Try again","Retry","primary"):"",!0);case"interrupted":return n("quiet",'<div class="m-text">Interrupted \xB7 continued below</div>',"");case"canceled":return n("quiet",'<div class="m-text">Stopped.</div>',t?Be("retry",`data-act="send" ${i}`,"Send again","Send again","primary"):"",!0);default:return""}}const xs=e=>(e?.blocked||[]).filter(t=>!t.allowed);function nl(e){const t=xs(e);return t.length===1?{act:"allow",say:"Blocked",btn:"Allow",tip:`The agent wasn\u2019t allowed to use ${t[0].label}. Allow it on this canvas and let the agent carry on.`}:{act:"allow",say:`${t.length} blocked`,btn:"Allow all",tip:`The agent wasn\u2019t allowed to use: ${t.map(i=>i.label).join(" \xB7 ")}. Allow them all on this canvas and let the agent carry on. (Press the pin itself to see them one by one.)`}}function ja(e){if(!e.blocked?.length)return"";const t=k()&&!X;return`<div class="m-blocked">${e.blocked.map((n,i)=>`<div class="blk${n.allowed?" ok":""}">
15
+ </linearGradient></defs><g class="auras"></g>`);const e=new Set([...kl()].filter(i=>!(B?.inkStrokes||[]).includes(i))),t=new Set,n=kt.querySelector("g.auras");n.querySelectorAll("path").forEach(i=>{t.has(i.dataset.for)||i.remove()});for(const i of f.strokes){if(!t.has(i.id)||n.querySelector(`path[data-for="${i.id}"]`))continue;const s=document.createElementNS("http://www.w3.org/2000/svg","path");s.dataset.for=i.id,s.setAttribute("d",Di(i.points)),s.setAttribute("class","aura-stroke"),s.setAttribute("stroke","url(#aura-grad)"),s.setAttribute("filter","url(#aura-blur)"),n.appendChild(s)}const a=new Set(f.strokes.map(i=>i.id));kt.querySelectorAll("path[data-id]").forEach(i=>{a.has(i.dataset.id)||i.remove()});for(const i of f.strokes){let s=kt.querySelector(`path[data-id="${i.id}"]`);s||(s=document.createElementNS("http://www.w3.org/2000/svg","path"),s.dataset.id=i.id,s.setAttribute("d",Di(i.points)),kt.appendChild(s)),s.setAttribute("stroke",i.color),s.setAttribute("stroke-width",i.width),s.classList.toggle("used",!!i.commentId),s.classList.toggle("working",e.has(i.id)),s.style.display=i.commentId&&!e.has(i.id)&&!Vt.has(i.commentId)&&dn!==i.commentId?"none":""}eo()}function zn(e,t){for(let n=f.frames.length-1;n>=0;n--){const a=f.frames[n];if(e>=a.x&&e<=a.x+a.w&&t>=a.y&&t<=a.y+a.h)return a}return null}function de(e){try{return D.get(e)?.iframe.contentDocument||null}catch{return null}}function Ge(e,t,n){const a=D.get(e).iframe.getBoundingClientRect();return{lx:(t-a.left)/b.z,ly:(n-a.top)/b.z}}function Me(e,t,n){const a=de(e);if(!a)return null;try{return a.elementFromPoint(t,n)}catch{return null}}function Dt(e){if(!e||!e.ownerDocument)return"";const t=e.ownerDocument,n=[];for(let a=e;a&&a.nodeType===1&&a!==t.documentElement;a=a.parentElement){if(a.id&&/^[A-Za-z][\w-]*$/.test(a.id)){n.unshift(`#${a.id}`);break}let i=a.tagName.toLowerCase();const s=a.parentElement?[...a.parentElement.children].filter(o=>o.tagName===a.tagName):[];if(s.length>1&&(i+=`:nth-of-type(${s.indexOf(a)+1})`),n.unshift(i),a.tagName==="BODY"||n.length>7)break}return n.join(" > ")}function to(e){const t=typeof e.className=="string"&&e.className.trim()?"."+e.className.trim().split(/\s+/)[0]:"";return e.tagName.toLowerCase()+t}function Hi(e,t,n){const a=Me(e,t,n),i=de(e);let s=0,o=0;try{s=i.defaultView.scrollX,o=i.defaultView.scrollY}catch{}const r={x:t,y:n,sx:s,sy:o};if(a&&a!==i.documentElement){const c=a.getBoundingClientRect();Object.assign(r,{selector:Dt(a),tag:a.tagName.toLowerCase(),label:to(a),text:(a.innerText||a.getAttribute?.("aria-label")||a.getAttribute?.("alt")||"").replace(/\s+/g," ").trim().slice(0,140),html:a.outerHTML.length>1500?a.outerHTML.slice(0,1500)+"\u2026":a.outerHTML,fx:c.width?(t-c.left)/c.width:0,fy:c.height?(n-c.top)/c.height:0})}return r}const le="__canvas";function zi(e,t){const n=de(e);if(!n?.defaultView)return null;const a=n.defaultView,i=n.scrollingElement||n.documentElement;let s=a.scrollX,o=a.scrollY;const r=t.selector||t.container?.selector||t.elements?.[0]?.selector;try{for(let c=r&&n.querySelector(r)?.parentElement;c&&c!==i&&c!==n.documentElement;c=c.parentElement)s+=c.scrollLeft,o+=c.scrollTop}catch{}return{x:s,y:o}}function On(e,t){const n=e!==le&&t&&zi(e,t);return n&&(t.sx=n.x,t.sy=n.y),t}function Rn(e,t){if(e===le)return{x:t.wx,y:t.wy};if(t.scope==="frame"||t.scope==="point"||t.scope==="area"||t.scope==="elements"){if(t.scope==="frame")return{x:t.x,y:t.y};const i=zi(e,t)||{x:t.sx||0,y:t.sy||0};return{x:t.x-(i.x-(t.sx||0)),y:t.y-(i.y-(t.sy||0))}}const n=de(e);if(n&&t.selector)try{const i=n.querySelector(t.selector);if(i){const s=i.getBoundingClientRect();if(s.width||s.height)return{x:s.left+t.fx*s.width,y:s.top+t.fy*s.height}}}catch{}const a=zi(e,t)||{x:t.sx||0,y:t.sy||0};return{x:t.x-(a.x-(t.sx||0)),y:t.y-(a.y-(t.sy||0))}}function La(e,t,n,a="deep"){const{lx:i,ly:s}=Ge(e,t,n),o=de(e),r=Xa(e,Me(e,i,s),a==="drill"?"level":a);if(!r||r===o?.documentElement){V.hidden=!0;return}const c=D.get(e).iframe.getBoundingClientRect(),l=r.getBoundingClientRect(),d=b.z,u=Math.max(c.left,c.left+l.left*d),p=Math.max(c.top,c.top+l.top*d),h=Math.min(c.right,c.left+l.right*d),g=Math.min(c.bottom,c.top+l.bottom*d);Object.assign(V.style,{left:`${u}px`,top:`${p}px`,width:`${Math.max(0,h-u)}px`,height:`${Math.max(0,g-p)}px`}),V.dataset.tag=Ye(r),V.classList.toggle("sel",!!x?.els.includes(r));const v=[...r.children].filter(C=>!/^(SCRIPT|STYLE|BR)$/.test(C.tagName)).slice(0,30).map(C=>C.getBoundingClientRect()).filter(C=>C.width>3&&C.height>3),T=`${l.left},${l.top},${l.width},${l.height},${d},${v.length}`;V._k!==T&&(V._k=T,V.innerHTML=v.map(C=>`<i style="left:${(C.left-l.left)*d-1.5}px;top:${(C.top-l.top)*d-1.5}px;width:${C.width*d}px;height:${C.height*d}px"></i>`).join("")),V.hidden=!1}function Xt(e){return f.comments.filter(t=>t.id===e||t.parentId===e).sort((t,n)=>t.createdAt-n.createdAt)}function Ca(e){const t=Xt(e).filter(n=>n.kind!=="note");return t.some(n=>n.status==="working")?"working":t[t.length-1]?.status||"done"}function no(e){return f.comments.filter(t=>t.frameId===e&&!t.parentId&&t.kind!=="create").sort((t,n)=>t.createdAt-n.createdAt)}const ge=document.createElement("div");ge.id="peek",ge.className="pop",ge.hidden=!0,document.body.appendChild(ge);let ye=null,Ma=null,Ea=null,ft=null,un=null;const ao="Start listening to the Loop canvas again: run `loop watch` with the Monitor tool and keep it running.",Ct=(e,t)=>!!e&&je.x>=e.left-t&&je.x<=e.right+t&&je.y>=e.top-t&&je.y<=e.bottom+t,Mt=e=>document.querySelector(`.pin[data-key="${e}"] .pin-dot`)?.getBoundingClientRect()||null;function $l(e,t){if(!t||matchMedia("(prefers-reduced-motion: reduce)").matches)return;const n=e.getBoundingClientRect();if(!n.width||!n.height)return;const a=(c,l)=>Math.max(0,Math.min(l,c)),i=a(t.left-n.left,n.width-24),s=a(t.top-n.top,n.height-24),o=a(n.right-t.right,n.width-i-24),r=a(n.bottom-t.bottom,n.height-s-24);e._growing?.cancel(),e._growing=e.animate([{clipPath:`inset(${s}px ${o}px ${r}px ${i}px round 14px)`,opacity:.7},{clipPath:"inset(0px 0px 0px 0px round 18px)",opacity:1}],{duration:190,easing:"cubic-bezier(.2, .8, .2, 1)"})}function Ll(e){clearTimeout(Ma),!(ye===e||un===e)&&(document.querySelector(`.pin[data-key="${e}"]`)?.dataset.act||ye&&Ct(ge.getBoundingClientRect(),0)||(Ma=setTimeout(()=>{j===e||se||!f?.comments.some(t=>t.id===e)||!Ct(Mt(e),6)||j&&!It||B&&!H.hidden||Fn(e,null,!0)},j?30:80)))}let It=!1,it=null;function Cl(){un&&!Ct(Mt(un),4)&&(un=null),It&&j&&(z.contains(document.activeElement)||!!z.querySelector(".thread-reply textarea")?.value.trim()||Da.length?(It=!1,clearTimeout(it),it=null):Ct(z.getBoundingClientRect(),12)||Ct(Mt(j),8)?(clearTimeout(it),it=null):it||(it=setTimeout(()=>{it=null,It&&ee()},180))),ye&&(Ct(ge.getBoundingClientRect(),10)||Ct(Ea,8)?(clearTimeout(ft),ft=null):ft||(ft=setTimeout(()=>{ft=null,Re()},150)))}function Re(){if(clearTimeout(Ma),clearTimeout(ft),ft=null,!ye)return;Ct(Ea,4)&&(un=ye);const e=f?.comments.find(t=>t.id===ye);e&&Ht(e.frameId)?.querySelector(`.area[data-key="${ye}"]`)?.classList.remove("hover"),ye=null,ge.hidden=!0,Aa()}function io(e){const t=no(e.frameId).findIndex(n=>n.id===e.id)+1;return t?`<span class="pin-n" title="Comment ${t}">${t}</span>`:""}function Ml(){const e=f.comments.find(o=>o.id===ye);if(!e||j===ye)return Re();const t=Xt(e.id),n=t[t.length-1],a=t.length-(n===e?1:2),i=[[e.id,ji(e,n!==e)]];a>0&&i.push(["__more",`<div class="pk-gap">${a} more ${a===1?"message":"messages"}</div>`]),n!==e&&i.push([n.id,ji(n)]),ge.firstChild||(ge.innerHTML='<div class="thread-body"></div><div class="pk-bar"></div>'),so(ge.querySelector(".thread-body"),i);const s=`${io(e)}<span class="pk-who">${L(e.author?.name||"You")} \xB7 ${Ut(e.createdAt)}</span>
16
+ <button class="t-btn" data-pk="open" title="Open and reply">${Je.reply}</button>${$()?`<button class="t-btn" data-pk="resolve" title="${e.resolved?"Reopen":"Resolve"}">${e.resolved?Je.reopen:Je.resolve}</button>`:""}`;ge._bar!==s&&(ge._bar=s,ge.querySelector(".pk-bar").innerHTML=s),oo(ge),El()}function El(){if(!ye)return;const e=f.comments.find(a=>a.id===ye);if(!e?.anchor)return;const t=Rn(e.frameId,e.anchor),n=Ta(e.frameId,t.x,t.y);uo(ge,n.x,n.y,!1,Mt(ye)),Ea=Mt(ye)||Ea,Aa()}document.documentElement.addEventListener("pointerleave",()=>{ye&&!ft&&(ft=setTimeout(()=>{ft=null,Re()},150))}),ge.addEventListener("pointerdown",e=>e.stopPropagation()),ge.addEventListener("wheel",e=>e.stopPropagation()),ge.addEventListener("click",async e=>{const t=ye;if(!t)return;if(e.target.closest('[data-pk="resolve"]')){Re();try{await w("POST",`/__loop/api/comments/${t}/resolve`)}catch(a){y(a.message)}return}if(e.target.closest("a"))return;const n=ge.dataset.o;Re(),Fn(t,n)});function so(e,t){const n=e._cache||=new Map,a=new Set(t.map(s=>s[0]));for(const s of[...e.children])a.has(s.dataset.mid)||(n.delete(s.dataset.mid),s.remove());let i=null;for(const[s,o]of t){let r=[...e.children].find(l=>l.dataset.mid===s);r||(r=document.createElement("div"),r.className="m",r.dataset.mid=s),n.get(s)!==o&&(n.set(s,o),r.innerHTML=o);const c=i?i.nextSibling:e.firstChild;c!==r&&e.insertBefore(r,c),i=r}}function oo(e){e.querySelectorAll("[data-step-for]").forEach(t=>{const n=f.comments.find(i=>i.id===t.dataset.stepFor),a=n&&f.live[n.frameId];$e(t,a?.commentId===n?.id&&a.step||"Working\u2026"),n&&wo(n.id,e),a?.commentId===n?.id&&ro(n.id,a.partial||"",e)}),e.querySelectorAll("[data-elapsed-from]").forEach(t=>$e(t,xa(+t.dataset.elapsedFrom)))}function ro(e,t,n=document){n.querySelectorAll(`[data-partial-for="${e}"]`).forEach(a=>{if(a._src===t)return;a._src=t,a.hidden=!t,a.innerHTML=t?qa(t):"";const i=a.closest(".thread-body");i&&i.scrollHeight-i.scrollTop-i.clientHeight<80&&(i.scrollTop=i.scrollHeight)})}const lo=new Map;function co(e){const t=f.live[e];return t?(t.partial||"").trim().split(`
17
+ `)[0].replace(/[*_`#>]/g,"").trim()||t.step||"Working\u2026":""}function Sl(e){const t=f.live[e],n=Sa(e);if(!t||!n)return;const a=f.comments.find(o=>o.id===t.commentId)?.parentId||t.commentId,i=n.querySelector(`.pin[data-key="${a}"] .pl`);if(!i)return;const s=co(e);i.textContent!==s&&(i.textContent=s,(t.partial||"").trim()||(i.classList.remove("tick"),i.offsetWidth,i.classList.add("tick")))}async function Tl(e){const t=e.dataset.act,n=e.dataset.cid;if(!t||!n)return;if(t==="see")return Fn(e.dataset.key||n);delete e.dataset.act;const a=e.querySelector(".pl");a._h=null,a.textContent=t==="send"?"Sending\u2026":t==="allow"?"Allowed":"Starting\u2026";try{await w("POST",`/__loop/api/comments/${n}/${t}`,t==="allow"?{all:!0,i:f.comments.find(i=>i.id===n)?.blocked?.findIndex(i=>!i.allowed)}:void 0)}catch(i){y(i.message);const s=f.comments.find(o=>o.id===n)?.frameId;s&&Et(s)}}function Nn(){for(const e of f.frames)Et(e.id);Et(le)}function Sa(e){return e===le?m("#canvas-pins"):D.get(e)?.pins}function Ht(e){return e===le?m("#canvas-pins"):D.get(e)?.el.querySelector(".areas")}function Et(e){const t=Sa(e);if(!t)return;const n={pins:t},a=no(e),i=a.map((u,p)=>({key:u.id,n:p+1,c:u})).filter(u=>!u.c.resolved||j===u.key);B?.frameId===e&&!B.prompt&&i.push({key:"__draft",n:a.length+1,draft:!0});const s=new Set(i.map(u=>u.key));n.pins.querySelectorAll(".pin").forEach(u=>{s.has(u.dataset.key)||u.remove()});for(const u of i){let p=n.pins.querySelector(`.pin[data-key="${u.key}"]`);p||(p=document.createElement("div"),p.className="pin",p.dataset.key=u.key,p.innerHTML='<div class="pin-dot"><b class="pn"></b><svg class="pw" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="5.5"/></svg><span class="pl"></span></div>',p.addEventListener("pointerdown",q=>q.stopPropagation()),u.draft||p.addEventListener("click",q=>{if(q.stopPropagation(),p.dataset.act&&q.target.closest(".pin-act"))return Tl(p);if(p.classList.contains("making")&&q.target.closest(".pl")){const ne=f.comments.find(R=>R.id===u.key);if(ne?.optionSection)return pi.delete(ne.optionSection),Ir(ne.optionSection)}Fn(u.key)}),p.addEventListener("pointerenter",()=>{Ht(e)?.querySelector(`.area[data-key="${u.key}"]`)?.classList.add("hover"),u.draft||Ll(u.key)}),p.addEventListener("pointerleave",()=>{ye!==u.key&&(Ht(e)?.querySelector(`.area[data-key="${u.key}"]`)?.classList.remove("hover"),clearTimeout(Ma))}),n.pins.appendChild(p));const h=p.querySelector(".pn"),g=!!u.c&&(u.c.author?.guest||!!u.c.author?.name&&u.c.author.name!==U.name);let v=u.draft?"draft":Ca(u.key);!u.draft&&v==="done"&&j===u.key&&Ds(u.key);const T=!u.draft&&v==="done"&&Jr(u.key);T?h._ck!==1&&(h._ck=1,h.innerHTML=nl):(h._ck&&(h._ck=0,h.textContent=""),$e(h,String(u.n)));const C=!u.draft&&f.frames.some(q=>q.building&&q.optionOf?.cid===u.key)&&!(v==="queued"&&f.agent.mode==="inbox"&&!f.chatListening);C&&v!=="working"&&(v="working");const k=lo.get(u.key);lo.set(u.key,v),k==="working"&&v!=="working"&&v!=="queued"&&(p._ended=v==="done"?T?null:"Done":v==="error"?"Failed":"Stopped",clearTimeout(p._endT),p._endT=setTimeout(()=>{p._ended=null,f&&Et(e)},2400));const M=p.querySelector(".pl"),E=!u.draft&&Xt(u.key).filter(q=>q.kind!=="note").pop(),N=!u.draft&&$()&&!X&&E&&(v==="queued"&&!E.local&&!E.background&&f.agent.mode==="inbox"&&!f.chatListening?f.chatHistory?{act:"background",say:"Chat isn\u2019t listening",btn:"Carry on here",tip:"The chat this was sent to isn\u2019t listening. Carry on in the background from a copy of that chat, with everything it knows. It also starts by itself in a moment."}:{act:"background",say:"Chat isn\u2019t listening",btn:"Run in new chat",tip:"The chat this was sent to isn\u2019t listening. Run it in a new session instead (without that chat\u2019s history). It also starts by itself in a moment."}:v==="waiting"?{act:"send",say:"Waiting for you",btn:"Send",tip:"Send this comment to the agent"}:(v==="done"||v==="error")&&Wi(E).length?Bl(E):null);if(N){p.dataset.act=N.act,p.dataset.cid=E.id;const q=`<span>${L(N.say)}</span><button class="pin-act" title="${L(N.tip)}">${L(N.btn)}${N.act==="background"?`<kbd>${rt==="metaKey"?"\u2318":"Ctrl"}\u21B5</kbd>`:""}</button>`;M._h!==q&&(M._h=q,M.innerHTML=q)}else p.dataset.act&&(delete p.dataset.act,M._h=null,M.textContent="");if(v==="working"){const q=f.live[e],ne=q&&(f.comments.find(R=>R.id===q.commentId)?.parentId||q.commentId)===u.key;$e(M,C?"Making options \u2192":ne?co(e):"Working\u2026")}else T&&!N?$e(M,"Done"):p._ended&&$e(M,p._ended);p.className=`pin ${v}${u.c?.resolved?" resolved":""}${j===u.key||u.draft?" active":""}${v==="working"?" talking":N?" talking needs":T?" talking done-new":p._ended?" talking ended":""}${p.classList.contains("carded")?" carded":""}${p.classList.contains("ping")?" ping":""}${p.classList.contains("low")?" low":""}${g?" theirs":""}${C?" making":""}`}const o=f.live[e]?.commentId,r=o&&(f.comments.find(u=>u.id===o)?.parentId||o),c=i.filter(u=>u.draft?B?.area:u.c?.anchor?.scope==="area"||u.c?.anchor?.area||u.key===r&&(u.c?.anchor?.scope==="elements"||u.c?.anchor?.scope==="frame"||Ii(u.key).length)),l=new Set(c.map(u=>u.key)),d=Ht(e);d.querySelectorAll(".area:not(.picking)").forEach(u=>{l.has(u.dataset.key)||u.remove()});for(const u of c){let p=d.querySelector(`.area[data-key="${u.key}"]`);p||(p=document.createElement("div"),p.dataset.key=u.key,d.prepend(p));const h=!u.draft&&u.key!==r&&Ca(u.key)==="queued";p.className=`area${u.draft?" draft show":""}${j===u.key?" show":""}${u.key===r?" show working":""}${h?" show queued":""}${u.c?.anchor?.scope==="frame"?" whole":""}${u.key===r&&Ii(u.key).length&&u.c?.anchor?.scope!=="area"&&!u.c?.anchor?.area?" inkbox":""}`}ut(e),c.some(u=>u.key===r)&&tl(),Hn()}function ut(e){const t=Sa(e);!t||!f||(x?.frameId===e&&Pe(),Ht(e)?.querySelectorAll(".area[data-key]").forEach(n=>{const a=n.dataset.key==="__draft"?B?.anchor:f.comments.find(c=>c.id===n.dataset.key)?.anchor;if(!a)return;if(a.scope==="frame"){const c=f.frames.find(l=>l.id===e);if(!c)return;Object.assign(n.style,{left:"0px",top:"0px",width:`${c.w}px`,height:`${c.h}px`});return}if(n.classList.contains("inkbox")){const c=Ii(n.dataset.key),l=f.frames.find(M=>M.id===e),d=l&&De(l),u=f.strokes.filter(M=>c.includes(M.id)).flatMap(M=>fn(M));if(!d||u.length<2){n.style.width="0";return}const p=u.filter((M,E)=>E%2===0).map(M=>M-d.x),h=u.filter((M,E)=>E%2).map(M=>M-d.y),g=12,v=Math.max(0,Math.min(...p)-g),T=Math.max(0,Math.min(...h)-g),C=Math.min(d.w,Math.max(...p)+g),k=Math.min(d.h,Math.max(...h)+g);Object.assign(n.style,{left:`${v}px`,top:`${T}px`,width:`${Math.max(0,C-v)}px`,height:`${Math.max(0,k-T)}px`});return}if(a.scope==="elements"){const c=de(e),l=(a.elements||[]).map(g=>{try{return c?.querySelector(g.selector)?.getBoundingClientRect()}catch{return null}}).filter(g=>g&&(g.width||g.height));if(!l.length){n.style.width="0";return}const d=Math.min(...l.map(g=>g.left)),u=Math.min(...l.map(g=>g.top)),p=Math.max(...l.map(g=>g.right)),h=Math.max(...l.map(g=>g.bottom));Object.assign(n.style,{left:`${d}px`,top:`${u}px`,width:`${p-d}px`,height:`${h-u}px`});return}const{x:i,y:s}=Rn(e,a),o=a.area?a.area.w:a.w,r=a.area?a.area.h:a.h;Object.assign(n.style,{left:`${i}px`,top:`${s}px`,width:`${o}px`,height:`${r}px`})}),t.querySelectorAll(".pin").forEach(n=>{const a=n.dataset.key==="__draft"?B?.anchor:f.comments.find(r=>r.id===n.dataset.key)?.anchor;if(!a){n.hidden=!0;return}const{x:i,y:s}=Rn(e,a);n.style.left=`${i}px`,n.style.top=`${s}px`;const o=f.frames.find(r=>r.id===e);n.hidden=!!o&&(i<-4||s<-4||i>o.w+4||s>o.h+4),n.classList.toggle("low",e!==le&&s*b.z<34*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1))}),(B?.frameId===e||j&&f.comments.find(n=>n.id===j)?.frameId===e)&&_e())}function Ta(e,t,n){if(e===le)return{x:b.x+t*b.z,y:b.y+n*b.z};const a=De(f.frames.find(i=>i.id===e));return{x:b.x+(a.x+t)*b.z,y:b.y+(a.y+n)*b.z}}function fo(e,t,n,a){const i=e.offsetWidth||340,s=e.offsetHeight||140,o=28*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1);let r=a?t+o+10:t+18,c=a?Math.min(a.top,n)-4:n-18;r+i>innerWidth-12&&(r=t-i-10),r=Math.max(12,Math.min(r,innerWidth-i-12)),c=Math.max(60,Math.min(c,innerHeight-s-76)),e.style.left=`${r}px`,e.style.top=`${c}px`}let zt=28;function uo(e,t,n,a,i){zt=28*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1),i&&i.height>4&&(t=i.left,n=i.bottom,zt=i.height),a&&(e.style.maxHeight="");const s=e.offsetWidth||340;let o=e.offsetHeight||140;const r=n-56,c=innerHeight-12-(n-zt),l=innerWidth-12-t,d=t+zt-12;let u=a&&e._side;u&&(u[0]==="b"?o>r&&c>r:o>c&&r>c)&&(u=(u[0]==="b"?"t":"b")+u[1]);const p=a?o:Math.max(o,380);if(u||(u=(p<=r||r>=c?"b":"t")+(s<=l||l>=d?"l":"r")),a){e._side=u;const C=u[0]==="b"?r:c;o>C&&(e.style.maxHeight=`${Math.max(180,Math.floor(C))}px`,o=e.offsetHeight)}const h=u[1]==="l"?t:t+zt-s,g=u[0]==="b"?n-o:n-zt,v=Math.max(12,Math.min(h,innerWidth-s-12)),T=Math.max(56,Math.min(g,innerHeight-o-12));e.style.left=`${Math.round(v)}px`,e.style.top=`${Math.round(T)}px`,e.dataset.o=u,e.style.transformOrigin=`${Math.max(0,Math.min(s,t+zt/2-v))}px ${Math.max(0,Math.min(o,n-zt/2-T))}px`,e.classList.toggle("at-pin",u==="bl"&&v===h&&T===g),e._covers=v===h&&T===g}function Aa(){const e=new Set;j&&!z.hidden&&!z.classList.contains("docked")&&z._covers&&e.add(j),ye&&!ge.hidden&&ge._covers&&e.add(ye),document.querySelectorAll(".pin").forEach(t=>t.classList.toggle("carded",e.has(t.dataset.key)))}function _e(){if(f){if(Bt(),Zo(),B?.prompt&&!H.hidden){const e=De(f.frames.find(t=>t.id===B.frameId));if(e){const t=Ri(e),n=b.z,a=e.w*(1-2*t.lx)*n,i=Math.min(44,t.fs*n),s=D.get(e.id)?.el.querySelector(".frame-body"),o=!!s;if(H.classList.toggle("onpage",o),o)H.dataset.on=t.on,H.parentElement!==s&&(Ni(s),H.style.left=H.style.top=H.style.width=""),(H._pz!==n||H._pw!==e.w)&&(H._pz=n,H._pw=e.w,ot(W));else{Ni(document.body),H._pz=H._pw=null;const r=H.offsetWidth||380,c=H.offsetHeight||200,l=b.y+(e.y+e.h/2)*n;fo(H,b.x+(e.x+e.w)*n,l-c/2+18)}}}else if(B&&!H.hidden){const e=Rn(B.frameId,B.anchor),t=Ta(B.frameId,e.x,e.y);fo(H,t.x,t.y,Mt("__draft"))}if(j&&!z.hidden&&!z.classList.contains("docked")){const e=f.comments.find(t=>t.id===j);if(e?.anchor){const t=Rn(e.frameId,e.anchor),n=Ta(e.frameId,t.x,t.y);uo(z,n.x,n.y,!0,Mt(j)),z._grow&&(z._grow=!1,$l(z,Mt(j)))}}if(Aa(),Cn(),Ze){const e=Ta(Ze.frameId,Ze.lx,Ze.ly),t=m("#ink-chip");t.style.left=`${e.x+10}px`,t.style.top=`${e.y+10}px`}}}function Oi(e){return f.strokes.filter(t=>t.frameId===e&&!t.commentId&&_s.has(t.id))}function st(e,t,n,a,i){Ne&&jn(!0),ee(),Bn(),H.classList.remove("prompt"),Bi();const s=e===le?null:i?Hi(e,i.x+i.w/2,i.y+i.h/2):Hi(e,t,n),o=Oi(e);B={frameId:e,picked:s,lx:t,ly:n,area:i||null,inkStrokes:o.map(l=>l.id)},ql(e===le?"canvas":i?"area":"point");const r=m("#composer-area");r.classList.remove("chip-frame"),r.hidden=!i,i&&(r.textContent=e===le?`Area \xB7 ${B.anchor.near.length||"no"} frame${B.anchor.near.length===1?"":"s"}`:`Area \xB7 ${B.anchor.elements.length} element${B.anchor.elements.length===1?"":"s"}`);const c=m("#composer-ink");c.hidden=!o.length,c.innerHTML=`${Co}<span>${o.length} mark${o.length===1?"":"s"}</span>`,W.placeholder=$()?"Ask for a change":"Add a comment",Kn.length=0,H.hidden=!1,W.value="",ot(W),Zi.paint(),Et(e),_e(),qt(),setTimeout(()=>W.focus({preventScroll:!0}),0),Fi(e)}function po(e,t){return f.frames.map(n=>({f:n,d:Math.hypot(Math.max(n.x-e,0,e-n.x-n.w),Math.max(n.y-t,0,t-n.y-n.h))})).sort((n,a)=>n.d-a.d).slice(0,2).filter(n=>n.d<1200).map(n=>n.f.name)}function Al(e){const t=f.frames.filter(n=>n.x<e.x+e.w&&n.x+n.w>e.x&&n.y<e.y+e.h&&n.y+n.h>e.y).map(n=>n.name);return t.length?t:po(e.x+e.w/2,e.y+e.h/2)}function _l(e,t){const n=de(e);if(!n?.body)return[];const a=Math.max(12,Math.min(t.w,t.h)*.08),i=t.x-a,s=t.y-a,o=t.x+t.w+a,r=t.y+t.h+a,c=[];for(const u of n.body.querySelectorAll("*")){if(c.length>600)break;const p=u.getBoundingClientRect();!p.width||!p.height||["SCRIPT","STYLE","LINK","META"].includes(u.tagName)||p.left>=i&&p.top>=s&&p.right<=o&&p.bottom<=r&&c.push(u)}const l=new Set(c);let d=c.filter(u=>{for(let p=u.parentElement;p;p=p.parentElement)if(l.has(p))return!1;return!0});if(!d.length){const u=Me(e,t.x+t.w/2,t.y+t.h/2);u&&u!==n.documentElement&&(d=[u])}return d.slice(0,14).map(u=>({selector:Dt(u),tag:u.tagName.toLowerCase(),text:(u.innerText||u.getAttribute("aria-label")||u.getAttribute("alt")||"").replace(/\s+/g," ").trim().slice(0,80)}))}function Pl(e,t){const n=de(e);let a=Me(e,t.x+t.w/2,t.y+t.h/2);for(;a&&a!==n?.body;){const i=a.getBoundingClientRect();if(i.left<=t.x+2&&i.top<=t.y+2&&i.right>=t.x+t.w-2&&i.bottom>=t.y+t.h-2)break;a=a.parentElement}return a&&a!==n?.documentElement?{selector:Dt(a),tag:a.tagName.toLowerCase(),text:(a.innerText||"").replace(/\s+/g," ").trim().slice(0,80)}:null}function ql(e){const t=B;if(!t)return;const n=f.frames.find(a=>a.id===t.frameId);t.scope=e,e==="canvas"&&t.area?t.anchor={scope:e,wx:t.area.x,wy:t.area.y,area:{w:t.area.w,h:t.area.h},near:Al(t.area)}:e==="canvas"?t.anchor={scope:e,wx:t.lx,wy:t.ly,near:po(t.lx,t.ly)}:e==="area"?t.anchor={scope:e,x:t.area.x,y:t.area.y,w:t.area.w,h:t.area.h,sx:t.picked?.sx||0,sy:t.picked?.sy||0,elements:_l(t.frameId,t.area),container:Pl(t.frameId,t.area)}:t.anchor={...t.picked||{},scope:"point",x:t.lx,y:t.ly,fx:void 0,fy:void 0},On(t.frameId,t.anchor),Et(t.frameId),_e()}function Ri(e){const t=e.w<=480;let n="light";if(e.fill==="none")n="canvas";else if(/^#[0-9a-f]{6}$/i.test(e.fill||"")){const a=parseInt(e.fill.slice(1),16);.299*(a>>16)+.587*(a>>8&255)+.114*(a&255)<140&&(n="dark")}return{fs:Math.max(e.w*.037,Math.min(30,e.w*.077)),lx:t?.09:.11,ty:t?.15:.27,on:n,what:e.w<=1024?"screen":"page"}}function Ni(e){if(H.parentElement===e)return;const t=document.activeElement===W;e.appendChild(H),t&&W.focus({preventScroll:!0})}function Bi(){H.classList.remove("onpage"),Ni(document.body),H._pz=H._pw=null,document.querySelectorAll(".frame.prompting").forEach(e=>e.classList.remove("prompting"))}const Dl={Mobile:["Login","Onboarding","Home feed","Profile","Settings","Checkout"],Tablet:["Dashboard","Reader","Calendar","Settings","Kanban board"],Desktop:["Landing page","Dashboard","Pricing","Sign up","Settings","Blog post"]};function _a(e){const t=f?.frames.find(a=>a.id===e);if(!t)return;ee(),Bn(),Bi();const n=t.w<=480?"Mobile":t.w<=1024?"Tablet":"Desktop";B={frameId:e,picked:null,lx:24,ly:24,area:null,inkStrokes:[],prompt:!0,scope:"frame",anchor:{scope:"frame",x:24,y:24}},H.classList.add("prompt"),D.get(e)?.el.classList.add("prompting"),m("#prompt-title").textContent=`What should \u201C${t.name}\u201D be?`,m("#prompt-ideas").innerHTML=Dl[n].map(a=>`<button>${L(a)}</button>`).join(""),m("#composer-area").hidden=!0,m("#composer-ink").hidden=!0,W.placeholder=`Describe this ${Ri(t).what}`,Kn.length=0,H.hidden=!1,W.value="",ot(W),Zi.paint(),_e(),setTimeout(()=>W.focus({preventScroll:!0}),0),Fi(e)}m("#prompt-ideas").addEventListener("click",e=>{const t=e.target.closest("button");t&&(W.value=`${t.textContent} `,ot(W),Zi.paint(),W.focus(),W.setSelectionRange(W.value.length,W.value.length))});function te(){H.classList.contains("soft")&&(H.querySelector(".hint").innerHTML="<kbd>\u21B5</kbd> send \xB7 <kbd>\u21E7\u21B5</kbd> new line \xB7 <kbd>esc</kbd>"),H.classList.remove("prompt","soft"),Bi(),go=null,To(),B?.deep&&Ve(),document.querySelectorAll(".frame.whole").forEach(t=>t.classList.remove("whole"));const e=B?.frameId;B=null,H.hidden=!0,e&&Et(e),f&&qt()}function ot(e){e.style.height="auto",e.style.height=`${Math.min(e===W&&H.classList.contains("onpage")?innerHeight*.45/b.z:180,e.scrollHeight)}px`}W.addEventListener("input",()=>ot(W)),or(W),W.addEventListener("keydown",e=>{if(e.stopPropagation(),e.key==="Enter"&&!e.shiftKey&&!e.isComposing){if(e.preventDefault(),B?.deep&&!W.value.trim()&&!Kn.length&&x?.els.length===1&&xn(x.els[0],!0)&&$()){const{frameId:t,els:n}=x;te(),kn(t,n[0]);return}mo()}e.key==="Escape"&&te()});async function mo(){const e=Kn.splice(0),t=W.value.trim()||(e.length?"See the attached reference.":"");if(!t||!B)return;const n=B;te(),Ee("select");const a=f.strokes.filter(o=>n.inkStrokes.includes(o.id)),i={id:ga(),frameId:n.frameId,text:t,anchor:n.anchor,author:{name:U.name,color:U.color},inkStrokes:n.inkStrokes,attachments:e,refs:rr(W,t)};a.length&&n.frameId!==le&&Object.assign(i,Il(n.frameId,a));const s=Pa(i);try{const o=await w("POST","/__loop/api/comments",i);o?.id&&o.id!==i.id&&s(),$()||y("Comment added \u2014 the host will send it to the agent")}catch(o){s(),y(o.message)}}function Pa(e){if(X)return()=>{};const t={id:e.id,frameId:e.frameId,parentId:e.parentId||null,text:e.text,anchor:e.anchor||f.comments.find(n=>n.id===e.parentId)?.anchor||null,author:{...e.author,guest:!$()},inkStrokes:e.inkStrokes||[],status:$()?"queued":"waiting",reply:null,createdAt:Date.now(),local:!0,...e.attachments?.length?{attachments:e.attachments.map(n=>({name:n.name,type:n.type,url:n.data}))}:{}};f.comments.push(t);for(const n of f.strokes)t.inkStrokes.includes(n.id)&&(n.commentId=t.id);return wa(),()=>{f.comments=f.comments.filter(n=>n!==t),wa()}}const ho=new Map;function Fi(e){!f||X||!$()||!e||Date.now()-(ho.get(e)||0)<6e4||(ho.set(e,Date.now()),w("POST",`/__loop/api/frames/${e}/warm`).catch(()=>{}))}function Il(e,t){const n=f.frames.find(l=>l.id===e),a=de(e),i=new Map;for(const l of t){const d=l.points.length/2,u=Math.max(1,Math.floor(d/14));for(let p=0;p<d;p+=u){const h=l.points[p*2]-(l.fx??n.x),g=l.points[p*2+1]-(l.fy??n.y),v=Me(e,h,g);if(!v||v===a?.documentElement||v===a?.body)continue;const T=Dt(v);i.has(T)||i.set(T,{selector:T,tag:v.tagName.toLowerCase(),text:(v.innerText||"").replace(/\s+/g," ").trim().slice(0,60),el:v})}}const s=[...i.values()].slice(0,10),o=Math.min(1,1280/Math.max(n.w,n.h)),r=document.createElement("canvas");r.width=Math.round(n.w*o),r.height=Math.round(n.h*o);const c=r.getContext("2d");c.scale(o,o),c.fillStyle="#fff",c.fillRect(0,0,n.w,n.h),c.strokeStyle="#C8C8CE",c.lineWidth=2,c.strokeRect(1,1,n.w-2,n.h-2),c.font="14px ui-monospace, Menlo, monospace";for(const l of s)try{const d=l.el.getBoundingClientRect();c.strokeStyle="#2F5BFF",c.setLineDash([6,4]),c.lineWidth=1.5,c.strokeRect(d.left,d.top,d.width,d.height),c.setLineDash([]),c.fillStyle="#2F5BFF",c.fillText(l.tag+(l.text?` "${l.text.slice(0,30)}"`:""),d.left+4,Math.max(14,d.top-4))}catch{}c.strokeStyle=Li,c.lineWidth=4,c.lineCap="round",c.lineJoin="round";for(const l of t){c.beginPath();for(let d=0;d<l.points.length;d+=2){const u=l.points[d]-(l.fx??n.x),p=l.points[d+1]-(l.fy??n.y);d?c.lineTo(u,p):c.moveTo(u,p)}c.stroke()}return{ink:s.map(({el:l,...d})=>d),annotationPng:r.toDataURL("image/png")}}function Pd(e,t,n){Ze={frameId:e,lx:t,ly:n},m("#ink-chip").hidden=!1,_e()}function Bn(){Ze=null,m("#ink-chip").hidden=!0}let go=null;function Hl(e,t,n){if(!(!H.hidden&&W.value.trim())){if(e){const a=f.frames.find(l=>l.id===e),i=Oi(e),s=i.flatMap(l=>fn(l).filter((d,u)=>u%2===0)),o=i.flatMap(l=>fn(l).filter((d,u)=>u%2===1)),r=(s.length?(Math.min(...s)+Math.max(...s))/2:t[t.length-2])-a.x,c=(o.length?(Math.min(...o)+Math.max(...o))/2:t[t.length-1])-a.y;st(e,r,c)}else st(le,t[t.length-2],t[t.length-1],"canvas");B&&(B.soft=!0,H.classList.add("soft"),W.placeholder="What should change here?",H.querySelector(".hint").innerHTML="<kbd>\u21B5</kbd> send \xB7 <kbd>esc</kbd> skip",go={x:n.clientX,y:n.clientY,t:Date.now()})}}addEventListener("pointerdown",e=>{!B?.soft||H.hidden||H.contains(e.target)||W.value.trim()||K==="pen"&&e.target.closest("#viewport")||te()},!0),W.addEventListener("input",()=>{B?.soft&&W.value.trim()&&(B.soft=!1,H.classList.remove("soft"))}),m("#ink-chip button").addEventListener("click",()=>{if(!Ze)return;const e=Oi(Ze.frameId),t=f.frames.find(o=>o.id===Ze.frameId),n=e.flatMap(o=>fn(o).filter((r,c)=>c%2===0)),a=e.flatMap(o=>fn(o).filter((r,c)=>c%2===1)),i=n.length?(Math.min(...n)+Math.max(...n))/2-t.x:Ze.lx,s=a.length?(Math.min(...a)+Math.max(...a))/2-t.y:Ze.ly;st(Ze.frameId,i,s)});function Fn(e,t,n){Ne&&jn(!0),clearTimeout(it),it=null,It=!!n,e!==j&&(pt=!1),te(),Bn(),e!==j&&(Da.length=0),Re(),e!==j&&(z.dataset.tid="",z._side=t||null,z.classList.remove("in","grow"),z.offsetWidth,z.classList.add(t?"grow":"in"),z._grow=!t),j=e,z.hidden=!1;{const a=f.comments.find(i=>i.id===e);Ds(e)&&a&&Et(a.frameId)}z.classList.toggle("docked",pt),pt&&(z.style.left=z.style.top=z.style.maxHeight=""),Ia(),Nn(),_e()}function ee(){j&&(To(),(Vt.size||dn)&&(Vt.clear(),dn=null,qt()),Ct(Mt(j),4)&&(un=j),clearTimeout(it),it=null,It=!1,pt=!1,j=null,z.hidden=!0,z.dataset.tid="",Nn(),Aa())}const Ut=e=>{const t=(Date.now()-e)/1e3;return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:new Date(e).toLocaleDateString()};function Zt(e){if(!e)return"";const t=/claude-([a-z]+)-(\d+)(?:-(\d+))?/i.exec(e);if(t)return`${t[1][0].toUpperCase()}${t[1].slice(1)} ${t[2]}${t[3]&&t[3].length<=2?"."+t[3]:""}`;const n=/^gpt-([\d.]+)(?:-([a-z]+))?/i.exec(e);return n?`GPT-${n[1]}${n[2]?" "+n[2][0].toUpperCase()+n[2].slice(1):""}`:e}function qd(e){const t=[];if(e.model&&t.push(Zt(e.model)),e.startedAt&&e.finishedAt){const n=Math.round((e.finishedAt-e.startedAt)/1e3);t.push(n<60?`${n}s`:`${Math.floor(n/60)}m ${n%60}s`)}return t.length?`<div class="a-meta">${L(t.join(" \xB7 "))}</div>`:""}const Dd=A("check","s"),zl={claude:'<svg class="lg claude" viewBox="0 0 24 24"><path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z"/></svg>',codex:'<svg class="lg" viewBox="0 0 24 24"><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>',loop:'<svg class="lg ring" viewBox="0 0 24 24"><circle cx="12" cy="12" r="6.5"/></svg>'};function Ol(e){const t=String(e?.model||"").toLowerCase();return/claude|opus|sonnet|haiku|fable|mythos/.test(t)?"claude":/gpt|codex|^o\d/.test(t)||f?.agentBin==="codex"?"codex":f?.agentBin==="claude"?"claude":"loop"}const Rl={claude:"Claude",codex:"Codex",loop:"Agent"},yo=e=>{const t=Ol(e);return`<span class="m-mark" title="${Rl[t]}">${zl[t]}</span>`};function Id(e){if(!(e.startedAt&&e.finishedAt))return"";const t=Math.round((e.finishedAt-e.startedAt)/1e3);return`<span title="${L(e.model?Zt(e.model):"")}">Worked ${t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`}</span>`}const Wn={undo:A("undo"),before:A("before"),redo:A("redo"),copy:A("copy"),check:A("check"),stop:A("stop"),send:A("up"),retry:A("retry"),steer:A("steer"),bg:A("play"),x:A("x")},Qe=(e,t,n,a,i="")=>`<button class="a-btn${a?" lbl":""}${i?" "+i:""}" ${t} title="${L(n)}" aria-label="${L(n)}">${Wn[e]}${a?`<span>${L(a)}</span>`:""}</button>`;function Nl(e){const t=$(),n=(i,s,o,r)=>`<div class="m-agent ${i}">${yo(e)}<div class="m-body">${s}${o?`<div class="m-acts${r?" show":""}">${o}</div>`:""}</div></div>`,a=`data-id="${e.id}"`;switch(e.status){case"waiting":return n("quiet",'<div class="m-text">Waiting for the host to send this to the agent.</div>',t?Qe("send",`data-act="send" ${a}`,"Send to the agent","Send","primary"):"",!0);case"queued":{if(e.local)return n("quiet",'<div class="m-work"><span class="a-text">Sending\u2026</span></div>',"");const i=e.parentId||e.id,s=t&&Xt(i).some(l=>l.status==="working"),o=f.agent.mode==="inbox"&&!e.background,r=o&&!f.chatListening,c=s?"Queued \xB7 runs after the current change":r?f.chatHistory?"Your chat isn\u2019t listening, so this carries on in the background in a moment, with what that chat knows.":"Your chat isn\u2019t listening, so this starts in a new session in a moment.":o?"Sent to your chat":"Queued";return n("quiet",`<div class="m-work"><span class="a-text">${c}</span></div>`,t?`${s?Qe("steer",`data-act="steer" ${a}`,"Steer: stop the current run and include this message in it","Steer","primary"):""}${r?Qe("bg",`data-act="background" ${a}`,f.chatHistory?"Carry on now in the background, from a copy of your chat":"Run it now in the background, without your chat\u2019s context","Run now"):""}${Qe("x",`data-act="cancel" ${a}`,"Cancel")}`:"",!0)}case"working":return n("",`<ol class="m-steps" data-steps-for="${e.id}"></ol><div class="m-work"><span class="a-text" data-step-for="${e.id}"></span><span class="m-time" data-elapsed-from="${f.live[e.frameId]?.startedAt||e.startedAt||e.createdAt}"></span>${t?Qe("stop",`data-act="cancel" ${a}`,"Stop"):""}</div><div class="m-text md m-stream" data-partial-for="${e.id}" hidden></div>`,"");case"done":return n("",`${jl(e)}<div class="m-text md">${e.undone?"Reverted.":qa(e.reply||"Done.")}</div>${Yl(e)}${bo(e)}`,`${e.snapshot&&!X&&f.frames.find(i=>i.id===e.frameId)?.kind==="folder"?Qe("before",`data-act="before" ${a}`,"See the frame before this change"):""}${t&&e.snapshot&&!e.undone?Qe("undo",`data-act="undo" ${a}`,"Undo this change"):""}${t&&e.undone&&e.redoSnap?Qe("redo",`data-act="redo" ${a}`,"Redo this change"):""}${Qe("copy",`data-copy="${e.id}"`,"Copy the reply")}<time>${Ut(e.finishedAt||e.createdAt)}</time>`);case"error":return n("error",`<div class="m-text">${L(e.reply||"Something went wrong.")}</div>${bo(e)}`,t?Qe("retry",`data-act="send" ${a}`,"Try again","Retry","primary"):"",!0);case"interrupted":return n("quiet",'<div class="m-text">Interrupted \xB7 continued below</div>',"");case"canceled":return n("quiet",'<div class="m-text">Stopped.</div>',t?Qe("retry",`data-act="send" ${a}`,"Send again","Send again","primary"):"",!0);default:return""}}const Wi=e=>(e?.blocked||[]).filter(t=>!t.allowed);function Bl(e){const t=Wi(e);return t.length===1?{act:"allow",say:"Blocked",btn:"Allow",tip:`The agent wasn\u2019t allowed to use ${t[0].label}. Allow it on this canvas and let the agent carry on.`}:{act:"allow",say:`${t.length} blocked`,btn:"Allow all",tip:`The agent wasn\u2019t allowed to use: ${t.map(a=>a.label).join(" \xB7 ")}. Allow them all on this canvas and let the agent carry on. (Press the pin itself to see them one by one.)`}}function bo(e){if(!e.blocked?.length)return"";const t=$()&&!X;return`<div class="m-blocked">${e.blocked.map((n,a)=>`<div class="blk${n.allowed?" ok":""}">
18
18
  <span class="blk-k">${n.allowed?"Allowed":"Blocked"}</span><code title="${L(n.cmd||n.label)}">${L(n.label)}</code>
19
- ${!n.allowed&&t?`<button class="blk-go" data-act="allow" data-id="${e.id}" data-k="${i}" title="Let the agent use this on this canvas from now on, and carry on">Allow</button>`:""}</div>`).join("")}${t&&xs(e).length>1?`<div class="blk blk-all"><button class="blk-go" data-act="allowall" data-id="${e.id}" title="Let the agent use all of these on this canvas from now on, and carry on">Allow all</button></div>`:""}</div>`}const il={read:T("read"),edit:T("edit"),find:T("find"),look:T("look"),run:T("run"),think:T("think"),add:T("add")},sl=e=>il[/^(Reading)/.test(e)?"read":/^(Editing|Writing)/.test(e)?"edit":/^Searching/.test(e)?"find":/^(Looking|Taking)/.test(e)?"look":/^(Adding|Setting|Making)/.test(e)?"add":/^(Running)/.test(e)?"run":"think"],Ya=e=>e.say?`<li class="say"><div class="md">${yi(e.s)}</div></li>`:`<li>${sl(e.s)}<span>${L(e.s)}</span></li>`;function al(e){const t=(e.steps||[]).filter(s=>s.s!=="Thinking\u2026"),n=e.startedAt&&e.finishedAt?Math.round((e.finishedAt-e.startedAt)/1e3):0;if(!n&&!t.length)return"";const i=n?`Worked for ${n<60?`${n}s`:`${Math.floor(n/60)}m ${n%60}s`}`:"Worked";return t.length?`<details class="m-did"><summary><span>${i}</span>${T("right","s")}</summary><ol class="m-steps">${t.map(Ya).join("")}</ol></details>`:`<div class="m-did flat"><span>${i}</span></div>`}function Ka(e,t=document){const n=u.comments.find(r=>r.id===e);if(!n)return;const i=(n.steps||[]).filter(r=>r.s!=="Thinking\u2026"),s=u.live[n.frameId]?.commentId===e?u.live[n.frameId].step:null,o=(i.length&&!i[i.length-1].say&&i[i.length-1].s===s?i.slice(0,-1):i).slice(-8).map(Ya).join("");t.querySelectorAll(`[data-steps-for="${e}"]`).forEach(r=>{r._h!==o&&(r._h=o,r.innerHTML=o,r.hidden=!o)})}function ks(e,t){return e.kind==="note"?`<div class="m-agent">${Wa(e)}<div class="m-body"><div class="m-text md">${yi(e.text)}</div><div class="m-acts">${Be("copy",`data-copy="${e.id}"`,"Copy")}<time>${jt(e.createdAt)}</time></div></div></div>`:`<div class="m-user">
20
- <div class="bubble${e.attachments?.length?" has-files":""}">${ll(e)}<div class="b-text">${L(e.text)}</div>${cl(e)}</div>
21
- <div class="m-meta">${e.author?.guest||e.author?.name&&e.author.name!==V.name?`${L(e.author?.name||"Guest")} \xB7 `:""}${jt(e.createdAt)}</div>
22
- </div>${t?"":tl(e)}`}function ol(){for(const[e,t]of H){const n=[...u.comments].reverse().find(d=>d.frameId===e&&d.options?.some(p=>p.files?.length&&!p.frameId)&&!d.optionChosen&&!d.optionsCleared);let i=t.el.querySelector(":scope > .opt-strip");if(!n||!k()){i?.remove();continue}const s=u.frames.find(d=>d.id===e),a=s?s.w/s.h:1.5,o=Math.round(Math.min(150,Math.max(70,84*a))),r=Math.round(o/a),l=n.options.filter(d=>d.files?.length&&!d.frameId),c=n.id+"|"+(n.optionApplied||"")+"|"+l.map(d=>d.id+(d.thumb||"")).join(",");if(i?.dataset.key===c)continue;i||(i=document.createElement("div"),i.className="opt-strip",t.el.appendChild(i),i.addEventListener("pointerdown",d=>d.stopPropagation()),i.addEventListener("click",async d=>{const p=d.target.closest("[data-opt]"),h=d.target.closest("[data-use]"),g=i.dataset.cid;try{h?(await w("POST",`/__loop/api/comments/${g}/choose`,{option:h.dataset.use}),b(`Using option ${h.dataset.use}`)):p&&await w("POST",`/__loop/api/comments/${g}/preview`,{option:p.dataset.opt||null})}catch(v){b(v.message)}})),i.dataset.key=c,i.dataset.cid=n.id;const f=(d,p,h)=>`<button class="os-tile${(n.optionApplied||"")===d?" on":""}" data-opt="${d}" title="${d?`Preview ${L(p)}`:"Back to the original"}">
23
- <span class="os-img" style="width:${o}px;height:${r}px">${h?`<img src="${L(h)}" alt="">`:`<b>${d||"\xB7"}</b>`}</span>
24
- <span class="os-name">${d?`<i>${d}</i>`:""}${L(p)}</span></button>`;i.innerHTML=`<span class="os-label">Options</span>${f("","Original",n.origThumb||"")}${l.map(d=>f(d.id,d.name,d.thumb)).join("")}
25
- ${n.optionApplied?`<button class="os-use" data-use="${n.optionApplied}">Use ${n.optionApplied}</button>`:""}`,l.some(d=>!d.thumb)&&s?.kind==="folder"&&!n._thumbsAsked&&(n._thumbsAsked=!0,w("POST",`/__loop/api/comments/${n.id}/thumbs`).catch(()=>{}))}}function rl(e){const t=(e.options||[]).filter(i=>i.files?.length);if(!t.length)return"";if(t.some(i=>i.frameId)||e.optionsCleared){const i=t.filter(s=>s.frameId&&u.frames.some(a=>a.id===s.frameId));return i.length?`<div class="m-opts">${i.map(s=>`<button class="opt${e.optionChosen===s.id?" on":""}" data-goto="${s.frameId}" title="Go to this option's frame"><b>${L(s.id)}</b>${L(s.name)}</button>`).join("")}</div>`:e.optionChosen?`<div class="m-opts chosen"><span class="opt on"><b>${L(e.optionChosen)}</b>${L(t.find(s=>s.id===e.optionChosen)?.name||"")}</span><span class="opt-note">Chosen</span></div>`:""}if(e.optionChosen){const i=t.find(s=>s.id===e.optionChosen);return`<div class="m-opts chosen"><span class="opt on"><b>${L(i?.id||"")}</b>${L(i?.name||"")}</span><span class="opt-note">Chosen</span></div>`}const n=k();return`<div class="m-opts">${t.map(i=>`<button class="opt${e.optionApplied===i.id?" on":""}" ${n?`data-opt="${i.id}" data-for="${e.id}"`:"disabled"} title="Preview in the frame"><b>${L(i.id)}</b>${L(i.name)}</button>`).join("")}
26
- ${n&&e.optionApplied?`<span class="opt-acts"><button class="opt-use" data-use="${e.optionApplied}" data-for="${e.id}">Use ${L(e.optionApplied)}</button><button class="opt-orig" data-opt="" data-for="${e.id}">Original</button></span>`:`<span class="opt-note">${n?"Click an option to preview it in the frame":"Options"}</span>`}</div>`}D.addEventListener("click",async e=>{const t=e.target.closest("[data-goto]");if(t){const a=t.dataset.goto;u.frames.some(o=>o.id===a)&&(J(),ie(a),Ge(!0,[a]));return}const n=e.target.closest("[data-opt]"),i=e.target.closest("[data-use]");if(!n&&!i)return;const s=(n||i).dataset.for;try{i?(await w("POST",`/__loop/api/comments/${s}/choose`,{option:i.dataset.use}),b(`Using option ${i.dataset.use}`)):await w("POST",`/__loop/api/comments/${s}/preview`,{option:n.dataset.opt||null})}catch(a){b(a.message)}});function yi(e){const t=s=>L(s).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<b>$1</b>").replace(/(^|[\s(])\*([^*\s][^*]*)\*/g,"$1<i>$2</i>"),n=[];let i=null;for(const s of String(e).split(`
27
- `)){const a=/^\s*(?:[-*•]|\d+\.)\s+(.*)$/.exec(s);if(a){i||(i=[],n.push(i)),i.push(t(a[1]));continue}i=null,s.trim()&&n.push(`<p>${t(s)}</p>`)}return n.map(s=>Array.isArray(s)?`<ul>${s.map(a=>`<li>${a}</li>`).join("")}</ul>`:s).join("")}function ll(e){return e.attachments?.length?`<div class="m-files">${e.attachments.map(t=>t.type.startsWith("image/")?`<a href="${L(t.url)}" target="_blank" rel="noopener"><img src="${L(t.url)}" alt="${L(t.name)}"></a>`:`<a class="f" href="${L(t.url)}" target="_blank" rel="noopener">${on.file}<span>${L(t.name)}</span></a>`).join("")}</div>`:""}const vi=[];function cl(e){const t=(e.inkStrokes||[]).filter(i=>u.strokes.some(s=>s.id===i)).length;if(!t)return"";const n=Ft.has(e.id);return`<button class="m-marks${n?" on":""}" data-marks="${e.id}" title="${n?"Hide":"Show"} the marks on the canvas">${Ga}<span>${n?"Hide":`${t} mark${t===1?"":"s"}`}</span></button>`}D.addEventListener("pointerover",e=>{const t=e.target.closest("[data-marks]");t&&nn!==t.dataset.marks&&(nn=t.dataset.marks,xt())}),D.addEventListener("pointerout",e=>{const t=e.target.closest("[data-marks]");t&&!t.contains(e.relatedTarget)&&(nn=null,xt())}),D.addEventListener("click",e=>{const t=e.target.closest("[data-marks]");if(!t)return;const n=t.dataset.marks;Ft.has(n)?Ft.delete(n):Ft.add(n),xt(),bi()});function bi(){const e=u.comments.find(s=>s.id===W);if(!e)return J();if(D.dataset.tid!==e.id){D.dataset.tid=e.id,D.innerHTML=`<div class="t-tools"></div><div class="thread-body"></div>
28
- <div class="thread-reply"><div class="cbox"><div class="c-files" hidden></div><textarea rows="1" placeholder="Reply"></textarea></div></div>`,D._tools=null;const s=D.querySelector("textarea"),a=async()=>{const r=u.comments.find(h=>h.id===W);if(!r)return;const l=vi.splice(0),c=s.value.trim()||(l.length?"See the attached reference.":"");if(!c)return;s.value="",gt(s),o.paint();const f={id:Jn(),frameId:r.frameId,parentId:r.id,text:c,author:{name:V.name,color:V.color},attachments:l},d=gi(f),p=D.querySelector(".thread-body");p&&(p.scrollTop=p.scrollHeight);try{const h=await w("POST","/__loop/api/comments",f);h?.id&&h.id!==f.id&&d()}catch(h){d(),b(h.message)}},o=eo(D.querySelector(".thread-reply .cbox"),vi,a);gt(s),s.addEventListener("input",()=>gt(s)),s.addEventListener("keydown",r=>{if(r.stopPropagation(),r.key==="Escape")return J();r.key==="Enter"&&!r.shiftKey&&!r.isComposing&&(r.preventDefault(),a())}),s.addEventListener("focus",()=>ws(u.comments.find(r=>r.id===W)?.frameId),{once:!0})}const t=`
29
- ${_a(e)}
30
- <span class="t-title">${L(e.frameId===ce?"Canvas":u.frames.find(s=>s.id===e.frameId)?.name||"")}</span>
19
+ ${!n.allowed&&t?`<button class="blk-go" data-act="allow" data-id="${e.id}" data-k="${a}" title="Let the agent use this on this canvas from now on, and carry on">Allow</button>`:""}</div>`).join("")}${t&&Wi(e).length>1?`<div class="blk blk-all"><button class="blk-go" data-act="allowall" data-id="${e.id}" title="Let the agent use all of these on this canvas from now on, and carry on">Allow all</button></div>`:""}</div>`}const Fl={read:A("read"),edit:A("edit"),find:A("find"),look:A("look"),run:A("run"),think:A("think"),add:A("add")},Wl=e=>Fl[/^(Reading)/.test(e)?"read":/^(Editing|Writing)/.test(e)?"edit":/^Searching/.test(e)?"find":/^(Looking|Taking)/.test(e)?"look":/^(Adding|Setting|Making)/.test(e)?"add":/^(Running)/.test(e)?"run":"think"],vo=e=>e.say?`<li class="say"><div class="md">${qa(e.s)}</div></li>`:`<li>${Wl(e.s)}<span>${L(e.s)}</span></li>`;function jl(e){const t=(e.steps||[]).filter(i=>i.s!=="Thinking\u2026"),n=e.startedAt&&e.finishedAt?Math.round((e.finishedAt-e.startedAt)/1e3):0;if(!n&&!t.length)return"";const a=n?`Worked for ${n<60?`${n}s`:`${Math.floor(n/60)}m ${n%60}s`}`:"Worked";return t.length?`<details class="m-did"><summary><span>${a}</span>${A("right","s")}</summary><ol class="m-steps">${t.map(vo).join("")}</ol></details>`:`<div class="m-did flat"><span>${a}</span></div>`}function wo(e,t=document){const n=f.comments.find(r=>r.id===e);if(!n)return;const a=(n.steps||[]).filter(r=>r.s!=="Thinking\u2026"),i=f.live[n.frameId]?.commentId===e?f.live[n.frameId].step:null,o=(a.length&&!a[a.length-1].say&&a[a.length-1].s===i?a.slice(0,-1):a).slice(-8).map(vo).join("");t.querySelectorAll(`[data-steps-for="${e}"]`).forEach(r=>{r._h!==o&&(r._h=o,r.innerHTML=o,r.hidden=!o)})}function ji(e,t){return e.kind==="note"?`<div class="m-agent">${yo(e)}<div class="m-body"><div class="m-text md">${qa(e.text)}</div><div class="m-acts">${Qe("copy",`data-copy="${e.id}"`,"Copy")}<time>${Ut(e.createdAt)}</time></div></div></div>`:`<div class="m-user">
20
+ <div class="bubble${e.attachments?.length?" has-files":""}">${Vl(e)}<div class="b-text">${L(e.text)}</div>${Xl(e)}</div>
21
+ <div class="m-meta">${e.author?.guest||e.author?.name&&e.author.name!==U.name?`${L(e.author?.name||"Guest")} \xB7 `:""}${Ut(e.createdAt)}</div>
22
+ </div>${t?"":Nl(e)}`}function Kl(){for(const[e,t]of D){const n=[...f.comments].reverse().find(u=>u.frameId===e&&u.options?.some(p=>p.files?.length&&!p.frameId)&&!u.optionChosen&&!u.optionsCleared);let a=t.el.querySelector(":scope > .opt-strip");if(!n||!$()){a?.remove();continue}const i=f.frames.find(u=>u.id===e),s=i?i.w/i.h:1.5,o=Math.round(Math.min(150,Math.max(70,84*s))),r=Math.round(o/s),c=n.options.filter(u=>u.files?.length&&!u.frameId),l=n.id+"|"+(n.optionApplied||"")+"|"+c.map(u=>u.id+(u.thumb||"")).join(",");if(a?.dataset.key===l)continue;a||(a=document.createElement("div"),a.className="opt-strip",t.el.appendChild(a),a.addEventListener("pointerdown",u=>u.stopPropagation()),a.addEventListener("click",async u=>{const p=u.target.closest("[data-opt]"),h=u.target.closest("[data-use]"),g=a.dataset.cid;try{h?(await w("POST",`/__loop/api/comments/${g}/choose`,{option:h.dataset.use}),y(`Using option ${h.dataset.use}`)):p&&await w("POST",`/__loop/api/comments/${g}/preview`,{option:p.dataset.opt||null})}catch(v){y(v.message)}})),a.dataset.key=l,a.dataset.cid=n.id;const d=(u,p,h)=>`<button class="os-tile${(n.optionApplied||"")===u?" on":""}" data-opt="${u}" title="${u?`Preview ${L(p)}`:"Back to the original"}">
23
+ <span class="os-img" style="width:${o}px;height:${r}px">${h?`<img src="${L(h)}" alt="">`:`<b>${u||"\xB7"}</b>`}</span>
24
+ <span class="os-name">${u?`<i>${u}</i>`:""}${L(p)}</span></button>`;a.innerHTML=`<span class="os-label">Options</span>${d("","Original",n.origThumb||"")}${c.map(u=>d(u.id,u.name,u.thumb)).join("")}
25
+ ${n.optionApplied?`<button class="os-use" data-use="${n.optionApplied}">Use ${n.optionApplied}</button>`:""}`,c.some(u=>!u.thumb)&&i?.kind==="folder"&&!n._thumbsAsked&&(n._thumbsAsked=!0,w("POST",`/__loop/api/comments/${n.id}/thumbs`).catch(()=>{}))}}function Yl(e){const t=(e.options||[]).filter(a=>a.files?.length);if(!t.length)return"";if(t.some(a=>a.frameId)||e.optionsCleared){const a=t.filter(i=>i.frameId&&f.frames.some(s=>s.id===i.frameId));return a.length?`<div class="m-opts">${a.map(i=>`<button class="opt${e.optionChosen===i.id?" on":""}" data-goto="${i.frameId}" title="Go to this option's frame"><b>${L(i.id)}</b>${L(i.name)}</button>`).join("")}</div>`:e.optionChosen?`<div class="m-opts chosen"><span class="opt on"><b>${L(e.optionChosen)}</b>${L(t.find(i=>i.id===e.optionChosen)?.name||"")}</span><span class="opt-note">Chosen</span></div>`:""}if(e.optionChosen){const a=t.find(i=>i.id===e.optionChosen);return`<div class="m-opts chosen"><span class="opt on"><b>${L(a?.id||"")}</b>${L(a?.name||"")}</span><span class="opt-note">Chosen</span></div>`}const n=$();return`<div class="m-opts">${t.map(a=>`<button class="opt${e.optionApplied===a.id?" on":""}" ${n?`data-opt="${a.id}" data-for="${e.id}"`:"disabled"} title="Preview in the frame"><b>${L(a.id)}</b>${L(a.name)}</button>`).join("")}
26
+ ${n&&e.optionApplied?`<span class="opt-acts"><button class="opt-use" data-use="${e.optionApplied}" data-for="${e.id}">Use ${L(e.optionApplied)}</button><button class="opt-orig" data-opt="" data-for="${e.id}">Original</button></span>`:`<span class="opt-note">${n?"Click an option to preview it in the frame":"Options"}</span>`}</div>`}z.addEventListener("click",async e=>{const t=e.target.closest("[data-goto]");if(t){const s=t.dataset.goto;f.frames.some(o=>o.id===s)&&(ee(),Z(s),Oe(!0,[s]));return}const n=e.target.closest("[data-opt]"),a=e.target.closest("[data-use]");if(!n&&!a)return;const i=(n||a).dataset.for;try{a?(await w("POST",`/__loop/api/comments/${i}/choose`,{option:a.dataset.use}),y(`Using option ${a.dataset.use}`)):await w("POST",`/__loop/api/comments/${i}/preview`,{option:n.dataset.opt||null})}catch(s){y(s.message)}});function qa(e){const t=i=>L(i).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<b>$1</b>").replace(/(^|[\s(])\*([^*\s][^*]*)\*/g,"$1<i>$2</i>"),n=[];let a=null;for(const i of String(e).split(`
27
+ `)){const s=/^\s*(?:[-*•]|\d+\.)\s+(.*)$/.exec(i);if(s){a||(a=[],n.push(a)),a.push(t(s[1]));continue}a=null,i.trim()&&n.push(`<p>${t(i)}</p>`)}return n.map(i=>Array.isArray(i)?`<ul>${i.map(s=>`<li>${s}</li>`).join("")}</ul>`:i).join("")}function Vl(e){return e.attachments?.length?`<div class="m-files">${e.attachments.map(t=>t.type.startsWith("image/")?`<a href="${L(t.url)}" target="_blank" rel="noopener"><img src="${L(t.url)}" alt="${L(t.name)}"></a>`:`<a class="f" href="${L(t.url)}" target="_blank" rel="noopener">${pn.file}<span>${L(t.name)}</span></a>`).join("")}</div>`:""}const Da=[];function Xl(e){const t=(e.inkStrokes||[]).filter(a=>f.strokes.some(i=>i.id===a)).length;if(!t)return"";const n=Vt.has(e.id);return`<button class="m-marks${n?" on":""}" data-marks="${e.id}" title="${n?"Hide":"Show"} the marks on the canvas">${Co}<span>${n?"Hide":`${t} mark${t===1?"":"s"}`}</span></button>`}z.addEventListener("pointerover",e=>{const t=e.target.closest("[data-marks]");t&&dn!==t.dataset.marks&&(dn=t.dataset.marks,qt())}),z.addEventListener("pointerout",e=>{const t=e.target.closest("[data-marks]");t&&!t.contains(e.relatedTarget)&&(dn=null,qt())}),z.addEventListener("click",e=>{const t=e.target.closest("[data-marks]");if(!t)return;const n=t.dataset.marks;Vt.has(n)?Vt.delete(n):Vt.add(n),qt(),Ia()});function Ia(){const e=f.comments.find(i=>i.id===j);if(!e)return ee();if(z.dataset.tid!==e.id){z.dataset.tid=e.id,z.innerHTML=`<div class="t-tools"></div><div class="thread-body"></div>
28
+ <div class="thread-reply"><div class="cbox"><div class="c-files" hidden></div><textarea rows="1" placeholder="Reply"></textarea></div></div>`,z._tools=null;const i=z.querySelector("textarea");or(i);const s=async()=>{const r=f.comments.find(h=>h.id===j);if(!r)return;const c=Da.splice(0),l=i.value.trim()||(c.length?"See the attached reference.":"");if(!l)return;i.value="",ot(i),o.paint();const d={id:ga(),frameId:r.frameId,parentId:r.id,text:l,author:{name:U.name,color:U.color},attachments:c,refs:rr(i,l)},u=Pa(d),p=z.querySelector(".thread-body");p&&(p.scrollTop=p.scrollHeight);try{const h=await w("POST","/__loop/api/comments",d);h?.id&&h.id!==d.id&&u()}catch(h){u(),y(h.message)}},o=So(z.querySelector(".thread-reply .cbox"),Da,s);ot(i),i.addEventListener("input",()=>ot(i)),i.addEventListener("keydown",r=>{if(r.stopPropagation(),r.key==="Escape")return ee();r.key==="Enter"&&!r.shiftKey&&!r.isComposing&&(r.preventDefault(),s())}),i.addEventListener("focus",()=>Fi(f.comments.find(r=>r.id===j)?.frameId),{once:!0})}const t=`
29
+ ${io(e)}
30
+ <span class="t-title">${L(e.frameId===le?"Canvas":f.frames.find(i=>i.id===e.frameId)?.name||"")}</span>
31
31
  ${e.resolved?'<span class="t-state">Resolved</span>':""}
32
- <button class="t-btn" data-act="dock" title="${st?"Collapse":"Expand"}">${st?Fe.collapse:Fe.expand}</button>
33
- <button class="t-btn" data-act="resolve" title="${e.resolved?"Reopen":"Resolve"}">${e.resolved?Fe.reopen:Fe.resolve}</button>
34
- <span class="t-more"><button class="t-btn" data-act="more" title="More">${Fe.more}</button>
35
- <span class="t-menu" hidden><button data-act="delete">${Fe.trash}<span>Delete thread</span></button></span></span>
36
- <button class="t-btn" data-act="close" title="Close (esc)">${Fe.close}</button>`;D._tools!==t&&(D._tools=t,D.querySelector(".t-tools").innerHTML=t);const n=D.querySelector(".thread-body"),i=n.scrollHeight-n.scrollTop-n.clientHeight<40;Pa(n,Wt(e.id).map(s=>[s.id,ks(s)])),qa(D),i&&(n.scrollTop=n.scrollHeight),Ce()}D.addEventListener("click",e=>{const t=e.target.closest("[data-copy]");if(!t)return;const n=u.comments.find(i=>i.id===t.dataset.copy);navigator.clipboard?.writeText(n?.kind==="note"?n.text:n?.reply||"").then(()=>{t.innerHTML=Pn.check,t.classList.add("ok"),setTimeout(()=>{t.innerHTML=Pn.copy,t.classList.remove("ok")},1200)}).catch(()=>{})});let st=!1;const Fe={expand:T("expand"),collapse:T("collapse"),resolve:T("resolve"),reopen:T("reopen"),more:T("more"),close:T("x"),reply:T("reply"),trash:T("trash")};function Va(){m("#comments-panel").hidden=!0,St(),Re&&(Re=null,He()),m("#shortcuts")?.setAttribute("hidden","")}let qe=!!$e.get("loop.hideComments",!1);function qn(e){qe=e?!1:!qe,$e.set("loop.hideComments",qe),document.body.classList.toggle("no-comments",qe),qe&&(Pe(),J(),ne()),m("#comments-btn").classList.toggle("off",qe),m("#comments-btn").dataset.tip=qe?"Comments are hidden (\u21E7C to show)":"All comments",b(qe?"Comments hidden \xB7 \u21E7C to show":"Comments shown",1600)}document.body.classList.toggle("no-comments",qe),m("#comments-btn").classList.toggle("off",qe);let wi="open";function Xa(){return u.comments.filter(e=>!e.parentId&&e.kind!=="create").sort((e,t)=>t.createdAt-e.createdAt)}function dl(){const e=u?Xa().filter(t=>!t.resolved).length:0;m("#comments-count").textContent=e||"",m("#comments-btn").classList.toggle("has",e>0),m("#comments-panel").hidden||$s()}function $s(){const e=Xa(),t=e.filter(o=>!o.resolved),n=e.filter(o=>o.resolved),i=m("#comments-panel .cp-tabs");i.querySelector('[data-tab="open"] span').textContent=t.length||"",i.querySelector('[data-tab="resolved"] span').textContent=n.length||"",i.querySelectorAll("button").forEach(o=>o.classList.toggle("on",o.dataset.tab===wi));const s=wi==="open"?t:n,a=o=>o.frameId===ce?"Canvas":u.frames.find(r=>r.id===o.frameId)?.name||"Deleted frame";m("#comments-panel .cp-list").innerHTML=s.length?s.map(o=>{const r=ci(o.id);return`
37
- <div class="cp-item${W===o.id?" on":""}" data-id="${o.id}" title="${L(`${o.author?.name||"You"} \xB7 ${a(o)} \xB7 ${jt(o.createdAt)}`)}">
38
- <span class="cp-av${r==="working"||r==="queued"?" busy":r==="error"?" err":""}">${aa(o.author?.name||V.name,o.author?.color||V.color)}</span>
32
+ <button class="t-btn" data-act="dock" title="${pt?"Collapse":"Expand"}">${pt?Je.collapse:Je.expand}</button>
33
+ <button class="t-btn" data-act="resolve" title="${e.resolved?"Reopen":"Resolve"}">${e.resolved?Je.reopen:Je.resolve}</button>
34
+ <span class="t-more"><button class="t-btn" data-act="more" title="More">${Je.more}</button>
35
+ <span class="t-menu" hidden><button data-act="delete">${Je.trash}<span>Delete thread</span></button></span></span>
36
+ <button class="t-btn" data-act="close" title="Close (esc)">${Je.close}</button>`;z._tools!==t&&(z._tools=t,z.querySelector(".t-tools").innerHTML=t);const n=z.querySelector(".thread-body"),a=n.scrollHeight-n.scrollTop-n.clientHeight<40;so(n,Xt(e.id).map(i=>[i.id,ji(i)])),oo(z),a&&(n.scrollTop=n.scrollHeight),_e()}z.addEventListener("click",e=>{const t=e.target.closest("[data-copy]");if(!t)return;const n=f.comments.find(a=>a.id===t.dataset.copy);navigator.clipboard?.writeText(n?.kind==="note"?n.text:n?.reply||"").then(()=>{t.innerHTML=Wn.check,t.classList.add("ok"),setTimeout(()=>{t.innerHTML=Wn.copy,t.classList.remove("ok")},1200)}).catch(()=>{})});let pt=!1;const Je={expand:A("expand"),collapse:A("collapse"),resolve:A("resolve"),reopen:A("reopen"),more:A("more"),close:A("x"),reply:A("reply"),trash:A("trash")};function xo(){m("#comments-panel").hidden=!0,gt(),Ke&&(Ke=null,Fe()),m("#shortcuts")?.setAttribute("hidden","")}let Ne=!!Ae.get("loop.hideComments",!1);function jn(e){Ne=e?!1:!Ne,Ae.set("loop.hideComments",Ne),document.body.classList.toggle("no-comments",Ne),Ne&&(Re(),ee(),te()),m("#comments-btn").classList.toggle("off",Ne),m("#comments-btn").dataset.tip=Ne?"Comments are hidden (\u21E7C to show)":"All comments",y(Ne?"Comments hidden \xB7 \u21E7C to show":"Comments shown",1600)}document.body.classList.toggle("no-comments",Ne),m("#comments-btn").classList.toggle("off",Ne);let Ha="open";function ko(){return f.comments.filter(e=>!e.parentId&&e.kind!=="create").sort((e,t)=>t.createdAt-e.createdAt)}function Ul(){const e=f?ko().filter(t=>!t.resolved).length:0;m("#comments-count").textContent=e||"",m("#comments-btn").classList.toggle("has",e>0),m("#comments-panel").hidden||Ki()}function Ki(){const e=ko(),t=e.filter(o=>!o.resolved),n=e.filter(o=>o.resolved),a=m("#comments-panel .cp-tabs");a.querySelector('[data-tab="open"] span').textContent=t.length||"",a.querySelector('[data-tab="resolved"] span').textContent=n.length||"",a.querySelectorAll("button").forEach(o=>o.classList.toggle("on",o.dataset.tab===Ha));const i=Ha==="open"?t:n,s=o=>o.frameId===le?"Canvas":f.frames.find(r=>r.id===o.frameId)?.name||"Deleted frame";m("#comments-panel .cp-list").innerHTML=i.length?i.map(o=>{const r=Ca(o.id);return`
37
+ <div class="cp-item${j===o.id?" on":""}" data-id="${o.id}" title="${L(`${o.author?.name||"You"} \xB7 ${s(o)} \xB7 ${Ut(o.createdAt)}`)}">
38
+ <span class="cp-av${r==="working"||r==="queued"?" busy":r==="error"?" err":""}">${As(o.author?.name||U.name,o.author?.color||U.color)}</span>
39
39
  <span class="cp-text">${L(o.text)}</span>
40
- ${k()?`<button class="cp-res" data-res="${o.id}" title="${o.resolved?"Reopen":"Resolve"}">${o.resolved?Fe.reopen:Fe.resolve}</button>`:""}
41
- </div>`}).join(""):`<div class="cp-empty">${wi==="open"?"No open comments. Press C and click anything to leave one.":"Nothing resolved yet."}</div>`}function Ls(e,t){qe&&qn(!0),J(),Pe(),E&&bt();const n=e.frameId!==ce&&u.frames.find(s=>s.id===e.frameId),i=e.anchor;if(n&&i){H.get(n.id)?.parked&&(ie(n.id),Ln());try{const a=i.selector||i.container?.selector||i.elements?.[0]?.selector,o=a&&le(n.id)?.querySelector(a),r=o?.getBoundingClientRect();r&&(r.top<0||r.bottom>n.h||r.left<0||r.right>n.w)&&o.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}}requestAnimationFrame(()=>{const s=m("#comments-panel").hidden?0:364;if(n){ie(n.id);const a=24,o=76,r=innerWidth-s-a-24,l=innerHeight-o-96,c=Math.min(1,r/n.w,l/n.h);et({z:c,x:a+(r-n.w*c)/2-n.x*c,y:o+(l-n.h*c)/2-n.y*c},380)}else{const a=(i?.wx||0)+(i?.area?.w||0)/2,o=(i?.wy||0)+(i?.area?.h||0)/2,r=Math.max(y.z,.8);et({z:r,x:(innerWidth-s)/2-a*r,y:innerHeight/2-o*r},380)}setTimeout(()=>{if(e.resolved||t)return An(e.id);it(e.frameId);const a=ui(e.frameId)?.querySelector(`.pin[data-key="${e.id}"]`);a&&(a.classList.remove("ping"),a.offsetWidth,a.classList.add("ping"),setTimeout(()=>a.classList.remove("ping"),2200))},420)})}m("#comments-btn").addEventListener("click",()=>{const e=m("#comments-panel");e.hidden=!e.hidden,e.hidden||(St?.(),$s())}),m("#comments-panel").addEventListener("pointerdown",e=>e.stopPropagation()),m("#comments-panel").addEventListener("wheel",e=>e.stopPropagation()),m("#comments-panel").addEventListener("click",async e=>{if(e.target.closest(".cp-x")){m("#comments-panel").hidden=!0;return}const t=e.target.closest("[data-tab]");if(t){wi=t.dataset.tab,$s();return}const n=e.target.closest("[data-res]");if(n){try{await w("POST",`/__loop/api/comments/${n.dataset.res}/resolve`)}catch(a){b(a.message)}return}const i=e.target.closest(".cp-item");if(!i)return;const s=u.comments.find(a=>a.id===i.dataset.id);s&&Ls(s)}),m("#comments-panel").addEventListener("dblclick",e=>{const t=e.target.closest(".cp-item");if(!t||e.target.closest("[data-res]"))return;const n=u.comments.find(i=>i.id===t.dataset.id);n&&Ls(n,!0)});const on={plus:T("plus"),mic:T("mic"),up:T("up"),file:T("file"),x:T("x","s")},Ua=6,fl=8e6,Za=window.SpeechRecognition||window.webkitSpeechRecognition,In=[],Ga=T("pen","s"),ul={fable:"Fable",opus:"Opus",sonnet:"Sonnet",haiku:"Haiku"},pl={minimal:"Minimal",low:"Low",medium:"Medium",high:"High",xhigh:"Extra high",max:"Max",ultra:"Ultra"},Cs=e=>ul[e]||_n(e),Ms=e=>pl[e]||e,ye=document.createElement("div");ye.id="model-menu",ye.className="menu model-menu",ye.hidden=!0,document.body.appendChild(ye);let xi=null;function Qa(){const e=u?.models;if(!e)return;const t=e.runner==="codex"?"Codex default":e.chat.model||e.chat.effort?"Same as your chat":"Default",n=(i,s,a,o)=>`<button class="tm-item${(e.pick[i]||"")===s?" on":""}" data-mm="${i}" data-v="${L(s)}"><span class="tm-check"></span><span>${L(a)}</span>${o?`<kbd>${L(o)}</kbd>`:""}</button>`;ye.innerHTML=`<div class="mm-title">Model</div>${n("model","",t,e.chat.model?Cs(e.chat.model):"")}${e.models.map(i=>n("model",i,Cs(i))).join("")}
42
- <div class="mm-title">Effort</div>${n("effort","",t,e.chat.effort?Ms(e.chat.effort):"")}${e.efforts.map(i=>n("effort",i,Ms(i))).join("")}
43
- ${u.agent.mode==="inbox"?'<p class="mm-note">Your chat answers with its own model. This is for the runs Loop starts itself.</p>':""}`}function Ja(){if(!xi?.isConnected){ye.hidden=!0;return}const e=xi.getBoundingClientRect(),t=ye.offsetWidth,n=ye.offsetHeight,i=e.top-n-8>=8||e.top>innerHeight-e.bottom;ye.style.left=`${Math.max(8,Math.min(innerWidth-t-8,e.right-t))}px`,ye.style.top=`${Math.max(8,Math.min(innerHeight-n-8,i?e.top-n-8:e.bottom+8))}px`}document.addEventListener("click",e=>{const t=e.target.closest(".c-model.pick");if(t){if(!ye.hidden&&xi===t){ye.hidden=!0;return}xi=t,Qa(),ye.hidden=!1,Ja()}}),ye.addEventListener("pointerdown",e=>e.stopPropagation()),ye.addEventListener("click",async e=>{const t=e.target.closest("[data-mm]");if(t){if(u.models){const n=u.models,i=t.dataset.mm;n.pick[i]=t.dataset.v||null,n[i]=n.pick[i]||n.chat[i],Es()}try{await w("POST","/__loop/api/settings",{pick:{[t.dataset.mm]:t.dataset.v||null}})}catch(n){b(n.message)}}}),addEventListener("pointerdown",e=>{!ye.hidden&&!e.target.closest("#model-menu, .c-model")&&(ye.hidden=!0)},!0),addEventListener("keydown",e=>{e.key==="Escape"&&!ye.hidden&&(ye.hidden=!0,e.stopPropagation())},!0);function Es(){const e=ml(),t=!!u?.models&&k();document.querySelectorAll(".c-model").forEach(n=>{n.textContent!==e&&(n.textContent=e),n.classList.toggle("pick",t),n.title=t?"Model and effort":""}),ye.hidden||(Qa(),Ja())}function ml(){if(!u)return"";if(!k())return"Host reviews first";const e=u.models;if(e?.model){const i=u.agent.lastModel,s=e.pick.model&&i&&i.startsWith(`claude-${e.pick.model}-`)?i:e.model;return Cs(s)+(e.pick.effort?` \xB7 ${Ms(e.pick.effort)}`:"")}const t=u.agent.lastModel;return t&&(u.agentBin==="codex"?!/^claude/.test(t):/^claude/.test(t))?_n(t):u.agentLabel||"Agent"}const hl=e=>new Promise((t,n)=>{const i=new FileReader;i.onload=()=>t(i.result),i.onerror=n,i.readAsDataURL(e)});function eo(e,t,n){e.insertAdjacentHTML("beforeend",`<div class="c-foot"><button type="button" class="c-btn" data-box="attach" title="Attach images or files \u2014 or drop them here">${on.plus}</button><input type="file" multiple hidden><span class="c-model"></span>${Za?`<button type="button" class="c-btn" data-box="mic" title="Dictate">${on.mic}</button>`:""}<button type="button" class="c-send" data-box="send" title="Send (\u21B5)">${on.up}</button></div>`);const i=e.querySelector("textarea"),s=e.querySelector("input[type=file]"),a=e.querySelector(".c-files"),o=e.querySelector(".c-send"),r=()=>{o.disabled=!i.value.trim()&&!t.length},l=()=>{a.hidden=!t.length,a.innerHTML=t.map((f,d)=>`<span class="c-file${f.type.startsWith("image/")?" img":""}" title="${L(f.name)}">${f.type.startsWith("image/")?`<img src="${f.data}" alt="">`:`${on.file}<span>${L(f.name)}</span>`}<button type="button" data-rm="${d}" title="Remove">${on.x}</button></span>`).join(""),Es(),r()},c=async f=>{for(const d of f){if(t.length>=Ua){b(`Up to ${Ua} files per message`);break}if(d.size>fl){b(`${d.name} is over 8 MB`);continue}t.push({name:d.name||"pasted-image.png",type:d.type||"application/octet-stream",data:await hl(d)})}l(),i.focus()};return s.addEventListener("change",()=>{c([...s.files]),s.value=""}),e.addEventListener("click",f=>{const d=f.target.closest("[data-rm]");if(d){t.splice(+d.dataset.rm,1),l();return}const p=f.target.closest("[data-box]");p&&(p.dataset.box==="attach"?s.click():p.dataset.box==="mic"?gl(i,p,r):p.dataset.box==="send"&&n())}),e.addEventListener("dragover",f=>{[...f.dataTransfer.types].includes("Files")&&(f.preventDefault(),f.stopPropagation(),e.classList.add("drop"))}),e.addEventListener("dragleave",f=>{e.contains(f.relatedTarget)||e.classList.remove("drop")}),e.addEventListener("drop",f=>{f.preventDefault(),f.stopPropagation(),e.classList.remove("drop"),c([...f.dataTransfer.files])}),i.addEventListener("paste",f=>{const d=[...f.clipboardData?.files||[]];d.length&&(f.preventDefault(),c(d))}),i.addEventListener("input",r),l(),{paint:l}}let rn=null;function gl(e,t,n){if(rn){rn.stop();return}const i=new Za;i.continuous=!0,i.interimResults=!0,i.lang=navigator.language||"en-US";const s=e.value&&!/\s$/.test(e.value)?e.value+" ":e.value;i.onresult=a=>{let o="";for(const r of a.results)o+=r[0].transcript;e.value=s+o,gt(e),n()},i.onend=()=>{rn=null,t.classList.remove("on"),e.focus()},i.onerror=a=>{a.error==="not-allowed"||a.error==="service-not-allowed"?b("Allow microphone access to dictate"):["aborted","no-speech"].includes(a.error)||b(`Dictation stopped (${a.error})`)},rn=i,t.classList.add("on");try{i.start()}catch{rn=null,t.classList.remove("on")}}function to(){try{rn?.stop()}catch{}}const Ss=eo(z.querySelector(".cbox"),In,()=>Na());D.addEventListener("pointerdown",e=>{e.stopPropagation(),$t=!1}),D.addEventListener("click",async e=>{const t=e.target.closest("[data-act]");if(!t)return;const n=t.dataset.act,i=t.dataset.id||W;try{if(n==="close")return J();if(n==="dock"){st=!st,$t=!1,D.classList.toggle("docked",st),st&&(D.style.left=D.style.top=D.style.maxHeight=""),bi(),Ce();return}if(n==="more"){const s=D.querySelector(".t-menu");s.hidden=!s.hidden;return}if(n==="allow"){t.disabled=!0,t.textContent="Allowing\u2026",await w("POST",`/__loop/api/comments/${i}/allow`,{i:+t.dataset.k});return}if(n==="allowall"){t.disabled=!0,t.textContent="Allowing\u2026",await w("POST",`/__loop/api/comments/${i}/allow`,{all:!0,i:u.comments.find(s=>s.id===i)?.blocked?.findIndex(s=>!s.allowed)});return}if(n==="before"){const s=u.comments.find(a=>a.id===i);s&&(ir(s.frameId,s.id),Tt(s.frameId));return}if(n==="delete"){confirm("Delete this comment thread? This can\u2019t be undone.")&&(await w("DELETE",`/__loop/api/comments/${W}`),J());return}if(n==="resolve"){const s=u.comments.find(a=>a.id===W)?.resolved;await w("POST",`/__loop/api/comments/${W}/resolve`),s||(J(),b("Resolved. Find it in Comments \u2192 Resolved"));return}if(n==="undo"){let s=await fetch(`/__loop/api/comments/${i}/undo`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}),a=await s.json().catch(()=>({}));if(s.status===409&&a.error==="newer"){if(!confirm(`This frame has ${a.newer} newer change${a.newer===1?"":"s"} after this one. Undoing this reverts ${a.newer===1?"it":"them"} too. Continue?`))return;s=await fetch(`/__loop/api/comments/${i}/undo`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({force:!0})}),a=await s.json().catch(()=>({}))}if(!s.ok)throw new Error(a.error||"Could not undo");b(a.reverted>1?`Reverted ${a.reverted} changes`:"Change reverted");return}await w("POST",`/__loop/api/comments/${i}/${n}`),n==="redo"&&b("Change re-applied")}catch(s){b(s.message)}}),z.addEventListener("pointerdown",e=>e.stopPropagation()),m("#empty .empty-set").addEventListener("pointerdown",e=>e.stopPropagation()),m("#empty").addEventListener("click",e=>{const t=e.target.closest(".empty-frame");t&&k()&&Dn(t.dataset.name,+t.dataset.w,+t.dataset.h)});for(const e of["click","dblclick","contextmenu"])z.addEventListener(e,t=>{z.classList.contains("onpage")&&t.stopPropagation()});addEventListener("scroll",()=>{for(const e of[document.scrollingElement,document.body,q])e&&(e.scrollTop||e.scrollLeft)&&(e.scrollTop=0,e.scrollLeft=0)},!0);let Ie=!1;function we(e){if(!((e==="frame"||e==="section")&&!k())){if(Ie=e==="use",Ie&&(e="select"),!Ie&&de&&!E&&(de=null,ot()),e!=="deep"&&$&&Ye(),F?.soft&&!U.value.trim()&&ne(),j=e,q.dataset.tool=e,e!=="select"&&de&&(de=null,ot()),e==="select"||e==="hand"){const t=m("#move-btn");t.dataset.tool!==e&&(t.dataset.tool=e,t.innerHTML=T(e==="hand"?"hand":"select"),t.title=e==="hand"?"Hand (H)":"Select (V)")}if(document.querySelectorAll("#tool-menu [data-pick-tool]").forEach(t=>t.classList.toggle("on",t.dataset.pickTool===e&&!Ie)),document.querySelectorAll("#toolbar [data-tool]").forEach(t=>t.classList.toggle("on",t.dataset.tool===(Ie?"use":e))),q.dataset.use=Ie?"1":"",Gs(),wo(),Ie&&$&&(ne(),Ye()),Y.hidden=!0,e!=="pen"&&Tn(),u)for(const t of u.frames)Q(t);He()}}document.querySelectorAll("#toolbar [data-tool]").forEach(e=>e.addEventListener("click",()=>we(e.dataset.tool)));const at=m("#tool-menu");m("#move-caret").addEventListener("click",e=>{if(e.stopPropagation(),!at.hidden){at.hidden=!0;return}at.hidden=!1;const t=m("#move-caret").closest(".tb-group").getBoundingClientRect();at.style.left=`${Math.round(t.left)}px`,at.style.bottom=`${Math.round(innerHeight-t.top+8)}px`,at.style.top="auto"}),at.addEventListener("click",e=>{const t=e.target.closest("[data-pick-tool]");t&&(we(t.dataset.pickTool),at.hidden=!0)}),addEventListener("pointerdown",e=>{!at.hidden&&!e.target.closest("#tool-menu, #move-caret")&&(at.hidden=!0)},!0);let Re=null,de=null;function Ts(e){if(de!==e&&(de=e,u))for(const t of u.frames)Q(t)}function no(e,t,n){if(!n)return!1;const i=e?.ownerDocument;if(!i)return!1;const s=i.defaultView,a=i.scrollingElement||i.documentElement;for(let o=e.nodeType===1?e:e.parentElement;o;o=o.parentElement){const r=o===a||o===i.body,l=s.getComputedStyle(o),c=t==="x"?l.overflowX:l.overflowY;if(!r&&!/(auto|scroll|overlay)/.test(c))continue;const f=r?a:o,d=t==="x"?f.scrollLeft:f.scrollTop,p=t==="x"?f.scrollWidth-f.clientWidth:f.scrollHeight-f.clientHeight;if(p>1&&(n>0?d<p-1:d>0))return!0;if(r)break}return!1}function ot(){document.activeElement?.tagName==="IFRAME"&&document.activeElement.blur(),window.focus()}function ie(e){if(Se&&(Se=null,Nt()),e!==Re&&(Re=null),(e||de)&&(de=null,ot()),I=e,K.clear(),u)for(const t of u.frames)Q(t);He(),Wn(),Vi()}let ae=null,ln={fid:null,t:0,x:0,y:0};q.addEventListener("pointermove",e=>{const t=e.target.closest?.(".frame")?.dataset.id||null;t!==$n&&($n=t,tn())}),q.addEventListener("pointerleave",()=>{$n&&($n=null,tn())}),q.addEventListener("pointerdown",e=>{if(tn(),!u||e.target.closest(".pin, .stop, .rename, .count, .dims"))return;_&&e.target.closest(".frame")?.dataset.id!==_.fid&&Xe();const t=E&&e.button===0&&e.target.closest(".frame-body")&&e.target.closest(".frame")?.dataset.id;if(t&&t!==E.fid&&z.hidden&&!W)return e.preventDefault(),Vt(t);if(E&&e.button===0&&e.target.closest(".frame:not(.edge-zone)")?.dataset.id!==E.fid){!z.hidden||W?(ne(),J()):bt();return}const n=e.target.closest(".edge-zone")?null:e.target.closest(".frame"),i=n?.dataset.id;if(E&&e.button===0&&i&&i!==E.fid)return e.preventDefault(),Vt(i);if(e.button===1||j==="hand"||Bt)return vl(e);if(e.button!==0)return;if(j==="pen")return xl(e);if(j==="frame"||j==="section")return bl(e);if(j==="erase"){ae={type:"erase"},ao(e),q.setPointerCapture(e.pointerId);return}if(j==="deep"){if(i&&e.target.closest(".frame-body")){dn(i,e);return}Ye(),ne(),J();return}if(j==="comment"&&i&&e.target.closest(".frame-label")){e.preventDefault(),J(),Mt(i,0,0),F.scope="frame",F.anchor=Mn(i,{scope:"frame",x:0,y:0});const r=m("#composer-area");r.hidden=!1,r.innerHTML=`${T("frame")}<b>${L(u.frames.find(l=>l.id===i)?.name||"Frame")}</b><span>Whole frame</span>`,r.classList.add("chip-frame"),U.placeholder="What should change about this screen?",H.get(i)?.el.classList.add("whole"),ht(i),Ce();return}if(j==="comment"){const r=i&&e.target.closest(".frame-body");if(!r&&(!z.hidden||W)){ne(),J();return}ae={type:"cpick",fid:r?i:ce,sx:e.clientX,sy:e.clientY,area:!1,rect:null},q.setPointerCapture(e.pointerId);return}if(e.altKey&&k()&&!Ie&&!E&&i&&e.target.closest(".frame-body")&&!e.target.closest(".pin")&&!wn(u.frames.find(r=>r.id===i)||{})){const{lx:r,ly:l}=tt(i,e.clientX,e.clientY),c=Me(i,r,l),f=le(i),d=$?.frameId===i?$.els[$.els.length-1]:null,p=d&&d.contains(c)?d:Pi(i,c,"deep");if(p&&p!==f?.documentElement&&p!==f?.body){p!==d&&dn(i,e),ae={type:"edrag",fid:i,el:p,sx:e.clientX,sy:e.clientY,moved:!1},q.classList.add("dragging"),q.setPointerCapture(e.pointerId);return}}if(!Ie&&(!E||i===E.fid)&&i&&e.target.closest(".frame-body")&&!e.target.closest(".pin")&&!wn(u.frames.find(r=>r.id===i)||{})&&!H.get(i)?.el.classList.contains("empty")){const r=performance.now(),l=Bn.fid===i&&r-Bn.t<420&&Math.hypot(e.clientX-Bn.x,e.clientY-Bn.y)<6;Bn={fid:i,t:l?0:r,x:e.clientX,y:e.clientY};const c=$?.frameId===i?$.els[$.els.length-1]:null;if(l&&c&&k()&&un(c,!0)){pn(i,c);return}if(l)return;if(J(),c&&k()&&!e.shiftKey&&!E&&$.els.length===1&&c.isConnected&&c.parentElement&&c!==le(i)?.body){const{lx:f,ly:d}=tt(i,e.clientX,e.clientY),p=Me(i,f,d);if(p&&c.contains(p)){ae={type:e[lt]?"efree":"emove",fid:i,el:c,sx:e.clientX,sy:e.clientY,moved:!1,ev:{clientX:e.clientX,clientY:e.clientY,shiftKey:!1}},q.classList.add("dragging"),q.setPointerCapture(e.pointerId);return}}dn(i,e,e[lt]?"deep":"step");return}$&&!e.target.closest(".pin")&&Ye(),ne();const s=i?null:e.target.closest(".section"),a=s?s.dataset.id:null;if(a&&e.target.closest(".srz")&&k())return Pc(a,e);if(a&&!e.target.closest(".sec-label")&&!e.shiftKey){J(),de&&(de=null,ot()),Qi(a),k()&&tr(a,e);return}if(a&&e.target.closest(".sec-label")){J();const r=performance.now(),l=Zi.id===a&&r-Zi.t<420;return Zi={id:a,t:r},Qi(a),k()?l&&e.target.closest(".sec-name")?(e.preventDefault(),Zi.t=0,zc(a)):tr(a,e):void 0}if(e.target.closest(".resize")&&k())return wl(i,e);if(i&&e.shiftKey&&k()){mc(i),J();return}if(e.target.closest(".frame-label")){J();const r=performance.now(),l=ln.fid===i&&r-ln.t<420&&Math.hypot(e.clientX-ln.x,e.clientY-ln.y)<6;if(ln={fid:i,t:r,x:e.clientX,y:e.clientY},l&&k()&&e.target.closest(".name")&&!H.get(i)?.renaming)return e.preventDefault(),ie(i),ln.t=0,ka(i);if(K.has(i))return k()?io(i,e):void 0;if(ie(i),!k())return;so(i,e),ae.onDims=!!e.target.closest(".dims");return}if(i&&e.target.closest(".frame-body")&&wn(u.frames.find(r=>r.id===i)||{})){J();const r=performance.now(),l=Ui.fid===i&&r-Ui.t<420;if(Ui={fid:i,t:r},l)return Ui.t=0,ie(i),Ge(!0,[i]);if(K.has(i))return k()?io(i,e):void 0;ie(i),k()&&so(i,e);return}if(J(),!i&&!e.shiftKey&&(ie(null),de)){de=null,ot();for(const r of u.frames)Q(r)}yl(e,i),ae.clickSid=a||null});function yl(e,t){const n=re(e.clientX,e.clientY);ae={type:"marquee",x0:n.x,y0:n.y,clickFid:t,base:e.shiftKey?new Set([...K,...I?[I]:[]]):new Set},q.classList.add("dragging"),q.setPointerCapture(e.pointerId)}function io(e,t){const n=[...K];ae={type:"gmove",ids:n,sx:t.clientX,sy:t.clientY,from:Object.fromEntries(n.map(i=>{const s=u.frames.find(a=>a.id===i);return[i,{x:s.x,y:s.y}]})),moved:!1},q.classList.add("dragging"),q.setPointerCapture(t.pointerId)}function vl(e){ae={type:"pan",sx:e.clientX,sy:e.clientY,vx:y.x,vy:y.y},q.classList.add("dragging"),q.setPointerCapture(e.pointerId)}function so(e,t){const n=u.frames.find(i=>i.id===e);ae={type:"move",fid:e,sx:t.clientX,sy:t.clientY,fx:n.x,fy:n.y,moved:!1,dup:t.altKey,kids:t.altKey?[]:Al(e).map(i=>({id:i.id,x:i.x,y:i.y}))},q.classList.add("dragging"),q.setPointerCapture(t.pointerId)}function bl(e){const t=re(e.clientX,e.clientY);ae={type:"draw",x0:t.x,y0:t.y,rect:null},q.classList.add("dragging"),q.setPointerCapture(e.pointerId)}function wl(e,t){const n=u.frames.find(s=>s.id===e),i=t.target.closest(".resize")?.dataset.dir||"se";ae={type:"resize",fid:e,dir:i,sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,w:n.w,h:n.h},q.classList.add("dragging"),q.setPointerCapture(t.pointerId)}function xl(e){Tn(),F?.soft&&!U.value.trim()&&ne();const t=re(e.clientX,e.clientY),n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("stroke",as),n.setAttribute("stroke-width",3/y.z),dt.appendChild(n),ae={type:"stroke",points:[t.x,t.y],path:n,width:3/y.z},q.classList.add("dragging"),q.setPointerCapture(e.pointerId)}const kl=11;function $l(e,t,n,i,s,a){const o=s-n,r=a-i,l=o*o+r*r,c=l?Math.max(0,Math.min(1,((e-n)*o+(t-i)*r)/l)):0;return Math.hypot(e-(n+c*o),t-(i+c*r))}function ao(e){const t=re(e.clientX,e.clientY);for(const n of[...u.strokes]){if(n.commentId||String(n.id).startsWith("ink-"))continue;const i=kl/y.z+(n.width||3)/2,s=sn(n);let a=!1;for(let o=0;o+1<s.length&&!a;o+=2){const r=o+3<s.length?s[o+2]:s[o],l=o+3<s.length?s[o+3]:s[o+1];a=$l(t.x,t.y,s[o],s[o+1],r,l)<=i}a&&(u.strokes=u.strokes.filter(o=>o.id!==n.id),dt.querySelector(`path[data-id="${n.id}"]`)?.remove(),w("DELETE",`/__loop/api/strokes/${n.id}`).catch(()=>{}),Z("Erase mark",()=>je({strokes:[n]}),()=>w("DELETE",`/__loop/api/strokes/${n.id}`)))}}q.addEventListener("pointermove",e=>{if(zr(e.clientX,e.clientY),!ae){if(j==="comment"){const n=e.target.closest?.(".frame-body")&&!e.target.closest(".pin")&&e.target.closest(".frame")?.dataset.id,i=n&&u.frames.find(s=>s.id===n);i&&!wn(i)&&(!E||n===E.fid)&&!H.get(n)?.el.classList.contains("empty")?li(n,e.clientX,e.clientY,"block"):Y.hidden=!0}if(j==="deep"){const n=e.target.closest(".frame-body")&&e.target.closest(".frame")?.dataset.id;n&&!e.target.closest(".pin")?li(n,e.clientX,e.clientY):Y.hidden=!0}else if(j==="select"&&!Ie&&!ve){const n=e.target.closest?.(".frame-body")&&e.target.closest(".frame")?.dataset.id,i=n&&u.frames.find(s=>s.id===n);i&&(!E||n===E.fid)&&(E||!wn(i))&&!e.target.closest(".pin")&&!H.get(n)?.el.classList.contains("empty")?li(n,e.clientX,e.clientY,e[lt]?"deep":"step"):Y.hidden=!0}return}const t=ae;if(t.type==="pan")y.x=t.vx+e.clientX-t.sx,y.y=t.vy+e.clientY-t.sy,se();else if(t.type==="smove"){const n=(e.clientX-t.sx)/y.z,i=(e.clientY-t.sy)/y.z;if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<3)return;t.moved=!0,Xn.set(t.sid,{x:t.x0+n,y:t.y0+i});for(const[s,a]of Object.entries(t.from))_e.set(s,{x:a.x+n,y:a.y+i}),Q(u.frames.find(o=>o.id===s));Nt(),Ce()}else if(t.type==="sresize"){const n=(e.clientX-t.sx)/y.z,i=(e.clientY-t.sy)/y.z,s=120;let a=t.x0,o=t.y0,r=t.w,l=t.h;t.dir.includes("e")&&(r=t.w+n),t.dir.includes("s")&&(l=t.h+i),t.dir.includes("w")&&(r=t.w-n,a=t.x0+n),t.dir.includes("n")&&(l=t.h-i,o=t.y0+i),r<s&&(t.dir.includes("w")&&(a=t.x0+t.w-s),r=s),l<s&&(t.dir.includes("n")&&(o=t.y0+t.h-s),l=s),Xn.set(t.sid,{x:a,y:o,w:r,h:l}),Nt()}else if(t.type==="move"&&t.dup){t.moved=!0;const n=u.frames.find(s=>s.id===t.fid);if(t.to={x:t.fx+(e.clientX-t.sx)/y.z,y:t.fy+(e.clientY-t.sy)/y.z},!e.metaKey&&!e.ctrlKey){const s=Xs({...t.to,w:n.w,h:n.h},null);t.to.x+=s.dx,t.to.y+=s.dy,vt(s.guides)}else vt([]);const i=m("#dup-ghost");Object.assign(i.style,{left:`${t.to.x}px`,top:`${t.to.y}px`,width:`${n.w}px`,height:`${n.h}px`}),i.querySelector("span").textContent=`${n.name} copy`,i.hidden=!1}else if(t.type==="move"){t.moved=!0;const n=u.frames.find(a=>a.id===t.fid),i={x:t.fx+(e.clientX-t.sx)/y.z,y:t.fy+(e.clientY-t.sy)/y.z};if(e.shiftKey&&(Math.abs(i.x-t.fx)>=Math.abs(i.y-t.fy)?i.y=t.fy:i.x=t.fx),!e.metaKey&&!e.ctrlKey){const a=Xs({...i,w:n.w,h:n.h},t.fid);(!e.shiftKey||i.y===t.fy)&&(i.x+=a.dx),(!e.shiftKey||i.x===t.fx)&&(i.y+=a.dy),vt(a.guides)}else vt([]);_e.set(t.fid,i);for(const a of t.kids||[]){_e.set(a.id,{x:a.x+i.x-t.fx,y:a.y+i.y-t.fy});const o=u.frames.find(r=>r.id===a.id);o&&Q(o)}const s=(u.sections||[]).find(a=>Gi(a,{...n,...i}));Rt.querySelectorAll(".section").forEach(a=>a.classList.toggle("target",a.dataset.id===s?.id)),Q(n),Ce()}else if(t.type==="marquee"){const n=re(e.clientX,e.clientY),i={x:Math.min(t.x0,n.x),y:Math.min(t.y0,n.y),w:Math.abs(n.x-t.x0),h:Math.abs(n.y-t.y0)};if(!t.moved&&i.w*y.z<4&&i.h*y.z<4)return;!t.moved&&t.clickFid&&!e.shiftKey&&ie(null),t.moved=!0;const s=m("#marquee");s.hidden=!1,Object.assign(s.style,{left:`${i.x}px`,top:`${i.y}px`,width:`${i.w}px`,height:`${i.h}px`});const a=u.frames.filter(o=>o.x<i.x+i.w&&o.x+o.w>i.x&&o.y<i.y+i.h&&o.y+o.h>i.y).map(o=>o.id);Ks([...new Set([...t.base,...a])])}else if(t.type==="gmove"){t.moved=!0;let n=(e.clientX-t.sx)/y.z,i=(e.clientY-t.sy)/y.z;const s=t.ids.map(a=>{const o=u.frames.find(r=>r.id===a);return{x:t.from[a].x+n,y:t.from[a].y+i,w:o.w,h:o.h}});if(!e.metaKey&&!e.ctrlKey){const a=Vs(s),o=Xs(a,new Set(t.ids));n+=o.dx,i+=o.dy,vt(o.guides)}else vt([]);for(const a of t.ids)_e.set(a,{x:t.from[a].x+n,y:t.from[a].y+i}),Q(u.frames.find(o=>o.id===a));gn()}else if(t.type==="cpick"){if(!t.area&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)>6&&(t.area=!0,Y.hidden=!0,ne(),J(),q.classList.add("dragging")),!t.area)return;let n,i;if(t.fid===ce)n=re(t.sx,t.sy),i=re(e.clientX,e.clientY);else{const a=u.frames.find(r=>r.id===t.fid),o=r=>({x:Math.max(0,Math.min(a.w,r.lx)),y:Math.max(0,Math.min(a.h,r.ly))});n=o(tt(t.fid,t.sx,t.sy)),i=o(tt(t.fid,e.clientX,e.clientY))}t.rect={x:Math.min(n.x,i.x),y:Math.min(n.y,i.y),w:Math.abs(i.x-n.x),h:Math.abs(i.y-n.y)};let s=Lt(t.fid).querySelector(".area.picking");s||(s=document.createElement("div"),s.className="area picking show",Lt(t.fid).prepend(s)),Object.assign(s.style,{left:`${t.rect.x}px`,top:`${t.rect.y}px`,width:`${t.rect.w}px`,height:`${t.rect.h}px`})}else if(t.type==="efree"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<5)return;if(!t.moved){t.moved=!0,Y.hidden=!0;const a=t.el,o=a.parentElement,r=a.ownerDocument.defaultView,l=a.getBoundingClientRect(),c=o.getBoundingClientRect(),f=r.getComputedStyle(o);t.base=a.getAttribute("style"),t.pbase=o.getAttribute("style"),t.props={},t.pprops={},f.position==="static"&&(o.style.position="relative",t.pprops.position="relative"),t.x0=l.left-c.left-o.clientLeft+o.scrollLeft,t.y0=l.top-c.top-o.clientTop+o.scrollTop,Object.assign(t.props,{position:"absolute",margin:"0",width:r.getComputedStyle(a).width,left:`${Math.round(t.x0)}px`,top:`${Math.round(t.y0)}px`});for(const[d,p]of Object.entries(t.props))a.style.setProperty(d,p)}const n=y.z,i=Math.round(t.x0+(e.clientX-t.sx)/n),s=Math.round(t.y0+(e.clientY-t.sy)/n);t.props.left=`${i}px`,t.props.top=`${s}px`,t.el.style.left=t.props.left,t.el.style.top=t.props.top,Ae(),It()}else if(t.type==="emove"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<5)return;t.moved||(t.moved=!0,t.op=t.el.style.opacity,t.el.style.opacity=".35",Y.hidden=!0,te.hidden=!0,t.line=document.createElement("div"),t.line.id="el-line",document.body.appendChild(t.line));const n=H.get(t.fid).iframe.getBoundingClientRect(),i=y.z,s=(e.clientX-n.left)/i,a=(e.clientY-n.top)/i;if(!t.box){const R=t.el.getBoundingClientRect();t.box=document.createElement("div"),t.box.id="el-drag",t.bx=n.left+R.left*i,t.by=n.top+R.top*i,Object.assign(t.box.style,{width:`${R.width*i}px`,height:`${R.height*i}px`}),document.body.appendChild(t.box)}if(t.box.style.transform=`translate(${t.bx+e.clientX-t.sx}px, ${t.by+e.clientY-t.sy}px)`,t.intoBox||(t.intoBox=document.createElement("div"),t.intoBox.id="el-into",document.body.appendChild(t.intoBox)),document.querySelectorAll(".frame.drop-into").forEach(R=>R.classList.remove("drop-into")),t.before=void 0,t.into=null,t.line.hidden=!0,t.intoBox.hidden=!0,t.out=e.clientX<n.left||e.clientX>n.right||e.clientY<n.top||e.clientY>n.bottom,t.out){const R=re(e.clientX,e.clientY),oe=Cn(R.x,R.y);oe&&oe.id!==t.fid&&H.get(oe.id)?.el.classList.add("drop-into");return}const o=t.el.ownerDocument,r=o.body,l=t.el.parentElement,c=Me(t.fid,s,a),f=R=>[...R.children].some(oe=>oe!==t.el&&Ws(oe))||!R.children.length&&!R.textContent.trim()&&/^(block|flex|grid|flow-root|list-item)$/.test(o.defaultView.getComputedStyle(R).display);let d=!c||c===o.documentElement?r:c;if(t.el.contains(d))d=l;else{for(;d!==r&&!f(d);)d=d.parentElement;t.el.contains(d)&&(d=l)}if(d!==r&&d!==l&&!d.contains(t.el)){const R=d.getBoundingClientRect(),oe=7/i;(s-R.left<oe||R.right-s<oe||a-R.top<oe||R.bottom-a<oe)&&(d=d.parentElement)}const p=[...d.children].filter(Ws),h=p.filter(R=>R!==t.el),g=h.map(R=>R.getBoundingClientRect()),v=d.getBoundingClientRect(),S=(R,oe,Jt,dr)=>Object.assign(t.line.style,{left:`${n.left+R*i}px`,top:`${n.top+oe*i}px`,width:`${Jt}px`,height:`${dr}px`,marginLeft:"0",marginTop:"0"}),A=()=>{d!==l&&(Object.assign(t.intoBox.style,{left:`${n.left+v.left*i}px`,top:`${n.top+v.top*i}px`,width:`${v.width*i}px`,height:`${v.height*i}px`}),t.intoBox.hidden=!1)};if(!h.length){if(d===l)return;t.into=d,t.before=null,S(v.left+4,v.top+4,Math.max(8,(v.width-8)*i),2),t.line.hidden=!1,A();return}const x=p.slice(0,2).map(R=>R.getBoundingClientRect()),M=x.length>1&&Math.abs(x[1].left-x[0].left)>Math.abs(x[1].top-x[0].top);let C=g.findIndex(R=>M?s<R.left+R.width/2:a<R.top+R.height/2);C<0&&(C=h.length);const B=h[C]||null;if(d===l&&B===(p[p.indexOf(t.el)+1]||null))return;t.into=d,t.before=B;const P=g[C-1],ee=g[C];if(M){const R=P&&ee?(P.right+ee.left)/2:ee?ee.left-4:P.right+4,oe=ee||P;S(R,oe.top,2,oe.height*i),t.line.style.marginLeft="-1px"}else{const R=P&&ee?(P.bottom+ee.top)/2:ee?ee.top-4:P.bottom+4,oe=ee||P;S(Math.max(oe.left,v.left),R,Math.min(oe.width,v.width)*i,2),t.line.style.marginTop="-1px"}A(),t.line.hidden=!1}else if(t.type==="edrag"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<4)return;if(!t.moved){t.moved=!0,t.copy=Ds(t.fid,t.el);const o=Oe(u.frames.find(r=>r.id===t.fid));t.x0=o.x+t.copy.x,t.y0=o.y+t.copy.y,t.ghost=document.createElement("div"),t.ghost.id="el-ghost",t.ghost.innerHTML=t.copy.html,Object.assign(t.ghost.style,{width:`${t.copy.w}px`,height:`${t.copy.h}px`}),ct.appendChild(t.ghost),Y.hidden=!0}const n=(e.clientX-t.sx)/y.z,i=(e.clientY-t.sy)/y.z;t.ghost.style.transform=`translate(${t.x0+n}px, ${t.y0+i}px)`;const s=re(e.clientX,e.clientY),a=Cn(s.x,s.y);document.querySelectorAll(".frame.drop-into").forEach(o=>o.classList.remove("drop-into")),a&&H.get(a.id)?.el.classList.add("drop-into")}else if(t.type==="draw"){const n=re(e.clientX,e.clientY),i={x:Math.min(t.x0,n.x),y:Math.min(t.y0,n.y),w:Math.abs(n.x-t.x0),h:Math.abs(n.y-t.y0)};if(e.shiftKey&&(i.w=i.h=Math.max(i.w,i.h)),t.rect=i,j==="section"){t.sec||(t.sec=document.createElement("div"),t.sec.className="section drawing",t.sec.innerHTML='<div class="sec-label"><span class="sec-name">Section</span></div>',Rt.appendChild(t.sec)),Object.assign(t.sec.style,{left:`${i.x}px`,top:`${i.y}px`,width:`${i.w}px`,height:`${i.h}px`});return}const s=m("#draw-box");Object.assign(s.style,{left:`${i.x}px`,top:`${i.y}px`,width:`${i.w}px`,height:`${i.h}px`}),s.querySelector("span").textContent=`${Math.round(i.w)} \xD7 ${Math.round(i.h)}`,s.hidden=!1}else if(t.type==="resize"){const n=(e.clientX-t.sx)/y.z,i=(e.clientY-t.sy)/y.z,s=120;let a=t.x0,o=t.y0,r=t.w,l=t.h;if(t.dir.includes("e")&&(r=t.w+n),t.dir.includes("s")&&(l=t.h+i),t.dir.includes("w")&&(r=t.w-n,a=t.x0+n),t.dir.includes("n")&&(l=t.h-i,o=t.y0+i),e.shiftKey&&t.dir.length===2){const f=Math.max(r/t.w,l/t.h),d=t.w*f,p=t.h*f;t.dir.includes("w")&&(a=t.x0+t.w-d),t.dir.includes("n")&&(o=t.y0+t.h-p),r=d,l=p}r<s&&(t.dir.includes("w")&&(a=t.x0+t.w-s),r=s),l<s&&(t.dir.includes("n")&&(o=t.y0+t.h-s),l=s);const c={x:a,y:o,w:r,h:l};if(!e.metaKey&&!e.ctrlKey&&!e.shiftKey){const f=wc(c,t.fid,t.dir);Object.assign(c,f.rect),vt(f.guides)}else vt([]);_e.set(t.fid,c),Q(u.frames.find(f=>f.id===t.fid)),m("#fp-sw")&&(m("#fp-sw").value=Math.round(c.w),m("#fp-sh").value=Math.round(c.h))}else if(t.type==="stroke"){const n=re(e.clientX,e.clientY),i=t.points.length;if(Math.hypot(n.x-t.points[i-2],n.y-t.points[i-1])*y.z<1.5)return;t.points.push(n.x,n.y),t.path.setAttribute("d",us(t.points))}else t.type==="erase"&&ao(e)});const oo=async e=>{const t=ae;if(t){if(ae=null,q.classList.remove("dragging"),vt([]),Rt.querySelectorAll(".section.target").forEach(n=>n.classList.remove("target")),t.type==="smove"||t.type==="sresize"){const n=Xn.get(t.sid),i=u.sections.find(r=>r.id===t.sid);if(Xn.delete(t.sid),!n||!i)return;const s=t.type==="smove"?{x:t.x0,y:t.y0}:{x:t.x0,y:t.y0,w:t.w,h:t.h},a={...n},o=t.sid;if(Object.assign(i,n),w("PATCH",`/__loop/api/sections/${o}`,n).catch(r=>b(r.message)),t.type==="smove"){const r=t.from,l={};for(const c of Object.keys(r)){const f=_e.get(c);_e.delete(c);const d=u.frames.find(p=>p.id===c);f&&d&&(Object.assign(d,f),l[c]={x:f.x,y:f.y})}xe(l),Z("Move section",()=>Promise.all([wt(o,s),xe(r)]),()=>Promise.all([wt(o,a),xe(l)]))}else Z("Resize section",()=>wt(o,s),()=>wt(o,a));Nt();return}if(t.type==="marquee"){if(m("#marquee").hidden=!0,!t.moved&&!t.clickFid&&t.clickSid){Qi(t.clickSid);return}if(!t.moved&&t.clickFid){const n=t.clickFid,i=u.frames.find(o=>o.id===n);if(H.get(n)?.el.classList.contains("empty")){ie(n),hi(n);return}ie(n),Ts(n);const s=re(e.clientX,e.clientY),a=i&&Me(n,s.x-i.x,s.y-i.y);try{H.get(n)?.iframe.focus()}catch{}if(a&&a!==le(n)?.documentElement)try{a.focus?.({preventScroll:!0,focusVisible:!1}),a.click?.()}catch{}}return}if(t.type==="gmove"){if(!t.moved)return;ge=null,Ni();const n=t.from,i={};for(const s of t.ids){const a=_e.get(s);_e.delete(s);const o=u.frames.find(r=>r.id===s);a&&o&&(Object.assign(o,a),i[s]={x:a.x,y:a.y})}xe(i),Z(`Move ${t.ids.length} frames`,()=>xe(n),()=>xe(i));return}if(t.type==="cpick"){if(document.querySelectorAll(".area.picking").forEach(a=>a.remove()),t.area&&t.rect&&t.rect.w*y.z>8&&t.rect.h*y.z>8)return Mt(t.fid,t.rect.x,t.rect.y,null,t.rect);if(t.area)return;if(t.fid===ce){const a=re(t.sx,t.sy);return Mt(ce,a.x,a.y,"canvas")}const{lx:n,ly:i}=tt(t.fid,t.sx,t.sy);if(H.get(t.fid)?.el.classList.contains("empty"))return hi(t.fid);const s=Pi(t.fid,Me(t.fid,n,i),"block");return s?(ne(),J(),Y.hidden=!0,$={frameId:t.fid,els:[s],scope:s.parentElement},So()):Mt(t.fid,n,i)}if(t.type==="efree")return t.moved?Jl(t):dn(t.fid,t.ev,"deep");if(t.type==="emove")return t.line?.remove(),t.box?.remove(),t.intoBox?.remove(),document.querySelectorAll(".frame.drop-into").forEach(n=>n.classList.remove("drop-into")),t.moved&&(t.el.style.opacity=t.op||""),t.moved&&qt(),t.moved&&!t.el.getAttribute("style")&&t.el.removeAttribute("style"),t.moved?t.out?ic(t,e):t.into?ec(t.fid,t.el,t.into,t.before):void 0:dn(t.fid,t.ev,"step");if(t.type==="edrag"){if(t.ghost?.remove(),document.querySelectorAll(".frame.drop-into").forEach(o=>o.classList.remove("drop-into")),!t.moved)return;const n=re(e.clientX,e.clientY),i=Cn(n.x,n.y);if(i){const o=Oe(i),r=Me(i.id,n.x-o.x,n.y-o.y);return Fs(t.copy,i.id,r)}const s=(e.clientX-t.sx)/y.z,a=(e.clientY-t.sy)/y.z;return Os(t.copy,t.x0+s,t.y0+a)}if(t.type==="draw"){m("#draw-box").hidden=!0,t.sec?.remove();const n=t.rect;if(j==="section"){we("select"),n&&n.w*y.z>24&&n.h*y.z>24&&qc({x:n.x,y:n.y,w:n.w,h:n.h});return}n&&n.w*y.z>12&&n.h*y.z>12?Dn("Frame",n.w,n.h,n.x,n.y):j==="frame"&&Dn(fe.name,fe.w,fe.h,t.x0,t.y0);return}if(t.type==="move"&&t.dup){m("#dup-ghost").hidden=!0,t.moved&&t.to&&ts(t.fid,t.to);return}if(t.type==="move"&&!t.moved&&t.onDims){Re=Re===t.fid?null:t.fid,He();return}if(t.type==="move"&&t.moved||t.type==="resize"){const n=_e.get(t.fid),i=u.frames.find(a=>a.id===t.fid),s=t.type==="move"?{x:t.fx,y:t.fy}:{x:t.x0,y:t.y0,w:t.w,h:t.h};if(n&&i&&Object.assign(i,n),_e.delete(t.fid),n){const a=t.fid,o=t.type==="move"?t.kids||[]:[];let r;if(t.type==="move"&&i){const d=new Set([a,...o.map(h=>h.id)]),p=$o({...i,...n},d)?.id;(p||void 0)!==i.parent&&(r=p||null)}w("PATCH",`/__loop/api/frames/${a}`,r===void 0?n:{...n,parent:r}).catch(d=>b(d.message)),r!==void 0&&i&&(i.parent=r||void 0);const l={...n},c={},f={};for(const d of o){const p=_e.get(d.id);_e.delete(d.id),p&&(c[d.id]={x:d.x,y:d.y},f[d.id]={x:Math.round(p.x),y:Math.round(p.y)})}o.length&&xe(f),Z(t.type==="move"?"Move frame":"Resize frame",()=>Promise.all([At(a,s),o.length&&xe(c)]),()=>Promise.all([At(a,l),o.length&&xe(f)]))}t.type==="resize"&&setTimeout(()=>it(t.fid),50)}else if(t.type==="stroke"){const n=t.points;n.length<4&&n.push(n[0]+.5,n[1]+.5);const i=new Map;for(let a=0;a<n.length;a+=2){const o=Cn(n[a],n[a+1]);o&&i.set(o.id,(i.get(o.id)||0)+1)}const s=[...i.entries()].sort((a,o)=>o[1]-a[1])[0]?.[0]||null;try{const a=await w("POST","/__loop/api/strokes",{points:n,color:as,width:t.width,frameId:s});oa.add(a.id),Z("Draw mark",()=>w("DELETE",`/__loop/api/strokes/${a.id}`),()=>je({strokes:[a]})),t.path.remove(),u.strokes.find(o=>o.id===a.id)||u.strokes.push(a),xt(),Gr(s,n,e)}catch(a){t.path.remove(),b(a.message)}}}};q.addEventListener("pointerup",oo),q.addEventListener("pointercancel",oo),q.addEventListener("pointerleave",()=>{Y.hidden=!0}),addEventListener("wheel",e=>{if(E&&e.target.closest?.("#viewport")){e.preventDefault();try{const i=e.deltaMode===1?16:1,{lx:s,ly:a}=tt(E.fid,e.clientX,e.clientY),o=Me(E.fid,s,a),r=le(E.fid)?.defaultView;if(o&&r){let l=o;const c=r.document.scrollingElement||r.document.documentElement;for(;l&&l!==c&&l!==r.document.body;l=l.parentElement){const f=r.getComputedStyle(l).overflowY;if(/(auto|scroll|overlay)/.test(f)&&l.scrollHeight>l.clientHeight+1)break}(l&&l!==r.document.body?l:c).scrollTop+=e.deltaY*i,Y.hidden=!0,requestAnimationFrame(()=>{Ae(),Ce()})}}catch{}return}if(e.ctrlKey||e.metaKey)return pa(e,e.clientX,e.clientY);if(!e.target.closest?.("#viewport"))return;e.preventDefault();const t=e.deltaMode===1?16:1,n=e.target.closest?.(".frame-body")&&e.target.closest(".frame")?.dataset.id;if(n&&($?.frameId===n||I===n)&&Math.abs(e.deltaY)>=Math.abs(e.deltaX))try{const{lx:i,ly:s}=tt(n,e.clientX,e.clientY),a=Me(n,i,s),o=le(n)?.defaultView;if(a&&o&&no(a,"y",e.deltaY)){let r=a;const l=o.document.scrollingElement||o.document.documentElement;for(;r&&r!==l&&r!==o.document.body;r=r.parentElement){const c=o.getComputedStyle(r).overflowY;if(/(auto|scroll|overlay)/.test(c)&&r.scrollHeight>r.clientHeight+1&&(e.deltaY>0?r.scrollTop<r.scrollHeight-r.clientHeight-1:r.scrollTop>0))break}(r&&r!==o.document.body?r:l).scrollTop+=e.deltaY*t,Y.hidden=!0,requestAnimationFrame(()=>{Ae(),Ce()});return}}catch{}y.x-=e.deltaX*t,y.y-=e.deltaY*t,cs()},{passive:!1,capture:!0});let ki=1;addEventListener("gesturestart",e=>{e.preventDefault(),ki=y.z}),addEventListener("gesturechange",e=>{e.preventDefault(),!E&&ut(e.clientX,e.clientY,ki*e.scale/y.z)});const Et=()=>{const e=document.activeElement;return e&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.isContentEditable)};addEventListener("keydown",e=>{if(Et())return;if(e.code==="Space"&&!Bt){Bt=!0,q.classList.add("panning"),u&&u.frames.forEach(Q),e.preventDefault();return}if(e.metaKey||e.ctrlKey){if(e.key.toLowerCase()==="z"){e.preventDefault(),e.shiftKey?Nn():_i();return}if(e.key.toLowerCase()==="c"&&$&&!ve&&k()){e.preventDefault();const n=$.els[$.els.length-1];Ve=Ds($.frameId,n),Gt=null;try{navigator.clipboard?.write?.([new ClipboardItem({"text/html":new Blob([Ve.html],{type:"text/html"}),"text/plain":new Blob([Ve.html],{type:"text/plain"})})]).catch(()=>{})}catch{}b(`Copied \u201C${Ve.name}\u201D \u2014 \u2318V to paste`,1600);return}if(e.key.toLowerCase()==="v"&&Ve&&!Gt&&k()){if(e.preventDefault(),$){Fs(Ve,$.frameId,$.els[$.els.length-1]);return}const n=u.frames.find(r=>r.id===Ve.fid),i=Ve.w,s=Ve.h,a=r=>u.frames.some(l=>r.x<l.x+l.w+40&&r.x+i+40>l.x&&r.y<l.y+l.h+40&&r.y+s+40>l.y);let o=n?{x:n.x+n.w+80,y:n.y}:re(innerWidth/2-i*y.z/2,innerHeight/2-s*y.z/2);a(o)&&(o=Ps(i,s)),Os(Ve,o.x,o.y);return}if(e.key.toLowerCase()==="c"&&e.shiftKey&&I&&!$){e.preventDefault(),Yl(I);return}if(e.key.toLowerCase()==="c"&&I&&k()){e.preventDefault(),Gt=I,Ve=null,b(`Copied \u201C${u.frames.find(n=>n.id===I)?.name}\u201D \u2014 \u2318V to paste`,1600);return}if(e.key.toLowerCase()==="v"&&Gt&&k()){e.preventDefault(),u.frames.find(n=>n.id===Gt)?ts(Gt):b("The copied frame no longer exists");return}if(e.key.toLowerCase()==="d"&&$?.els.length===1&&k()){e.preventDefault(),tc();return}if(e.key.toLowerCase()==="d"&&K.size&&k()){e.preventDefault(),[...K].forEach(n=>ts(n));return}if(e.key.toLowerCase()==="d"&&I&&k()){e.preventDefault(),ts(I);return}if(e.key.toLowerCase()==="a"&&k()){e.preventDefault(),Ks(u.frames.map(n=>n.id));return}if(e.key.toLowerCase()==="y"&&e.ctrlKey){e.preventDefault(),Nn();return}e.key==="0"&&(e.preventDefault(),y.z=1,se()),(e.key==="="||e.key==="+")&&(e.preventDefault(),ut(innerWidth/2,innerHeight/2,1.25)),e.key==="-"&&(e.preventDefault(),ut(innerWidth/2,innerHeight/2,.8));return}const t=e.key.toLowerCase();if(t==="v")we("select");else if(t==="h")we("hand");else if(t==="p")we("pen");else if(t==="e")we("erase");else if(t==="s"&&e.shiftKey&&k())we(j==="section"?"select":"section");else if((e.key==="Backspace"||e.key==="Delete")&&$&&k())e.preventDefault(),Oo();else if((e.key==="Backspace"||e.key==="Delete")&&Se&&k())nr(Se);else if(t==="c"&&e.shiftKey)qn();else if(t==="c")qe&&qn(!0),we("comment");else if(t==="i"||t==="u")we("use");else if(t==="d"&&e.shiftKey)sa();else if(t==="n"&&k())As();else if(t==="f"&&e.shiftKey&&k())I?ji(I):b("Select a frame to freeze it");else if(t==="k"&&k()&&I)Yi(I);else if(t==="f"&&k())we(j==="frame"?"select":"frame");else if(e.key==="!"||e.shiftKey&&e.code==="Digit1")Ge();else if(e.key==="@"||e.shiftKey&&e.code==="Digit2"){const n=K.size?[...K]:I?[I]:Se?Un(u.sections.find(i=>i.id===Se)).map(i=>i.id):[];n.length?Ge(!0,n):b("Select something to zoom to it")}else if($&&j!=="frame"&&/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&k()&&!E)e.preventDefault(),sc(e.key);else if(j==="frame"&&/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&k()&&!E)e.preventDefault(),Tl(e.key);else if(j==="frame"&&e.key==="Enter"&&!m("#preset-menu").hidden)e.preventDefault(),m("#preset-menu").hidden=!0;else if(/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&k()&&!E&&!_&&(I||K.size||Se)){const n=e.shiftKey?10:1;_c(e.key==="ArrowLeft"?-n:e.key==="ArrowRight"?n:0,e.key==="ArrowUp"?-n:e.key==="ArrowDown"?n:0)&&e.preventDefault()}else if(e.key==="="||e.key==="+")ut(innerWidth/2,innerHeight/2,1.25);else if(e.key==="-")ut(innerWidth/2,innerHeight/2,.8);else if(e.key==="Escape"&&$)Ye(),ne();else if(e.key==="Escape")z.hidden?W?J():!m("#agent-menu").hidden||!m("#share-menu").hidden?St():E?bt():(ie(null),we("select")):ne();else if((e.key==="Backspace"||e.key==="Delete")&&K.size&&k())hc([...K]);else if(e.altKey&&k()&&K.size>=2&&Ro[e.code])e.preventDefault(),No(Ro[e.code]);else if((e.key==="Backspace"||e.key==="Delete")&&I&&k()){const n=u.frames.find(i=>i.id===I);n&&_l(n.id).then(()=>{I=null,He()})}}),addEventListener("keyup",e=>{e.code==="Space"&&(Bt=!1,q.classList.remove("panning"),u&&u.frames.forEach(Q))}),addEventListener("blur",()=>{Bt&&(Bt=!1,q.classList.remove("panning"))}),m("#zoom-in").onclick=()=>ut(innerWidth/2,innerHeight/2,1.25),m("#zoom-out").onclick=()=>ut(innerWidth/2,innerHeight/2,.8),m("#zoom-level").onclick=()=>Ge();function St(){m("#agent-menu").hidden=!0,m("#share-menu").hidden=!0}function ro(e,t){const n=t.getBoundingClientRect();e.hidden=!1,e.style.top=`${n.bottom+8}px`,e.style.left=`${Math.max(12,Math.min(n.right-e.offsetWidth,innerWidth-e.offsetWidth-12))}px`}m("#agent-pill").addEventListener("click",e=>{if(e.stopPropagation(),!k())return;const t=m("#agent-menu"),n=!t.hidden;St(),n||ro(t,e.currentTarget)}),document.querySelectorAll("#agent-menu .menu-item").forEach(e=>e.addEventListener("click",async()=>{try{await w("POST","/__loop/api/settings",{mode:e.dataset.mode,runner:e.dataset.runner}),b(e.dataset.mode==="inbox"?"Comments will queue for your agent session":`Loop will run ${e.dataset.runner==="codex"?"Codex":"Claude Code"} on each comment`)}catch(t){b(t.message)}St()})),m("#agent-allowed").addEventListener("click",async e=>{const t=e.target.closest("[data-disallow]");if(t)try{await w("POST","/__loop/api/settings",{disallow:t.dataset.disallow})}catch(n){b(n.message)}});function Ll(){const e=!!u.emailSharing;m("#share-menu > .menu-title").textContent=e?"Invite people":"Share this canvas",m("#invite-signin").hidden=!e||!!Te?.user,m("#invite-form").hidden=!e||!Te?.user;const t=m("#share-menu .lan-share");t.open=!e,t.querySelector("summary").hidden=!e,t.classList.toggle("only",!e)}function $i(){const e=u.share||{};m("#share-lan").value=e.lan||"No network connection",m("#share-public-row").hidden=!e.public,m("#share-public").value=e.public||"",m("#share-public-btn").hidden=!!e.public,m("#share-public-btn").textContent=e.tunnelAvailable?"Create public link":"Create public link (needs cloudflared)"}m("#share-btn").addEventListener("click",async e=>{if(e.stopPropagation(),!k()){try{await navigator.clipboard.writeText(location.href),b("Link copied")}catch{b(location.href,5e3)}return}const t=m("#share-menu"),n=!t.hidden;St(),n||($i(),Ll(),m("#share-public-note").textContent="",ro(t,e.currentTarget),Mi())}),m("#share-public-btn").addEventListener("click",async()=>{const e=m("#share-public-note"),t=m("#share-public-btn");t.disabled=!0,e.textContent="Opening a tunnel\u2026";try{u.share=await w("POST","/__loop/api/share/public"),e.textContent="Live while this Mac is awake and Loop is running.",$i()}catch(n){e.textContent=n.message}t.disabled=!1}),m("#share-rotate").addEventListener("click",async()=>{confirm("Reset share links? Anyone using the old links loses access.")&&(u.share=await w("POST","/__loop/api/share/rotate"),$i(),b("Links reset"))}),document.querySelectorAll("[data-copy]").forEach(e=>e.addEventListener("click",async()=>{const t=m("#"+e.dataset.copy).value;try{await navigator.clipboard.writeText(t),b("Link copied")}catch{m("#"+e.dataset.copy).select()}})),document.querySelectorAll(".menu").forEach(e=>e.addEventListener("pointerdown",t=>t.stopPropagation())),addEventListener("pointerdown",e=>{e.target.closest(".menu, #agent-pill, #share-btn")||St()});let lo="1440x1024";function As(){St(),m("#new-frame").hidden=!1;const e=m("#new-frame-input");e.value="",setTimeout(()=>e.focus(),0)}function Li(){m("#new-frame").hidden=!0}m("#new-frame [data-close]").addEventListener("click",Li),m("#new-frame").addEventListener("pointerdown",e=>{e.target.id==="new-frame"&&Li()}),document.querySelectorAll("#size-pick button").forEach(e=>e.addEventListener("click",()=>{lo=e.dataset.size,document.querySelectorAll("#size-pick button").forEach(t=>t.classList.toggle("on",t===e))})),m("#new-frame-input").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Escape"&&Li(),e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),co())}),m("#new-frame-go").addEventListener("click",co);async function co(){const e=m("#new-frame-input").value.trim();if(!e)return;const[t,n]=lo.split("x").map(Number),i=/^(https?:\/\/|\/|~\/|\.\.?\/)/.test(e)&&!/\s/.test(e);try{const s=await w("POST","/__loop/api/frames",i?{src:e,w:t,h:n}:{prompt:e,w:t,h:n});Li(),setTimeout(()=>{ie(null),Ge(!0,[s.id])},80)}catch(s){b(s.message,4e3)}}function fo(){m("#name-input").value=V.name||"",m("#name-go").textContent=V.name?"Save":"Join",m("#name-modal").hidden=!1,setTimeout(()=>m("#name-input").select(),30)}m("#presence").addEventListener("click",e=>{e.target.closest(".avatar.me")&&fo()}),m("#name-modal").addEventListener("keydown",e=>{e.key==="Escape"&&V.name&&(m("#name-modal").hidden=!0)}),m("#name-go").addEventListener("click",uo),m("#name-input").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Enter"&&uo()});function uo(){const e=m("#name-input").value.trim();e&&(V.name=e,$e.set("loop.me",V),m("#name-modal").hidden=!0,ri(),k()&&!X&&w("POST","/__loop/api/settings",{hostName:e}).catch(t=>b(t.message)))}let Te=null,Ci=null;async function po(e){if(Ci)return Ci;const{createClient:t}=await import("https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.49.4/+esm");return Ci=t(e.url,e.key,{auth:{flowType:"pkce",detectSessionInUrl:!0,persistSession:!0,storageKey:"loop-host-auth"}}),Ci}async function Mi(){if(!(X||!k())&&u.emailSharing){try{Te=await w("GET","/__loop/api/cloud")}catch(e){m("#invite-note").textContent=e.message;return}Cl()}}function mo(e,t){return t?`<img src="${L(t)}" alt="" referrerpolicy="no-referrer">`:L($a(e))}function Cl(){const e=!!Te?.user;m("#invite-signin").hidden=e,m("#invite-form").hidden=!e,e&&(m("#me-avatar").innerHTML=mo(Te.user.name,Te.user.avatar),m("#me-email").textContent=Te.user.email,m("#cloud-link").value=Te.link||"",Te.error&&!m("#invite-note").textContent&&(m("#invite-note").textContent=Te.error),m("#members").innerHTML=(Te.members||[]).map(t=>`
44
- <div class="member"><span class="m-av">${mo(t.name||t.email,t.avatar_url)}</span>
40
+ ${$()?`<button class="cp-res" data-res="${o.id}" title="${o.resolved?"Reopen":"Resolve"}">${o.resolved?Je.reopen:Je.resolve}</button>`:""}
41
+ </div>`}).join(""):`<div class="cp-empty">${Ha==="open"?"No open comments. Press C and click anything to leave one.":"Nothing resolved yet."}</div>`}function Yi(e,t){Ne&&jn(!0),ee(),Re(),S&&dt();const n=e.frameId!==le&&f.frames.find(i=>i.id===e.frameId),a=e.anchor;if(n&&a){D.get(n.id)?.parked&&(Z(n.id),Hn());try{const s=a.selector||a.container?.selector||a.elements?.[0]?.selector,o=s&&de(n.id)?.querySelector(s),r=o?.getBoundingClientRect();r&&(r.top<0||r.bottom>n.h||r.left<0||r.right>n.w)&&o.scrollIntoView({block:"center",inline:"center",behavior:"instant"})}catch{}}requestAnimationFrame(()=>{const i=m("#comments-panel").hidden?0:364;if(n){Z(n.id);const s=24,o=76,r=innerWidth-i-s-24,c=innerHeight-o-96,l=Math.min(1,r/n.w,c/n.h);ct({z:l,x:s+(r-n.w*l)/2-n.x*l,y:o+(c-n.h*l)/2-n.y*l},380)}else{const s=(a?.wx||0)+(a?.area?.w||0)/2,o=(a?.wy||0)+(a?.area?.h||0)/2,r=Math.max(b.z,.8);ct({z:r,x:(innerWidth-i)/2-s*r,y:innerHeight/2-o*r},380)}setTimeout(()=>{if(e.resolved||t)return Fn(e.id);ut(e.frameId);const s=Sa(e.frameId)?.querySelector(`.pin[data-key="${e.id}"]`);s&&(s.classList.remove("ping"),s.offsetWidth,s.classList.add("ping"),setTimeout(()=>s.classList.remove("ping"),2200))},420)})}m("#comments-btn").addEventListener("click",()=>{const e=m("#comments-panel");e.hidden=!e.hidden,e.hidden||(gt?.(),Ki())}),m("#comments-panel").addEventListener("pointerdown",e=>e.stopPropagation()),m("#comments-panel").addEventListener("wheel",e=>e.stopPropagation()),m("#comments-panel").addEventListener("click",async e=>{if(e.target.closest(".cp-x")){m("#comments-panel").hidden=!0;return}const t=e.target.closest("[data-tab]");if(t){Ha=t.dataset.tab,Ki();return}const n=e.target.closest("[data-res]");if(n){try{await w("POST",`/__loop/api/comments/${n.dataset.res}/resolve`)}catch(s){y(s.message)}return}const a=e.target.closest(".cp-item");if(!a)return;const i=f.comments.find(s=>s.id===a.dataset.id);i&&Yi(i)}),m("#comments-panel").addEventListener("dblclick",e=>{const t=e.target.closest(".cp-item");if(!t||e.target.closest("[data-res]"))return;const n=f.comments.find(a=>a.id===t.dataset.id);n&&Yi(n,!0)});const pn={plus:A("plus"),mic:A("mic"),up:A("up"),file:A("file"),x:A("x","s")},$o=6,Zl=8e6,Lo=window.SpeechRecognition||window.webkitSpeechRecognition,Kn=[],Co=A("pen","s"),Gl={fable:"Fable",opus:"Opus",sonnet:"Sonnet",haiku:"Haiku"},Ql={minimal:"Minimal",low:"Low",medium:"Medium",high:"High",xhigh:"Extra high",max:"Max",ultra:"Ultra"},Vi=e=>Gl[e]||Zt(e),Xi=e=>Ql[e]||e,ve=document.createElement("div");ve.id="model-menu",ve.className="menu model-menu",ve.hidden=!0,document.body.appendChild(ve);let za=null;function Mo(){const e=f?.models;if(!e)return;const t=e.runner==="codex"?"Codex default":e.chat.model||e.chat.effort?"Same as your chat":"Default",n=(a,i,s,o)=>`<button class="tm-item${(e.pick[a]||"")===i?" on":""}" data-mm="${a}" data-v="${L(i)}"><span class="tm-check"></span><span>${L(s)}</span>${o?`<kbd>${L(o)}</kbd>`:""}</button>`;ve.innerHTML=`<div class="mm-title">Model</div>${n("model","",t,e.chat.model?Vi(e.chat.model):"")}${e.models.map(a=>n("model",a,Vi(a))).join("")}
42
+ <div class="mm-title">Effort</div>${n("effort","",t,e.chat.effort?Xi(e.chat.effort):"")}${e.efforts.map(a=>n("effort",a,Xi(a))).join("")}
43
+ ${f.agent.mode==="inbox"?'<p class="mm-note">Your chat answers with its own model. This is for the runs Loop starts itself.</p>':""}`}function Eo(){if(!za?.isConnected){ve.hidden=!0;return}const e=za.getBoundingClientRect(),t=ve.offsetWidth,n=ve.offsetHeight,a=e.top-n-8>=8||e.top>innerHeight-e.bottom;ve.style.left=`${Math.max(8,Math.min(innerWidth-t-8,e.right-t))}px`,ve.style.top=`${Math.max(8,Math.min(innerHeight-n-8,a?e.top-n-8:e.bottom+8))}px`}document.addEventListener("click",e=>{const t=e.target.closest(".c-model.pick");if(t){if(!ve.hidden&&za===t){ve.hidden=!0;return}za=t,Mo(),ve.hidden=!1,Eo()}}),ve.addEventListener("pointerdown",e=>e.stopPropagation()),ve.addEventListener("click",async e=>{const t=e.target.closest("[data-mm]");if(t){if(f.models){const n=f.models,a=t.dataset.mm;n.pick[a]=t.dataset.v||null,n[a]=n.pick[a]||n.chat[a],Ui()}try{await w("POST","/__loop/api/settings",{pick:{[t.dataset.mm]:t.dataset.v||null}})}catch(n){y(n.message)}}}),addEventListener("pointerdown",e=>{!ve.hidden&&!e.target.closest("#model-menu, .c-model")&&(ve.hidden=!0)},!0),addEventListener("keydown",e=>{e.key==="Escape"&&!ve.hidden&&(ve.hidden=!0,e.stopPropagation())},!0);function Ui(){const e=Jl(),t=!!f?.models&&$();document.querySelectorAll(".c-model").forEach(n=>{n.textContent!==e&&(n.textContent=e),n.classList.toggle("pick",t),n.title=t?"Model and effort":""}),ve.hidden||(Mo(),Eo())}function Jl(){if(!f)return"";if(!$())return"Host reviews first";const e=f.models;if(e?.model){const a=f.agent.lastModel,i=e.pick.model&&a&&a.startsWith(`claude-${e.pick.model}-`)?a:e.model;return Vi(i)+(e.pick.effort?` \xB7 ${Xi(e.pick.effort)}`:"")}const t=f.agent.lastModel;return t&&(f.agentBin==="codex"?!/^claude/.test(t):/^claude/.test(t))?Zt(t):f.agentLabel||"Agent"}const ec=e=>new Promise((t,n)=>{const a=new FileReader;a.onload=()=>t(a.result),a.onerror=n,a.readAsDataURL(e)});function So(e,t,n){e.insertAdjacentHTML("beforeend",`<div class="c-foot"><button type="button" class="c-btn" data-box="attach" title="Attach images or files \u2014 or drop them here">${pn.plus}</button><input type="file" multiple hidden><span class="c-model"></span>${Lo?`<button type="button" class="c-btn" data-box="mic" title="Dictate">${pn.mic}</button>`:""}<button type="button" class="c-send" data-box="send" title="Send (\u21B5)">${pn.up}</button></div>`);const a=e.querySelector("textarea"),i=e.querySelector("input[type=file]"),s=e.querySelector(".c-files"),o=e.querySelector(".c-send"),r=()=>{o.disabled=!a.value.trim()&&!t.length},c=()=>{s.hidden=!t.length,s.innerHTML=t.map((d,u)=>`<span class="c-file${d.type.startsWith("image/")?" img":""}" title="${L(d.name)}">${d.type.startsWith("image/")?`<img src="${d.data}" alt="">`:`${pn.file}<span>${L(d.name)}</span>`}<button type="button" data-rm="${u}" title="Remove">${pn.x}</button></span>`).join(""),Ui(),r()},l=async d=>{for(const u of d){if(t.length>=$o){y(`Up to ${$o} files per message`);break}if(u.size>Zl){y(`${u.name} is over 8 MB`);continue}t.push({name:u.name||"pasted-image.png",type:u.type||"application/octet-stream",data:await ec(u)})}c(),a.focus()};return i.addEventListener("change",()=>{l([...i.files]),i.value=""}),e.addEventListener("click",d=>{const u=d.target.closest("[data-rm]");if(u){t.splice(+u.dataset.rm,1),c();return}const p=d.target.closest("[data-box]");p&&(p.dataset.box==="attach"?i.click():p.dataset.box==="mic"?tc(a,p,r):p.dataset.box==="send"&&n())}),e.addEventListener("dragover",d=>{[...d.dataTransfer.types].includes("Files")&&(d.preventDefault(),d.stopPropagation(),e.classList.add("drop"))}),e.addEventListener("dragleave",d=>{e.contains(d.relatedTarget)||e.classList.remove("drop")}),e.addEventListener("drop",d=>{d.preventDefault(),d.stopPropagation(),e.classList.remove("drop"),l([...d.dataTransfer.files])}),a.addEventListener("paste",d=>{const u=[...d.clipboardData?.files||[]];u.length&&(d.preventDefault(),l(u))}),a.addEventListener("input",r),c(),{paint:c}}let mn=null;function tc(e,t,n){if(mn){mn.stop();return}const a=new Lo;a.continuous=!0,a.interimResults=!0,a.lang=navigator.language||"en-US";const i=e.value&&!/\s$/.test(e.value)?e.value+" ":e.value;a.onresult=s=>{let o="";for(const r of s.results)o+=r[0].transcript;e.value=i+o,ot(e),n()},a.onend=()=>{mn=null,t.classList.remove("on"),e.focus()},a.onerror=s=>{s.error==="not-allowed"||s.error==="service-not-allowed"?y("Allow microphone access to dictate"):["aborted","no-speech"].includes(s.error)||y(`Dictation stopped (${s.error})`)},mn=a,t.classList.add("on");try{a.start()}catch{mn=null,t.classList.remove("on")}}function To(){try{mn?.stop()}catch{}}const Zi=So(H.querySelector(".cbox"),Kn,()=>mo());z.addEventListener("pointerdown",e=>{e.stopPropagation(),It=!1}),z.addEventListener("click",async e=>{const t=e.target.closest("[data-act]");if(!t)return;const n=t.dataset.act,a=t.dataset.id||j;try{if(n==="close")return ee();if(n==="dock"){pt=!pt,It=!1,z.classList.toggle("docked",pt),pt&&(z.style.left=z.style.top=z.style.maxHeight=""),Ia(),_e();return}if(n==="more"){const i=z.querySelector(".t-menu");i.hidden=!i.hidden;return}if(n==="allow"){t.disabled=!0,t.textContent="Allowing\u2026",await w("POST",`/__loop/api/comments/${a}/allow`,{i:+t.dataset.k});return}if(n==="allowall"){t.disabled=!0,t.textContent="Allowing\u2026",await w("POST",`/__loop/api/comments/${a}/allow`,{all:!0,i:f.comments.find(i=>i.id===a)?.blocked?.findIndex(i=>!i.allowed)});return}if(n==="before"){const i=f.comments.find(s=>s.id===a);i&&(Ls(i.frameId,i.id),St(i.frameId));return}if(n==="delete"){confirm("Delete this comment thread? This can\u2019t be undone.")&&(await w("DELETE",`/__loop/api/comments/${j}`),ee());return}if(n==="resolve"){const i=f.comments.find(s=>s.id===j)?.resolved;await w("POST",`/__loop/api/comments/${j}/resolve`),i||(ee(),y("Resolved. Find it in Comments \u2192 Resolved"));return}if(n==="undo"){let i=await fetch(`/__loop/api/comments/${a}/undo`,{method:"POST",headers:{"content-type":"application/json"},body:"{}"}),s=await i.json().catch(()=>({}));if(i.status===409&&s.error==="newer"){if(!confirm(`This frame has ${s.newer} newer change${s.newer===1?"":"s"} after this one. Undoing this reverts ${s.newer===1?"it":"them"} too. Continue?`))return;i=await fetch(`/__loop/api/comments/${a}/undo`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({force:!0})}),s=await i.json().catch(()=>({}))}if(!i.ok)throw new Error(s.error||"Could not undo");y(s.reverted>1?`Reverted ${s.reverted} changes`:"Change reverted");return}await w("POST",`/__loop/api/comments/${a}/${n}`),n==="redo"&&y("Change re-applied")}catch(i){y(i.message)}}),H.addEventListener("pointerdown",e=>e.stopPropagation()),m("#empty .empty-set").addEventListener("pointerdown",e=>e.stopPropagation()),m("#empty").addEventListener("click",e=>{const t=e.target.closest(".empty-frame");t&&$()&&bn(t.dataset.name,+t.dataset.w,+t.dataset.h)});for(const e of["click","dblclick","contextmenu"])H.addEventListener(e,t=>{H.classList.contains("onpage")&&t.stopPropagation()});addEventListener("scroll",()=>{for(const e of[document.scrollingElement,document.body,I])e&&(e.scrollTop||e.scrollLeft)&&(e.scrollTop=0,e.scrollLeft=0)},!0);let Be=!1;function Ee(e){if(!((e==="frame"||e==="section")&&!$())){if(Be=e==="use",Be&&(e="select"),!Be&&fe&&!S&&(fe=null,ht()),e!=="deep"&&x&&Ve(),B?.soft&&!W.value.trim()&&te(),K=e,I.dataset.tool=e,e!=="select"&&fe&&(fe=null,ht()),e==="select"||e==="hand"){const t=m("#move-btn");t.dataset.tool!==e&&(t.dataset.tool=e,t.innerHTML=A(e==="hand"?"hand":"select"),t.title=e==="hand"?"Hand (H)":"Select (V)")}if(document.querySelectorAll("#tool-menu [data-pick-tool]").forEach(t=>t.classList.toggle("on",t.dataset.pickTool===e&&!Be)),document.querySelectorAll("#toolbar [data-tool]").forEach(t=>t.classList.toggle("on",t.dataset.tool===(Be?"use":e))),I.dataset.use=Be?"1":"",ws(),Xo(),Be&&x&&(te(),Ve()),V.hidden=!0,e!=="pen"&&Bn(),f)for(const t of f.frames)J(t);Fe()}}document.querySelectorAll("#toolbar [data-tool]").forEach(e=>e.addEventListener("click",()=>Ee(e.dataset.tool)));const mt=m("#tool-menu");m("#move-caret").addEventListener("click",e=>{if(e.stopPropagation(),!mt.hidden){mt.hidden=!0;return}mt.hidden=!1;const t=m("#move-caret").closest(".tb-group").getBoundingClientRect();mt.style.left=`${Math.round(t.left)}px`,mt.style.bottom=`${Math.round(innerHeight-t.top+8)}px`,mt.style.top="auto"}),mt.addEventListener("click",e=>{const t=e.target.closest("[data-pick-tool]");t&&(Ee(t.dataset.pickTool),mt.hidden=!0)}),addEventListener("pointerdown",e=>{!mt.hidden&&!e.target.closest("#tool-menu, #move-caret")&&(mt.hidden=!0)},!0);let Ke=null,fe=null;function Gi(e){if(fe!==e&&(fe=e,f))for(const t of f.frames)J(t)}function Ao(e,t,n){if(!n)return!1;const a=e?.ownerDocument;if(!a)return!1;const i=a.defaultView,s=a.scrollingElement||a.documentElement;for(let o=e.nodeType===1?e:e.parentElement;o;o=o.parentElement){const r=o===s||o===a.body,c=i.getComputedStyle(o),l=t==="x"?c.overflowX:c.overflowY;if(!r&&!/(auto|scroll|overlay)/.test(l))continue;const d=r?s:o,u=t==="x"?d.scrollLeft:d.scrollTop,p=t==="x"?d.scrollWidth-d.clientWidth:d.scrollHeight-d.clientHeight;if(p>1&&(n>0?u<p-1:u>0))return!0;if(r)break}return!1}function ht(){document.activeElement?.tagName==="IFRAME"&&document.activeElement.blur(),window.focus()}function Z(e){if(ke&&(ke=null,wt()),e!==Ke&&(Ke=null),(e||fe)&&(fe=null,ht()),_=e,Y.clear(),f)for(const t of f.frames)J(t);Fe(),oa(),ui()}let se=null,hn={fid:null,t:0,x:0,y:0};I.addEventListener("pointermove",e=>{const t=e.target.closest?.(".frame")?.dataset.id||null;t!==In&&(In=t,cn())}),I.addEventListener("pointerleave",()=>{In&&(In=null,cn())}),I.addEventListener("pointerdown",e=>{if(cn(),!f||e.target.closest(".pin, .stop, .rename, .count, .dims"))return;P&&e.target.closest(".frame")?.dataset.id!==P.fid&&nt();const t=S&&e.button===0&&e.target.closest(".frame-body")&&e.target.closest(".frame")?.dataset.id;if(t&&t!==S.fid&&H.hidden&&!j)return e.preventDefault(),vt(t);if(S&&e.button===0&&e.target.closest(".frame:not(.edge-zone)")?.dataset.id!==S.fid){!H.hidden||j?(te(),ee()):dt();return}const n=e.target.closest(".edge-zone")?null:e.target.closest(".frame"),a=n?.dataset.id;if(S&&e.button===0&&a&&a!==S.fid)return e.preventDefault(),vt(a);if(e.button===1||K==="hand"||Yt)return ac(e);if(e.button!==0)return;if(K==="pen")return oc(e);if(K==="frame"||K==="section")return ic(e);if(K==="erase"){se={type:"erase"},qo(e),I.setPointerCapture(e.pointerId);return}if(K==="deep"){if(a&&e.target.closest(".frame-body")){Qt(a,e);return}Ve(),te(),ee();return}if(K==="comment"&&a&&e.target.closest(".frame-label")){e.preventDefault(),ee(),st(a,0,0),B.scope="frame",B.anchor=On(a,{scope:"frame",x:0,y:0});const r=m("#composer-area");r.hidden=!1,r.innerHTML=`${A("frame")}<b>${L(f.frames.find(c=>c.id===a)?.name||"Frame")}</b><span>Whole frame</span>`,r.classList.add("chip-frame"),W.placeholder="What should change about this screen?",D.get(a)?.el.classList.add("whole"),Et(a),_e();return}if(K==="comment"){const r=a&&e.target.closest(".frame-body");if(!r&&(!H.hidden||j)){te(),ee();return}se={type:"cpick",fid:r?a:le,sx:e.clientX,sy:e.clientY,area:!1,rect:null},I.setPointerCapture(e.pointerId);return}if(e.altKey&&$()&&!Be&&!S&&a&&e.target.closest(".frame-body")&&!e.target.closest(".pin")&&!Tn(f.frames.find(r=>r.id===a)||{})){const{lx:r,ly:c}=Ge(a,e.clientX,e.clientY),l=Me(a,r,c),d=de(a),u=x?.frameId===a?x.els[x.els.length-1]:null,p=u&&u.contains(l)?u:Xa(a,l,"deep");if(p&&p!==d?.documentElement&&p!==d?.body){p!==u&&Qt(a,e),se={type:"edrag",fid:a,el:p,sx:e.clientX,sy:e.clientY,moved:!1},I.classList.add("dragging"),I.setPointerCapture(e.pointerId);return}}if(!Be&&(!S||a===S.fid)&&a&&e.target.closest(".frame-body")&&!e.target.closest(".pin")&&!Tn(f.frames.find(r=>r.id===a)||{})&&!D.get(a)?.el.classList.contains("empty")){const r=performance.now(),c=Jn.fid===a&&r-Jn.t<420&&Math.hypot(e.clientX-Jn.x,e.clientY-Jn.y)<6;Jn={fid:a,t:c?0:r,x:e.clientX,y:e.clientY};const l=x?.frameId===a?x.els[x.els.length-1]:null;if(c&&l&&$()&&xn(l,!0)){kn(a,l);return}if(c)return;if(ee(),l&&$()&&!e.shiftKey&&!S&&x.els.length===1&&l.isConnected&&l.parentElement&&l!==de(a)?.body){const{lx:d,ly:u}=Ge(a,e.clientX,e.clientY),p=Me(a,d,u);if(p&&l.contains(p)){se={type:e[rt]?"efree":"emove",fid:a,el:l,sx:e.clientX,sy:e.clientY,moved:!1,ev:{clientX:e.clientX,clientY:e.clientY,shiftKey:!1}},I.classList.add("dragging"),I.setPointerCapture(e.pointerId);return}}Qt(a,e,e[rt]?"deep":"smart");return}x&&!e.target.closest(".pin")&&Ve(),te();const i=a?null:e.target.closest(".section"),s=i?i.dataset.id:null;if(s&&e.target.closest(".srz")&&$())return $d(s,e);if(s&&!e.target.closest(".sec-label")&&!e.shiftKey){ee(),fe&&(fe=null,ht()),yi(s),$()&&zr(s,e);return}if(s&&e.target.closest(".sec-label")){ee();const r=performance.now(),c=hi.id===s&&r-hi.t<420;return hi={id:s,t:r},yi(s),$()?c&&e.target.closest(".sec-name")?(e.preventDefault(),hi.t=0,Rr(s)):zr(s,e):void 0}if(e.target.closest(".resize")&&$())return sc(a,e);if(a&&e.shiftKey&&$()){od(a),ee();return}if(e.target.closest(".frame-label")){ee();const r=performance.now(),c=hn.fid===a&&r-hn.t<420&&Math.hypot(e.clientX-hn.x,e.clientY-hn.y)<6;if(hn={fid:a,t:r,x:e.clientX,y:e.clientY},c&&$()&&e.target.closest(".name")&&!D.get(a)?.renaming)return e.preventDefault(),Z(a),hn.t=0,_i(a);if(Y.has(a))return $()?_o(a,e):void 0;if(Z(a),!$())return;Po(a,e),se.onDims=!!e.target.closest(".dims");return}if(a&&e.target.closest(".frame-body")&&Tn(f.frames.find(r=>r.id===a)||{})){ee();const r=performance.now(),c=mi.fid===a&&r-mi.t<420;if(mi={fid:a,t:r},c)return mi.t=0,Z(a),Oe(!0,[a]);if(Y.has(a))return $()?_o(a,e):void 0;Z(a),$()&&Po(a,e);return}if(ee(),!a&&!e.shiftKey&&(Z(null),fe)){fe=null,ht();for(const r of f.frames)J(r)}nc(e,a),se.clickSid=s||null});function nc(e,t){const n=re(e.clientX,e.clientY);se={type:"marquee",x0:n.x,y0:n.y,clickFid:t,base:e.shiftKey?new Set([...Y,..._?[_]:[]]):new Set},I.classList.add("dragging"),I.setPointerCapture(e.pointerId)}function _o(e,t){const n=[...Y];se={type:"gmove",ids:n,sx:t.clientX,sy:t.clientY,from:Object.fromEntries(n.map(a=>{const i=f.frames.find(s=>s.id===a);return[a,{x:i.x,y:i.y}]})),moved:!1},I.classList.add("dragging"),I.setPointerCapture(t.pointerId)}function ac(e){se={type:"pan",sx:e.clientX,sy:e.clientY,vx:b.x,vy:b.y},I.classList.add("dragging"),I.setPointerCapture(e.pointerId)}function Po(e,t){const n=f.frames.find(a=>a.id===e);se={type:"move",fid:e,sx:t.clientX,sy:t.clientY,fx:n.x,fy:n.y,moved:!1,dup:t.altKey,kids:t.altKey?[]:yc(e).map(a=>({id:a.id,x:a.x,y:a.y}))},I.classList.add("dragging"),I.setPointerCapture(t.pointerId)}function ic(e){const t=re(e.clientX,e.clientY);se={type:"draw",x0:t.x,y0:t.y,rect:null},I.classList.add("dragging"),I.setPointerCapture(e.pointerId)}function sc(e,t){const n=f.frames.find(i=>i.id===e),a=t.target.closest(".resize")?.dataset.dir||"se";se={type:"resize",fid:e,dir:a,sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,w:n.w,h:n.h},I.classList.add("dragging"),I.setPointerCapture(t.pointerId)}function oc(e){Bn(),B?.soft&&!W.value.trim()&&te();const t=re(e.clientX,e.clientY),n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("stroke",Li),n.setAttribute("stroke-width",3/b.z),kt.appendChild(n),se={type:"stroke",points:[t.x,t.y],path:n,width:3/b.z},I.classList.add("dragging"),I.setPointerCapture(e.pointerId)}const rc=11;function lc(e,t,n,a,i,s){const o=i-n,r=s-a,c=o*o+r*r,l=c?Math.max(0,Math.min(1,((e-n)*o+(t-a)*r)/c)):0;return Math.hypot(e-(n+l*o),t-(a+l*r))}function qo(e){const t=re(e.clientX,e.clientY);for(const n of[...f.strokes]){if(n.commentId||String(n.id).startsWith("ink-"))continue;const a=rc/b.z+(n.width||3)/2,i=fn(n);let s=!1;for(let o=0;o+1<i.length&&!s;o+=2){const r=o+3<i.length?i[o+2]:i[o],c=o+3<i.length?i[o+3]:i[o+1];s=lc(t.x,t.y,i[o],i[o+1],r,c)<=a}s&&(f.strokes=f.strokes.filter(o=>o.id!==n.id),kt.querySelector(`path[data-id="${n.id}"]`)?.remove(),w("DELETE",`/__loop/api/strokes/${n.id}`).catch(()=>{}),G("Erase mark",()=>He({strokes:[n]}),()=>w("DELETE",`/__loop/api/strokes/${n.id}`)))}}I.addEventListener("pointermove",e=>{if(xl(e.clientX,e.clientY),!se){if(K==="comment"){const n=e.target.closest?.(".frame-body")&&!e.target.closest(".pin")&&e.target.closest(".frame")?.dataset.id,a=n&&f.frames.find(i=>i.id===n);a&&!Tn(a)&&(!S||n===S.fid)&&!D.get(n)?.el.classList.contains("empty")?La(n,e.clientX,e.clientY,"block"):V.hidden=!0}if(K==="deep"){const n=e.target.closest(".frame-body")&&e.target.closest(".frame")?.dataset.id;n&&!e.target.closest(".pin")?La(n,e.clientX,e.clientY):V.hidden=!0}else if(K==="select"&&!Be&&!xe){const n=e.target.closest?.(".frame-body")&&e.target.closest(".frame")?.dataset.id,a=n&&f.frames.find(i=>i.id===n);a&&(!S||n===S.fid)&&(S||!Tn(a))&&!e.target.closest(".pin")&&!D.get(n)?.el.classList.contains("empty")?La(n,e.clientX,e.clientY,e[rt]?"deep":"smart"):V.hidden=!0}return}const t=se;if(t.type==="pan")b.x=t.vx+e.clientX-t.sx,b.y=t.vy+e.clientY-t.sy,ie();else if(t.type==="smove"){const n=(e.clientX-t.sx)/b.z,a=(e.clientY-t.sy)/b.z;if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<3)return;t.moved=!0,ua.set(t.sid,{x:t.x0+n,y:t.y0+a});for(const[i,s]of Object.entries(t.from))ze.set(i,{x:s.x+n,y:s.y+a}),J(f.frames.find(o=>o.id===i));wt(),_e()}else if(t.type==="sresize"){const n=(e.clientX-t.sx)/b.z,a=(e.clientY-t.sy)/b.z,i=120;let s=t.x0,o=t.y0,r=t.w,c=t.h;t.dir.includes("e")&&(r=t.w+n),t.dir.includes("s")&&(c=t.h+a),t.dir.includes("w")&&(r=t.w-n,s=t.x0+n),t.dir.includes("n")&&(c=t.h-a,o=t.y0+a),r<i&&(t.dir.includes("w")&&(s=t.x0+t.w-i),r=i),c<i&&(t.dir.includes("n")&&(o=t.y0+t.h-i),c=i),ua.set(t.sid,{x:s,y:o,w:r,h:c}),wt(),gi({x:s,y:o,w:r,h:c})}else if(t.type==="move"&&t.dup){t.moved=!0;const n=f.frames.find(i=>i.id===t.fid);if(t.to={x:t.fx+(e.clientX-t.sx)/b.z,y:t.fy+(e.clientY-t.sy)/b.z},!e.metaKey&&!e.ctrlKey){const i=ys({...t.to,w:n.w,h:n.h},null);t.to.x+=i.dx,t.to.y+=i.dy,At(i.guides)}else At([]);const a=m("#dup-ghost");Object.assign(a.style,{left:`${t.to.x}px`,top:`${t.to.y}px`,width:`${n.w}px`,height:`${n.h}px`}),a.querySelector("span").textContent=`${n.name} copy`,a.hidden=!1}else if(t.type==="move"){t.moved=!0;const n=f.frames.find(s=>s.id===t.fid),a={x:t.fx+(e.clientX-t.sx)/b.z,y:t.fy+(e.clientY-t.sy)/b.z};if(e.shiftKey&&(Math.abs(a.x-t.fx)>=Math.abs(a.y-t.fy)?a.y=t.fy:a.x=t.fx),!e.metaKey&&!e.ctrlKey){const s=ys({...a,w:n.w,h:n.h},t.fid);(!e.shiftKey||a.y===t.fy)&&(a.x+=s.dx),(!e.shiftKey||a.x===t.fx)&&(a.y+=s.dy),At(s.guides)}else At([]);ze.set(t.fid,a);for(const s of t.kids||[]){ze.set(s.id,{x:s.x+a.x-t.fx,y:s.y+a.y-t.fy});const o=f.frames.find(r=>r.id===s.id);o&&J(o)}const i=(f.sections||[]).find(s=>An(s,{...n,...a}));Kt.querySelectorAll(".section").forEach(s=>s.classList.toggle("target",s.dataset.id===i?.id)),J(n),_e()}else if(t.type==="marquee"){const n=re(e.clientX,e.clientY),a={x:Math.min(t.x0,n.x),y:Math.min(t.y0,n.y),w:Math.abs(n.x-t.x0),h:Math.abs(n.y-t.y0)};if(!t.moved&&a.w*b.z<4&&a.h*b.z<4)return;!t.moved&&t.clickFid&&!e.shiftKey&&Z(null),t.moved=!0;const i=m("#marquee");i.hidden=!1,Object.assign(i.style,{left:`${a.x}px`,top:`${a.y}px`,width:`${a.w}px`,height:`${a.h}px`});const s=f.frames.filter(o=>o.x<a.x+a.w&&o.x+o.w>a.x&&o.y<a.y+a.h&&o.y+o.h>a.y).map(o=>o.id);hs([...new Set([...t.base,...s])])}else if(t.type==="gmove"){t.moved=!0;let n=(e.clientX-t.sx)/b.z,a=(e.clientY-t.sy)/b.z;const i=t.ids.map(s=>{const o=f.frames.find(r=>r.id===s);return{x:t.from[s].x+n,y:t.from[s].y+a,w:o.w,h:o.h}});if(!e.metaKey&&!e.ctrlKey){const s=gs(i),o=ys(s,new Set(t.ids));n+=o.dx,a+=o.dy,At(o.guides)}else At([]);for(const s of t.ids)ze.set(s,{x:t.from[s].x+n,y:t.from[s].y+a}),J(f.frames.find(o=>o.id===s));Cn()}else if(t.type==="cpick"){if(!t.area&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)>6&&(t.area=!0,V.hidden=!0,te(),ee(),I.classList.add("dragging")),!t.area)return;let n,a;if(t.fid===le)n=re(t.sx,t.sy),a=re(e.clientX,e.clientY);else{const s=f.frames.find(r=>r.id===t.fid),o=r=>({x:Math.max(0,Math.min(s.w,r.lx)),y:Math.max(0,Math.min(s.h,r.ly))});n=o(Ge(t.fid,t.sx,t.sy)),a=o(Ge(t.fid,e.clientX,e.clientY))}t.rect={x:Math.min(n.x,a.x),y:Math.min(n.y,a.y),w:Math.abs(a.x-n.x),h:Math.abs(a.y-n.y)};let i=Ht(t.fid).querySelector(".area.picking");i||(i=document.createElement("div"),i.className="area picking show",Ht(t.fid).prepend(i)),Object.assign(i.style,{left:`${t.rect.x}px`,top:`${t.rect.y}px`,width:`${t.rect.w}px`,height:`${t.rect.h}px`})}else if(t.type==="efree"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<5)return;if(!t.moved){t.moved=!0,V.hidden=!0;const s=t.el,o=s.parentElement,r=s.ownerDocument.defaultView,c=s.getBoundingClientRect(),l=o.getBoundingClientRect(),d=r.getComputedStyle(o);t.base=s.getAttribute("style"),t.pbase=o.getAttribute("style"),t.props={},t.pprops={},d.position==="static"&&(o.style.position="relative",t.pprops.position="relative"),t.x0=c.left-l.left-o.clientLeft+o.scrollLeft,t.y0=c.top-l.top-o.clientTop+o.scrollTop,Object.assign(t.props,{position:"absolute",margin:"0",width:r.getComputedStyle(s).width,left:`${Math.round(t.x0)}px`,top:`${Math.round(t.y0)}px`});for(const[u,p]of Object.entries(t.props))s.style.setProperty(u,p)}const n=b.z,a=Math.round(t.x0+(e.clientX-t.sx)/n),i=Math.round(t.y0+(e.clientY-t.sy)/n);t.props.left=`${a}px`,t.props.top=`${i}px`,t.el.style.left=t.props.left,t.el.style.top=t.props.top,Pe(),Bt()}else if(t.type==="emove"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<5)return;t.moved||(t.moved=!0,t.op=t.el.style.opacity,t.el.style.opacity=".35",V.hidden=!0,ae.hidden=!0,t.line=document.createElement("div"),t.line.id="el-line",document.body.appendChild(t.line));const n=D.get(t.fid).iframe.getBoundingClientRect(),a=b.z,i=(e.clientX-n.left)/a,s=(e.clientY-n.top)/a;if(!t.box){const R=t.el.getBoundingClientRect();t.box=document.createElement("div"),t.box.id="el-drag",t.bx=n.left+R.left*a,t.by=n.top+R.top*a,Object.assign(t.box.style,{width:`${R.width*a}px`,height:`${R.height*a}px`}),document.body.appendChild(t.box)}if(t.box.style.transform=`translate(${t.bx+e.clientX-t.sx}px, ${t.by+e.clientY-t.sy}px)`,t.intoBox||(t.intoBox=document.createElement("div"),t.intoBox.id="el-into",document.body.appendChild(t.intoBox)),document.querySelectorAll(".frame.drop-into").forEach(R=>R.classList.remove("drop-into")),t.before=void 0,t.into=null,t.line.hidden=!0,t.intoBox.hidden=!0,t.out=e.clientX<n.left||e.clientX>n.right||e.clientY<n.top||e.clientY>n.bottom,t.out){const R=re(e.clientX,e.clientY),ce=zn(R.x,R.y);ce&&ce.id!==t.fid&&D.get(ce.id)?.el.classList.add("drop-into");return}const o=t.el.ownerDocument,r=o.body,c=t.el.parentElement,l=Me(t.fid,i,s),d=R=>[...R.children].some(ce=>ce!==t.el&&fs(ce))||!R.children.length&&!R.textContent.trim()&&/^(block|flex|grid|flow-root|list-item)$/.test(o.defaultView.getComputedStyle(R).display);let u=!l||l===o.documentElement?r:l;if(t.el.contains(u))u=c;else{for(;u!==r&&!d(u);)u=u.parentElement;t.el.contains(u)&&(u=c)}if(u!==r&&u!==c&&!u.contains(t.el)){const R=u.getBoundingClientRect(),ce=7/a;(i-R.left<ce||R.right-i<ce||s-R.top<ce||R.bottom-s<ce)&&(u=u.parentElement)}const p=[...u.children].filter(fs),h=p.filter(R=>R!==t.el),g=h.map(R=>R.getBoundingClientRect()),v=u.getBoundingClientRect(),T=(R,ce,rn,Yr)=>Object.assign(t.line.style,{left:`${n.left+R*a}px`,top:`${n.top+ce*a}px`,width:`${rn}px`,height:`${Yr}px`,marginLeft:"0",marginTop:"0"}),C=()=>{u!==c&&(Object.assign(t.intoBox.style,{left:`${n.left+v.left*a}px`,top:`${n.top+v.top*a}px`,width:`${v.width*a}px`,height:`${v.height*a}px`}),t.intoBox.hidden=!1)};if(!h.length){if(u===c)return;t.into=u,t.before=null,T(v.left+4,v.top+4,Math.max(8,(v.width-8)*a),2),t.line.hidden=!1,C();return}const k=p.slice(0,2).map(R=>R.getBoundingClientRect()),M=k.length>1&&Math.abs(k[1].left-k[0].left)>Math.abs(k[1].top-k[0].top);let E=g.findIndex(R=>M?i<R.left+R.width/2:s<R.top+R.height/2);E<0&&(E=h.length);const N=h[E]||null;if(u===c&&N===(p[p.indexOf(t.el)+1]||null))return;t.into=u,t.before=N;const q=g[E-1],ne=g[E];if(M){const R=q&&ne?(q.right+ne.left)/2:ne?ne.left-4:q.right+4,ce=ne||q;T(R,ce.top,2,ce.height*a),t.line.style.marginLeft="-1px"}else{const R=q&&ne?(q.bottom+ne.top)/2:ne?ne.top-4:q.bottom+4,ce=ne||q;T(Math.max(ce.left,v.left),R,Math.min(ce.width,v.width)*a,2),t.line.style.marginTop="-1px"}C(),t.line.hidden=!1}else if(t.type==="edrag"){if(!t.moved&&Math.hypot(e.clientX-t.sx,e.clientY-t.sy)<4)return;if(!t.moved){t.moved=!0,t.copy=na(t.fid,t.el);const o=De(f.frames.find(r=>r.id===t.fid));t.x0=o.x+t.copy.x,t.y0=o.y+t.copy.y,t.ghost=document.createElement("div"),t.ghost.id="el-ghost",t.ghost.innerHTML=t.copy.html,Object.assign(t.ghost.style,{width:`${t.copy.w}px`,height:`${t.copy.h}px`}),xt.appendChild(t.ghost),V.hidden=!0}const n=(e.clientX-t.sx)/b.z,a=(e.clientY-t.sy)/b.z;t.ghost.style.transform=`translate(${t.x0+n}px, ${t.y0+a}px)`;const i=re(e.clientX,e.clientY),s=zn(i.x,i.y);document.querySelectorAll(".frame.drop-into").forEach(o=>o.classList.remove("drop-into")),s&&D.get(s.id)?.el.classList.add("drop-into")}else if(t.type==="draw"){const n=re(e.clientX,e.clientY),a={x:Math.min(t.x0,n.x),y:Math.min(t.y0,n.y),w:Math.abs(n.x-t.x0),h:Math.abs(n.y-t.y0)};if(e.shiftKey&&(a.w=a.h=Math.max(a.w,a.h)),t.rect=a,K==="section"){t.sec||(t.sec=document.createElement("div"),t.sec.className="section drawing",t.sec.innerHTML='<div class="sec-label"><span class="sec-name">Section</span></div>',Kt.appendChild(t.sec)),Object.assign(t.sec.style,{left:`${a.x}px`,top:`${a.y}px`,width:`${a.w}px`,height:`${a.h}px`}),gi(a);return}const i=m("#draw-box");Object.assign(i.style,{left:`${a.x}px`,top:`${a.y}px`,width:`${a.w}px`,height:`${a.h}px`}),i.querySelector("span").textContent=`${Math.round(a.w)} \xD7 ${Math.round(a.h)}`,i.hidden=!1}else if(t.type==="resize"){const n=(e.clientX-t.sx)/b.z,a=(e.clientY-t.sy)/b.z,i=120;let s=t.x0,o=t.y0,r=t.w,c=t.h;if(t.dir.includes("e")&&(r=t.w+n),t.dir.includes("s")&&(c=t.h+a),t.dir.includes("w")&&(r=t.w-n,s=t.x0+n),t.dir.includes("n")&&(c=t.h-a,o=t.y0+a),e.shiftKey&&t.dir.length===2){const d=Math.max(r/t.w,c/t.h),u=t.w*d,p=t.h*d;t.dir.includes("w")&&(s=t.x0+t.w-u),t.dir.includes("n")&&(o=t.y0+t.h-p),r=u,c=p}r<i&&(t.dir.includes("w")&&(s=t.x0+t.w-i),r=i),c<i&&(t.dir.includes("n")&&(o=t.y0+t.h-i),c=i);const l={x:s,y:o,w:r,h:c};if(!e.metaKey&&!e.ctrlKey&&!e.shiftKey){const d=fd(l,t.fid,t.dir);Object.assign(l,d.rect),At(d.guides)}else At([]);ze.set(t.fid,l),J(f.frames.find(d=>d.id===t.fid)),m("#fp-sw")&&(m("#fp-sw").value=Math.round(l.w),m("#fp-sh").value=Math.round(l.h))}else if(t.type==="stroke"){const n=re(e.clientX,e.clientY),a=t.points.length;if(Math.hypot(n.x-t.points[a-2],n.y-t.points[a-1])*b.z<1.5)return;t.points.push(n.x,n.y),t.path.setAttribute("d",Di(t.points))}else t.type==="erase"&&qo(e)});const Do=async e=>{const t=se;if(t){if(se=null,I.classList.remove("dragging"),At([]),Kt.querySelectorAll(".section.target").forEach(n=>n.classList.remove("target")),t.type==="smove"||t.type==="sresize"){gi(null);const n=ua.get(t.sid),a=f.sections.find(r=>r.id===t.sid);if(ua.delete(t.sid),!n||!a)return;const i=t.type==="smove"?{x:t.x0,y:t.y0}:{x:t.x0,y:t.y0,w:t.w,h:t.h},s={...n},o=t.sid;if(Object.assign(a,n),w("PATCH",`/__loop/api/sections/${o}`,n).catch(r=>y(r.message)),t.type==="smove"){const r=t.from,c={};for(const l of Object.keys(r)){const d=ze.get(l);ze.delete(l);const u=f.frames.find(p=>p.id===l);d&&u&&(Object.assign(u,d),c[l]={x:d.x,y:d.y})}Se(c),G("Move section",()=>Promise.all([Pt(o,i),Se(r)]),()=>Promise.all([Pt(o,s),Se(c)]))}else G("Resize section",()=>Pt(o,i),()=>Pt(o,s));wt();return}if(t.type==="marquee"){if(m("#marquee").hidden=!0,!t.moved&&!t.clickFid&&t.clickSid){yi(t.clickSid);return}if(!t.moved&&t.clickFid){const n=t.clickFid,a=f.frames.find(o=>o.id===n);if(D.get(n)?.el.classList.contains("empty")){Z(n),_a(n);return}Z(n),Gi(n);const i=re(e.clientX,e.clientY),s=a&&Me(n,i.x-a.x,i.y-a.y);try{D.get(n)?.iframe.focus()}catch{}if(s&&s!==de(n)?.documentElement)try{s.focus?.({preventScroll:!0,focusVisible:!1}),s.click?.()}catch{}}return}if(t.type==="gmove"){if(!t.moved)return;be=null,oi();const n=t.from,a={};for(const i of t.ids){const s=ze.get(i);ze.delete(i);const o=f.frames.find(r=>r.id===i);s&&o&&(Object.assign(o,s),a[i]={x:s.x,y:s.y})}Se(a),G(`Move ${t.ids.length} frames`,()=>Se(n),()=>Se(a));return}if(t.type==="cpick"){if(document.querySelectorAll(".area.picking").forEach(s=>s.remove()),t.area&&t.rect&&t.rect.w*b.z>8&&t.rect.h*b.z>8)return st(t.fid,t.rect.x,t.rect.y,null,t.rect);if(t.area)return;if(t.fid===le){const s=re(t.sx,t.sy);return st(le,s.x,s.y,"canvas")}const{lx:n,ly:a}=Ge(t.fid,t.sx,t.sy);if(D.get(t.fid)?.el.classList.contains("empty"))return _a(t.fid);const i=Xa(t.fid,Me(t.fid,n,a),"block");return i?(te(),ee(),V.hidden=!0,x={frameId:t.fid,els:[i],scope:i.parentElement},ea()):st(t.fid,n,a)}if(t.type==="efree")return t.moved?Yc(t):Qt(t.fid,t.ev,"deep");if(t.type==="emove")return t.line?.remove(),t.box?.remove(),t.intoBox?.remove(),document.querySelectorAll(".frame.drop-into").forEach(n=>n.classList.remove("drop-into")),t.moved&&(t.el.style.opacity=t.op||""),t.moved&&bt(),t.moved&&!t.el.getAttribute("style")&&t.el.removeAttribute("style"),t.moved?t.out?Uc(t,e):t.into?Vc(t.fid,t.el,t.into,t.before):void 0:Qt(t.fid,t.ev,"smart");if(t.type==="edrag"){if(t.ghost?.remove(),document.querySelectorAll(".frame.drop-into").forEach(o=>o.classList.remove("drop-into")),!t.moved)return;const n=re(e.clientX,e.clientY),a=zn(n.x,n.y);if(a){const o=De(a),r=Me(a.id,n.x-o.x,n.y-o.y);return ti(t.copy,a.id,r)}const i=(e.clientX-t.sx)/b.z,s=(e.clientY-t.sy)/b.z;return Qa(t.copy,t.x0+i,t.y0+s)}if(t.type==="draw"){m("#draw-box").hidden=!0,t.sec?.remove(),gi(null);const n=t.rect;if(K==="section"){Ee("select"),n&&n.w*b.z>24&&n.h*b.z>24&&Ld({x:n.x,y:n.y,w:n.w,h:n.h});return}n&&n.w*b.z>12&&n.h*b.z>12?bn("Frame",n.w,n.h,n.x,n.y):K==="frame"&&bn(ue.name,ue.w,ue.h,t.x0,t.y0);return}if(t.type==="move"&&t.dup){m("#dup-ghost").hidden=!0,t.moved&&t.to&&qn(t.fid,t.to);return}if(t.type==="move"&&!t.moved&&t.onDims){Ke=Ke===t.fid?null:t.fid,Fe();return}if(t.type==="move"&&t.moved||t.type==="resize"){const n=ze.get(t.fid),a=f.frames.find(s=>s.id===t.fid),i=t.type==="move"?{x:t.fx,y:t.fy}:{x:t.x0,y:t.y0,w:t.w,h:t.h};if(n&&a&&Object.assign(a,n),ze.delete(t.fid),n){const s=t.fid,o=t.type==="move"?t.kids||[]:[];let r;if(t.type==="move"&&a){const u=new Set([s,...o.map(h=>h.id)]),p=Go({...a,...n},u)?.id;(p||void 0)!==a.parent&&(r=p||null)}w("PATCH",`/__loop/api/frames/${s}`,r===void 0?n:{...n,parent:r}).catch(u=>y(u.message)),r!==void 0&&a&&(a.parent=r||void 0);const c={...n},l={},d={};for(const u of o){const p=ze.get(u.id);ze.delete(u.id),p&&(l[u.id]={x:u.x,y:u.y},d[u.id]={x:Math.round(p.x),y:Math.round(p.y)})}o.length&&Se(d),G(t.type==="move"?"Move frame":"Resize frame",()=>Promise.all([Rt(s,i),o.length&&Se(l)]),()=>Promise.all([Rt(s,c),o.length&&Se(d)]))}t.type==="resize"&&setTimeout(()=>ut(t.fid),50)}else if(t.type==="stroke"){const n=t.points;n.length<4&&n.push(n[0]+.5,n[1]+.5);const a=new Map;for(let s=0;s<n.length;s+=2){const o=zn(n[s],n[s+1]);o&&a.set(o.id,(a.get(o.id)||0)+1)}const i=[...a.entries()].sort((s,o)=>o[1]-s[1])[0]?.[0]||null;try{const s=await w("POST","/__loop/api/strokes",{points:n,color:Li,width:t.width,frameId:i});_s.add(s.id),G("Draw mark",()=>w("DELETE",`/__loop/api/strokes/${s.id}`),()=>He({strokes:[s]})),t.path.remove(),f.strokes.find(o=>o.id===s.id)||f.strokes.push(s),qt(),Hl(i,n,e)}catch(s){t.path.remove(),y(s.message)}}}};I.addEventListener("pointerup",Do),I.addEventListener("pointercancel",Do),I.addEventListener("pointerleave",()=>{V.hidden=!0}),addEventListener("wheel",e=>{if(S&&e.target.closest?.("#viewport")){e.preventDefault();try{const a=e.deltaMode===1?16:1,{lx:i,ly:s}=Ge(S.fid,e.clientX,e.clientY),o=Me(S.fid,i,s),r=de(S.fid)?.defaultView;if(o&&r){let c=o;const l=r.document.scrollingElement||r.document.documentElement;for(;c&&c!==l&&c!==r.document.body;c=c.parentElement){const d=r.getComputedStyle(c).overflowY;if(/(auto|scroll|overlay)/.test(d)&&c.scrollHeight>c.clientHeight+1)break}(c&&c!==r.document.body?c:l).scrollTop+=e.deltaY*a,V.hidden=!0,requestAnimationFrame(()=>{Pe(),_e()})}}catch{}return}if(e.ctrlKey||e.metaKey)return Os(e,e.clientX,e.clientY);if(!e.target.closest?.("#viewport"))return;e.preventDefault();const t=e.deltaMode===1?16:1,n=e.target.closest?.(".frame-body")&&e.target.closest(".frame")?.dataset.id;if(n&&(x?.frameId===n||_===n)&&Math.abs(e.deltaY)>=Math.abs(e.deltaX))try{const{lx:a,ly:i}=Ge(n,e.clientX,e.clientY),s=Me(n,a,i),o=de(n)?.defaultView;if(s&&o&&Ao(s,"y",e.deltaY)){let r=s;const c=o.document.scrollingElement||o.document.documentElement;for(;r&&r!==c&&r!==o.document.body;r=r.parentElement){const l=o.getComputedStyle(r).overflowY;if(/(auto|scroll|overlay)/.test(l)&&r.scrollHeight>r.clientHeight+1&&(e.deltaY>0?r.scrollTop<r.scrollHeight-r.clientHeight-1:r.scrollTop>0))break}(r&&r!==o.document.body?r:c).scrollTop+=e.deltaY*t,V.hidden=!0,requestAnimationFrame(()=>{Pe(),_e()});return}}catch{}b.x-=e.deltaX*t,b.y-=e.deltaY*t,Si()},{passive:!1,capture:!0});let Oa=1;addEventListener("gesturestart",e=>{e.preventDefault(),Oa=b.z}),addEventListener("gesturechange",e=>{e.preventDefault(),!S&&Lt(e.clientX,e.clientY,Oa*e.scale/b.z)});const Ot=()=>{const e=document.activeElement;return e&&(e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.isContentEditable)};addEventListener("keydown",e=>{if(Ot())return;if(e.code==="Space"&&!Yt){Yt=!0,I.classList.add("panning"),f&&f.frames.forEach(J),e.preventDefault();return}if(e.metaKey||e.ctrlKey){if(e.key.toLowerCase()==="z"){e.preventDefault(),e.shiftKey?Qn():Va();return}if(e.key.toLowerCase()==="c"&&x&&!xe&&$()){e.preventDefault();const n=x.els[x.els.length-1];pe=na(x.frameId,n),Xe=null;try{navigator.clipboard?.write?.([new ClipboardItem({"text/html":new Blob([pe.html],{type:"text/html"}),"text/plain":new Blob([pe.html],{type:"text/plain"})})]).catch(()=>{})}catch{}y(`Copied \u201C${pe.name}\u201D \u2014 \u2318V to paste`,1600);return}if(e.key.toLowerCase()==="v"&&pe&&!Xe&&$()){if(e.preventDefault(),x){ti(pe,x.frameId,x.els[x.els.length-1]);return}const n=f.frames.find(r=>r.id===pe.fid),a=pe.w,i=pe.h,s=r=>f.frames.some(c=>r.x<c.x+c.w+40&&r.x+a+40>c.x&&r.y<c.y+c.h+40&&r.y+i+40>c.y);let o=n?{x:n.x+n.w+80,y:n.y}:re(innerWidth/2-a*b.z/2,innerHeight/2-i*b.z/2);s(o)&&(o=ts(a,i)),Qa(pe,o.x,o.y);return}if(e.key.toLowerCase()==="s"&&e.shiftKey&&$()){e.preventDefault();const n=ke||_&&f.sections.find(a=>An(a,f.frames.find(i=>i.id===_)||{}))?.id;n?bi(n):y("Select a section to remove it (its frames stay)");return}if(e.key.toLowerCase()==="f"&&e.shiftKey&&$()){e.preventDefault(),_?Jo(_):y("Select a frame to unframe it (what is inside stays)");return}if(e.key.toLowerCase()==="c"&&e.shiftKey&&_&&!x){e.preventDefault(),ar(_);return}if(e.key.toLowerCase()==="l"&&e.shiftKey&&(x||_)){e.preventDefault(),os(x?x.frameId:_,x?x.els[x.els.length-1]:null);return}if(e.key.toLowerCase()==="c"&&_&&$()){e.preventDefault(),Xe=_,pe=null,y(`Copied \u201C${f.frames.find(n=>n.id===_)?.name}\u201D \u2014 \u2318V to paste`,1600);return}if(e.key.toLowerCase()==="v"&&Xe&&$()){e.preventDefault(),f.frames.find(n=>n.id===Xe)?qn(Xe):y("The copied frame no longer exists");return}if(e.key.toLowerCase()==="d"&&x?.els.length===1&&$()){e.preventDefault(),pr();return}if(e.key.toLowerCase()==="d"&&Y.size&&$()){e.preventDefault(),[...Y].forEach(n=>qn(n));return}if(e.key.toLowerCase()==="d"&&_&&$()){e.preventDefault(),qn(_);return}if(e.key.toLowerCase()==="a"&&$()){e.preventDefault(),hs(f.frames.map(n=>n.id));return}if(e.key.toLowerCase()==="y"&&e.ctrlKey){e.preventDefault(),Qn();return}e.key==="0"&&(e.preventDefault(),b.z=1,ie()),(e.key==="="||e.key==="+")&&(e.preventDefault(),Lt(innerWidth/2,innerHeight/2,1.25)),e.key==="-"&&(e.preventDefault(),Lt(innerWidth/2,innerHeight/2,.8));return}const t=e.key.toLowerCase();if(t==="s"&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),S)return dt();const n=_||x?.frameId||(Y.size===1?[...Y][0]:null)||_t;n&&f.frames.some(a=>a.id===n)?vt(n):y("Select a frame, then press S to open it on stage");return}if(t==="v")Ee("select");else if(t==="h")Ee("hand");else if(t==="p")Ee("pen");else if(t==="e")Ee("erase");else if(t==="s"&&e.shiftKey&&$())Ee(K==="section"?"select":"section");else if((e.key==="Backspace"||e.key==="Delete")&&x&&$())e.preventDefault(),ms();else if((e.key==="Backspace"||e.key==="Delete")&&ke&&$())bi(ke);else if(t==="c"&&e.shiftKey)jn();else if(t==="c"){if(Ne&&jn(!0),x?.els.length){e.preventDefault(),ea();return}Ee("comment")}else if(t==="x")Ee("use");else if(t==="d"&&e.shiftKey)Ts();else if(t==="n"&&$())Ji();else if(t==="f"&&e.shiftKey&&$())_?ra(_):y("Select a frame to freeze it");else if(t==="k"&&$()&&_)di(_);else if(t==="f"&&$())Ee(K==="frame"?"select":"frame");else if(e.key==="!"||e.shiftKey&&e.code==="Digit1")Oe();else if(e.key==="@"||e.shiftKey&&e.code==="Digit2")Io(!1);else if(x&&K!=="frame"&&/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&$()&&!S)e.preventDefault(),Zc(e.key);else if(K==="frame"&&/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&$()&&!S)e.preventDefault(),gc(e.key);else if(K==="frame"&&e.key==="Enter"&&!m("#preset-menu").hidden)e.preventDefault(),m("#preset-menu").hidden=!0;else if(/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&$()&&!S&&!P&&(_||Y.size||ke)){const n=e.shiftKey?10:1;kd(e.key==="ArrowLeft"?-n:e.key==="ArrowRight"?n:0,e.key==="ArrowUp"?-n:e.key==="ArrowDown"?n:0)&&e.preventDefault()}else if(e.key==="="||e.key==="+")Lt(innerWidth/2,innerHeight/2,1.25);else if(e.key==="-")Lt(innerWidth/2,innerHeight/2,.8);else if(e.key==="Escape"&&x){const n=x.els.length===1&&x.els[0],a=n?.parentElement,i=n?.ownerDocument;a&&a!==i.body&&a!==i.documentElement&&H.hidden?(x={frameId:x.frameId,els:[a],scope:a.parentElement},Za(x.frameId)):(Ve(),te())}else if(e.key==="Escape")H.hidden?j?ee():!m("#agent-menu").hidden||!m("#share-menu").hidden?gt():S?dt():(Z(null),Ee("select")):te();else if((e.key==="Backspace"||e.key==="Delete")&&Y.size&&$())wr([...Y]);else if(e.altKey&&$()&&Y.size>=2&&br[e.code])e.preventDefault(),vr(br[e.code]);else if((e.key==="Backspace"||e.key==="Delete")&&_&&$()){const n=f.frames.find(a=>a.id===_);n&&bc(n.id).then(()=>{_=null,Fe()})}}),addEventListener("keyup",e=>{e.code==="Space"&&(Yt=!1,I.classList.remove("panning"),f&&f.frames.forEach(J))}),addEventListener("blur",()=>{Yt&&(Yt=!1,I.classList.remove("panning"))}),m("#zoom-in").onclick=()=>Lt(innerWidth/2,innerHeight/2,1.25),m("#zoom-out").onclick=()=>Lt(innerWidth/2,innerHeight/2,.8),m("#zoom-level").onclick=()=>Io(!0);function Io(e){if(x?.els.length){const n=f.frames.find(a=>a.id===x.frameId);if(n){const a=x.els.map(c=>c.getBoundingClientRect()),i=Math.min(...a.map(c=>c.left)),s=Math.min(...a.map(c=>c.top)),o=Math.max(...a.map(c=>c.right)),r=Math.max(...a.map(c=>c.bottom));return Rs({x:n.x+i,y:n.y+s,w:o-i,h:r-s},2)}}const t=Y.size?[...Y]:_?[_]:ke?an(f.sections.find(n=>n.id===ke)).map(n=>n.id):[];if(t.length)return Oe(!0,t);if(e)return Oe();y("Select something to zoom to it")}function gt(){m("#agent-menu").hidden=!0,m("#share-menu").hidden=!0}function Ho(e,t){const n=t.getBoundingClientRect();e.hidden=!1,e.style.top=`${n.bottom+8}px`,e.style.left=`${Math.max(12,Math.min(n.right-e.offsetWidth,innerWidth-e.offsetWidth-12))}px`}const Hd="loop watch";function cc(e){const t=m("#reconnect-pop");if(!t||t.hidden)return;const n=t.querySelector(".rc-status");e==="on"&&!t.classList.contains("done")&&(t.classList.add("done"),n.innerHTML='<i class="rc-ok"></i><span>Connected. Comments go to your chat again.</span>',setTimeout(()=>{t.hidden=!0,t.classList.remove("done")},1600))}function Qi(e){let t=m("#reconnect-pop");t||(t=document.createElement("div"),t.id="reconnect-pop",t.hidden=!0,document.body.appendChild(t),t.addEventListener("pointerdown",s=>s.stopPropagation()),t.addEventListener("click",async s=>{const o=s.target.closest("[data-rc]");if(o){if(o.dataset.rc==="copy")try{await navigator.clipboard.writeText(ao),o.textContent="Copied",t.querySelector(".rc-status").hidden=!1,setTimeout(()=>{o.textContent="Copy"},1600)}catch{y("Select the line and copy it")}if(o.dataset.rc==="close"&&(t.hidden=!0),o.dataset.rc==="loop"){t.hidden=!0;try{await w("POST","/__loop/api/settings",{mode:"headless"}),y(`${f.agentLabel||"Claude Code"} will run your comments directly`)}catch(r){y(r.message)}}}}),addEventListener("pointerdown",s=>{!t.hidden&&!t.contains(s.target)&&!s.target.closest("#reconnect-btn")&&(t.hidden=!0)}));const n=f.agentBin==="codex"?"Codex":"Claude Code";t.classList.remove("done"),t.innerHTML=`<div class="rc-head"><b>Reconnect your chat</b><button class="rc-x" data-rc="close" aria-label="Close"><svg viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8"/></svg></button></div>
44
+ <ol class="rc-steps">
45
+ <li><span class="rc-n">1</span><span>Go to the ${n} chat that opened this canvas</span></li>
46
+ <li><span class="rc-n">2</span><span>Paste this and send it<span class="rc-code"><code>${L(ao)}</code><button data-rc="copy">Copy</button></span></span></li>
47
+ <li><span class="rc-n">3</span><span class="rc-status"><i class="rc-spin"></i><span>Waiting for your chat\u2026</span></span></li>
48
+ </ol>
49
+ <div class="rc-foot">Meanwhile, comments run in the background. <button data-rc="loop">Let ${n} run them directly instead</button></div>`,t.hidden=!1;const a=e.getBoundingClientRect(),i=t.offsetWidth;t.style.left=`${Math.max(12,Math.min(innerWidth-i-12,a.right-i))}px`,t.style.top=`${a.bottom+8}px`}m("#reconnect-btn").addEventListener("click",e=>{e.stopPropagation(),Yn();const t=m("#reconnect-pop");if(t&&!t.hidden){t.hidden=!0;return}gt?.(),Qi(m("#agent-pill"))}),m("#reconnect-btn").addEventListener("keydown",e=>{(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),e.stopPropagation(),e.currentTarget.click())});let Le=null,Gt=0;function Ra(){const e=m("#agent-pill")._info;if(!e)return;const t=[Le&&!Le.hidden&&Le,!m("#agent-menu").hidden&&m("#am-card")].filter(Boolean);if(!t.length)return;const n=e.state==="away"?["away","Disconnected"]:e.state==="offline"?["offline",`${L(f.hostName||"Host")} is offline`]:e.n?["busy",`Working${e.n>1?` on ${e.n}`:""}`]:["on",f.agent.mode==="inbox"?"Connected":"Ready"],a=e.ctx?.pct??0,i=2*Math.PI*27,s=[e.ctx&&["Context",`<span class="ac-bar"><i style="width:${a}%"></i></span><b>${a}%</b><small>${e.ctx.used} of ${e.ctx.window}</small>`],e.model&&["Model",L(e.model)],["Comments go to",f.agent.mode==="inbox"?e.state==="away"?"Background, for now":"Your chat":`${L(e.who)}, run by Loop`],e.n&&["Working now",`${e.n} comment${e.n>1?"s":""}`],e.queued&&["Waiting",`${e.queued} comment${e.queued>1?"s":""}`],e.waiting&&$()&&["To review",`${e.waiting} from guests`],f.agent.chat?.permission&&f.agent.mode==="inbox"&&["Permissions",f.agent.chat.permission==="bypassPermissions"?"Allowed without asking":f.agent.chat.permission==="auto"?"Auto":L(f.agent.chat.permission)]].filter(Boolean),o=`ac-${n[0]}${e.ctx?" ac-ctx":""}${a>=95?" ac-full":a>=80?" ac-high":""}`;for(const r of t){const c=r.id==="am-card";r.className=o,r.innerHTML=`<div class="ac-top"><span class="ac-mark"><svg class="ac-ring" viewBox="0 0 60 60" aria-hidden="true"><circle class="t" cx="30" cy="30" r="27"/>${e.ctx?`<circle class="f" cx="30" cy="30" r="27" stroke-dasharray="${i*a/100} ${i}"/>`:""}</svg><span class="ac-logo">${qi[e.runner]}</span></span>
50
+ <b class="ac-name">${L(e.who)}</b><span class="ac-state"><i></i>${n[1]}</span></div>
51
+ <div class="ac-rows">${s.filter(([l])=>!(c&&l==="Comments go to")).map(([l,d])=>`<div class="ac-row"><span>${l}</span><span class="ac-v">${d}</span></div>`).join("")}</div>
52
+ ${e.state==="away"&&$()?'<button class="ac-btn" data-ac="reconnect">Reconnect</button>':c?"":'<div class="ac-hint">Click for settings</div>'}`}}function dc(){if(Le||(Le=document.createElement("div"),Le.id="agent-card",Le.hidden=!0,document.body.appendChild(Le),Le.addEventListener("pointerenter",()=>clearTimeout(Gt)),Le.addEventListener("pointerleave",()=>{Gt=setTimeout(Yn,180)}),Le.addEventListener("click",n=>{n.target.closest('[data-ac="reconnect"]')&&(Yn(),Qi(m("#agent-pill")))})),!m("#agent-menu").hidden||m("#reconnect-pop")&&!m("#reconnect-pop").hidden)return;Le.hidden=!1,Ra();const e=m("#agent-pill").getBoundingClientRect(),t=Le.offsetWidth;Le.style.left=`${Math.max(12,Math.min(innerWidth-t-12,e.left+e.width/2-t/2))}px`,Le.style.top=`${e.bottom+8}px`}function Yn(){clearTimeout(Gt),Le&&(Le.hidden=!0)}m("#agent-pill").addEventListener("pointerenter",()=>{clearTimeout(Gt),Gt=setTimeout(dc,220)}),m("#agent-pill").addEventListener("pointerleave",()=>{clearTimeout(Gt),Gt=setTimeout(Yn,180)}),m("#am-card").addEventListener("click",e=>{e.target.closest('[data-ac="reconnect"]')&&(gt(),Qi(m("#agent-pill")))}),m("#agent-pill").addEventListener("click",e=>{if(e.stopPropagation(),Yn(),setTimeout(Ra,0),!$())return;const t=m("#agent-menu"),n=!t.hidden;gt(),n||Ho(t,e.currentTarget)}),document.querySelectorAll("#agent-menu .am-opt").forEach(e=>e.addEventListener("click",async()=>{try{await w("POST","/__loop/api/settings",{mode:e.dataset.mode,runner:e.dataset.runner}),y(e.dataset.mode==="inbox"?"Comments will queue for your agent session":`Loop will run ${e.dataset.runner==="codex"?"Codex":"Claude Code"} on each comment`)}catch(t){y(t.message)}gt()}));let gn=!1;m("#agent-allowed").addEventListener("click",e=>{const t=e.target.closest(".al-head");t&&(e.stopPropagation(),gn=!gn,t.setAttribute("aria-expanded",gn),t.nextElementSibling.hidden=!gn)}),m("#agent-allowed").addEventListener("click",async e=>{const t=e.target.closest("[data-disallow]");if(t)try{await w("POST","/__loop/api/settings",{disallow:t.dataset.disallow})}catch(n){y(n.message)}});function fc(){const e=!!f.emailSharing;m("#share-menu > .menu-title").textContent=e?"Invite people":"Share this canvas",m("#invite-signin").hidden=!e||!!Ie?.user,m("#invite-form").hidden=!e||!Ie?.user;const t=m("#share-menu .lan-share");t.open=!e,t.querySelector("summary").hidden=!e,t.classList.toggle("only",!e)}function Na(){const e=f.share||{};m("#share-lan").value=e.lan||"No network connection",m("#share-public-row").hidden=!e.public,m("#share-public").value=e.public||"",m("#share-public-btn").hidden=!!e.public,m("#share-public-btn").textContent=e.tunnelAvailable?"Create public link":"Create public link (needs cloudflared)"}m("#share-btn").addEventListener("click",async e=>{if(e.stopPropagation(),!$()){try{await navigator.clipboard.writeText(location.href),y("Link copied")}catch{y(location.href,5e3)}return}const t=m("#share-menu"),n=!t.hidden;gt(),n||(Na(),fc(),m("#share-public-note").textContent="",Ho(t,e.currentTarget),Wa())}),m("#share-public-btn").addEventListener("click",async()=>{const e=m("#share-public-note"),t=m("#share-public-btn");t.disabled=!0,e.textContent="Opening a tunnel\u2026";try{f.share=await w("POST","/__loop/api/share/public"),e.textContent="Live while this Mac is awake and Loop is running.",Na()}catch(n){e.textContent=n.message}t.disabled=!1}),m("#share-rotate").addEventListener("click",async()=>{confirm("Reset share links? Anyone using the old links loses access.")&&(f.share=await w("POST","/__loop/api/share/rotate"),Na(),y("Links reset"))}),document.querySelectorAll("[data-copy]").forEach(e=>e.addEventListener("click",async()=>{const t=m("#"+e.dataset.copy).value;try{await navigator.clipboard.writeText(t),y("Link copied")}catch{m("#"+e.dataset.copy).select()}})),document.querySelectorAll(".menu").forEach(e=>e.addEventListener("pointerdown",t=>t.stopPropagation())),addEventListener("pointerdown",e=>{e.target.closest(".menu, #agent-pill, #share-btn")||gt()});let zo="1440x1024";function Ji(){gt(),m("#new-frame").hidden=!1;const e=m("#new-frame-input");e.value="",setTimeout(()=>e.focus(),0)}function Ba(){m("#new-frame").hidden=!0}m("#new-frame [data-close]").addEventListener("click",Ba),m("#new-frame").addEventListener("pointerdown",e=>{e.target.id==="new-frame"&&Ba()}),document.querySelectorAll("#size-pick button").forEach(e=>e.addEventListener("click",()=>{zo=e.dataset.size,document.querySelectorAll("#size-pick button").forEach(t=>t.classList.toggle("on",t===e))})),m("#new-frame-input").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Escape"&&Ba(),e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),Oo())}),m("#new-frame-go").addEventListener("click",Oo);async function Oo(){const e=m("#new-frame-input").value.trim();if(!e)return;const[t,n]=zo.split("x").map(Number),a=/^(https?:\/\/|\/|~\/|\.\.?\/)/.test(e)&&!/\s/.test(e);try{const i=await w("POST","/__loop/api/frames",a?{src:e,w:t,h:n}:{prompt:e,w:t,h:n});Ba(),setTimeout(()=>{Z(null),Oe(!0,[i.id])},80)}catch(i){y(i.message,4e3)}}function Ro(){m("#name-input").value=U.name||"",m("#name-go").textContent=U.name?"Save":"Join",m("#name-modal").hidden=!1,setTimeout(()=>m("#name-input").select(),30)}m("#presence").addEventListener("click",e=>{e.target.closest(".avatar.me")&&Ro()}),m("#name-modal").addEventListener("keydown",e=>{e.key==="Escape"&&U.name&&(m("#name-modal").hidden=!0)}),m("#name-go").addEventListener("click",No),m("#name-input").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Enter"&&No()});function No(){const e=m("#name-input").value.trim();e&&(U.name=e,Ae.set("loop.me",U),m("#name-modal").hidden=!0,$a(),$()&&!X&&w("POST","/__loop/api/settings",{hostName:e}).catch(t=>y(t.message)))}let Ie=null,Fa=null;async function Bo(e){if(Fa)return Fa;const{createClient:t}=await import("https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.49.4/+esm");return Fa=t(e.url,e.key,{auth:{flowType:"pkce",detectSessionInUrl:!0,persistSession:!0,storageKey:"loop-host-auth"}}),Fa}async function Wa(){if(!(X||!$())&&f.emailSharing){try{Ie=await w("GET","/__loop/api/cloud")}catch(e){m("#invite-note").textContent=e.message;return}uc()}}function Fo(e,t){return t?`<img src="${L(t)}" alt="" referrerpolicy="no-referrer">`:L(Zs(e))}function uc(){const e=!!Ie?.user;m("#invite-signin").hidden=e,m("#invite-form").hidden=!e,e&&(m("#me-avatar").innerHTML=Fo(Ie.user.name,Ie.user.avatar),m("#me-email").textContent=Ie.user.email,m("#cloud-link").value=Ie.link||"",Ie.error&&!m("#invite-note").textContent&&(m("#invite-note").textContent=Ie.error),m("#members").innerHTML=(Ie.members||[]).map(t=>`
53
+ <div class="member"><span class="m-av">${Fo(t.name||t.email,t.avatar_url)}</span>
45
54
  <span class="m-text"><div class="m-name">${L(t.name||t.email)}</div><div class="m-sub">${t.name?L(t.email)+" \xB7 ":""}${t.joined_at?"Joined":"Invited"}${t.role==="viewer"?" \xB7 can view":""}</div></span>
46
- <button class="m-x" title="Remove" data-email="${L(t.email)}">\xD7</button></div>`).join(""))}m("#members").addEventListener("click",async e=>{const t=e.target.closest("[data-email]");if(t&&confirm(`Remove ${t.dataset.email} from this canvas?`))try{await w("DELETE",`/__loop/api/cloud/members/${encodeURIComponent(t.dataset.email)}`),Mi()}catch(n){b(n.message)}}),m("#cloud-google").addEventListener("click",async()=>{try{const e=Te||await w("GET","/__loop/api/cloud");if(!(await fetch(`${e.config.url}/auth/v1/settings`,{headers:{apikey:e.config.key}}).then(s=>s.json()).catch(()=>({external:{google:!0}}))).external?.google){m("#invite-note").textContent="",b("Google sign-in isn\u2019t switched on yet. Enable the Google provider in Supabase (Authentication \u2192 Sign In / Providers).",7e3);return}const n=await po(e.config),{error:i}=await n.auth.signInWithOAuth({provider:"google",options:{redirectTo:`${location.origin}/__loop/?loop_auth=1`}});if(i)throw i}catch(e){b(e.message||"Google sign-in is not available",5e3)}}),m("#cloud-signout").addEventListener("click",async()=>{await w("POST","/__loop/api/cloud/signout"),Te=null,Mi()});async function Ml(){if(!(X||!new URLSearchParams(location.search).has("loop_auth"))){try{const e=await w("GET","/__loop/api/cloud"),t=await po(e.config);let{data:n}=await t.auth.getSession();for(let s=0;!n.session&&s<20;s++)await new Promise(a=>setTimeout(a,150)),{data:n}=await t.auth.getSession();if(!n.session)throw new Error("Google sign-in did not complete");t.auth.stopAutoRefresh();const{user:i}=await w("POST","/__loop/api/cloud/session",{access_token:n.session.access_token,refresh_token:n.session.refresh_token,expires_at:n.session.expires_at});try{localStorage.removeItem("loop-host-auth")}catch{}b(`Signed in as ${i.email}`),setTimeout(()=>m("#share-btn").click(),300)}catch(e){b(e.message,5e3)}history.replaceState(null,"","/__loop/")}}async function ho(e){const t=le(e);if(!t?.documentElement)throw new Error("screen not loaded yet");const n=`<!doctype html>
47
- `+t.documentElement.outerHTML;return w("POST","/__loop/api/cloud/snapshot",{frameId:e,html:n})}async function El(e){await w("POST","/__loop/api/cloud/publish");const t=u.frames.filter(i=>i.kind==="route");let n=0;for(const i of t){e.textContent=`Uploading screens\u2026 ${++n}/${t.length}`;try{await ho(i.id)}catch(s){console.warn("snapshot",i.name,s)}}}function Sl(e){const t=u?.frames.find(n=>n.id===e);X||!t||t.kind!=="route"||!Te?.canvasId||!Te?.user||setTimeout(()=>ho(e).catch(()=>{}),2500)}m("#invite-go").addEventListener("click",go),m("#invite-emails").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Enter"&&go()});async function go(){const e=m("#invite-emails").value.split(/[\s,;]+/).map(i=>i.trim()).filter(Boolean),t=m("#invite-note"),n=m("#invite-go");if(!e.length){t.textContent="Add one or more email addresses.";return}n.disabled=!0;try{await El(t),t.textContent="Sending invites\u2026";const i=await w("POST","/__loop/api/cloud/invite",{emails:e});m("#invite-emails").value="",t.textContent=i.warning?i.warning:i.failed?.length?`Invited, but email failed for ${i.failed.map(s=>s.email).join(", ")} \u2014 share the link with them.`:`Invite${i.emailed.length===1?"":"s"} sent to ${i.emailed.join(", ")}.`,await Mi()}catch(i){t.textContent=i.message}n.disabled=!1}const Ei=[["Mobile",393,852],["Tablet",834,1194],["Desktop",1440,1024]],Si=[["Phone",[["iPhone 16",393,852],["iPhone 16 Pro Max",440,956],["iPhone SE",375,667],["Android (compact)",412,917],["Android (large)",448,998]]],["Tablet",[["iPad mini",744,1133],['iPad Pro 11"',834,1194],['iPad Pro 13"',1032,1376],["Android tablet",800,1280]]],["Desktop",[["Desktop",1440,1024],["MacBook Air",1280,832],['MacBook Pro 14"',1512,982],["Desktop HD",1920,1080],["Wide",1728,1117]]]],yo={Mobile:T("phone"),Tablet:T("tablet"),Desktop:T("desktop")};let fe=$e.get("loop.framePreset",null)||{name:"Desktop",w:1440,h:1024};const vo={Phone:T("phone"),Tablet:T("tablet"),Desktop:T("desktop")},We=document.createElement("div");We.id="frame-ghost",We.hidden=!0,We.innerHTML="<span></span>",ct.appendChild(We);let cn=null;function Hn(){const e=j==="frame"&&!!cn&&!ae&&!!u&&k();if(We.hidden!==!e&&(We.hidden=!e),!e)return;const t=re(cn.x,cn.y),n=We.style,i=`<b>${L(fe.name)}</b>${fe.w} \xD7 ${fe.h}`;n.left=`${t.x}px`,n.top=`${t.y}px`,n.width=`${fe.w}px`,n.height=`${fe.h}px`,We._l!==i&&(We._l=i,We.firstChild.innerHTML=i)}addEventListener("pointermove",e=>{if(j!=="frame"){We.hidden||(We.hidden=!0);return}cn=q.contains(e.target)?{x:e.clientX,y:e.clientY}:null,Hn()},!0),addEventListener("pointerup",()=>{j==="frame"&&requestAnimationFrame(Hn)},!0),addEventListener("wheel",()=>{j==="frame"&&cn&&requestAnimationFrame(Hn)},{capture:!0,passive:!0});function Ti(){const e=m("#preset-menu"),t=m("#toolbar"),n=!e.hidden&&e.dataset.mode==="new";if(t.classList.toggle("menu-open",n),m("#frame-tray .tr-more")?.classList.toggle("open",n),!n)return;const i=t.getBoundingClientRect();e.style.left=`${i.left}px`,e.style.width=`${i.width}px`,e.style.bottom=`${innerHeight-i.top-1}px`,e.style.top="",e.classList.toggle("narrow",i.width<470)}new MutationObserver(Ti).observe(m("#preset-menu"),{attributes:!0,attributeFilter:["hidden","data-mode"]}),new ResizeObserver(Ti).observe(m("#toolbar")),addEventListener("resize",Ti);const bo=()=>document.querySelectorAll('#preset-menu[data-mode="new"] .pm-row').forEach(e=>e.classList.toggle("on",+e.dataset.w===fe.w&&+e.dataset.h===fe.h));function Tl(e){const t=m("#preset-menu"),n=!t.hidden&&t.dataset.mode==="new",i=e==="ArrowRight"||e==="ArrowDown"?1:-1,s=e==="ArrowLeft"||e==="ArrowRight";if(!n){if(e==="ArrowUp")_s(),t.hidden=!1;else if(s){const c=[...Ei].reverse(),f=c.findIndex(([,g,v])=>fe.w===g&&fe.h===v),[d,p,h]=c[f<0?i>0?0:c.length-1:(f+i+c.length)%c.length];zn(d,p,h)}return}const a=[...t.querySelectorAll(".pm-group")].map(c=>[...c.querySelectorAll(".pm-row")]);let o=a.findIndex(c=>c.some(f=>f.classList.contains("on"))),r=o<0?-1:a[o].findIndex(c=>c.classList.contains("on"));if(o<0)o=0,r=0;else if(s)o=Math.max(0,Math.min(a.length-1,o+i)),r=Math.min(r,a[o].length-1);else if(r+=i,r<0&&(r=0),r>=a[o].length){t.hidden=!0;return}const l=a[o][r];zn(l.dataset.name,+l.dataset.w,+l.dataset.h),bo(),l.scrollIntoView({block:"nearest"})}function zn(e,t,n){fe={name:e,w:Math.round(t),h:Math.round(n)},$e.set("loop.framePreset",fe),wo()}function wo(){const e=m("#toolbar"),t=m("#frame-tray"),n=j==="frame"&&!!u&&k();if(e.classList.toggle("tray-open",n),!n){m("#preset-menu").hidden=!0,cn=null,Hn();return}const i=(r,l)=>fe.w===r&&fe.h===l,s=[...Ei].reverse(),a=s.some(([,r,l])=>i(r,l)),o=s.map(([r,l,c])=>`<button class="tr-dev${i(l,c)?" on":""}" data-w="${l}" data-h="${c}" data-name="${r}" title="${r} \xB7 ${l} \xD7 ${c}">${yo[r]}</button>`).join("")+`<button class="tr-more${a?"":" on"}" title="All sizes">${a?"<span>More</span>":`<span>${L(fe.name)}</span>`}<small>${fe.w} \xD7 ${fe.h}</small>${T("down")}</button>`;t._h!==o&&(t._h=o,t.innerHTML=o),Hn(),Ti()}function _s(e){const t=m("#preset-menu"),n=e||fe,i=(s,a)=>Math.round(n.w)===s&&Math.round(n.h)===a;if(t.dataset.mode=e?"resize":"new",t.classList.toggle("for-frame",!!e),t.classList.toggle("docked",!e),e&&(t.style.width=t.style.bottom="",t.classList.remove("narrow")),e){const s=[e.kind==="frozen"?e.from?'<button class="pm-act" data-act="live">Open live</button>':"":`<button class="pm-act" data-act="freeze">${Wi}<span>Freeze a copy</span><kbd>\u21E7F</kbd></button>`,Kt(e)?`<button class="pm-act${e.keyboard?" on":""}" data-act="keyboard"><span>Keyboard</span><kbd>K</kbd></button>`:""].join("");t.innerHTML=`<div class="pm-custom pm-top"><span>Size</span><label>W<input id="pm-w" inputmode="numeric" value="${Math.round(e.w)}"></label><label>H<input id="pm-h" inputmode="numeric" value="${Math.round(e.h)}"></label><button id="pm-use">Apply</button></div>`+Si.map(([a,o])=>`<div class="pm-group"><div class="pm-title">${vo[a]||""}<span>${a}</span></div>${o.map(([r,l,c])=>`<button class="pm-row${i(l,c)?" on":""}" data-w="${l}" data-h="${c}" data-name="${L(r)}"><span>${L(r)}</span><small>${l} \xD7 ${c}</small></button>`).join("")}</div>`).join("")+(s?`<div class="pm-acts">${s}</div>`:"");return}t.innerHTML=[...Si].reverse().map(([s,a])=>`<div class="pm-group"><div class="pm-title">${vo[s]||""}<span>${s}</span></div>${a.map(([o,r,l])=>`<button class="pm-row${i(r,l)?" on":""}" data-w="${r}" data-h="${l}" data-name="${L(o)}"><span>${L(o)}</span><small>${r} \xD7 ${l}</small></button>`).join("")}</div>`).join("")+`<div class="pm-custom"><span>Custom</span><label>W<input id="pm-w" inputmode="numeric" value="${fe.w}"></label><label>H<input id="pm-h" inputmode="numeric" value="${fe.h}"></label><button id="pm-use">Use</button></div><button class="pm-describe" id="pm-describe">${T("frame")}<span>Describe a frame for the agent</span><kbd>N</kbd></button>`}m("#frame-tray").addEventListener("pointerdown",e=>e.stopPropagation()),m("#frame-tray").addEventListener("click",e=>{const t=e.target.closest(".tr-dev");if(t){zn(t.dataset.name,+t.dataset.w,+t.dataset.h),bo();return}if(e.target.closest(".tr-more")){const n=m("#preset-menu");if(!n.hidden){n.hidden=!0;return}_s(),n.hidden=!1}}),m("#preset-menu").addEventListener("pointerdown",e=>e.stopPropagation()),m("#preset-menu").addEventListener("click",e=>{const t=m("#preset-menu");if(t.dataset.mode==="resize"){const i=e.target.closest("[data-act]")?.dataset.act;if(i&&I){i==="freeze"?ji(I):i==="live"?jo(I):i==="keyboard"&&Yi(I),xo(!0);return}const s=e.target.closest(".pm-row");if(s){On(+s.dataset.w,+s.dataset.h);return}if(e.target.closest("#pm-use")){const a=+m("#pm-w").value,o=+m("#pm-h").value;a>=40&&o>=40&&On(a,o)}return}const n=e.target.closest(".pm-row");if(n){zn(n.dataset.name,+n.dataset.w,+n.dataset.h),t.hidden=!0;return}if(e.target.closest("#pm-use")){const i=+m("#pm-w").value,s=+m("#pm-h").value;i>=40&&s>=40&&(zn("Frame",i,s),t.hidden=!0);return}e.target.closest("#pm-describe")&&(m("#preset-menu").hidden=!0,we("select"),As())}),m("#preset-menu").addEventListener("keydown",e=>{e.key==="Enter"&&(e.target.id==="pm-w"||e.target.id==="pm-h")&&m("#pm-use").click(),e.key==="Escape"&&(m("#preset-menu").hidden=!0,e.stopPropagation())}),addEventListener("pointerdown",e=>{const t=m("#preset-menu");t.hidden||e.target.closest("#preset-menu, #frame-tray, .frame > .dims")||(t.hidden=!0,t.dataset.mode==="resize"&&Re&&(Re=null))},!0);function xo(e){const t=m("#preset-menu"),n=u&&k()&&!X&&j==="select"&&I&&Re===I&&u.frames.find(s=>s.id===I);if(!n){t.dataset.mode==="resize"&&(t.hidden=!0);return}const i=`${n.id}|${Math.round(n.w)}|${Math.round(n.h)}|${n.kind}|${!!n.keyboard}`;(e||t.dataset.mode!=="resize"||t._key!==i&&!t.contains(document.activeElement))&&(_s(n),t._for=n.id,t._key=i),t.hidden=!1,ko()}function ko(){const e=m("#preset-menu");if(e.hidden||e.dataset.mode!=="resize")return;const t=H.get(e._for)?.el.querySelector(":scope > .dims");if(!t)return;const n=t.getBoundingClientRect(),i=t.parentElement.querySelector(".frame-body").getBoundingClientRect(),s=e.offsetWidth,a=e.offsetHeight;let o=i.right+14,r=Math.max(60,Math.min(i.bottom-a,innerHeight-a-76));o+s>innerWidth-12&&(o=i.left-14-s),o<12&&(o=Math.max(12,Math.min(n.left+n.width/2-s/2,innerWidth-s-12)),r=n.bottom+8,r+a>innerHeight-70&&(r=Math.max(12,n.top-a-8))),e.style.left=`${Math.round(o)}px`,e.style.top=`${Math.round(r)}px`}function Ai(e){const t=new Set(u.frames.map(n=>n.name));if(!t.has(e))return e;for(let n=2;;n++)if(!t.has(`${e} ${n}`))return`${e} ${n}`}function Ps(e,t,n){const i=n||re(innerWidth/2,innerHeight/2),s=(r,l)=>u.frames.some(c=>r<c.x+c.w+80&&r+e+80>c.x&&l<c.y+c.h+80&&l+t+80>c.y),a=Math.round(i.x-e/2),o=Math.round(i.y-t/2);for(let r=0;r<30;r++)for(const[l,c]of[[1,0],[0,1],[-1,0],[0,-1]]){const f=a+l*r*(e*.5+80),d=o+c*r*(t*.5+80);if(!s(f,d))return{x:f,y:d}}return{x:a,y:o}}function Tt(e){if(E)return;const t=u.frames.find(s=>s.id===e);if(!t)return;const n={x:y.x+t.x*y.z,y:y.y+t.y*y.z},i={x:n.x+t.w*y.z,y:n.y+t.h*y.z};(n.x<0||n.y<60||i.x>innerWidth||i.y>innerHeight-80)&&Ge(!0,[e])}function Al(e){const t=[],n=i=>{for(const s of u.frames)s.parent===i&&!t.includes(s)&&(t.push(s),n(s.id))};return n(e),t}function $o(e,t=new Set){return u.frames.filter(n=>!t.has(n.id)&&e.x>=n.x&&e.y>=n.y&&e.x+e.w<=n.x+n.w&&e.y+e.h<=n.y+n.h).sort((n,i)=>n.w*n.h-i.w*i.h)[0]||null}async function Dn(e,t,n,i,s){const a=i!=null?{x:Math.round(i),y:Math.round(s)}:Ps(t,n),o=i!=null?$o({...a,w:t,h:n})?.id:null;try{const r=await w("POST","/__loop/api/frames",{new:!0,blank:!0,name:Ai(e),w:Math.round(t),h:Math.round(n),...a,...o?{parent:o}:{}});Ze=r.id,ei=r.id;let l=null;Z("Add frame",async()=>{l=_t(r.id)||l,await w("DELETE",`/__loop/api/frames/${r.id}`)},()=>je(l||{frames:[r]})),we("select"),u.frames.find(c=>c.id===r.id)&&(Ze=ei=null,ie(r.id),Tt(r.id),setTimeout(()=>hi(r.id),340))}catch(r){b(r.message)}}function He(){const e=m("#frame-panel");e.hidden=!0,xo()}async function On(e,t){const n=u.frames.find(o=>o.id===I);if(!n||!(e>0&&t>0))return;const i={w:n.w,h:n.h},s={w:Math.round(e),h:Math.round(t)},a=n.id;(i.w!==s.w||i.h!==s.h)&&Z("Resize frame",()=>At(a,i),()=>At(a,s)),Object.assign(n,s),Q(n);try{await w("PATCH",`/__loop/api/frames/${n.id}`,{w:n.w,h:n.h})}catch(o){b(o.message)}He(),setTimeout(()=>it(n.id),60)}m("#frame-panel").addEventListener("pointerdown",e=>e.stopPropagation()),m("#frame-panel").addEventListener("click",e=>{const t=e.target.closest('[data-pick="frame-fill"]');if(t)return Oi(t);if(e.target.closest(".fp-fill-none")){const n=u.frames.find(s=>s.id===I);if(!n)return;const i=n.fill==="none"?null:"none";zt={id:n.id,before:n.fill||null},n.fill=i||void 0,Q(n),w("PATCH",`/__loop/api/frames/${n.id}`,{fill:i}).catch(s=>b(s.message)),Do(),He()}}),m("#frame-panel").addEventListener("wheel",e=>e.stopPropagation()),m("#frame-panel").addEventListener("click",e=>{const t=e.target.closest("[data-act]")?.dataset.act;if(t&&I){t==="freeze"?ji(I):t==="live"?jo(I):t==="keyboard"&&Yi(I);return}if(e.target.closest("#fp-close")){j==="frame"?we("select"):(Re=null,He());return}if(e.target.closest("#fp-describe")){we("select"),As();return}if(e.target.closest("#fp-make")){const i=+m("#fp-w").value,s=+m("#fp-h").value;i>0&&s>0&&Dn("Frame",i,s);return}const n=e.target.closest("[data-w]");n&&(j==="frame"?Dn(n.dataset.name,+n.dataset.w,+n.dataset.h):On(+n.dataset.w,+n.dataset.h))}),m("#frame-panel").addEventListener("keydown",e=>{if(e.stopPropagation(),e.key==="Escape"){e.target.blur();return}if(e.key==="Enter"){if(e.target.id==="fp-sw"||e.target.id==="fp-sh"){const t=+m("#fp-sw").value,n=+m("#fp-sh").value;e.target.blur(),On(t,n)}(e.target.id==="fp-w"||e.target.id==="fp-h")&&m("#fp-make").click()}}),m("#frame-panel").addEventListener("focusout",e=>{if((e.target.id==="fp-sw"||e.target.id==="fp-sh")&&!m("#frame-panel").contains(e.relatedTarget)){const t=u.frames.find(s=>s.id===I),n=+m("#fp-sw")?.value,i=+m("#fp-sh")?.value;t&&(n!==Math.round(t.w)||i!==Math.round(t.h))&&On(n,i)}});const Rn=[],qs=[];let Is=!1;function Z(e,t,n){Is||X||!k()||(Rn.push({label:e,undo:t,redo:n}),Rn.length>200&&Rn.shift(),qs.length=0)}async function Lo(e,t,n){const i=e.pop();if(!i){b(n==="undo"?"Nothing to undo":"Nothing to redo",1200);return}Is=!0;try{await i[n](),t.push(i),b(`${n==="undo"?"Undo":"Redo"}: ${i.label}`,1400)}catch(s){b(`Couldn't ${n}: ${s.message}`)}finally{Is=!1}}const _i=()=>Lo(Rn,qs,"undo"),Nn=()=>Lo(qs,Rn,"redo");function At(e,t){const n=u.frames.find(i=>i.id===e);return n&&(Object.assign(n,t),Q(n),He(),setTimeout(()=>it(e),50)),w("PATCH",`/__loop/api/frames/${e}`,t)}const je=e=>w("POST","/__loop/api/restore",e);function _t(e){const t=u.frames.find(n=>n.id===e);return t?{frames:[{...t}],comments:u.comments.filter(n=>n.frameId===e).map(n=>({...n}))}:null}async function _l(e){const t=_t(e);t&&(await w("DELETE",`/__loop/api/frames/${e}`),Z("Delete frame",()=>je(t),()=>w("DELETE",`/__loop/api/frames/${e}`)),b(`Deleted \u201C${t.frames[0].name}\u201D \u2014 \u2318Z to undo`,2600))}let $=null,Bn={fid:null,t:0,x:0,y:0};function Co(e){let t=e;for(let n=0;n<6;n++){const i=[...t.children].filter(o=>!/^(SCRIPT|STYLE|LINK|META|NOSCRIPT|TEMPLATE)$/.test(o.tagName));if(i.length!==1||!i[0].children.length)break;const s=t.getBoundingClientRect();if(i[0].getBoundingClientRect().width<s.width*.9)break;t=i[0]}return t}function Pi(e,t,n){const i=le(e),s=i?.body;if(!t||!s||t===i.documentElement)return null;if(n==="block")return s.contains(t)?Pl(t,s):null;if(n==="deep"||!s.contains(t))return t===s?null:t;if(n==="outer"){const c=$?.frameId===e?$.els[$.els.length-1]:null,f=c?.isConnected&&c.contains(t)?c:t,d=f.parentElement;return!d||d===s?f:d}const a=$?.frameId===e,o=a?$.els[$.els.length-1]:null;let r=(n==="drill"||n==="step")&&o?.isConnected&&o.contains(t)?o:a&&$.scope?.isConnected?$.scope:Co(s);for(;r!==s&&!r.contains(t);)r=r.parentElement;if(t===r)return r===s?null:r;let l=t;for(;l.parentElement&&l.parentElement!==r;)l=l.parentElement;return l}function Pl(e,t){let n=e.closest?.("svg")||e;for(;n&&n!==t;n=n.parentElement){if(n.tagName.toLowerCase()==="svg")continue;const i=[...n.children].filter(a=>!/^(SCRIPT|STYLE|BR|TEMPLATE)$/.test(a.tagName)).length,s=n.getBoundingClientRect();if(i&&n.ownerDocument.defaultView.getComputedStyle(n).display!=="inline"&&s.width>24&&s.height>16)return n}return null}function rt(e){const t=[...e.childNodes].filter(o=>o.nodeType===3).map(o=>o.data).join(" ").replace(/\s+/g," ").trim();if(t&&!e.children.length)return t.length>28?t.slice(0,27)+"\u2026":t;const n=e.tagName.toLowerCase(),i={img:"Image",svg:"Icon",picture:"Image",video:"Video",canvas:"Canvas",button:"Button",a:"Link",input:"Field",textarea:"Field",select:"Menu",ul:"List",ol:"List",li:"Item",nav:"Navigation",header:"Header",footer:"Footer",form:"Form",table:"Table",label:"Label",section:"Section",main:"Main",aside:"Aside",article:"Article"},s=(e.getAttribute("aria-label")||"").trim();if(i[n]&&(n==="button"||n==="a")&&(t||s))return`${i[n]} \xB7 ${(t||s).slice(0,22)}`;if(i[n])return i[n];if(/^h[1-6]$/.test(n))return"Heading";const a=typeof e.className=="string"&&e.className.trim().split(/\s+/).find(o=>/^[a-zA-Z][a-zA-Z0-9_-]{2,}$/.test(o)&&!/[:\[]/.test(o)&&!/\d/.test(o))||(/^[a-zA-Z][\w-]*$/.test(e.id)?e.id:"");if(a){const o=a.replace(/[-_]+/g," ").replace(/([a-z])([A-Z])/g,"$1 $2").trim();return o[0].toUpperCase()+o.slice(1).toLowerCase()}return t?"Text":"Frame"}let Pt={fid:null,x:0,y:0,n:0,t:0},Ee=null,qi=0;function ql(e,t,n){if(n!=="step"){n==="deep"&&j==="select"&&$e.set("loop.knowsDeep",1),Pt.n=0;return}const i=performance.now(),s=Pt.fid===e&&i-Pt.t<2500&&Math.hypot(t.clientX-Pt.x,t.clientY-Pt.y)<14;Pt={fid:e,x:t.clientX,y:t.clientY,n:s?Pt.n+1:1,t:i},Pt.n>=3&&!Ee&&!$e.get("loop.knowsDeep",0)&&$e.get("loop.deepTipSeen",0)<2&&Mo(t.clientX,t.clientY)}function Mo(e,t,n){Ee&&Eo();const i=lt==="metaKey"?"\u2318":"Ctrl";Ee=document.createElement("div"),Ee.id="deep-tip",Ee.innerHTML=`<div class="dt-demo" aria-hidden="true"><div class="dt-card"><i class="dt-l t"></i><i class="dt-l a"></i><i class="dt-l b"></i><i class="dt-btn"></i></div>
48
- <i class="dt-o o1"></i><i class="dt-o o2"></i><i class="dt-o o3"></i><kbd class="dt-key">${i}</kbd>
55
+ <button class="m-x" title="Remove" data-email="${L(t.email)}">\xD7</button></div>`).join(""))}m("#members").addEventListener("click",async e=>{const t=e.target.closest("[data-email]");if(t&&confirm(`Remove ${t.dataset.email} from this canvas?`))try{await w("DELETE",`/__loop/api/cloud/members/${encodeURIComponent(t.dataset.email)}`),Wa()}catch(n){y(n.message)}}),m("#cloud-google").addEventListener("click",async()=>{try{const e=Ie||await w("GET","/__loop/api/cloud");if(!(await fetch(`${e.config.url}/auth/v1/settings`,{headers:{apikey:e.config.key}}).then(i=>i.json()).catch(()=>({external:{google:!0}}))).external?.google){m("#invite-note").textContent="",y("Google sign-in isn\u2019t switched on yet. Enable the Google provider in Supabase (Authentication \u2192 Sign In / Providers).",7e3);return}const n=await Bo(e.config),{error:a}=await n.auth.signInWithOAuth({provider:"google",options:{redirectTo:`${location.origin}/__loop/?loop_auth=1`}});if(a)throw a}catch(e){y(e.message||"Google sign-in is not available",5e3)}}),m("#cloud-signout").addEventListener("click",async()=>{await w("POST","/__loop/api/cloud/signout"),Ie=null,Wa()});async function pc(){if(!(X||!new URLSearchParams(location.search).has("loop_auth"))){try{const e=await w("GET","/__loop/api/cloud"),t=await Bo(e.config);let{data:n}=await t.auth.getSession();for(let i=0;!n.session&&i<20;i++)await new Promise(s=>setTimeout(s,150)),{data:n}=await t.auth.getSession();if(!n.session)throw new Error("Google sign-in did not complete");t.auth.stopAutoRefresh();const{user:a}=await w("POST","/__loop/api/cloud/session",{access_token:n.session.access_token,refresh_token:n.session.refresh_token,expires_at:n.session.expires_at});try{localStorage.removeItem("loop-host-auth")}catch{}y(`Signed in as ${a.email}`),setTimeout(()=>m("#share-btn").click(),300)}catch(e){y(e.message,5e3)}history.replaceState(null,"","/__loop/")}}async function Wo(e){const t=de(e);if(!t?.documentElement)throw new Error("screen not loaded yet");const n=`<!doctype html>
56
+ `+t.documentElement.outerHTML;return w("POST","/__loop/api/cloud/snapshot",{frameId:e,html:n})}async function mc(e){await w("POST","/__loop/api/cloud/publish");const t=f.frames.filter(a=>a.kind==="route");let n=0;for(const a of t){e.textContent=`Uploading screens\u2026 ${++n}/${t.length}`;try{await Wo(a.id)}catch(i){console.warn("snapshot",a.name,i)}}}function hc(e){const t=f?.frames.find(n=>n.id===e);X||!t||t.kind!=="route"||!Ie?.canvasId||!Ie?.user||setTimeout(()=>Wo(e).catch(()=>{}),2500)}m("#invite-go").addEventListener("click",jo),m("#invite-emails").addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Enter"&&jo()});async function jo(){const e=m("#invite-emails").value.split(/[\s,;]+/).map(a=>a.trim()).filter(Boolean),t=m("#invite-note"),n=m("#invite-go");if(!e.length){t.textContent="Add one or more email addresses.";return}n.disabled=!0;try{await mc(t),t.textContent="Sending invites\u2026";const a=await w("POST","/__loop/api/cloud/invite",{emails:e});m("#invite-emails").value="",t.textContent=a.warning?a.warning:a.failed?.length?`Invited, but email failed for ${a.failed.map(i=>i.email).join(", ")} \u2014 share the link with them.`:`Invite${a.emailed.length===1?"":"s"} sent to ${a.emailed.join(", ")}.`,await Wa()}catch(a){t.textContent=a.message}n.disabled=!1}const ja=[["Mobile",393,852],["Tablet",834,1194],["Desktop",1440,1024]],Ka=[["Phone",[["iPhone 16",393,852],["iPhone 16 Pro Max",440,956],["iPhone SE",375,667],["Android (compact)",412,917],["Android (large)",448,998]]],["Tablet",[["iPad mini",744,1133],['iPad Pro 11"',834,1194],['iPad Pro 13"',1032,1376],["Android tablet",800,1280]]],["Desktop",[["Desktop",1440,1024],["MacBook Air",1280,832],['MacBook Pro 14"',1512,982],["Desktop HD",1920,1080],["Wide",1728,1117]]]],Ko={Mobile:A("phone"),Tablet:A("tablet"),Desktop:A("desktop")};let ue=Ae.get("loop.framePreset",null)||{name:"Desktop",w:1440,h:1024};const Yo={Phone:A("phone"),Tablet:A("tablet"),Desktop:A("desktop")},et=document.createElement("div");et.id="frame-ghost",et.hidden=!0,et.innerHTML="<span></span>",xt.appendChild(et);let yn=null;function Vn(){const e=K==="frame"&&!!yn&&!se&&!!f&&$();if(et.hidden!==!e&&(et.hidden=!e),!e)return;const t=re(yn.x,yn.y),n=et.style,a=`<b>${L(ue.name)}</b>${ue.w} \xD7 ${ue.h}`;n.left=`${t.x}px`,n.top=`${t.y}px`,n.width=`${ue.w}px`,n.height=`${ue.h}px`,et._l!==a&&(et._l=a,et.firstChild.innerHTML=a)}addEventListener("pointermove",e=>{if(K!=="frame"){et.hidden||(et.hidden=!0);return}yn=I.contains(e.target)?{x:e.clientX,y:e.clientY}:null,Vn()},!0),addEventListener("pointerup",()=>{K==="frame"&&requestAnimationFrame(Vn)},!0),addEventListener("wheel",()=>{K==="frame"&&yn&&requestAnimationFrame(Vn)},{capture:!0,passive:!0});function Ya(){const e=m("#preset-menu"),t=m("#toolbar"),n=!e.hidden&&e.dataset.mode==="new";if(t.classList.toggle("menu-open",n),m("#frame-tray .tr-more")?.classList.toggle("open",n),!n)return;const a=t.getBoundingClientRect();e.style.left=`${a.left}px`,e.style.width=`${a.width}px`,e.style.bottom=`${innerHeight-a.top-1}px`,e.style.top="",e.classList.toggle("narrow",a.width<470)}new MutationObserver(Ya).observe(m("#preset-menu"),{attributes:!0,attributeFilter:["hidden","data-mode"]}),new ResizeObserver(Ya).observe(m("#toolbar")),addEventListener("resize",Ya);const Vo=()=>document.querySelectorAll('#preset-menu[data-mode="new"] .pm-row').forEach(e=>e.classList.toggle("on",+e.dataset.w===ue.w&&+e.dataset.h===ue.h));function gc(e){const t=m("#preset-menu"),n=!t.hidden&&t.dataset.mode==="new",a=e==="ArrowRight"||e==="ArrowDown"?1:-1,i=e==="ArrowLeft"||e==="ArrowRight";if(!n){if(e==="ArrowUp")es(),t.hidden=!1;else if(i){const l=[...ja].reverse(),d=l.findIndex(([,g,v])=>ue.w===g&&ue.h===v),[u,p,h]=l[d<0?a>0?0:l.length-1:(d+a+l.length)%l.length];Xn(u,p,h)}return}const s=[...t.querySelectorAll(".pm-group")].map(l=>[...l.querySelectorAll(".pm-row")]);let o=s.findIndex(l=>l.some(d=>d.classList.contains("on"))),r=o<0?-1:s[o].findIndex(l=>l.classList.contains("on"));if(o<0)o=0,r=0;else if(i)o=Math.max(0,Math.min(s.length-1,o+a)),r=Math.min(r,s[o].length-1);else if(r+=a,r<0&&(r=0),r>=s[o].length){t.hidden=!0;return}const c=s[o][r];Xn(c.dataset.name,+c.dataset.w,+c.dataset.h),Vo(),c.scrollIntoView({block:"nearest"})}function Xn(e,t,n){ue={name:e,w:Math.round(t),h:Math.round(n)},Ae.set("loop.framePreset",ue),Xo()}function Xo(){const e=m("#toolbar"),t=m("#frame-tray"),n=K==="frame"&&!!f&&$();if(e.classList.toggle("tray-open",n),!n){m("#preset-menu").hidden=!0,yn=null,Vn();return}const a=(r,c)=>ue.w===r&&ue.h===c,i=[...ja].reverse(),s=i.some(([,r,c])=>a(r,c)),o=i.map(([r,c,l])=>`<button class="tr-dev${a(c,l)?" on":""}" data-w="${c}" data-h="${l}" data-name="${r}" title="${r} \xB7 ${c} \xD7 ${l}">${Ko[r]}</button>`).join("")+`<button class="tr-more${s?"":" on"}" title="All sizes">${s?"<span>More</span>":`<span>${L(ue.name)}</span>`}<small>${ue.w} \xD7 ${ue.h}</small>${A("down")}</button>`;t._h!==o&&(t._h=o,t.innerHTML=o),Vn(),Ya()}function es(e){const t=m("#preset-menu"),n=e||ue,a=(i,s)=>Math.round(n.w)===i&&Math.round(n.h)===s;if(t.dataset.mode=e?"resize":"new",t.classList.toggle("for-frame",!!e),t.classList.toggle("docked",!e),e&&(t.style.width=t.style.bottom="",t.classList.remove("narrow")),e){const i=[e.kind==="frozen"?e.from?'<button class="pm-act" data-act="live">Open live</button>':"":`<button class="pm-act" data-act="freeze">${ci}<span>Freeze a copy</span><kbd>\u21E7F</kbd></button>`,en(e)?`<button class="pm-act${e.keyboard?" on":""}" data-act="keyboard"><span>Keyboard</span><kbd>K</kbd></button>`:""].join("");t.innerHTML=`<div class="pm-custom pm-top"><span>Size</span><label>W<input id="pm-w" inputmode="numeric" value="${Math.round(e.w)}"></label><label>H<input id="pm-h" inputmode="numeric" value="${Math.round(e.h)}"></label><button id="pm-use">Apply</button></div>`+Ka.map(([s,o])=>`<div class="pm-group"><div class="pm-title">${Yo[s]||""}<span>${s}</span></div>${o.map(([r,c,l])=>`<button class="pm-row${a(c,l)?" on":""}" data-w="${c}" data-h="${l}" data-name="${L(r)}"><span>${L(r)}</span><small>${c} \xD7 ${l}</small></button>`).join("")}</div>`).join("")+(i?`<div class="pm-acts">${i}</div>`:"");return}t.innerHTML=[...Ka].reverse().map(([i,s])=>`<div class="pm-group"><div class="pm-title">${Yo[i]||""}<span>${i}</span></div>${s.map(([o,r,c])=>`<button class="pm-row${a(r,c)?" on":""}" data-w="${r}" data-h="${c}" data-name="${L(o)}"><span>${L(o)}</span><small>${r} \xD7 ${c}</small></button>`).join("")}</div>`).join("")+`<div class="pm-custom"><span>Custom</span><label>W<input id="pm-w" inputmode="numeric" value="${ue.w}"></label><label>H<input id="pm-h" inputmode="numeric" value="${ue.h}"></label><button id="pm-use">Use</button></div><button class="pm-describe" id="pm-describe">${A("frame")}<span>Describe a frame for the agent</span><kbd>N</kbd></button>`}m("#frame-tray").addEventListener("pointerdown",e=>e.stopPropagation()),m("#frame-tray").addEventListener("click",e=>{const t=e.target.closest(".tr-dev");if(t){Xn(t.dataset.name,+t.dataset.w,+t.dataset.h),Vo();return}if(e.target.closest(".tr-more")){const n=m("#preset-menu");if(!n.hidden){n.hidden=!0;return}es(),n.hidden=!1}}),m("#preset-menu").addEventListener("pointerdown",e=>e.stopPropagation()),m("#preset-menu").addEventListener("click",e=>{const t=m("#preset-menu");if(t.dataset.mode==="resize"){const a=e.target.closest("[data-act]")?.dataset.act;if(a&&_){a==="freeze"?ra(_):a==="live"?Cr(_):a==="keyboard"&&di(_),Uo(!0);return}const i=e.target.closest(".pm-row");if(i){Zn(+i.dataset.w,+i.dataset.h);return}if(e.target.closest("#pm-use")){const s=+m("#pm-w").value,o=+m("#pm-h").value;s>=40&&o>=40&&Zn(s,o)}return}const n=e.target.closest(".pm-row");if(n){Xn(n.dataset.name,+n.dataset.w,+n.dataset.h),t.hidden=!0;return}if(e.target.closest("#pm-use")){const a=+m("#pm-w").value,i=+m("#pm-h").value;a>=40&&i>=40&&(Xn("Frame",a,i),t.hidden=!0);return}e.target.closest("#pm-describe")&&(m("#preset-menu").hidden=!0,Ee("select"),Ji())}),m("#preset-menu").addEventListener("keydown",e=>{e.key==="Enter"&&(e.target.id==="pm-w"||e.target.id==="pm-h")&&m("#pm-use").click(),e.key==="Escape"&&(m("#preset-menu").hidden=!0,e.stopPropagation())}),addEventListener("pointerdown",e=>{const t=m("#preset-menu");t.hidden||e.target.closest("#preset-menu, #frame-tray, .frame > .dims")||(t.hidden=!0,t.dataset.mode==="resize"&&Ke&&(Ke=null))},!0);function Uo(e){const t=m("#preset-menu"),n=f&&$()&&!X&&K==="select"&&_&&Ke===_&&f.frames.find(i=>i.id===_);if(!n){t.dataset.mode==="resize"&&(t.hidden=!0);return}const a=`${n.id}|${Math.round(n.w)}|${Math.round(n.h)}|${n.kind}|${!!n.keyboard}`;(e||t.dataset.mode!=="resize"||t._key!==a&&!t.contains(document.activeElement))&&(es(n),t._for=n.id,t._key=a),t.hidden=!1,Zo()}function Zo(){const e=m("#preset-menu");if(e.hidden||e.dataset.mode!=="resize")return;const t=D.get(e._for)?.el.querySelector(":scope > .dims");if(!t)return;const n=t.getBoundingClientRect(),a=t.parentElement.querySelector(".frame-body").getBoundingClientRect(),i=e.offsetWidth,s=e.offsetHeight;let o=a.right+14,r=Math.max(60,Math.min(a.bottom-s,innerHeight-s-76));o+i>innerWidth-12&&(o=a.left-14-i),o<12&&(o=Math.max(12,Math.min(n.left+n.width/2-i/2,innerWidth-i-12)),r=n.bottom+8,r+s>innerHeight-70&&(r=Math.max(12,n.top-s-8))),e.style.left=`${Math.round(o)}px`,e.style.top=`${Math.round(r)}px`}function Un(e){const t=new Set(f.frames.map(n=>n.name));if(!t.has(e))return e;for(let n=2;;n++)if(!t.has(`${e} ${n}`))return`${e} ${n}`}function ts(e,t,n){const a=n||re(innerWidth/2,innerHeight/2),i=(r,c)=>f.frames.some(l=>r<l.x+l.w+80&&r+e+80>l.x&&c<l.y+l.h+80&&c+t+80>l.y),s=Math.round(a.x-e/2),o=Math.round(a.y-t/2);for(let r=0;r<30;r++)for(const[c,l]of[[1,0],[0,1],[-1,0],[0,-1]]){const d=s+c*r*(e*.5+80),u=o+l*r*(t*.5+80);if(!i(d,u))return{x:d,y:u}}return{x:s,y:o}}function St(e){if(S)return;const t=f.frames.find(i=>i.id===e);if(!t)return;const n={x:b.x+t.x*b.z,y:b.y+t.y*b.z},a={x:n.x+t.w*b.z,y:n.y+t.h*b.z};(n.x<0||n.y<60||a.x>innerWidth||a.y>innerHeight-80)&&Oe(!0,[e])}function yc(e){const t=[],n=a=>{for(const i of f.frames)i.parent===a&&!t.includes(i)&&(t.push(i),n(i.id))};return n(e),t}function Go(e,t=new Set){return f.frames.filter(n=>!t.has(n.id)&&e.x>=n.x&&e.y>=n.y&&e.x+e.w<=n.x+n.w&&e.y+e.h<=n.y+n.h).sort((n,a)=>n.w*n.h-a.w*a.h)[0]||null}async function bn(e,t,n,a,i){const s=a!=null?{x:Math.round(a),y:Math.round(i)}:ts(t,n),o=a!=null?Go({...s,w:t,h:n})?.id:null;try{const r=await w("POST","/__loop/api/frames",{new:!0,blank:!0,name:Un(e),w:Math.round(t),h:Math.round(n),...s,...o?{parent:o}:{}});Ue=r.id,ya=r.id;let c=null;G("Add frame",async()=>{c=yt(r.id)||c,await w("DELETE",`/__loop/api/frames/${r.id}`)},()=>He(c||{frames:[r]})),Ee("select"),f.frames.find(l=>l.id===r.id)&&(Ue=ya=null,Z(r.id),St(r.id),setTimeout(()=>_a(r.id),340))}catch(r){y(r.message)}}function Fe(){const e=m("#frame-panel");e.hidden=!0,Uo()}async function Zn(e,t){const n=f.frames.find(o=>o.id===_);if(!n||!(e>0&&t>0))return;const a={w:n.w,h:n.h},i={w:Math.round(e),h:Math.round(t)},s=n.id;(a.w!==i.w||a.h!==i.h)&&G("Resize frame",()=>Rt(s,a),()=>Rt(s,i)),Object.assign(n,i),J(n);try{await w("PATCH",`/__loop/api/frames/${n.id}`,{w:n.w,h:n.h})}catch(o){y(o.message)}Fe(),setTimeout(()=>ut(n.id),60)}m("#frame-panel").addEventListener("pointerdown",e=>e.stopPropagation()),m("#frame-panel").addEventListener("click",e=>{const t=e.target.closest('[data-pick="frame-fill"]');if(t)return ii(t);if(e.target.closest(".fp-fill-none")){const n=f.frames.find(i=>i.id===_);if(!n)return;const a=n.fill==="none"?null:"none";Wt={id:n.id,before:n.fill||null},n.fill=a||void 0,J(n),w("PATCH",`/__loop/api/frames/${n.id}`,{fill:a}).catch(i=>y(i.message)),yr(),Fe()}}),m("#frame-panel").addEventListener("wheel",e=>e.stopPropagation()),m("#frame-panel").addEventListener("click",e=>{const t=e.target.closest("[data-act]")?.dataset.act;if(t&&_){t==="freeze"?ra(_):t==="live"?Cr(_):t==="keyboard"&&di(_);return}if(e.target.closest("#fp-close")){K==="frame"?Ee("select"):(Ke=null,Fe());return}if(e.target.closest("#fp-describe")){Ee("select"),Ji();return}if(e.target.closest("#fp-make")){const a=+m("#fp-w").value,i=+m("#fp-h").value;a>0&&i>0&&bn("Frame",a,i);return}const n=e.target.closest("[data-w]");n&&(K==="frame"?bn(n.dataset.name,+n.dataset.w,+n.dataset.h):Zn(+n.dataset.w,+n.dataset.h))}),m("#frame-panel").addEventListener("keydown",e=>{if(e.stopPropagation(),e.key==="Escape"){e.target.blur();return}if(e.key==="Enter"){if(e.target.id==="fp-sw"||e.target.id==="fp-sh"){const t=+m("#fp-sw").value,n=+m("#fp-sh").value;e.target.blur(),Zn(t,n)}(e.target.id==="fp-w"||e.target.id==="fp-h")&&m("#fp-make").click()}}),m("#frame-panel").addEventListener("focusout",e=>{if((e.target.id==="fp-sw"||e.target.id==="fp-sh")&&!m("#frame-panel").contains(e.relatedTarget)){const t=f.frames.find(i=>i.id===_),n=+m("#fp-sw")?.value,a=+m("#fp-sh")?.value;t&&(n!==Math.round(t.w)||a!==Math.round(t.h))&&Zn(n,a)}});const Gn=[],ns=[];let as=!1;function G(e,t,n){as||X||!$()||(Gn.push({label:e,undo:t,redo:n}),Gn.length>200&&Gn.shift(),ns.length=0)}async function Qo(e,t,n){const a=e.pop();if(!a){y(n==="undo"?"Nothing to undo":"Nothing to redo",1200);return}as=!0;try{await a[n](),t.push(a),y(`${n==="undo"?"Undo":"Redo"}: ${a.label}`,1400)}catch(i){y(`Couldn't ${n}: ${i.message}`)}finally{as=!1}}const Va=()=>Qo(Gn,ns,"undo"),Qn=()=>Qo(ns,Gn,"redo");function Rt(e,t){const n=f.frames.find(a=>a.id===e);return n&&(Object.assign(n,t),J(n),Fe(),setTimeout(()=>ut(e),50)),w("PATCH",`/__loop/api/frames/${e}`,t)}const He=e=>w("POST","/__loop/api/restore",e);function yt(e){const t=f.frames.find(n=>n.id===e);return t?{frames:[{...t}],comments:f.comments.filter(n=>n.frameId===e).map(n=>({...n}))}:null}async function Jo(e){const t=f.frames.find(l=>l.id===e);if(!t)return;const n=f.frames.filter(l=>l.parent===e),a=yt(e);if(n.length){for(const l of n)await w("PATCH",`/__loop/api/frames/${l.id}`,{parent:null});return await w("DELETE",`/__loop/api/frames/${e}`),Z(null),G("Unframe",async()=>{await He(a);for(const l of n)await w("PATCH",`/__loop/api/frames/${l.id}`,{parent:e})},async()=>{for(const l of n)await w("PATCH",`/__loop/api/frames/${l.id}`,{parent:null});await w("DELETE",`/__loop/api/frames/${e}`)}),y(`Unframed \u201C${t.name}\u201D: its ${n.length} frame${n.length===1?"":"s"} stay where they are \xB7 \u2318Z to undo`,2800)}if(t.kind!=="folder"||t.image)return y(t.image?"An image has no parts to keep.":"A live app page can\u2019t be taken apart. Unframe works on static pages, or frames that hold other frames.",3e3);const i=aa(e);if(!i?.body)return y("Open the frame first so its page has loaded");const s=l=>[...l.children].filter(d=>!/^(SCRIPT|STYLE|TEMPLATE|LINK|META|NOSCRIPT)$/.test(d.tagName)&&d.getBoundingClientRect().width>2&&d.getBoundingClientRect().height>2);let o=i.body,r=s(o);for(let l=0;l<4&&r.length===1&&s(r[0]).length;l++)o=r[0],r=s(o);if(!r.length)return y("Nothing in this frame to keep");if(r.length>40)return y(`That would make ${r.length} frames. Unframe works best on a page with a few parts.`,3e3);const c=[];try{for(const l of r){const d=na(e,l),u=await w("POST","/__loop/api/frames",{new:!0,name:Un(d.name||"Part"),w:d.w,h:d.h,x:Math.round(t.x+d.x),y:Math.round(t.y+d.y),html:nr(d),fill:"none"});c.push(u.id)}await w("DELETE",`/__loop/api/frames/${e}`),Z(null)}catch(l){for(const d of c)w("DELETE",`/__loop/api/frames/${d}`).catch(()=>{});return y(l.message)}G("Unframe",async()=>{for(const l of c)await w("DELETE",`/__loop/api/frames/${l}`);await He(a)},()=>y("Unframe again to split it once more")),y(`Unframed \u201C${t.name}\u201D into ${c.length} part${c.length===1?"":"s"} \xB7 \u2318Z to undo`,2800)}async function bc(e){const t=yt(e);t&&(await w("DELETE",`/__loop/api/frames/${e}`),G("Delete frame",()=>He(t),()=>w("DELETE",`/__loop/api/frames/${e}`)),y(`Deleted \u201C${t.frames[0].name}\u201D \u2014 \u2318Z to undo`,2600))}let x=null,Jn={fid:null,t:0,x:0,y:0};function er(e){let t=e;for(let n=0;n<6;n++){const a=[...t.children].filter(o=>!/^(SCRIPT|STYLE|LINK|META|NOSCRIPT|TEMPLATE)$/.test(o.tagName));if(a.length!==1||!a[0].children.length)break;const i=t.getBoundingClientRect();if(a[0].getBoundingClientRect().width<i.width*.9)break;t=a[0]}return t}function Xa(e,t,n){const a=de(e),i=a?.body;if(!t||!i||t===a.documentElement)return null;if(n==="block")return i.contains(t)?wc(t,i):null;if(n==="deep"||!i.contains(t))return t===i?null:t;if(n==="smart"){const l=x?.frameId===e?x.els[x.els.length-1]:null;if(l?.isConnected&&l!==i&&l.contains(t)){if(t===l)return l;let d=t;for(;d.parentElement&&d.parentElement!==l;)d=d.parentElement;return d}return vc(t,i)}if(n==="outer"){const l=x?.frameId===e?x.els[x.els.length-1]:null,d=l?.isConnected&&l.contains(t)?l:t,u=d.parentElement;return!u||u===i?d:u}const s=x?.frameId===e,o=s?x.els[x.els.length-1]:null;let r=(n==="drill"||n==="step")&&o?.isConnected&&o.contains(t)?o:s&&x.scope?.isConnected?x.scope:er(i);for(;r!==i&&!r.contains(t);)r=r.parentElement;if(t===r)return r===i?null:r;let c=t;for(;c.parentElement&&c.parentElement!==r;)c=c.parentElement;return c}function vc(e,t){if(!t.contains(e)||e===t)return null;const n=t.ownerDocument.defaultView,a=e.closest?.('button, a[href], input, select, textarea, label, img, picture, video, canvas, iframe, svg, [role="button"], [role="link"], [role="tab"], [role="checkbox"], [role="switch"]');if(a&&t.contains(a))return a.closest("svg")&&a.tagName.toLowerCase()!=="svg"?a.closest("svg"):a;let i=e;for(;i.parentElement&&i.parentElement!==t&&/^inline$/.test(n.getComputedStyle(i).display);)i=i.parentElement;const s=(o,r)=>{const c=o.getBoundingClientRect(),l=r.getBoundingClientRect();return Math.abs(c.left-l.left)<1&&Math.abs(c.top-l.top)<1&&Math.abs(c.width-l.width)<1&&Math.abs(c.height-l.height)<1};for(;i.parentElement&&i.parentElement!==t&&i.parentElement.children.length===1&&s(i,i.parentElement);)i=i.parentElement;return i===t?null:i}function wc(e,t){let n=e.closest?.("svg")||e;for(;n&&n!==t;n=n.parentElement){if(n.tagName.toLowerCase()==="svg")continue;const a=[...n.children].filter(s=>!/^(SCRIPT|STYLE|BR|TEMPLATE)$/.test(s.tagName)).length,i=n.getBoundingClientRect();if(a&&n.ownerDocument.defaultView.getComputedStyle(n).display!=="inline"&&i.width>24&&i.height>16)return n}return null}function Ye(e){const t=[...e.childNodes].filter(o=>o.nodeType===3).map(o=>o.data).join(" ").replace(/\s+/g," ").trim();if(t&&!e.children.length)return t.length>28?t.slice(0,27)+"\u2026":t;const n=e.tagName.toLowerCase(),a={img:"Image",svg:"Icon",picture:"Image",video:"Video",canvas:"Canvas",button:"Button",a:"Link",input:"Field",textarea:"Field",select:"Menu",ul:"List",ol:"List",li:"Item",nav:"Navigation",header:"Header",footer:"Footer",form:"Form",table:"Table",label:"Label",section:"Section",main:"Main",aside:"Aside",article:"Article"},i=(e.getAttribute("aria-label")||"").trim();if(a[n]&&(n==="button"||n==="a")&&(t||i))return`${a[n]} \xB7 ${(t||i).slice(0,22)}`;if(a[n])return a[n];if(/^h[1-6]$/.test(n))return"Heading";const s=typeof e.className=="string"&&e.className.trim().split(/\s+/).find(o=>/^[a-zA-Z][a-zA-Z0-9_-]{2,}$/.test(o)&&!/[:\[]/.test(o)&&!/\d/.test(o))||(/^[a-zA-Z][\w-]*$/.test(e.id)?e.id:"");if(s){const o=s.replace(/[-_]+/g," ").replace(/([a-z])([A-Z])/g,"$1 $2").trim();return o[0].toUpperCase()+o.slice(1).toLowerCase()}return t?"Text":"Frame"}let Nt={fid:null,x:0,y:0,n:0,t:0},qe=null,Ua=0;function xc(e,t,n){if(t?.ctx)return;if(n!=="step"&&n!=="smart"){n==="deep"&&K==="select"&&Ae.set("loop.knowsDeep",1),Nt.n=0;return}const a=performance.now(),i=Nt.fid===e&&a-Nt.t<2500&&Math.hypot(t.clientX-Nt.x,t.clientY-Nt.y)<14;Nt={fid:e,x:t.clientX,y:t.clientY,n:i?Nt.n+1:1,t:a},Nt.n>=3&&!qe&&!Ae.get("loop.knowsDeep",0)&&Ae.get("loop.deepTipSeen",0)<2&&tr(t.clientX,t.clientY)}function tr(e,t,n){qe&&is();const a=rt==="metaKey"?"\u2318":"Ctrl";qe=document.createElement("div"),qe.id="deep-tip",qe.innerHTML=`<div class="dt-demo" aria-hidden="true"><div class="dt-card"><i class="dt-l t"></i><i class="dt-l a"></i><i class="dt-l b"></i><i class="dt-btn"></i></div>
57
+ <i class="dt-o o1"></i><i class="dt-o o2"></i><i class="dt-o o3"></i><kbd class="dt-key">${a}</kbd>
49
58
  <svg class="dt-cur" viewBox="0 0 24 24"><path d="M5 3l14 7.5-6.2 1.6L10.5 19z"/></svg></div>
50
59
  <button class="dt-x" title="Close" aria-label="Close"><svg viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
51
- <div class="dt-say"><b>Go straight to it</b><span>Hold <kbd>${i}</kbd> and move over the page. Whatever is under the pointer gets picked, however deep it sits.</span></div>`,document.body.appendChild(Ee);const s=272,a=Ee.offsetHeight||190;Ee.style.left=Math.max(12,Math.min(innerWidth-s-12,e+18))+"px",Ee.style.top=Math.max(60,Math.min(innerHeight-a-90,t+22))+"px",n||$e.set("loop.deepTipSeen",$e.get("loop.deepTipSeen",0)+1);const o=Ee;o.querySelector(".dt-x").addEventListener("click",Eo),o.addEventListener("pointerdown",l=>l.stopPropagation());const r=()=>{if(Ee===o){if(o.matches(":hover")){qi=setTimeout(r,800);return}o.classList.add("docked"),o.style.left=innerWidth-o.offsetWidth-16+"px",o.style.top="60px"}};clearTimeout(qi),qi=setTimeout(r,4500)}function Eo(){clearTimeout(qi);const e=Ee;e&&(Ee=null,e.classList.add("out"),setTimeout(()=>e.remove(),180))}addEventListener("resize",()=>{Ee?.classList.contains("docked")&&(Ee.style.left=innerWidth-Ee.offsetWidth-16+"px")});function dn(e,t,n="deep"){ql(e,t,n);const{lx:i,ly:s}=tt(e,t.clientX,t.clientY),a=Me(e,i,s),o=le(e),r=$?.frameId===e?$.els[$.els.length-1]:null;if(n==="drill"&&r&&r.contains(a)&&(a===r||!r.children.length)&&un(r,!0)){pn(e,r);return}const l=Pi(e,a,n);if(!l||l===o?.documentElement)return;if(n==="drill"&&l===r&&un(r,!0)){pn(e,r);return}if(t.shiftKey&&$?.frameId===e){const f=$.els.indexOf(l);if(f>=0?$.els.splice(f,1):$.els.push(l),!$.els.length){Ye(),ne();return}}else z.hidden||ne(),$={frameId:e,els:[l],scope:l.parentElement};Y.hidden=!0,de===e&&(de=null,ot());const c=u.frames.find(f=>f.id===e);c&&Q(c),Hs(e)}function Hs(e){{const t=u.frames.find(n=>n.id===e);t&&Q(t)}J(),Pe(),Ae(),qt()}function So(){if(!$)return;const{frameId:e,els:t}=$,n=t[t.length-1].getBoundingClientRect(),i=H.get(e).iframe.getBoundingClientRect(),s=$;$=null,Mt(e,n.left+Math.min(n.width/2,60),n.top+Math.min(n.height/2,20)),$=s,F.deep=!0,F.anchor=Mn(e,{...F.anchor,scope:"elements",elements:t.map(Ii)}),U.placeholder=t.length>1?"What should change about these?":"What should change about this?";const a=m("#composer-area");a.hidden=!1,a.classList.remove("chip-frame"),a.textContent=t.length===1?rt(t[0]):`${t.length} layers`,te.hidden=!0,Ae(),Ce()}function Xc(){if(!$||$.els.length!==1)return!1;const e=$.frameId,t=$.els[0],n=le(e)?.body,i=t.parentElement;if(!n||!i||i===n||i===Co(n)||!n.contains(i))return!1;const s=i.getBoundingClientRect(),a=H.get(e).iframe.getBoundingClientRect();return $={frameId:e,els:[i],scope:i.parentElement},Hs(e),!0}function Ii(e){const t=e.outerHTML;return{selector:kt(e),tag:e.tagName.toLowerCase(),label:Sa(e),text:(e.innerText||e.getAttribute("aria-label")||e.getAttribute("alt")||"").replace(/\s+/g," ").trim().slice(0,120),html:t.length>900?t.slice(0,900)+"\u2026":t}}function Ae(){if(document.querySelectorAll(".deep-box").forEach(t=>t.remove()),!$)return;const e=Lt($.frameId);if(e)for(const t of $.els){const n=t.getBoundingClientRect(),i=document.createElement("div");i.className="deep-box",Object.assign(i.style,{left:`${n.left}px`,top:`${n.top}px`,width:`${n.width}px`,height:`${n.height}px`}),i.dataset.tag=rt(t),e.appendChild(i);const s=$.els.length===1&&t.parentElement,a=t.ownerDocument.body;if(s&&s!==a&&s!==t.ownerDocument.documentElement){const o=s.getBoundingClientRect(),r=document.createElement("div");r.className="deep-box par",Object.assign(r.style,{left:`${o.left}px`,top:`${o.top}px`,width:`${o.width}px`,height:`${o.height}px`}),e.appendChild(r)}}}function Ye(){if(Ht(),$=null,document.querySelectorAll(".deep-box").forEach(e=>e.remove()),O&&(clearTimeout(O.t),Object.keys(O.pending).length&&u.frames.find(e=>e.id===O.fid)?.kind==="folder"&&Ho()),te.hidden=!0,O=null,Y.hidden=!0,u)for(const e of u.frames)Q(e)}const lt=/Mac|iPhone|iPad/.test(navigator.platform)?"metaKey":"ctrlKey",Il=new Set(["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"]),Hl=new Set(["script","style","textarea","title"]),zl=new Set(["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hr","main","nav","ol","p","pre","section","table","ul"]),Dl={li:["li"],dt:["dt","dd"],dd:["dt","dd"],option:["option"],tr:["tr"],td:["td","th"],th:["td","th"]};function Ol(e){const t={tag:"#root",kids:[],parent:null},n=e.length;let i=t,s=0,a=0,o=0;const r=c=>{c>a&&i.kids.push({text:!0,a,b:c})},l=(c,f,d)=>{c.innerB=f,c.b=d,(c.tag==="svg"||c.tag==="math")&&(o=Math.max(0,o-1))};for(;s<n;){const c=e.indexOf("<",s);if(c<0)break;if(e.startsWith("<!--",c)){r(c);const C=e.indexOf("-->",c+4),B=C<0?n:C+3;i.kids.push({comment:!0,a:c,b:B}),s=a=B;continue}const f=e[c+1];if(f==="!"||f==="?"){r(c);const C=e.indexOf(">",c);s=a=C<0?n:C+1;continue}const d=/^<(\/?)([a-zA-Z][^\s/>]*)/.exec(e.slice(c,c+96));if(!d){s=c+1;continue}let p=c+d[0].length,h=null;for(;p<n;p++){const C=e[p];if(h)C===h&&(h=null);else if(C==='"'||C==="'")h=C;else if(C===">")break}if(p>=n)break;r(c);const g=d[2].toLowerCase(),v=p+1;if(d[1]){let C=i;for(;C!==t&&C.tag!==g;)C=C.parent;if(C!==t){for(let B=i;B!==C;B=B.parent)l(B,c,c);l(C,c,v),i=C.parent}s=a=v;continue}if(!o){zl.has(g)&&i.tag==="p"&&(l(i,c,c),i=i.parent);const C=Dl[g];C&&C.includes(i.tag)&&(l(i,c,c),i=i.parent)}const S={tag:g,a:c,openEnd:v,kids:[],parent:i,attrs:[],innerA:v,innerB:n,b:n},A=/([^\s"'<>\/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g,x=e.slice(c+d[0].length,p);for(let C;C=A.exec(x);){const B=c+d[0].length+C.index,P=C[2]??C[3]??C[4],ee=C[2]!=null?'"':C[3]!=null?"'":"",R=P==null?-1:B+C[0].length-P.length-(ee?1:0);S.attrs.push({name:C[1].toLowerCase(),a:B,b:B+C[0].length,va:R,vb:R<0?-1:R+P.length,q:ee,value:P})}i.kids.push(S);const M=e[p-1]==="/";if(Il.has(g)||M&&o){S.innerB=v,S.b=v,s=a=v;continue}if(Hl.has(g)&&!o){const C=new RegExp(`</${g}\\s*>`,"i"),B=e.slice(v),P=C.exec(B),ee=P?v+P.index:n,R=P?ee+P[0].length:n;ee>v&&S.kids.push({text:!0,a:v,b:ee}),S.innerB=ee,S.b=R,s=a=R;continue}(g==="svg"||g==="math")&&o++,i=S,s=a=v}return r(n),t}const Rl=e=>e.kids.filter(t=>t.tag),Hi=e=>[...e.childNodes].map(t=>t.nodeType===3?"t":t.nodeType===1?t.tagName.toLowerCase():"c").join(","),Nl=e=>e.kids.map(t=>t.text?"t":t.tag?t.tag:"c").join(","),Bl=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");async function ze(e,t){const n=u.frames.find(i=>i.id===e);if(!n||n.kind!=="folder"||X||!k())return null;try{const i=t.ownerDocument,s=[];for(let p=t;p&&p!==i.body;p=p.parentElement){if(!p.parentElement)return null;s.unshift(p)}const{text:a}=await w("GET",`/__loop/api/frames/${e}/source`),o=new DOMParser().parseFromString(a,"text/html"),r=p=>{if(p.tag==="body")return p;for(const h of p.kids)if(h.tag){const g=r(h);if(g)return g}return null};let l=o.body,c=r(Ol(a)),f=i.body;if(!l||!c)return null;const d=p=>`${p.tagName}#${p.id||""}.${typeof p.className=="string"?p.className.trim().split(/\s+/).filter(h=>!/^(on|active|is-|selected|open)/.test(h)).sort().join("."):""}`;for(const p of s){const h=Rl(c);if(h.length!==l.children.length)return null;const g=[...f.children],v=[...l.children];let S=0,A=-1;for(const x of g){let M=S;for(;M<v.length&&d(v[M])!==d(x)&&v[M].tagName!==x.tagName;)M++;if(M<v.length&&(d(v[M])===d(x)||v[M].tagName===x.tagName&&!g.slice(g.indexOf(x)+1).some(C=>d(C)===d(v[M]))))x===p&&(A=M),S=M+1;else if(x===p)return null}if(A<0||(l=v[A],c=h[A],f=p,!l||!c||l.tagName.toLowerCase()!==c.tag))return null}return l.tagName!==t.tagName?null:{src:a,P:l,N:c}}catch{return null}}/[?&]debug\b/.test(location.search)&&(window.__loop={locate:(...e)=>ze(...e),stage:e=>Vt(e),fit:e=>Ge(!0,[e])});let Ke=null;const zs=new Map;function Fl(e){const t=e instanceof(e.ownerDocument.defaultView.SVGElement||SVGElement),n=(t?"svg:":"")+e.tagName.toLowerCase();if(zs.has(n))return zs.get(n);if(!Ke){const o=document.createElement("iframe");o.style.cssText="position:fixed;left:-9999px;width:10px;height:10px;visibility:hidden",document.body.appendChild(o),Ke=o.contentDocument,Ke.open(),Ke.write("<!doctype html><html><body></body></html>"),Ke.close()}const i=t?Ke.createElementNS("http://www.w3.org/2000/svg",e.tagName):Ke.createElement(e.tagName);(t?Ke.body.querySelector("svg")||Ke.body.appendChild(Ke.createElementNS("http://www.w3.org/2000/svg","svg")):Ke.body).appendChild(i);const s=Ke.defaultView.getComputedStyle(i),a={};for(const o of s)a[o]=s.getPropertyValue(o);return i.remove(),zs.set(n,a),a}function Wl(e){let t="",n="";for(const i of e.querySelectorAll('link[rel~="stylesheet"]'))/fonts\.(googleapis|gstatic)\.com|typekit|fonts\.bunny/.test(i.href)&&(t+=`<link rel="stylesheet" href="${i.href}">`);for(const i of e.styleSheets){let s;try{s=i.cssRules}catch{continue}const a=i.href||e.baseURI;for(const o of s)o.constructor.name==="CSSFontFaceRule"?n+=o.cssText.replace(/url\((['"]?)([^'")]+)\1\)/g,(r,l,c)=>/^(data:|https?:)/.test(c)?r:`url("${new URL(c,a).href}")`):o.constructor.name==="CSSImportRule"&&/fonts/.test(o.href)&&(t+=`<link rel="stylesheet" href="${new URL(o.href,a).href}">`)}return t+(n?`<style>${n}</style>`:"")}function Ds(e,t){const n=t.ownerDocument,i=n.defaultView,s=t.cloneNode(!0),a=[t,...t.querySelectorAll("*")],o=[s,...s.querySelectorAll("*")];a.forEach((l,c)=>{const f=o[c];if(!f||f.nodeType!==1)return;if(/^(SCRIPT|NOSCRIPT|TEMPLATE)$/.test(l.tagName)){f.remove();return}const d=i.getComputedStyle(l),p=Fl(l);let h="";for(const g of d){const v=d.getPropertyValue(g);v!==p[g]&&!/^(transition|animation)/.test(g)&&(h+=`${g}:${v};`)}f.setAttribute("style",h),f.removeAttribute("contenteditable");for(const g of["src","href","poster"])f.hasAttribute(g)&&l[g]&&typeof l[g]=="string"&&f.setAttribute(g,l[g]);f.hasAttribute("srcset")&&f.removeAttribute("srcset")}),s.style.setProperty("margin","0"),s.style.setProperty("position","relative"),s.style.setProperty("inset","auto"),s.style.setProperty("transform","none");const r=t.getBoundingClientRect();return{html:s.outerHTML,fonts:Wl(n),w:Math.max(8,Math.ceil(r.width)),h:Math.max(8,Math.ceil(r.height)),name:rt(t),fid:e,x:r.left,y:r.top}}const jl=e=>`<!doctype html>
60
+ <div class="dt-say"><b>Go straight to it</b><span>Hold <kbd>${a}</kbd> and move over the page. Whatever is under the pointer gets picked, however deep it sits.</span></div>`,document.body.appendChild(qe);const i=272,s=qe.offsetHeight||190;qe.style.left=Math.max(12,Math.min(innerWidth-i-12,e+18))+"px",qe.style.top=Math.max(60,Math.min(innerHeight-s-90,t+22))+"px",n||Ae.set("loop.deepTipSeen",Ae.get("loop.deepTipSeen",0)+1);const o=qe;o.querySelector(".dt-x").addEventListener("click",is),o.addEventListener("pointerdown",c=>c.stopPropagation());const r=()=>{if(qe===o){if(o.matches(":hover")){Ua=setTimeout(r,800);return}o.classList.add("docked"),o.style.left=innerWidth-o.offsetWidth-16+"px",o.style.top="60px"}};clearTimeout(Ua),Ua=setTimeout(r,4500)}function is(){clearTimeout(Ua);const e=qe;e&&(qe=null,e.classList.add("out"),setTimeout(()=>e.remove(),180))}addEventListener("resize",()=>{qe?.classList.contains("docked")&&(qe.style.left=innerWidth-qe.offsetWidth-16+"px")});function Qt(e,t,n="deep"){xc(e,t,n);const{lx:a,ly:i}=Ge(e,t.clientX,t.clientY),s=Me(e,a,i),o=de(e),r=x?.frameId===e?x.els[x.els.length-1]:null;if(n==="drill"&&r&&r.contains(s)&&(s===r||!r.children.length)&&xn(r,!0)){kn(e,r);return}const c=Xa(e,s,n);if(!c||c===o?.documentElement)return;if(n==="drill"&&c===r&&xn(r,!0)){kn(e,r);return}if(t.shiftKey&&x?.frameId===e){const d=x.els.indexOf(c);if(d>=0?x.els.splice(d,1):x.els.push(c),!x.els.length){Ve(),te();return}}else H.hidden||te(),x={frameId:e,els:[c],scope:c.parentElement};V.hidden=!0,fe===e&&(fe=null,ht());const l=f.frames.find(d=>d.id===e);l&&J(l),Za(e)}function Za(e){{const t=f.frames.find(n=>n.id===e);t&&J(t)}ee(),Re(),Pe(),bt()}function ea(){if(!x)return;const{frameId:e,els:t}=x,n=t[t.length-1].getBoundingClientRect(),a=D.get(e).iframe.getBoundingClientRect(),i=x;x=null,st(e,n.left+Math.min(n.width/2,60),n.top+Math.min(n.height/2,20)),x=i,B.deep=!0,B.anchor=On(e,{...B.anchor,scope:"elements",elements:t.map(ta)}),W.placeholder=t.length>1?"What should change about these?":"What should change about this?";const s=m("#composer-area");s.hidden=!1,s.classList.remove("chip-frame"),s.textContent=t.length===1?Ye(t[0]):`${t.length} layers`,ae.hidden=!0,Pe(),_e()}function zd(){if(!x||x.els.length!==1)return!1;const e=x.frameId,t=x.els[0],n=de(e)?.body,a=t.parentElement;if(!n||!a||a===n||a===er(n)||!n.contains(a))return!1;const i=a.getBoundingClientRect(),s=D.get(e).iframe.getBoundingClientRect();return x={frameId:e,els:[a],scope:a.parentElement},Za(e),!0}function ta(e){const t=e.outerHTML;return{selector:Dt(e),tag:e.tagName.toLowerCase(),label:to(e),text:(e.innerText||e.getAttribute("aria-label")||e.getAttribute("alt")||"").replace(/\s+/g," ").trim().slice(0,120),html:t.length>900?t.slice(0,900)+"\u2026":t}}function Pe(){if(document.querySelectorAll(".deep-box").forEach(t=>t.remove()),!x)return;const e=Ht(x.frameId);if(e)for(const t of x.els){const n=t.getBoundingClientRect(),a=document.createElement("div");a.className="deep-box",Object.assign(a.style,{left:`${n.left}px`,top:`${n.top}px`,width:`${n.width}px`,height:`${n.height}px`}),a.dataset.tag=Ye(t),e.appendChild(a);const i=x.els.length===1&&t.parentElement,s=t.ownerDocument.body;if(i&&i!==s&&i!==t.ownerDocument.documentElement){const o=i.getBoundingClientRect(),r=document.createElement("div");r.className="deep-box par",Object.assign(r.style,{left:`${o.left}px`,top:`${o.top}px`,width:`${o.width}px`,height:`${o.height}px`}),e.appendChild(r)}}}function Ve(){if(Ft(),x=null,document.querySelectorAll(".deep-box").forEach(e=>e.remove()),O&&(clearTimeout(O.t),Object.keys(O.pending).length&&f.frames.find(e=>e.id===O.fid)?.kind==="folder"&&hr()),ae.hidden=!0,O=null,V.hidden=!0,f)for(const e of f.frames)J(e)}const rt=/Mac|iPhone|iPad/.test(navigator.platform)?"metaKey":"ctrlKey",kc=new Set(["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"]),$c=new Set(["script","style","textarea","title"]),Lc=new Set(["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hr","main","nav","ol","p","pre","section","table","ul"]),Cc={li:["li"],dt:["dt","dd"],dd:["dt","dd"],option:["option"],tr:["tr"],td:["td","th"],th:["td","th"]};function Mc(e){const t={tag:"#root",kids:[],parent:null},n=e.length;let a=t,i=0,s=0,o=0;const r=l=>{l>s&&a.kids.push({text:!0,a:s,b:l})},c=(l,d,u)=>{l.innerB=d,l.b=u,(l.tag==="svg"||l.tag==="math")&&(o=Math.max(0,o-1))};for(;i<n;){const l=e.indexOf("<",i);if(l<0)break;if(e.startsWith("<!--",l)){r(l);const E=e.indexOf("-->",l+4),N=E<0?n:E+3;a.kids.push({comment:!0,a:l,b:N}),i=s=N;continue}const d=e[l+1];if(d==="!"||d==="?"){r(l);const E=e.indexOf(">",l);i=s=E<0?n:E+1;continue}const u=/^<(\/?)([a-zA-Z][^\s/>]*)/.exec(e.slice(l,l+96));if(!u){i=l+1;continue}let p=l+u[0].length,h=null;for(;p<n;p++){const E=e[p];if(h)E===h&&(h=null);else if(E==='"'||E==="'")h=E;else if(E===">")break}if(p>=n)break;r(l);const g=u[2].toLowerCase(),v=p+1;if(u[1]){let E=a;for(;E!==t&&E.tag!==g;)E=E.parent;if(E!==t){for(let N=a;N!==E;N=N.parent)c(N,l,l);c(E,l,v),a=E.parent}i=s=v;continue}if(!o){Lc.has(g)&&a.tag==="p"&&(c(a,l,l),a=a.parent);const E=Cc[g];E&&E.includes(a.tag)&&(c(a,l,l),a=a.parent)}const T={tag:g,a:l,openEnd:v,kids:[],parent:a,attrs:[],innerA:v,innerB:n,b:n},C=/([^\s"'<>\/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g,k=e.slice(l+u[0].length,p);for(let E;E=C.exec(k);){const N=l+u[0].length+E.index,q=E[2]??E[3]??E[4],ne=E[2]!=null?'"':E[3]!=null?"'":"",R=q==null?-1:N+E[0].length-q.length-(ne?1:0);T.attrs.push({name:E[1].toLowerCase(),a:N,b:N+E[0].length,va:R,vb:R<0?-1:R+q.length,q:ne,value:q})}a.kids.push(T);const M=e[p-1]==="/";if(kc.has(g)||M&&o){T.innerB=v,T.b=v,i=s=v;continue}if($c.has(g)&&!o){const E=new RegExp(`</${g}\\s*>`,"i"),N=e.slice(v),q=E.exec(N),ne=q?v+q.index:n,R=q?ne+q[0].length:n;ne>v&&T.kids.push({text:!0,a:v,b:ne}),T.innerB=ne,T.b=R,i=s=R;continue}(g==="svg"||g==="math")&&o++,a=T,i=s=v}return r(n),t}const Ec=e=>e.kids.filter(t=>t.tag),Ga=e=>[...e.childNodes].map(t=>t.nodeType===3?"t":t.nodeType===1?t.tagName.toLowerCase():"c").join(","),Sc=e=>e.kids.map(t=>t.text?"t":t.tag?t.tag:"c").join(","),Tc=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");async function We(e,t){const n=f.frames.find(a=>a.id===e);if(!n||n.kind!=="folder"||X||!$())return null;try{const a=t.ownerDocument,i=[];for(let p=t;p&&p!==a.body;p=p.parentElement){if(!p.parentElement)return null;i.unshift(p)}const{text:s}=await w("GET",`/__loop/api/frames/${e}/source`),o=new DOMParser().parseFromString(s,"text/html"),r=p=>{if(p.tag==="body")return p;for(const h of p.kids)if(h.tag){const g=r(h);if(g)return g}return null};let c=o.body,l=r(Mc(s)),d=a.body;if(!c||!l)return null;const u=p=>`${p.tagName}#${p.id||""}.${typeof p.className=="string"?p.className.trim().split(/\s+/).filter(h=>!/^(on|active|is-|selected|open)/.test(h)).sort().join("."):""}`;for(const p of i){const h=Ec(l);if(h.length!==c.children.length)return null;const g=[...d.children],v=[...c.children];let T=0,C=-1;for(const k of g){let M=T;for(;M<v.length&&u(v[M])!==u(k)&&v[M].tagName!==k.tagName;)M++;if(M<v.length&&(u(v[M])===u(k)||v[M].tagName===k.tagName&&!g.slice(g.indexOf(k)+1).some(E=>u(E)===u(v[M]))))k===p&&(C=M),T=M+1;else if(k===p)return null}if(C<0||(c=v[C],l=h[C],d=p,!c||!l||c.tagName.toLowerCase()!==l.tag))return null}return c.tagName!==t.tagName?null:{src:s,P:c,N:l}}catch{return null}}/[?&]debug\b/.test(location.search)&&(window.__loop={locate:(...e)=>We(...e),stage:e=>vt(e),fit:e=>Oe(!0,[e])});let tt=null;const ss=new Map;function Ac(e){const t=e instanceof(e.ownerDocument.defaultView.SVGElement||SVGElement),n=(t?"svg:":"")+e.tagName.toLowerCase();if(ss.has(n))return ss.get(n);if(!tt){const o=document.createElement("iframe");o.style.cssText="position:fixed;left:-9999px;width:10px;height:10px;visibility:hidden",document.body.appendChild(o),tt=o.contentDocument,tt.open(),tt.write("<!doctype html><html><body></body></html>"),tt.close()}const a=t?tt.createElementNS("http://www.w3.org/2000/svg",e.tagName):tt.createElement(e.tagName);(t?tt.body.querySelector("svg")||tt.body.appendChild(tt.createElementNS("http://www.w3.org/2000/svg","svg")):tt.body).appendChild(a);const i=tt.defaultView.getComputedStyle(a),s={};for(const o of i)s[o]=i.getPropertyValue(o);return a.remove(),ss.set(n,s),s}function _c(e){let t="",n="";for(const a of e.querySelectorAll('link[rel~="stylesheet"]'))/fonts\.(googleapis|gstatic)\.com|typekit|fonts\.bunny/.test(a.href)&&(t+=`<link rel="stylesheet" href="${a.href}">`);for(const a of e.styleSheets){let i;try{i=a.cssRules}catch{continue}const s=a.href||e.baseURI;for(const o of i)o.constructor.name==="CSSFontFaceRule"?n+=o.cssText.replace(/url\((['"]?)([^'")]+)\1\)/g,(r,c,l)=>/^(data:|https?:)/.test(l)?r:`url("${new URL(l,s).href}")`):o.constructor.name==="CSSImportRule"&&/fonts/.test(o.href)&&(t+=`<link rel="stylesheet" href="${new URL(o.href,s).href}">`)}return t+(n?`<style>${n}</style>`:"")}function na(e,t){const n=t.ownerDocument,a=n.defaultView,i=t.cloneNode(!0),s=[t,...t.querySelectorAll("*")],o=[i,...i.querySelectorAll("*")];s.forEach((c,l)=>{const d=o[l];if(!d||d.nodeType!==1)return;if(/^(SCRIPT|NOSCRIPT|TEMPLATE)$/.test(c.tagName)){d.remove();return}const u=a.getComputedStyle(c),p=Ac(c);let h="";for(const g of u){const v=u.getPropertyValue(g);v!==p[g]&&!/^(transition|animation)/.test(g)&&(h+=`${g}:${v};`)}d.setAttribute("style",h),d.removeAttribute("contenteditable");for(const g of["src","href","poster"])d.hasAttribute(g)&&c[g]&&typeof c[g]=="string"&&d.setAttribute(g,c[g]);d.hasAttribute("srcset")&&d.removeAttribute("srcset")}),i.style.setProperty("margin","0"),i.style.setProperty("position","relative"),i.style.setProperty("inset","auto"),i.style.setProperty("transform","none");const r=t.getBoundingClientRect();return{html:i.outerHTML,fonts:_c(n),w:Math.max(8,Math.ceil(r.width)),h:Math.max(8,Math.ceil(r.height)),name:Ye(t),fid:e,x:r.left,y:r.top}}const nr=e=>`<!doctype html>
52
61
  <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${L(e.name)}</title>${e.fonts}<style>html,body{margin:0;background:transparent}</style></head>
53
62
  <body>
54
63
  ${e.html}
55
64
  </body></html>
56
- `;async function Os(e,t,n){return Ql(e,t,n)}function Yl(e){const t=u.frames.find(i=>i.id===e);if(!t)return;b("Copying a picture of the frame\u2026",4e3);const n=w("POST",`/__loop/api/frames/${e}/shot`).then(i=>fetch(`/__loop/shots/${i.path.split("/").pop()}`)).then(i=>{if(!i.ok)throw new Error("No picture");return i.blob()}).then(i=>i.type==="image/png"?i:new Blob([i],{type:"image/png"}));try{navigator.clipboard.write([new ClipboardItem({"image/png":n})]).then(()=>b(`Copied \u201C${t.name}\u201D as an image`,1800),i=>b(`Couldn\u2019t copy the picture (${i.message||i.name})`))}catch(i){b(`Couldn\u2019t copy the picture (${i.message})`)}}const To=/^image\/(png|jpeg|gif|webp|svg\+xml)$/;function Rs(e,t){return new Promise((n,i)=>{const s=new FileReader;s.onload=()=>n(s.result),s.onerror=i,s[t](e)})}function Ao(e){return new Promise(t=>{const n=new Image;n.onload=()=>t([n.naturalWidth||800,n.naturalHeight||600]),n.onerror=()=>t([800,600]),n.src=e})}function Kl(e,t,n=0){const s=e>0&&t>0&&e<innerWidth&&t<innerHeight?re(e,t):re(innerWidth/2,innerHeight/2);return{x:Math.round(s.x+n*40),y:Math.round(s.y+n*40)}}async function Ns(e,t,n,i=!1){if(!k())return b("Only the host can add frames");let s=0,a=0;for(const o of e){const r=Kl(t,n,a),l=(c,f)=>i&&u.frames.some(p=>r.x<p.x+p.w+40&&r.x+c+40>p.x&&r.y<p.y+p.h+40&&r.y+f+40>p.y)?Ps(c,f,{x:r.x+c/2,y:r.y+f/2}):r;try{let c=null;if(o.file&&To.test(o.file.type)){if(o.file.size>12e6){b("That image is too big (over 12 MB)");continue}const d=await Rs(o.file,"readAsDataURL");let[p,h]=await Ao(d);(/^Screen ?Shot|^Screenshot|^image\.png$/i.test(o.file.name||"")||p>1800)&&p>600&&(p=Math.round(p/2),h=Math.round(h/2));const v=Math.min(1,2400/Math.max(p,h));p=Math.round(p*v),h=Math.round(h*v),c=await w("POST","/__loop/api/frames",{image:d,name:o.file.name&&!/^image\.png$/i.test(o.file.name)?o.file.name:"Image",w:p,h,...l(p,h)})}else if(o.file&&/\.html?$/i.test(o.file.name)){const d=await Rs(o.file,"readAsText");c=await w("POST","/__loop/api/frames",{new:!0,name:Ai(o.file.name.replace(/\.html?$/i,"")),html:d,w:1280,h:800,...l(1280,800)})}else if(o.imageUrl){let[d,p]=await Ao(o.imageUrl);const h=Math.min(1,2400/Math.max(d,p));d=Math.round(d*h),p=Math.round(p*h),c=await w("POST","/__loop/api/frames",{imageUrl:o.imageUrl,name:decodeURIComponent(o.imageUrl.split(/[?#]/)[0].split("/").pop()||"Image"),w:d,h:p,...l(d,p)})}else if(o.url&&!Vl(o.url)&&!o.live){const d=await Ul(o.url,t,n);if(!d)continue;if(d==="rebuild"){const p=l(1440,1024);c=await w("POST","/__loop/api/frames",{prompt:Xl(o.url),name:Ai(`${_o(o.url)} (rebuilt)`),w:1440,h:1024,...p})}else c=await w("POST","/__loop/api/frames",{src:o.url,name:o.url.replace(/^https?:\/\//,"").replace(/\/$/,"").slice(0,60),w:1280,h:800,...l(1280,800)})}else if(o.url)c=await w("POST","/__loop/api/frames",{src:o.url,name:o.url.replace(/^https?:\/\//,"").replace(/\/$/,"").slice(0,60),w:1280,h:800,...l(1280,800)});else if(o.file){b(`${o.file.name} can't be put on the canvas (images and HTML files can)`);continue}if(!c)continue;let f=null;Z("Add frame",async()=>{f=_t(c.id)||f,await w("DELETE",`/__loop/api/frames/${c.id}`)},()=>je(f||{frames:[c]})),Ze=c.id,s++,a++}catch(c){b(c.message)}}return s}const Vl=e=>{try{return/^(localhost|127\.0\.0\.1|\[::1\])$/.test(new URL(e).hostname)}catch{return!1}},_o=e=>{try{const t=new URL(e);return(t.hostname.replace(/^www\./,"")+(t.pathname.length>1?" \xB7 "+t.pathname.replace(/\/$/,"").split("/").slice(-1)[0].replace(/[-_]+/g," ").replace(/\?.*$/,""):"")).slice(0,40)}catch{return"Page"}},Xl=e=>`Rebuild the design at ${e} as this frame's page, as close to the original as you can.
65
+ `;async function Qa(e,t,n){return Kc(e,t,n)}function ar(e){const t=f.frames.find(a=>a.id===e);if(!t)return;y("Copying a picture of the frame\u2026",4e3);const n=w("POST",`/__loop/api/frames/${e}/shot`).then(a=>fetch(`/__loop/shots/${a.path.split("/").pop()}`)).then(a=>{if(!a.ok)throw new Error("No picture");return a.blob()}).then(a=>a.type==="image/png"?a:new Blob([a],{type:"image/png"}));try{navigator.clipboard.write([new ClipboardItem({"image/png":n})]).then(()=>y(`Copied \u201C${t.name}\u201D as an image`,1800),a=>y(`Couldn\u2019t copy the picture (${a.message||a.name})`))}catch(a){y(`Couldn\u2019t copy the picture (${a.message})`)}}function Pc(e){const t=e.ownerDocument,n=[];for(let a=e;a&&a.nodeType===1&&a!==t.documentElement;a=a.parentElement){if(a.id&&/^[A-Za-z][\w-]*$/.test(a.id)&&t.querySelectorAll(`#${a.id}`).length===1){n.unshift(`#${a.id}`);break}if(a.tagName==="BODY"){n.unshift("body");break}const i=a.parentElement?[...a.parentElement.children].filter(s=>s.tagName===a.tagName):[];n.unshift(a.tagName.toLowerCase()+(i.length>1?`:nth-of-type(${i.indexOf(a)+1})`:""))}return n.join(" > ")}function qc(e,t){const n=f.frames.find(s=>s.id===e);if(!n)return null;const a=(f.publicLink||`${location.origin}/__loop/`).split("#")[0],i=t?Ye(t):n.name;return{url:`${a}#f=${encodeURIComponent(e)}${t?`&e=${encodeURIComponent(Pc(t))}`:""}&n=${encodeURIComponent(i)}`,label:i,frame:n.name}}function os(e,t){const n=qc(e,t);if(!n)return;const a=()=>y(`Copied a link to \u201C${n.label}\u201D${t?` in ${n.frame}`:""}. Paste it in a comment to point at it.`,2400);try{navigator.clipboard.write([new ClipboardItem({"text/plain":new Blob([n.url],{type:"text/plain"})})]).then(a,()=>navigator.clipboard.writeText(n.url).then(a,()=>y("Couldn\u2019t copy the link")))}catch{navigator.clipboard?.writeText(n.url).then(a,()=>y("Couldn\u2019t copy the link"))}}function ir(e){try{const t=new URL(String(e).trim());if(!/\/__loop\/?$/.test(t.pathname))return null;const n=new URLSearchParams(t.hash.slice(1));return n.get("f")?{f:n.get("f"),e:n.get("e"),n:n.get("n")}:null}catch{return null}}const aa=e=>{try{return D.get(e)?.iframe.contentDocument}catch{return null}};async function sr(){const e=ir(location.href);if(!e||!f)return;history.replaceState(null,"",location.pathname+location.search);const t=f.frames.find(n=>n.id===e.f);if(!t)return y("That frame is no longer on this canvas");if(S&&dt(),Z(t.id),Oe(!0,[t.id]),!!e.e){for(let n=0;n<40;n++){const a=aa(t.id)?.querySelector(e.e);if(a){Z(null),x={frameId:t.id,els:[a],scope:a.parentElement},Pe(),bt?.();return}await new Promise(i=>setTimeout(i,250))}y(`\u201C${e.n||"That element"}\u201D isn\u2019t on the page any more. Here is its frame.`,2600)}}addEventListener("hashchange",()=>sr());const Ja=new WeakMap;function or(e){e.addEventListener("paste",t=>{const n=ir(t.clipboardData?.getData("text/plain")||"");if(!n)return;const a=f.frames.find(l=>l.id===n.f);if(!a)return;t.preventDefault(),t.stopPropagation();const i=n.e?aa(a.id)?.querySelector(n.e):null,s=i?ta(i):null,o=(n.n||(i?Ye(i):a.name)).replace(/\s+/g," ").trim(),r={frameId:a.id,label:o,selector:n.e||void 0,tag:s?.tag,text:s?.text,html:s?.html||i?.outerHTML?.slice(0,3e3)};Ja.set(e,[...Ja.get(e)||[],r]);const c=`@${o}${n.e?` (${a.name})`:""}`;e.setRangeText(c+" ",e.selectionStart,e.selectionEnd,"end"),e.dispatchEvent(new Event("input"))})}function rr(e,t){const n=(Ja.get(e)||[]).filter(a=>t.includes(`@${a.label}`));return Ja.delete(e),n}const oe=document.createElement("div");oe.id="ctx",oe.hidden=!0,oe.setAttribute("role","menu"),document.body.appendChild(oe);let ia=[];const we={cmd:rt==="metaKey"?"\u2318":"Ctrl ",shift:"\u21E7"};function ei(e,t,n,a){ia=a.filter(Boolean);const i=ia.filter((r,c,l)=>!(r.sep&&(c===0||c===l.length-1||l[c-1].sep)));ia=i,oe.innerHTML=`${n?`<div class="cx-head">${n}</div>`:""}${i.map((r,c)=>r.sep?'<div class="cx-sep"></div>':`<button class="cx-item${r.danger?" danger":""}" data-i="${c}" role="menuitem"${r.disabled?" disabled":""}><span>${L(r.label)}</span>${r.keys?`<kbd>${L(r.keys)}</kbd>`:""}</button>`).join("")}`,oe.hidden=!1,oe.classList.remove("in"),oe.offsetWidth,oe.classList.add("in");const s=oe.offsetWidth,o=oe.offsetHeight;oe.style.left=`${Math.max(8,e+s+8>innerWidth?e-s:e)}px`,oe.style.top=`${Math.max(8,t+o+8>innerHeight?t-o:t)}px`,oe.style.transformOrigin=`${e+s+8>innerWidth?"right":"left"} ${t+o+8>innerHeight?"bottom":"top"}`,oe.querySelector(".cx-item:not([disabled])")?.focus({preventScroll:!0})}function vn(){oe.hidden||(oe.hidden=!0,ia=[])}oe.addEventListener("pointerdown",e=>e.stopPropagation()),oe.addEventListener("contextmenu",e=>e.preventDefault()),oe.addEventListener("click",e=>{const t=e.target.closest(".cx-item");if(!t||t.disabled)return;const n=ia[+t.dataset.i];vn(),n?.act()}),oe.addEventListener("pointermove",e=>{const t=e.target.closest(".cx-item:not([disabled])");t&&document.activeElement!==t&&t.focus({preventScroll:!0})}),oe.addEventListener("keydown",e=>{const t=[...oe.querySelectorAll(".cx-item:not([disabled])")],n=t.indexOf(document.activeElement);e.key==="ArrowDown"||e.key==="ArrowUp"?(e.preventDefault(),t[(n+(e.key==="ArrowDown"?1:-1)+t.length)%t.length]?.focus()):e.key==="Escape"?(e.preventDefault(),vn()):e.key==="Enter"&&(e.preventDefault(),document.activeElement?.click()),e.stopPropagation()}),addEventListener("pointerdown",e=>{oe.contains(e.target)||vn()},!0),addEventListener("blur",vn),addEventListener("resize",vn),I.addEventListener("wheel",vn,{passive:!0}),I.addEventListener("contextmenu",e=>{e.preventDefault(),lr(e.clientX,e.clientY,e.target)});function lr(e,t,n){if(!f)return;te?.(),is?.();const a=n?.closest?.(".frame"),i=a&&f.frames.find(r=>r.id===a.dataset.id);if(i&&n.closest(".frame-body")&&!a.classList.contains("empty")&&!n.closest(".pin")){const{lx:r,ly:c}=Ge(i.id,e,t),l=Me(i.id,r,c);let d=x?.frameId===i.id?x.els.find(u=>u===l||u.contains(l)):null;if(!d&&l&&l!==aa(i.id)?.documentElement&&l!==aa(i.id)?.body&&(Qt(i.id,{clientX:e,clientY:t,ctx:!0},"smart"),d=x?.frameId===i.id?x.els[x.els.length-1]:null),d)return Dc(i,d,e,t)}if(i)return Z(i.id),Ic(i,e,t);const s=n?.closest?.(".section"),o=s&&f.sections.find(r=>r.id===s.dataset.id);if(o)return zc(o,e,t);Oc(e,t)}function Dc(e,t,n,a){const i=$(),s=e.kind==="folder"&&!X,o=t.parentElement,r=t.ownerDocument,c=p=>{x={frameId:e.id,els:[p],scope:p.parentElement},Pe(),bt?.()},{lx:l,ly:d}=Ge(e.id,n,a);let u=Me(e.id,l,d);for(;u&&u.parentElement&&u.parentElement!==t;)u=u.parentElement;(u?.parentElement!==t||u===t)&&(u=null),ei(n,a,`<b>${L(Ye(t))}</b><span>${L(e.name)}</span>`,[{label:"Comment",keys:"C",act:()=>{c(t),ea()}},{label:"Copy link",keys:`${we.shift}${we.cmd}L`,act:()=>os(e.id,t)},{sep:1},i&&{label:"Copy",keys:`${we.cmd}C`,act:()=>{pe=na(e.id,t),Xe=null;try{navigator.clipboard?.write?.([new ClipboardItem({"text/html":new Blob([pe.html],{type:"text/html"}),"text/plain":new Blob([pe.html],{type:"text/plain"})})]).catch(()=>{})}catch{}y(`Copied \u201C${pe.name}\u201D \u2014 \u2318V to paste`,1600)}},i&&s&&pe&&{label:"Paste after it",keys:`${we.cmd}V`,act:()=>ti(pe,e.id,t)},i&&s&&{label:"Duplicate",keys:`${we.cmd}D`,act:()=>{c(t),pr()}},{sep:1},u&&{label:"Select inside",act:()=>c(u)},o&&o!==r.body&&o!==r.documentElement&&{label:"Select the box around it",act:()=>c(o)},{label:"Select its frame",act:()=>{Ve(),Z(e.id)}},i&&{sep:1},i&&(s?{label:"Delete",keys:"\u232B",danger:!0,act:()=>{c(t),ms()}}:{label:"Ask to remove it\u2026",act:()=>{c(t),ea(),W.value="Remove this.",ot(W),W.focus(),W.select()}})])}function Ic(e,t,n){const a=$(),i=["route","url","folder"].includes(e.kind)&&!e.image&&!e.sizeOf,s=D.get(e.id),o=s&&!s.count.hidden;ei(t,n,`<b>${L(e.name)}</b><span>${e.w} \xD7 ${e.h}</span>`,[a&&e.optionOf&&{label:"Use this option",act:()=>Hc(e)},a&&e.optionOf&&{sep:1},{label:"Open on stage",keys:"S",act:()=>vt(e.id)},{label:"Comment on the frame",act:()=>{const r=s.el.querySelector(".frame-body").getBoundingClientRect();st(e.id,24,24)}},{sep:1},{label:"Copy link",keys:`${we.shift}${we.cmd}L`,act:()=>os(e.id,null)},{label:"Copy as image",keys:`${we.shift}${we.cmd}C`,act:()=>ar(e.id)},a&&{label:"Copy",keys:`${we.cmd}C`,act:()=>{Xe=e.id,pe=null,y(`Copied \u201C${e.name}\u201D \u2014 \u2318V to paste`,1600)}},a&&{label:"Duplicate",keys:`${we.cmd}D`,act:()=>qn(e.id)},a&&(e.kind==="route"||e.kind==="url")&&{label:"Duplicate as an editable copy",act:()=>ud(e.id)},a&&e.draftOf&&{label:"Make it real in the app\u2026",act:()=>{Z(e.id),st(e.id,24,24),W.value="Build this into the app.",ot(W),W.focus(),W.select()}},a&&{sep:1},a&&{label:"Rename",act:()=>_i(e.id)},a&&i&&{label:"See it at other sizes",act:()=>Pr(e)},o&&{label:"Versions",act:()=>Ls(e.id)},a&&e.kind!=="frozen"&&{label:"Freeze a copy",keys:`${we.shift}F`,act:()=>ra(e.id)},a&&{sep:1},a&&(f.frames.some(r=>r.parent===e.id)||e.kind==="folder"&&!e.image)&&{label:"Unframe (keep what\u2019s inside)",keys:`${we.shift}${we.cmd}F`,act:()=>Jo(e.id)},a&&{label:"Delete",keys:"\u232B",danger:!0,act:()=>wr([e.id])}])}async function Hc(e){const t=e.optionOf;if(t)try{await w("POST",`/__loop/api/comments/${t.cid}/choose`,{option:t.oid}),y(t.live?"Now the real screen. The other options are gone.":"The original now has this option. Its old version is kept in its versions.",2600)}catch(n){y(n.message)}}function zc(e,t,n){const a=$(),i=an(e).length;a&&(ke=e.id,wt?.()),ei(t,n,`<b>${L(e.name)}</b><span>${i} frame${i===1?"":"s"}</span>`,[{label:"Fit to the section",act:()=>Oe(!0,an(e).map(s=>s.id).concat([]))},a&&{label:"Rename",act:()=>Rr(e.id)},a&&{sep:1},a&&{label:i?"Unsection (keep the frames)":"Delete section",keys:`${we.shift}${we.cmd}S`,act:()=>bi(e.id)},a&&i&&{label:`Delete section and its ${i} frame${i===1?"":"s"}`,danger:!0,act:()=>Or(e.id)}])}function Oc(e,t){const n=$(),a=re(e,t);ei(e,t,"",[n&&(Xe||pe)&&{label:"Paste here",keys:`${we.cmd}V`,act:()=>{Xe&&f.frames.find(i=>i.id===Xe)?qn(Xe,{x:Math.round(a.x),y:Math.round(a.y)}):pe&&Qa(pe,a.x,a.y)}},n&&{label:"New frame here",act:()=>bn("Frame",1440,1024,a.x,a.y)},{label:"Comment here",act:()=>st(le,a.x,a.y,"canvas")},{sep:1},{label:"Fit everything",keys:`${we.shift}1`,act:()=>Oe(!0)},n&&!X&&{label:"Canvas history",act:()=>Kr(!0)},{label:"Keyboard shortcuts",keys:"?",act:()=>Ms(!0)}])}const cr=/^image\/(png|jpeg|gif|webp|svg\+xml)$/;function rs(e,t){return new Promise((n,a)=>{const i=new FileReader;i.onload=()=>n(i.result),i.onerror=a,i[t](e)})}function dr(e){return new Promise(t=>{const n=new Image;n.onload=()=>t([n.naturalWidth||800,n.naturalHeight||600]),n.onerror=()=>t([800,600]),n.src=e})}function Rc(e,t,n=0){const i=e>0&&t>0&&e<innerWidth&&t<innerHeight?re(e,t):re(innerWidth/2,innerHeight/2);return{x:Math.round(i.x+n*40),y:Math.round(i.y+n*40)}}async function ls(e,t,n,a=!1){if(!$())return y("Only the host can add frames");let i=0,s=0;for(const o of e){const r=Rc(t,n,s),c=(l,d)=>a&&f.frames.some(p=>r.x<p.x+p.w+40&&r.x+l+40>p.x&&r.y<p.y+p.h+40&&r.y+d+40>p.y)?ts(l,d,{x:r.x+l/2,y:r.y+d/2}):r;try{let l=null;if(o.file&&cr.test(o.file.type)){if(o.file.size>12e6){y("That image is too big (over 12 MB)");continue}const u=await rs(o.file,"readAsDataURL");let[p,h]=await dr(u);(/^Screen ?Shot|^Screenshot|^image\.png$/i.test(o.file.name||"")||p>1800)&&p>600&&(p=Math.round(p/2),h=Math.round(h/2));const v=Math.min(1,2400/Math.max(p,h));p=Math.round(p*v),h=Math.round(h*v),l=await w("POST","/__loop/api/frames",{image:u,name:o.file.name&&!/^image\.png$/i.test(o.file.name)?o.file.name:"Image",w:p,h,...c(p,h)})}else if(o.file&&/\.html?$/i.test(o.file.name)){const u=await rs(o.file,"readAsText");l=await w("POST","/__loop/api/frames",{new:!0,name:Un(o.file.name.replace(/\.html?$/i,"")),html:u,w:1280,h:800,...c(1280,800)})}else if(o.imageUrl){let[u,p]=await dr(o.imageUrl);const h=Math.min(1,2400/Math.max(u,p));u=Math.round(u*h),p=Math.round(p*h),l=await w("POST","/__loop/api/frames",{imageUrl:o.imageUrl,name:decodeURIComponent(o.imageUrl.split(/[?#]/)[0].split("/").pop()||"Image"),w:u,h:p,...c(u,p)})}else if(o.url&&!Nc(o.url)&&!o.live){const u=await Fc(o.url,t,n);if(!u)continue;if(u==="rebuild"){const p=c(1440,1024);l=await w("POST","/__loop/api/frames",{prompt:Bc(o.url),source:o.url,name:Un(`${cs(o.url)} (rebuilt)`),w:1440,h:1024,...p})}else l=await w("POST","/__loop/api/frames",{src:o.url,name:o.url.replace(/^https?:\/\//,"").replace(/\/$/,"").slice(0,60),w:1280,h:800,...c(1280,800)})}else if(o.url)l=await w("POST","/__loop/api/frames",{src:o.url,name:o.url.replace(/^https?:\/\//,"").replace(/\/$/,"").slice(0,60),w:1280,h:800,...c(1280,800)});else if(o.file){y(`${o.file.name} can't be put on the canvas (images and HTML files can)`);continue}if(!l)continue;let d=null;G("Add frame",async()=>{d=yt(l.id)||d,await w("DELETE",`/__loop/api/frames/${l.id}`)},()=>He(d||{frames:[l]})),Ue=l.id,i++,s++}catch(l){y(l.message)}}return i}const Nc=e=>{try{return/^(localhost|127\.0\.0\.1|\[::1\])$/.test(new URL(e).hostname)}catch{return!1}},cs=e=>{try{const t=new URL(e);return(t.hostname.replace(/^www\./,"")+(t.pathname.length>1?" \xB7 "+t.pathname.replace(/\/$/,"").split("/").slice(-1)[0].replace(/[-_]+/g," ").replace(/\?.*$/,""):"")).slice(0,40)}catch{return"Page"}},Bc=e=>`Rebuild the design at ${e} as this frame's page, as close to the original as you can.
57
66
  If it is a link to a file in a design tool and you have a tool or connector that can read that file, read the file's structure (layout and spacing, text and its styles, colours, effects, components and their variants, variables, images and icons) rather than working from a picture of it; otherwise work from what you can see at the address.
58
67
  Use the real text. Use the original's colours, type and spacing exactly. Make the frame the size of the original if it differs (the size command is in your instructions).
59
- When it is built, compare your page with the original (a render of it, or the page itself) and fix every difference you can see; repeat until they match.`;function Ul(e,t,n){return new Promise(i=>{document.querySelector("#url-ask")?.remove();const s=document.createElement("div");s.id="url-ask",s.innerHTML=`<div class="ua-host">${L(_o(e))}</div>
68
+ When it is built, compare your page with the original (a render of it, or the page itself) and fix every difference you can see; repeat until they match.`;function Fc(e,t,n){return new Promise(a=>{document.querySelector("#url-ask")?.remove();const i=document.createElement("div");i.id="url-ask",i.innerHTML=`<div class="ua-host">${L(cs(e))}</div>
60
69
  <button data-how="live" class="ua-opt"><b>Show it live</b><span>The site itself, as it is now</span><kbd>\u21B5</kbd></button>
61
- <button data-how="rebuild" class="ua-opt"><b>Rebuild it as a page</b><span>The agent recreates it here, so you can comment on it and change it</span><kbd>R</kbd></button>`,document.body.appendChild(s);const a=t>0&&t<innerWidth?t:innerWidth/2,o=n>0&&n<innerHeight?n:innerHeight/2;s.style.left=`${Math.max(12,Math.min(innerWidth-312,a-20))}px`,s.style.top=`${Math.max(60,Math.min(innerHeight-200,o+12))}px`;const r=f=>{removeEventListener("keydown",l,!0),removeEventListener("pointerdown",c,!0),s.remove(),i(f)},l=f=>{f.key==="Escape"?(f.preventDefault(),f.stopPropagation(),r(null)):f.key==="Enter"?(f.preventDefault(),f.stopPropagation(),r(s.querySelector('[data-how="live"]').disabled?"rebuild":"live")):f.key.toLowerCase()==="r"&&(f.preventDefault(),f.stopPropagation(),r("rebuild"))},c=f=>{s.contains(f.target)||r(null)};addEventListener("keydown",l,!0),setTimeout(()=>addEventListener("pointerdown",c,!0),0),s.addEventListener("click",f=>{const d=f.target.closest("[data-how]");d&&!d.disabled&&r(d.dataset.how)}),w("POST","/__loop/api/probe-url",{url:e}).then(f=>{if(f.embeddable||!s.isConnected)return;const d=s.querySelector('[data-how="live"]');d.disabled=!0,d.querySelector("span").textContent=f.blocked?"This site doesn\u2019t allow being shown inside other pages":"This address didn\u2019t open (it may need you to sign in)",s.querySelector('[data-how="rebuild"]').classList.add("first")}).catch(()=>{})})}const Zl=e=>/^https?:\/\/[^\s]+$/i.test(e)&&e.length<2e3,Po=e=>/\.(png|jpe?g|gif|webp|svg)(\?|#|$)/i.test(e);addEventListener("blur",()=>{Gt=null,Ve=null}),document.addEventListener("paste",e=>{if(Et()||!u||!k())return;const t=[...e.clipboardData?.files||[]],n=(e.clipboardData?.getData("text/plain")||"").trim();if(t.length){e.preventDefault(),Ns(t.map(i=>({file:i})),De.x,De.y,!0);return}Zl(n)&&(e.preventDefault(),Ns([Po(n)?{imageUrl:n}:{url:n}],De.x,De.y,!0))});let fn=null;function qo(e,t){const n=[...H.values()].find(o=>{const r=o.el.querySelector(".frame-body")?.getBoundingClientRect();return r&&e>=r.left&&e<=r.right&&t>=r.top&&t<=r.bottom}),i=n&&u.frames.find(o=>o.id===n.id);if(!i||i.kind!=="folder"||i.image||!k())return null;const{lx:s,ly:a}=tt(i.id,e,t);for(let o=Me(i.id,s,a),r=0;o&&r<4;o=o.parentElement,r++){if(o.tagName==="IMG")return{fid:i.id,el:o,kind:"img"};try{if(/url\(/.test(o.ownerDocument.defaultView.getComputedStyle(o).backgroundImage))return{fid:i.id,el:o,kind:"bg"}}catch{}if(/^(BODY|HTML)$/.test(o.tagName))break}return null}function Bs(e){if(!e){Y.hidden=!0,q.classList.remove("swapping");return}const t=H.get(e.fid).iframe.getBoundingClientRect(),n=e.el.getBoundingClientRect(),i=y.z;Object.assign(Y.style,{left:`${t.left+n.left*i}px`,top:`${t.top+n.top*i}px`,width:`${n.width*i}px`,height:`${n.height*i}px`}),Y.dataset.tag="Replace image",Y.innerHTML="",Y._k=null,Y.classList.remove("sel"),Y.hidden=!1,q.classList.add("swapping")}async function Gl(e,t){if(!To.test(t.type))return b("Drop an image file (PNG, JPEG, GIF, WebP or SVG)");try{const n=await ze(e.fid,e.el);if(!n)return b("This picture is drawn by the page\u2019s script, so it can\u2019t be swapped by hand. Ask the agent instead.");const{path:i}=await w("POST",`/__loop/api/frames/${e.fid}/asset`,{image:await Rs(t,"readAsDataURL"),name:t.name}),{src:s,N:a}=n;let o;if(e.kind==="img"){const r=a.attrs.find(f=>f.name==="src");o=r&&r.va>=0?{a:r.va,b:r.vb,before:s.slice(r.va,r.vb),text:i}:r?{a:r.a,b:r.b,before:s.slice(r.a,r.b),text:`src="${i}"`}:(()=>{const f=s[a.openEnd-2]==="/"?a.openEnd-2:a.openEnd-1;return{a:f,b:f,before:"",text:` src="${i}"`}})();const l=a.attrs.find(f=>f.name==="srcset"),c=[o];l&&c.push({a:l.a-(s[l.a-1]===" "?1:0),b:l.b,before:s.slice(l.a-(s[l.a-1]===" "?1:0),l.b),text:""}),await Je(e.fid,c,"Replace image")}else await Je(e.fid,[js(s,a,{"background-image":`url('${i}')`})],"Replace image");b("Image replaced",1400)}catch(n){b(n.message)}}q.addEventListener("dragover",e=>{const t=[...e.dataTransfer?.types||[]];!t.includes("Files")&&!t.includes("text/uri-list")||(e.preventDefault(),e.dataTransfer.dropEffect="copy",fn=t.includes("Files")?qo(e.clientX,e.clientY):null,Bs(fn),q.classList.toggle("dropping",!fn))}),q.addEventListener("dragleave",e=>{(!e.relatedTarget||!q.contains(e.relatedTarget))&&(q.classList.remove("dropping"),fn=null,Bs(null))}),q.addEventListener("drop",e=>{q.classList.remove("dropping");const t=fn||([...e.dataTransfer?.files||[]].length===1?qo(e.clientX,e.clientY):null);if(fn=null,Bs(null),t&&e.dataTransfer.files.length===1){e.preventDefault(),Gl(t,e.dataTransfer.files[0]);return}const n=[...e.dataTransfer?.files||[]],i=(e.dataTransfer?.getData("text/uri-list")||"").split(`
62
- `).map(s=>s.trim()).find(s=>s&&!s.startsWith("#"));!n.length&&!i||(e.preventDefault(),Ns(n.length?n.map(s=>({file:s})):[Po(i)||(e.dataTransfer.types||[]).includes("Files")?{imageUrl:i}:{url:i}],e.clientX,e.clientY))});async function Ql(e,t,n){try{const i=await w("POST","/__loop/api/frames",{new:!0,name:Ai(e.name||"Element"),w:e.w,h:e.h,x:Math.round(t),y:Math.round(n),html:jl(e),fill:"none"});let s=null;return Z("Copy element",async()=>{s=_t(i.id)||s,await w("DELETE",`/__loop/api/frames/${i.id}`)},()=>je(s||{frames:[i]})),Ze=i.id,b(`Copied \u201C${e.name}\u201D to its own frame`,1600),!0}catch(i){b(i.message)}}async function Fs(e,t,n){const i=u.frames.find(l=>l.id===t);if(!i||i.kind!=="folder")return b("Elements can be pasted into static frames. For an app screen, ask the agent.");const s=le(t),a=n&&n!==s?.documentElement?n:s?.body,o=a&&await ze(t,a);if(!o)return b("Couldn\u2019t find that spot in the page\u2019s file. Try selecting another element first.");const r=a===s.body?o.N.innerB??o.N.b:o.N.b;try{return await Je(t,[{a:r,b:r,before:"",text:`
63
- ${e.html}`}],`Paste \u201C${e.name}\u201D`),b(`Pasted \u201C${e.name}\u201D into ${i.name}`,1600),!0}catch(l){b(l.message)}}let Ve=null;async function Je(e,t,n){await w("POST",`/__loop/api/frames/${e}/edit`,{edits:t,what:n});let i=0;const s=[...t].sort((a,o)=>a.a-o.a).map(a=>{const o={a:a.a+i,b:a.a+i+a.text.length,before:a.text,text:a.before};return i+=a.text.length-(a.b-a.a),o});Z(n,()=>w("POST",`/__loop/api/frames/${e}/edit`,{edits:s,what:`Undo: ${n}`}),()=>w("POST",`/__loop/api/frames/${e}/edit`,{edits:t,what:n}))}const Ws=e=>!/^(SCRIPT|STYLE|TEMPLATE|BR|LINK|META)$/.test(e.tagName)&&e.getBoundingClientRect().width>0;function Fn(e){const t=H.get(e);t&&(t.quietN=(t.quietN||0)+1,t.quietT=Date.now()+2500)}function js(e,t,n){const i=t.attrs.find(r=>r.name==="style"),s=new Map;for(const r of(i?.value||"").split(";")){const l=r.indexOf(":");l>0&&s.set(r.slice(0,l).trim().toLowerCase(),r.slice(l+1).trim())}for(const[r,l]of Object.entries(n))s.set(r,l);const a=[...s].map(([r,l])=>`${r}: ${l}`).join("; ").replace(/"/g,"'");if(i&&i.va>=0&&i.q)return{a:i.va,b:i.vb,before:e.slice(i.va,i.vb),text:i.q==='"'?a:a.replace(/'/g,'"')};if(i)return{a:i.a,b:i.b,before:e.slice(i.a,i.b),text:`style="${a}"`};const o=e[t.openEnd-2]==="/"?t.openEnd-2:t.openEnd-1;return{a:o,b:o,before:"",text:` style="${a}"`}}async function Jl(e){const{fid:t,el:n}=e,i=n.parentElement,s=()=>{e.base==null?n.removeAttribute("style"):n.setAttribute("style",e.base),e.pbase==null?i.removeAttribute("style"):i.setAttribute("style",e.pbase),Ae(),It()};try{const a=await ze(t,n),o=a&&Object.keys(e.pprops).length?await ze(t,i):null;if(!a||Object.keys(e.pprops).length&&!o){s(),b("This one can\u2019t be placed by hand (its page is a live app, or its own script draws it). Ask for it in a comment.",3200);return}const r=[js(a.src,a.N,e.props)];o&&r.push(js(a.src,o.N,e.pprops)),Fn(t),await Je(t,r,`Place ${rt(n)}`),Ae(),qt()}catch(a){s(),b(a.message)}}async function ec(e,t,n,i){if(yt)return;const s=[...n.children].filter(Ws).filter(o=>o!==t),a=i||s[s.length-1]||null;yt=!0;try{const o=await ze(e,t),r=o&&await ze(e,a||n);if(!o||!r){b("This one can\u2019t be moved by hand (its page is a live app, or its own script draws it). Ask for the move in a comment.",3200);return}const l=o.src,c=l.slice(o.N.a,o.N.b),f=(g,v)=>{const S=l.lastIndexOf(`
64
- `,g-1)+1,A=l.indexOf(`
65
- `,v),x=A<0?l.length:A,M=/^[ \t]*$/.test(l.slice(S,g))&&/^[ \t]*$/.test(l.slice(v,x));return M?{a:S,b:A<0?l.length:A+1,indent:l.slice(S,g),own:M}:{a:g,b:v,indent:"",own:M}},d=f(o.N.a,o.N.b);let p,h;if(a){const g=f(r.N.a,r.N.b);p=i?g.a:g.b,h=g.own?p>0&&l[p-1]!==`
70
+ <button data-how="rebuild" class="ua-opt"><b>Rebuild it as a page</b><span>The agent recreates it here, so you can comment on it and change it</span><kbd>R</kbd></button>`,document.body.appendChild(i);const s=t>0&&t<innerWidth?t:innerWidth/2,o=n>0&&n<innerHeight?n:innerHeight/2;i.style.left=`${Math.max(12,Math.min(innerWidth-312,s-20))}px`,i.style.top=`${Math.max(60,Math.min(innerHeight-200,o+12))}px`;const r=d=>{removeEventListener("keydown",c,!0),removeEventListener("pointerdown",l,!0),i.remove(),a(d)},c=d=>{d.key==="Escape"?(d.preventDefault(),d.stopPropagation(),r(null)):d.key==="Enter"?(d.preventDefault(),d.stopPropagation(),r(i.querySelector('[data-how="live"]').disabled?"rebuild":"live")):d.key.toLowerCase()==="r"&&(d.preventDefault(),d.stopPropagation(),r("rebuild"))},l=d=>{i.contains(d.target)||r(null)};addEventListener("keydown",c,!0),setTimeout(()=>addEventListener("pointerdown",l,!0),0),i.addEventListener("click",d=>{const u=d.target.closest("[data-how]");u&&!u.disabled&&r(u.dataset.how)}),w("POST","/__loop/api/probe-url",{url:e}).then(d=>{if(d.embeddable||!i.isConnected)return;const u=i.querySelector('[data-how="live"]');u.disabled=!0,u.querySelector("span").textContent=d.blocked?"This site doesn\u2019t allow being shown inside other pages":"This address didn\u2019t open (it may need you to sign in)",i.querySelector('[data-how="rebuild"]').classList.add("first")}).catch(()=>{})})}const Wc=e=>/^https?:\/\/[^\s]+$/i.test(e)&&e.length<2e3,fr=e=>/\.(png|jpe?g|gif|webp|svg)(\?|#|$)/i.test(e);addEventListener("blur",()=>{Xe=null,pe=null}),document.addEventListener("paste",e=>{if(Ot()||!f||!$())return;const t=[...e.clipboardData?.files||[]],n=(e.clipboardData?.getData("text/plain")||"").trim();if(t.length){e.preventDefault(),ls(t.map(a=>({file:a})),je.x,je.y,!0);return}Wc(n)&&(e.preventDefault(),ls([fr(n)?{imageUrl:n}:{url:n}],je.x,je.y,!0))});let wn=null;function ur(e,t){const n=[...D.values()].find(o=>{const r=o.el.querySelector(".frame-body")?.getBoundingClientRect();return r&&e>=r.left&&e<=r.right&&t>=r.top&&t<=r.bottom}),a=n&&f.frames.find(o=>o.id===n.id);if(!a||a.kind!=="folder"||a.image||!$())return null;const{lx:i,ly:s}=Ge(a.id,e,t);for(let o=Me(a.id,i,s),r=0;o&&r<4;o=o.parentElement,r++){if(o.tagName==="IMG")return{fid:a.id,el:o,kind:"img"};try{if(/url\(/.test(o.ownerDocument.defaultView.getComputedStyle(o).backgroundImage))return{fid:a.id,el:o,kind:"bg"}}catch{}if(/^(BODY|HTML)$/.test(o.tagName))break}return null}function ds(e){if(!e){V.hidden=!0,I.classList.remove("swapping");return}const t=D.get(e.fid).iframe.getBoundingClientRect(),n=e.el.getBoundingClientRect(),a=b.z;Object.assign(V.style,{left:`${t.left+n.left*a}px`,top:`${t.top+n.top*a}px`,width:`${n.width*a}px`,height:`${n.height*a}px`}),V.dataset.tag="Replace image",V.innerHTML="",V._k=null,V.classList.remove("sel"),V.hidden=!1,I.classList.add("swapping")}async function jc(e,t){if(!cr.test(t.type))return y("Drop an image file (PNG, JPEG, GIF, WebP or SVG)");try{const n=await We(e.fid,e.el);if(!n)return y("This picture is drawn by the page\u2019s script, so it can\u2019t be swapped by hand. Ask the agent instead.");const{path:a}=await w("POST",`/__loop/api/frames/${e.fid}/asset`,{image:await rs(t,"readAsDataURL"),name:t.name}),{src:i,N:s}=n;let o;if(e.kind==="img"){const r=s.attrs.find(d=>d.name==="src");o=r&&r.va>=0?{a:r.va,b:r.vb,before:i.slice(r.va,r.vb),text:a}:r?{a:r.a,b:r.b,before:i.slice(r.a,r.b),text:`src="${a}"`}:(()=>{const d=i[s.openEnd-2]==="/"?s.openEnd-2:s.openEnd-1;return{a:d,b:d,before:"",text:` src="${a}"`}})();const c=s.attrs.find(d=>d.name==="srcset"),l=[o];c&&l.push({a:c.a-(i[c.a-1]===" "?1:0),b:c.b,before:i.slice(c.a-(i[c.a-1]===" "?1:0),c.b),text:""}),await lt(e.fid,l,"Replace image")}else await lt(e.fid,[us(i,s,{"background-image":`url('${a}')`})],"Replace image");y("Image replaced",1400)}catch(n){y(n.message)}}I.addEventListener("dragover",e=>{const t=[...e.dataTransfer?.types||[]];!t.includes("Files")&&!t.includes("text/uri-list")||(e.preventDefault(),e.dataTransfer.dropEffect="copy",wn=t.includes("Files")?ur(e.clientX,e.clientY):null,ds(wn),I.classList.toggle("dropping",!wn))}),I.addEventListener("dragleave",e=>{(!e.relatedTarget||!I.contains(e.relatedTarget))&&(I.classList.remove("dropping"),wn=null,ds(null))}),I.addEventListener("drop",e=>{I.classList.remove("dropping");const t=wn||([...e.dataTransfer?.files||[]].length===1?ur(e.clientX,e.clientY):null);if(wn=null,ds(null),t&&e.dataTransfer.files.length===1){e.preventDefault(),jc(t,e.dataTransfer.files[0]);return}const n=[...e.dataTransfer?.files||[]],a=(e.dataTransfer?.getData("text/uri-list")||"").split(`
71
+ `).map(i=>i.trim()).find(i=>i&&!i.startsWith("#"));!n.length&&!a||(e.preventDefault(),ls(n.length?n.map(i=>({file:i})):[fr(a)||(e.dataTransfer.types||[]).includes("Files")?{imageUrl:a}:{url:a}],e.clientX,e.clientY))});async function Kc(e,t,n){try{const a=await w("POST","/__loop/api/frames",{new:!0,name:Un(e.name||"Element"),w:e.w,h:e.h,x:Math.round(t),y:Math.round(n),html:nr(e),fill:"none"});let i=null;return G("Copy element",async()=>{i=yt(a.id)||i,await w("DELETE",`/__loop/api/frames/${a.id}`)},()=>He(i||{frames:[a]})),Ue=a.id,y(`Copied \u201C${e.name}\u201D to its own frame`,1600),!0}catch(a){y(a.message)}}async function ti(e,t,n){const a=f.frames.find(c=>c.id===t);if(!a||a.kind!=="folder")return y("Elements can be pasted into static frames. For an app screen, ask the agent.");const i=de(t),s=n&&n!==i?.documentElement?n:i?.body,o=s&&await We(t,s);if(!o)return y("Couldn\u2019t find that spot in the page\u2019s file. Try selecting another element first.");const r=s===i.body?o.N.innerB??o.N.b:o.N.b;try{return await lt(t,[{a:r,b:r,before:"",text:`
72
+ ${e.html}`}],`Paste \u201C${e.name}\u201D`),y(`Pasted \u201C${e.name}\u201D into ${a.name}`,1600),!0}catch(c){y(c.message)}}let pe=null;async function lt(e,t,n){await w("POST",`/__loop/api/frames/${e}/edit`,{edits:t,what:n});let a=0;const i=[...t].sort((s,o)=>s.a-o.a).map(s=>{const o={a:s.a+a,b:s.a+a+s.text.length,before:s.text,text:s.before};return a+=s.text.length-(s.b-s.a),o});G(n,()=>w("POST",`/__loop/api/frames/${e}/edit`,{edits:i,what:`Undo: ${n}`}),()=>w("POST",`/__loop/api/frames/${e}/edit`,{edits:t,what:n}))}const fs=e=>!/^(SCRIPT|STYLE|TEMPLATE|BR|LINK|META)$/.test(e.tagName)&&e.getBoundingClientRect().width>0;function sa(e){const t=D.get(e);t&&(t.quietN=(t.quietN||0)+1,t.quietT=Date.now()+2500)}function us(e,t,n){const a=t.attrs.find(r=>r.name==="style"),i=new Map;for(const r of(a?.value||"").split(";")){const c=r.indexOf(":");c>0&&i.set(r.slice(0,c).trim().toLowerCase(),r.slice(c+1).trim())}for(const[r,c]of Object.entries(n))i.set(r,c);const s=[...i].map(([r,c])=>`${r}: ${c}`).join("; ").replace(/"/g,"'");if(a&&a.va>=0&&a.q)return{a:a.va,b:a.vb,before:e.slice(a.va,a.vb),text:a.q==='"'?s:s.replace(/'/g,'"')};if(a)return{a:a.a,b:a.b,before:e.slice(a.a,a.b),text:`style="${s}"`};const o=e[t.openEnd-2]==="/"?t.openEnd-2:t.openEnd-1;return{a:o,b:o,before:"",text:` style="${s}"`}}async function Yc(e){const{fid:t,el:n}=e,a=n.parentElement,i=()=>{e.base==null?n.removeAttribute("style"):n.setAttribute("style",e.base),e.pbase==null?a.removeAttribute("style"):a.setAttribute("style",e.pbase),Pe(),Bt()};try{const s=await We(t,n),o=s&&Object.keys(e.pprops).length?await We(t,a):null;if(!s||Object.keys(e.pprops).length&&!o){i(),y("This one can\u2019t be placed by hand (its page is a live app, or its own script draws it). Ask for it in a comment.",3200);return}const r=[us(s.src,s.N,e.props)];o&&r.push(us(s.src,o.N,e.pprops)),sa(t),await lt(t,r,`Place ${Ye(n)}`),Pe(),bt()}catch(s){i(),y(s.message)}}async function Vc(e,t,n,a){if(Tt)return;const i=[...n.children].filter(fs).filter(o=>o!==t),s=a||i[i.length-1]||null;Tt=!0;try{const o=await We(e,t),r=o&&await We(e,s||n);if(!o||!r){y("This one can\u2019t be moved by hand (its page is a live app, or its own script draws it). Ask for the move in a comment.",3200);return}const c=o.src,l=c.slice(o.N.a,o.N.b),d=(g,v)=>{const T=c.lastIndexOf(`
73
+ `,g-1)+1,C=c.indexOf(`
74
+ `,v),k=C<0?c.length:C,M=/^[ \t]*$/.test(c.slice(T,g))&&/^[ \t]*$/.test(c.slice(v,k));return M?{a:T,b:C<0?c.length:C+1,indent:c.slice(T,g),own:M}:{a:g,b:v,indent:"",own:M}},u=d(o.N.a,o.N.b);let p,h;if(s){const g=d(r.N.a,r.N.b);p=a?g.a:g.b,h=g.own?p>0&&c[p-1]!==`
66
75
  `?`
67
- ${g.indent}${c}`:`${g.indent}${c}
68
- `:c}else{p=r.N.innerB??r.N.openEnd;const g=l.lastIndexOf(`
69
- `,r.N.a-1)+1,v=(/^[ \t]*/.exec(l.slice(g,r.N.a))||[""])[0];h=`
70
- ${v} ${c}
71
- ${v}`}if(p>d.a&&p<d.b)return;i?n.insertBefore(t,i):a?a.after(t):n.appendChild(t),O?.el===t&&(O.sel=kt(t)),$.scope=t.parentElement,Ae(),qt(),Fn(e),await Je(e,[{a:d.a,b:d.b,before:l.slice(d.a,d.b),text:""},{a:p,b:p,before:"",text:h}],`Move ${rt(t)}`)}catch(o){b(o.message)}finally{yt=!1}}async function tc(){if(yt||!$||$.els.length!==1)return;const e=$.frameId,t=$.els[0];if(!(!t.isConnected||!t.parentElement)){yt=!0;try{const n=await ze(e,t);if(!n){b("This one can\u2019t be copied by hand (its page is a live app, or its own script draws it). Ask for it in a comment.",3200);return}const i=n.src,s=i.slice(n.N.a,n.N.b),a=s.indexOf(">"),o=i.lastIndexOf(`
72
- `,n.N.a-1)+1,r=i.indexOf(`
73
- `,n.N.b),l=r<0?i.length:r,c=s.slice(0,a).replace(/\sid\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/i,"")+s.slice(a),f=/^[ \t]*$/.test(i.slice(o,n.N.a))&&/^[ \t]*$/.test(i.slice(n.N.b,l)),d=f?l:n.N.b,p=f?`
74
- ${i.slice(o,n.N.a)}${c}`:c,h=t.cloneNode(!0);h.removeAttribute("id"),t.after(h),$={frameId:e,els:[h],scope:h.parentElement},Ae(),qt(),Fn(e),await Je(e,[{a:d,b:d,before:"",text:p}],`Duplicate ${rt(t)}`)}catch(n){b(n.message)}finally{yt=!1}}}async function nc(e,t,n){const i=t.isConnected?await ze(e,t):null;if(!i)return!1;const{src:s,N:a}=i;let o=a.a,r=a.b;const l=s.lastIndexOf(`
75
- `,o-1)+1,c=s.indexOf(`
76
- `,r);return/^[ \t]*$/.test(s.slice(l,o))&&/^[ \t]*$/.test(s.slice(r,c<0?s.length:c))&&(o=l,r=c<0?s.length:c+1),Ye(),t.remove(),Fn(e),await Je(e,[{a:o,b:r,before:s.slice(o,r),text:""}],n),!0}async function ic(e,t){const{fid:n,el:i}=e,s=rt(i),a=Ds(n,i),o=re(t.clientX,t.clientY),r=Cn(o.x,o.y);if(r?.id===n)return;let l;if(r){const c=Oe(r);l=await Fs(a,r.id,Me(r.id,o.x-c.x,o.y-c.y))}else{const c=re(e.bx+t.clientX-e.sx,e.by+t.clientY-e.sy);l=await Os(a,c.x,c.y)}if(l===!0)try{await nc(n,i,`Move \u201C${s}\u201D out`)?b(r?`Moved \u201C${s}\u201D into ${r.name}`:`Moved \u201C${s}\u201D to its own frame`,1800):b(`Copied \u201C${s}\u201D (the original stays: its page can\u2019t be changed by hand)`,3e3)}catch(c){b(c.message)}}let yt=!1;async function sc(e){if(yt||!$||$.els.length!==1)return;const t=$.frameId,n=$.els[0],i=n.parentElement;if(!i||!n.isConnected)return;const s=h=>!/^(SCRIPT|STYLE|TEMPLATE|BR|LINK|META)$/.test(h.tagName)&&h.getBoundingClientRect().width>0;let a=n.previousElementSibling;for(;a&&!s(a);)a=a.previousElementSibling;let o=n.nextElementSibling;for(;o&&!s(o);)o=o.nextElementSibling;const r=h=>{const g=h.getBoundingClientRect();return[g.left+g.width/2,g.top+g.height/2]},l=r(n),c=e==="ArrowLeft"||e==="ArrowRight",f=e==="ArrowRight"||e==="ArrowDown"?1:-1,d=h=>{if(!h)return!1;const g=r(h),v=g[0]-l[0],S=g[1]-l[1];return c?Math.abs(v)>Math.abs(S)&&Math.sign(v)===f:Math.abs(S)>=Math.abs(v)&&Math.sign(S)===f},p=d(a)?a:d(o)?o:null;if(p){yt=!0;try{const h=await ze(t,n),g=h&&await ze(t,p);if(!h||!g){b("This one can\u2019t be moved by hand (its page is a live app, or its own script draws it). Ask for the move in a comment.",3200);return}const v=h.src.slice(h.N.a,h.N.b),S=h.src.slice(g.N.a,g.N.b);p===a?i.insertBefore(n,p):i.insertBefore(p,n),O?.el===n&&(O.sel=kt(n)),Ae(),qt(),Fn(t),await Je(t,[{a:h.N.a,b:h.N.b,before:v,text:S},{a:g.N.a,b:g.N.b,before:S,text:v}],`Move ${rt(n)}`)}catch(h){b(h.message)}finally{yt=!1}}}async function Io(e,t,n,i){const s=t.getBoundingClientRect(),a=Mn(e,{...ms(e,s.left+Math.min(s.width/2,40),s.top+Math.min(s.height/2,20)),scope:"elements",elements:[n]}),o={id:Jn(),frameId:e,text:i,anchor:a,author:{name:V.name,color:V.color}},r=gi(o);try{const l=await w("POST","/__loop/api/comments",o);l?.id&&l.id!==o.id&&r()}catch(l){r(),b(l.message)}}let ve=null;function un(e,t){let n=e?.nodeType===3?e.parentElement:e;return!n||n.nodeType!==1||n.namespaceURI!=="http://www.w3.org/1999/xhtml"||/^(INPUT|TEXTAREA|SELECT|SCRIPT|STYLE|HTML|BODY)$/.test(n.tagName)||n.isContentEditable||![...n.childNodes].some(i=>i.nodeType===3&&i.data.trim())||!t&&n.closest('a, button, label, summary, select, [role="button"], [role="tab"], [role="link"]')?null:n}function pn(e,t){if(!k()||ve||X)return!1;ne(),J(),Pe(),Y.hidden=!0,te.hidden=!0,ve={fid:e,el:t,html:t.innerHTML,texts:[...t.childNodes].map(a=>a.nodeType===3?a.data:null),shape:Hi(t),desc:Ii(t),attr:t.getAttribute("contenteditable"),outline:[t.style.outline,t.style.outlineOffset,t.style.cursor]},t.setAttribute("contenteditable","plaintext-only"),t.contentEditable!=="plaintext-only"&&t.setAttribute("contenteditable","true"),Object.assign(t.style,{outline:"1.5px solid #2F5BFF",outlineOffset:"3px",cursor:"text"});const n=ve,i=u.frames.find(a=>a.id===e);i&&Q(i);const s=()=>{if(ve===n){try{H.get(e)?.iframe.focus()}catch{}t.focus({preventScroll:!0});try{const a=t.ownerDocument.getSelection(),o=t.ownerDocument.createRange();o.selectNodeContents(t),a.removeAllRanges(),a.addRange(o)}catch{}}};return n.t0=performance.now(),s(),setTimeout(s,40),t.addEventListener("blur",n.onBlur=()=>{performance.now()-n.t0<300?setTimeout(s,0):zi(!0)}),!0}async function zi(e){const t=ve;if(!t)return;ve=null;const{fid:n,el:i}=t;i.removeEventListener("blur",t.onBlur),t.attr==null?i.removeAttribute("contenteditable"):i.setAttribute("contenteditable",t.attr),[i.style.outline,i.style.outlineOffset,i.style.cursor]=t.outline,i.getAttribute("style")||i.removeAttribute("style");try{i.ownerDocument.getSelection().removeAllRanges(),i.blur()}catch{}{const p=u.frames.find(h=>h.id===n);p&&Q(p),ot()}const s=[...i.childNodes].map(p=>p.nodeType===3?p.data:null),a=p=>(p||"").replace(/\s+/g," ").trim(),o=a(t.texts.filter(p=>p!=null).join(" ")),r=a(i.textContent);if($?.frameId===n&&O&&(te.hidden=!1,It()),!e||!r||Hi(i)===t.shape&&s.every((p,h)=>a(p)===a(t.texts[h]))){i.innerHTML=t.html;return}const l=await ze(n,i);let c=null;if(l){const{src:p,P:h,N:g}=l,v=(A,x)=>/^\s*/.exec(A)[0]+Bl(x.trim())+/\s*$/.exec(A)[0],S=[...h.childNodes].map(A=>A.nodeType===3?A.data:null);Hi(h)===t.shape&&Nl(g)===t.shape&&S.every((A,x)=>a(A)===a(t.texts[x]))&&(Hi(i)===t.shape?c=s.map((A,x)=>A!=null&&a(A)!==a(t.texts[x])?{a:g.kids[x].a,b:g.kids[x].b,before:p.slice(g.kids[x].a,g.kids[x].b),text:v(p.slice(g.kids[x].a,g.kids[x].b),A)}:null).filter(Boolean):!i.children.length&&!h.children.length&&(c=[{a:g.innerA,b:g.innerB,before:p.slice(g.innerA,g.innerB),text:v(p.slice(g.innerA,g.innerB),i.textContent)}]))}if(c?.length)try{await Je(n,c,"Edited text"),b("Saved",1100);return}catch(p){b(p.message),i.innerHTML=t.html;return}($?.frameId!==n||$.els[0]!==i)&&($={frameId:n,els:[i],scope:i.parentElement},Hs(n)),O?.el===i&&(O.text={from:O.text?.from||o,to:r},O.held=!0,mn());const f=O,d=t.html;Z("Edited text",()=>{i.innerHTML=d,f&&(f.text=null),Ae(),O===f&&mn()},()=>{})}function ac(e,t,n){const i=r=>r[lt]&&j==="select"&&r.button===0,s=r=>{r.preventDefault(),r.stopImmediatePropagation()};for(const r of["pointerdown","mousedown","pointerup","mouseup","dblclick"])e.addEventListener(r,l=>{(i(l)&&!ve||performance.now()<0)&&s(l)},!0);e.addEventListener("click",r=>{if(performance.now()<0)return s(r);if(ve?.fid===t)return ve.el.contains(r.target)?s(r):void 0;if(!i(r))return;s(r);const[l,c]=n(r);Y.hidden=!0,dn(t,{clientX:l,clientY:c,shiftKey:r.shiftKey})},!0);let o=!1;e.addEventListener("mousemove",r=>{if(r[lt]&&j==="select"&&!ve){const[l,c]=n(r);li(t,l,c),o=!0}else o&&(o=!1,Y.hidden=!0)},!0),e.addEventListener("keyup",r=>{o&&(r.key==="Meta"||r.key==="Control")&&(o=!1,Y.hidden=!0)},!0),e.addEventListener("mouseleave",()=>{o&&(o=!1,Y.hidden=!0)}),e.addEventListener("dblclick",r=>{if(j!=="select"||!k()||ve||!r[lt])return;const l=un(r.target,!0);l&&(s(r),pn(t,l))},!0),e.addEventListener("keydown",r=>{ve?.fid===t&&(r.stopImmediatePropagation(),r.key==="Enter"&&!r.shiftKey&&!r.isComposing?(r.preventDefault(),zi(!0)):r.key==="Escape"&&(r.preventDefault(),zi(!1)))},!0);for(const r of["keyup","keypress"])e.addEventListener(r,l=>{ve?.fid===t&&(l.stopImmediatePropagation(),l.key===" "&&r==="keyup"&&l.preventDefault())},!0)}const oc='<svg class="qi" viewBox="0 0 16 16"><path d="M2 4.5V3h7v1.5M5.5 3v10M4 13h3"/><path d="M10 8.5V8h4.5v.5M12.25 8v5M11.25 13h2"/></svg>',rc='<svg class="qi" viewBox="0 0 16 16"><path d="M3 13V8a5 5 0 0 1 5-5h5"/><path d="M3 13h.01M13 3h.01" stroke-width="2.2"/></svg>',te=document.createElement("div");te.id="quick",te.hidden=!0;{const e=()=>document.body.classList.toggle("card-open",!D.hidden||!z.hidden);for(const t of[D,z])new MutationObserver(e).observe(t,{attributes:!0,attributeFilter:["hidden"]})}document.body.appendChild(te);let O=null;const Di=e=>{const t=/rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+))?/.exec(e||"");return!t||t[4]!=null&&+t[4]==0?"":"#"+[t[1],t[2],t[3]].map(n=>Math.round(+n).toString(16).padStart(2,"0")).join("")};function qt(){const e=$?.els.length===1?$.els[0]:null;if(!$||X){te.hidden=!0,O=null;return}if(!e){te.innerHTML=`<span class="q-count">${$.els.length} selected</span><span class="q-sep"></span><button class="q-btn" data-q="comment" title="Comment on these">${T("comment")}</button>`,te.hidden=!1,O=null,It();return}const t=$.frameId,n=e.ownerDocument.defaultView.getComputedStyle(e);if(O?.el!==e&&(O={fid:t,el:e,sel:kt(e),pending:{},text:null,held:!1,t:null,desc:Ii(e)}),!k()){te.innerHTML=`<button class="q-btn" data-q="comment" title="Comment on this">${T("comment")}</button>`,te.hidden=!1,It();return}const i=(a,o,r)=>`<button class="q-sw${r?"":" none"}" data-pick="${a}" data-val="${r}" title="${o} colour"><i style="${r?`background:${r}`:""}"></i><span>${o}</span></button>`,s=(a,o,r,l)=>`<div class="q-num" title="${r}"><span class="q-scrub" data-scrub="${a}" title="Drag to change ${r.toLowerCase()}">${o}</span><input type="text" inputmode="numeric" data-q="${a}" value="${Math.round(parseFloat(l)||0)}"></div>`;te.innerHTML=`${un(e,!0)?`<button class="q-btn" data-q="text" title="Edit the text (or double-click it)">${T("edit")}</button><span class="q-sep"></span>`:""}
77
- ${i("color","Text",Di(n.color))}${i("background-color","Fill",Di(n.backgroundColor))}${i("border-color","Border",parseFloat(n.borderTopWidth)?Di(n.borderTopColor):"")}
78
- <span class="q-sep"></span>${s("font-size",oc,"Text size",n.fontSize)}${s("border-radius",rc,"Corner radius",n.borderTopLeftRadius)}
79
- <span class="q-sep"></span><button class="q-btn" data-q="comment" title="Comment on this (for the agent)">${T("comment")}</button><button class="q-btn" data-q="delete" title="Delete (\u232B)">${T("trash")}</button><span class="q-note"></span>`,te.hidden=!1,mn(),It()}function It(){if(te.hidden||!$)return;const e=$.frameId,t=$.els[$.els.length-1],n=H.get(e);if(!n||!t?.isConnected)return;const i=n.iframe.getBoundingClientRect(),s=t.getBoundingClientRect(),a=y.z,o=i.left+s.left*a,r=i.top+s.top*a,l=i.top+s.bottom*a,c=te.offsetWidth,f=te.offsetHeight;let d=r-f-8;d<60&&(d=l+8),d+f>innerHeight-76&&(d=Math.max(60,r+8)),te.style.left=`${Math.round(Math.max(12,Math.min(o,innerWidth-c-12)))}px`,te.style.top=`${Math.round(d)}px`}function mn(e){const t=te.querySelector(".q-note");if(!t||!O)return;const n=u.frames.find(s=>s.id===O.fid)?.kind==="folder",i=Object.keys(O.pending).length+(O.text?1:0);t.innerHTML=e?`<span>${L(e)}</span>`:(O.held||!n)&&i?`<span>Only on screen</span><button class="q-send" data-q="send" title="Loop can't change this in the code by itself. Ask the agent to make it real">Send to agent</button>`:"",It()}function hn(e,t){if(!O)return;const{el:n}=O,i=(a,o)=>{n.style.setProperty(a,o),O.pending[a]=o};if(!O.base){const a=O,o=n.getAttribute("style");O.base=!0,setTimeout(()=>{a.base=!1},1500),(a.held||u.frames.find(r=>r.id===a.fid)?.kind!=="folder")&&Z("Edited style",()=>{o==null?a.el.removeAttribute("style"):a.el.setAttribute("style",o),a.pending={},Ae(),O===a&&qt()},()=>{})}e==="border-color"&&!parseFloat(n.ownerDocument.defaultView.getComputedStyle(n).borderTopWidth)&&(i("border-width","1px"),i("border-style","solid")),i(e,t),Ae();const s=u.frames.find(a=>a.id===O.fid)?.kind==="folder";clearTimeout(O.t),s?O.t=setTimeout(Ho,380):mn()}async function Ho(){const e=O;if(!e||!Object.keys(e.pending).length)return;const t=e.pending;e.pending={};const n=e.el.isConnected?await ze(e.fid,e.el):null;if(!n){e.pending={...t,...e.pending},e.held=!0,O===e&&mn();return}const{src:i,N:s}=n,a=s.attrs.find(c=>c.name==="style"),o=new Map;for(const c of(a?.value||"").split(";")){const f=c.indexOf(":");f>0&&o.set(c.slice(0,f).trim().toLowerCase(),c.slice(f+1).trim())}for(const[c,f]of Object.entries(t))o.set(c,f);"background-color"in t&&o.get("background")==="none"&&o.delete("background");const r=[...o].map(([c,f])=>`${c}: ${f}`).join("; ").replace(/"/g,"'");let l;if(a&&a.va>=0&&a.q)l={a:a.va,b:a.vb,before:i.slice(a.va,a.vb),text:a.q==='"'?r:r.replace(/'/g,'"')};else if(a)l={a:a.a,b:a.b,before:i.slice(a.a,a.b),text:`style="${r}"`};else{const c=i[s.openEnd-2]==="/"?s.openEnd-2:s.openEnd-1;l={a:c,b:c,before:"",text:` style="${r}"`}}try{await Je(e.fid,[l],"Edited style"),O===e&&mn("Saved")}catch(c){b(c.message)}}async function lc(e){const t=Object.entries(e.pending).map(([i,s])=>`${i}: ${s}`).join("; "),n=[e.text&&`Change this text from "${e.text.from.slice(0,300)}" to "${e.text.to.slice(0,600)}".`,t&&`Set these on this element: ${t}.`].filter(Boolean);n.length&&(e.pending={},e.text=null,e.held=!1,Ye(),await Io(e.fid,e.el,e.desc,`${n.join(" ")} Make it in the source and change nothing else.`))}te.addEventListener("pointerdown",e=>e.stopPropagation()),te.addEventListener("input",e=>{const t=e.target.closest("[data-q]");if(!(!t||!O)&&t.type==="color"){const n=t.closest(".q-sw");n.classList.remove("none"),n.querySelector("i").style.background=t.value,hn(t.dataset.q,t.value)}}),te.addEventListener("change",e=>{const t=e.target.closest("input[data-q]");t&&t.value.trim()!==""&&!isNaN(+t.value)&&hn(t.dataset.q,`${Math.max(0,Math.min(400,Math.round(+t.value)))}px`)}),te.addEventListener("keydown",e=>{if(e.stopPropagation(),(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="z"){e.preventDefault(),e.target.blur?.(),e.shiftKey?Nn():_i();return}if(e.key==="Escape")return e.target.blur?.(),Ye();if(e.key==="Enter")return e.target.blur?.();const t=e.target.closest("input[data-q]");t&&(e.key==="ArrowUp"||e.key==="ArrowDown")&&(e.preventDefault(),t.value=Math.max(0,Math.min(400,(parseInt(t.value)||0)+(e.key==="ArrowUp"?1:-1)*(e.shiftKey?10:1))),hn(t.dataset.q,`${t.value}px`))}),te.addEventListener("pointerdown",e=>{const t=e.target.closest("[data-scrub]");if(!t||!O)return;e.preventDefault();const n=t.parentElement.querySelector("input"),i=parseInt(n.value)||0,s=e.clientX;t.setPointerCapture(e.pointerId),document.body.classList.add("scrubbing");const a=r=>{const l=Math.max(0,Math.min(400,Math.round(i+(r.clientX-s)/2*(r.shiftKey?10:1))));String(l)!==n.value&&(n.value=l,hn(t.dataset.scrub,`${l}px`))},o=()=>{t.removeEventListener("pointermove",a),document.body.classList.remove("scrubbing")};t.addEventListener("pointermove",a),t.addEventListener("pointerup",o,{once:!0}),t.addEventListener("pointercancel",o,{once:!0})}),te.addEventListener("click",e=>{const t=e.target.closest("[data-pick]");if(t&&O)return Oi(t);const n=e.target.closest("button[data-q]");if(!n)return;if(n.dataset.q==="comment")return So();if(n.dataset.q==="delete")return Oo();const i=e.target.closest("[data-pick]");if(i&&O)return Oi(i);if(O)if(n.dataset.q==="text"){const{fid:s,el:a}=O;pn(s,a)}else n.dataset.q==="send"&&lc(O)});const be=document.createElement("div");be.id="cpick",be.hidden=!0,document.body.appendChild(be);let G=null;const cc=(e,t,n)=>{const i=s=>{const a=(s+e/60)%6;return n-n*t*Math.max(0,Math.min(a,4-a,1))};return[i(5),i(3),i(1)].map(s=>Math.round(s*255))},dc=e=>"#"+e.map(t=>t.toString(16).padStart(2,"0")).join("");function Ys(e){const t=/^#?([0-9a-f]{6})$/i.exec(e||"");if(!t)return{h:0,s:0,v:1};const n=parseInt(t[1],16),i=(n>>16&255)/255,s=(n>>8&255)/255,a=(n&255)/255,o=Math.max(i,s,a),r=o-Math.min(i,s,a);return{h:r?o===i?((s-a)/r+6)%6*60:o===s?((a-i)/r+2)*60:((i-s)/r+4)*60:0,s:o?r/o:0,v:o}}function fc(e){const t=new Map;for(const n of[...e.body.querySelectorAll("*")].slice(0,1500)){const i=e.defaultView.getComputedStyle(n);for(const s of[i.color,i.backgroundColor,i.borderTopWidth!=="0px"?i.borderTopColor:""]){const a=Di(s);a&&t.set(a,(t.get(a)||0)+1)}}return[...t].sort((n,i)=>i[1]-n[1]).slice(0,14).map(n=>n[0])}function Oi(e){if(G?.btn===e)return Ht();Ht();const t=e.dataset.val||"#ffffff";G={prop:e.dataset.pick,btn:e,...Ys(t)};const n=(()=>{try{return fc(O.el.ownerDocument)}catch{return[]}})();be.innerHTML=`<div class="cp-sv"><i></i></div><div class="cp-hue"><i></i></div>
76
+ ${g.indent}${l}`:`${g.indent}${l}
77
+ `:l}else{p=r.N.innerB??r.N.openEnd;const g=c.lastIndexOf(`
78
+ `,r.N.a-1)+1,v=(/^[ \t]*/.exec(c.slice(g,r.N.a))||[""])[0];h=`
79
+ ${v} ${l}
80
+ ${v}`}if(p>u.a&&p<u.b)return;a?n.insertBefore(t,a):s?s.after(t):n.appendChild(t),O?.el===t&&(O.sel=Dt(t)),x.scope=t.parentElement,Pe(),bt(),sa(e),await lt(e,[{a:u.a,b:u.b,before:c.slice(u.a,u.b),text:""},{a:p,b:p,before:"",text:h}],`Move ${Ye(t)}`)}catch(o){y(o.message)}finally{Tt=!1}}async function pr(){if(Tt||!x||x.els.length!==1)return;const e=x.frameId,t=x.els[0];if(!(!t.isConnected||!t.parentElement)){Tt=!0;try{const n=await We(e,t);if(!n){y("This one can\u2019t be copied by hand (its page is a live app, or its own script draws it). Ask for it in a comment.",3200);return}const a=n.src,i=a.slice(n.N.a,n.N.b),s=i.indexOf(">"),o=a.lastIndexOf(`
81
+ `,n.N.a-1)+1,r=a.indexOf(`
82
+ `,n.N.b),c=r<0?a.length:r,l=i.slice(0,s).replace(/\sid\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/i,"")+i.slice(s),d=/^[ \t]*$/.test(a.slice(o,n.N.a))&&/^[ \t]*$/.test(a.slice(n.N.b,c)),u=d?c:n.N.b,p=d?`
83
+ ${a.slice(o,n.N.a)}${l}`:l,h=t.cloneNode(!0);h.removeAttribute("id"),t.after(h),x={frameId:e,els:[h],scope:h.parentElement},Pe(),bt(),sa(e),await lt(e,[{a:u,b:u,before:"",text:p}],`Duplicate ${Ye(t)}`)}catch(n){y(n.message)}finally{Tt=!1}}}async function Xc(e,t,n){const a=t.isConnected?await We(e,t):null;if(!a)return!1;const{src:i,N:s}=a;let o=s.a,r=s.b;const c=i.lastIndexOf(`
84
+ `,o-1)+1,l=i.indexOf(`
85
+ `,r);return/^[ \t]*$/.test(i.slice(c,o))&&/^[ \t]*$/.test(i.slice(r,l<0?i.length:l))&&(o=c,r=l<0?i.length:l+1),Ve(),t.remove(),sa(e),await lt(e,[{a:o,b:r,before:i.slice(o,r),text:""}],n),!0}async function Uc(e,t){const{fid:n,el:a}=e,i=Ye(a),s=na(n,a),o=re(t.clientX,t.clientY),r=zn(o.x,o.y);if(r?.id===n)return;let c;if(r){const l=De(r);c=await ti(s,r.id,Me(r.id,o.x-l.x,o.y-l.y))}else{const l=re(e.bx+t.clientX-e.sx,e.by+t.clientY-e.sy);c=await Qa(s,l.x,l.y)}if(c===!0)try{await Xc(n,a,`Move \u201C${i}\u201D out`)?y(r?`Moved \u201C${i}\u201D into ${r.name}`:`Moved \u201C${i}\u201D to its own frame`,1800):y(`Copied \u201C${i}\u201D (the original stays: its page can\u2019t be changed by hand)`,3e3)}catch(l){y(l.message)}}let Tt=!1;async function Zc(e){if(Tt||!x||x.els.length!==1)return;const t=x.frameId,n=x.els[0],a=n.parentElement;if(!a||!n.isConnected)return;const i=h=>!/^(SCRIPT|STYLE|TEMPLATE|BR|LINK|META)$/.test(h.tagName)&&h.getBoundingClientRect().width>0;let s=n.previousElementSibling;for(;s&&!i(s);)s=s.previousElementSibling;let o=n.nextElementSibling;for(;o&&!i(o);)o=o.nextElementSibling;const r=h=>{const g=h.getBoundingClientRect();return[g.left+g.width/2,g.top+g.height/2]},c=r(n),l=e==="ArrowLeft"||e==="ArrowRight",d=e==="ArrowRight"||e==="ArrowDown"?1:-1,u=h=>{if(!h)return!1;const g=r(h),v=g[0]-c[0],T=g[1]-c[1];return l?Math.abs(v)>Math.abs(T)&&Math.sign(v)===d:Math.abs(T)>=Math.abs(v)&&Math.sign(T)===d},p=u(s)?s:u(o)?o:null;if(p){Tt=!0;try{const h=await We(t,n),g=h&&await We(t,p);if(!h||!g){y("This one can\u2019t be moved by hand (its page is a live app, or its own script draws it). Ask for the move in a comment.",3200);return}const v=h.src.slice(h.N.a,h.N.b),T=h.src.slice(g.N.a,g.N.b);p===s?a.insertBefore(n,p):a.insertBefore(p,n),O?.el===n&&(O.sel=Dt(n)),Pe(),bt(),sa(t),await lt(t,[{a:h.N.a,b:h.N.b,before:v,text:T},{a:g.N.a,b:g.N.b,before:T,text:v}],`Move ${Ye(n)}`)}catch(h){y(h.message)}finally{Tt=!1}}}async function mr(e,t,n,a){const i=t.getBoundingClientRect(),s=On(e,{...Hi(e,i.left+Math.min(i.width/2,40),i.top+Math.min(i.height/2,20)),scope:"elements",elements:[n]}),o={id:ga(),frameId:e,text:a,anchor:s,author:{name:U.name,color:U.color}},r=Pa(o);try{const c=await w("POST","/__loop/api/comments",o);c?.id&&c.id!==o.id&&r()}catch(c){r(),y(c.message)}}let xe=null;function xn(e,t){let n=e?.nodeType===3?e.parentElement:e;return!n||n.nodeType!==1||n.namespaceURI!=="http://www.w3.org/1999/xhtml"||/^(INPUT|TEXTAREA|SELECT|SCRIPT|STYLE|HTML|BODY)$/.test(n.tagName)||n.isContentEditable||![...n.childNodes].some(a=>a.nodeType===3&&a.data.trim())||!t&&n.closest('a, button, label, summary, select, [role="button"], [role="tab"], [role="link"]')?null:n}function kn(e,t){if(!$()||xe||X)return!1;te(),ee(),Re(),V.hidden=!0,ae.hidden=!0,xe={fid:e,el:t,html:t.innerHTML,texts:[...t.childNodes].map(s=>s.nodeType===3?s.data:null),shape:Ga(t),desc:ta(t),attr:t.getAttribute("contenteditable"),outline:[t.style.outline,t.style.outlineOffset,t.style.cursor]},t.setAttribute("contenteditable","plaintext-only"),t.contentEditable!=="plaintext-only"&&t.setAttribute("contenteditable","true"),Object.assign(t.style,{outline:"1.5px solid #2F5BFF",outlineOffset:"3px",cursor:"text"});const n=xe,a=f.frames.find(s=>s.id===e);a&&J(a);const i=()=>{if(xe===n){try{D.get(e)?.iframe.focus()}catch{}t.focus({preventScroll:!0});try{const s=t.ownerDocument.getSelection(),o=t.ownerDocument.createRange();o.selectNodeContents(t),s.removeAllRanges(),s.addRange(o)}catch{}}};return n.t0=performance.now(),i(),setTimeout(i,40),t.addEventListener("blur",n.onBlur=()=>{performance.now()-n.t0<300?setTimeout(i,0):ni(!0)}),!0}async function ni(e){const t=xe;if(!t)return;xe=null;const{fid:n,el:a}=t;a.removeEventListener("blur",t.onBlur),t.attr==null?a.removeAttribute("contenteditable"):a.setAttribute("contenteditable",t.attr),[a.style.outline,a.style.outlineOffset,a.style.cursor]=t.outline,a.getAttribute("style")||a.removeAttribute("style");try{a.ownerDocument.getSelection().removeAllRanges(),a.blur()}catch{}{const p=f.frames.find(h=>h.id===n);p&&J(p),ht()}const i=[...a.childNodes].map(p=>p.nodeType===3?p.data:null),s=p=>(p||"").replace(/\s+/g," ").trim(),o=s(t.texts.filter(p=>p!=null).join(" ")),r=s(a.textContent);if(x?.frameId===n&&O&&(ae.hidden=!1,Bt()),!e||!r||Ga(a)===t.shape&&i.every((p,h)=>s(p)===s(t.texts[h]))){a.innerHTML=t.html;return}const c=await We(n,a);let l=null;if(c){const{src:p,P:h,N:g}=c,v=(C,k)=>/^\s*/.exec(C)[0]+Tc(k.trim())+/\s*$/.exec(C)[0],T=[...h.childNodes].map(C=>C.nodeType===3?C.data:null);Ga(h)===t.shape&&Sc(g)===t.shape&&T.every((C,k)=>s(C)===s(t.texts[k]))&&(Ga(a)===t.shape?l=i.map((C,k)=>C!=null&&s(C)!==s(t.texts[k])?{a:g.kids[k].a,b:g.kids[k].b,before:p.slice(g.kids[k].a,g.kids[k].b),text:v(p.slice(g.kids[k].a,g.kids[k].b),C)}:null).filter(Boolean):!a.children.length&&!h.children.length&&(l=[{a:g.innerA,b:g.innerB,before:p.slice(g.innerA,g.innerB),text:v(p.slice(g.innerA,g.innerB),a.textContent)}]))}if(l?.length)try{await lt(n,l,"Edited text"),y("Saved",1100);return}catch(p){y(p.message),a.innerHTML=t.html;return}(x?.frameId!==n||x.els[0]!==a)&&(x={frameId:n,els:[a],scope:a.parentElement},Za(n)),O?.el===a&&(O.text={from:O.text?.from||o,to:r},O.held=!0,$n());const d=O,u=t.html;G("Edited text",()=>{a.innerHTML=u,d&&(d.text=null),Pe(),O===d&&$n()},()=>{})}function Gc(e,t,n){const a=r=>r[rt]&&K==="select"&&r.button===0,i=r=>{r.preventDefault(),r.stopImmediatePropagation()};for(const r of["pointerdown","mousedown","pointerup","mouseup","dblclick"])e.addEventListener(r,c=>{(a(c)&&!xe||performance.now()<0)&&i(c)},!0);e.addEventListener("click",r=>{if(performance.now()<0)return i(r);if(xe?.fid===t)return xe.el.contains(r.target)?i(r):void 0;if(!a(r))return;i(r);const[c,l]=n(r);V.hidden=!0,Qt(t,{clientX:c,clientY:l,shiftKey:r.shiftKey})},!0);let o=!1;e.addEventListener("mousemove",r=>{if(r[rt]&&K==="select"&&!xe){const[c,l]=n(r);La(t,c,l),o=!0}else o&&(o=!1,V.hidden=!0)},!0),e.addEventListener("keyup",r=>{o&&(r.key==="Meta"||r.key==="Control")&&(o=!1,V.hidden=!0)},!0),e.addEventListener("mouseleave",()=>{o&&(o=!1,V.hidden=!0)}),e.addEventListener("dblclick",r=>{if(K!=="select"||!$()||xe||!r[rt])return;const c=xn(r.target,!0);c&&(i(r),kn(t,c))},!0),e.addEventListener("keydown",r=>{xe?.fid===t&&(r.stopImmediatePropagation(),r.key==="Enter"&&!r.shiftKey&&!r.isComposing?(r.preventDefault(),ni(!0)):r.key==="Escape"&&(r.preventDefault(),ni(!1)))},!0);for(const r of["keyup","keypress"])e.addEventListener(r,c=>{xe?.fid===t&&(c.stopImmediatePropagation(),c.key===" "&&r==="keyup"&&c.preventDefault())},!0)}const Qc='<svg class="qi" viewBox="0 0 16 16"><path d="M2 4.5V3h7v1.5M5.5 3v10M4 13h3"/><path d="M10 8.5V8h4.5v.5M12.25 8v5M11.25 13h2"/></svg>',Jc='<svg class="qi" viewBox="0 0 16 16"><path d="M3 13V8a5 5 0 0 1 5-5h5"/><path d="M3 13h.01M13 3h.01" stroke-width="2.2"/></svg>',ae=document.createElement("div");ae.id="quick",ae.hidden=!0;{const e=()=>document.body.classList.toggle("card-open",!z.hidden||!H.hidden);for(const t of[z,H])new MutationObserver(e).observe(t,{attributes:!0,attributeFilter:["hidden"]})}document.body.appendChild(ae);let O=null;const ai=e=>{const t=/rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+))?/.exec(e||"");return!t||t[4]!=null&&+t[4]==0?"":"#"+[t[1],t[2],t[3]].map(n=>Math.round(+n).toString(16).padStart(2,"0")).join("")};function bt(){const e=x?.els.length===1?x.els[0]:null;if(!x||X){ae.hidden=!0,O=null;return}if(!e){ae.innerHTML=`<span class="q-count">${x.els.length} selected</span><span class="q-sep"></span><button class="q-btn" data-q="comment" title="Comment on these">${A("comment")}</button>`,ae.hidden=!1,O=null,Bt();return}const t=x.frameId,n=e.ownerDocument.defaultView.getComputedStyle(e);if(O?.el!==e&&(O={fid:t,el:e,sel:Dt(e),pending:{},text:null,held:!1,t:null,desc:ta(e)}),!$()){ae.innerHTML=`<button class="q-btn" data-q="comment" title="Comment on this">${A("comment")}</button>`,ae.hidden=!1,Bt();return}const a=(s,o,r)=>`<button class="q-sw${r?"":" none"}" data-pick="${s}" data-val="${r}" title="${o} colour"><i style="${r?`background:${r}`:""}"></i><span>${o}</span></button>`,i=(s,o,r,c)=>`<div class="q-num" title="${r}"><span class="q-scrub" data-scrub="${s}" title="Drag to change ${r.toLowerCase()}">${o}</span><input type="text" inputmode="numeric" data-q="${s}" value="${Math.round(parseFloat(c)||0)}"></div>`;ae.innerHTML=`${xn(e,!0)?`<button class="q-btn" data-q="text" title="Edit the text (or double-click it)">${A("edit")}</button><span class="q-sep"></span>`:""}
86
+ ${a("color","Text",ai(n.color))}${a("background-color","Fill",ai(n.backgroundColor))}${a("border-color","Border",parseFloat(n.borderTopWidth)?ai(n.borderTopColor):"")}
87
+ <span class="q-sep"></span>${i("font-size",Qc,"Text size",n.fontSize)}${i("border-radius",Jc,"Corner radius",n.borderTopLeftRadius)}
88
+ <span class="q-sep"></span><button class="q-btn" data-q="comment" title="Comment on this (for the agent)">${A("comment")}</button><button class="q-btn" data-q="delete" title="Delete (\u232B)">${A("trash")}</button><span class="q-note"></span>`,ae.hidden=!1,$n(),Bt()}function Bt(){if(ae.hidden||!x)return;const e=x.frameId,t=x.els[x.els.length-1],n=D.get(e);if(!n||!t?.isConnected)return;const a=n.iframe.getBoundingClientRect(),i=t.getBoundingClientRect(),s=b.z,o=a.left+i.left*s,r=a.top+i.top*s,c=a.top+i.bottom*s,l=ae.offsetWidth,d=ae.offsetHeight;let u=r-d-8;u<60&&(u=c+8),u+d>innerHeight-76&&(u=Math.max(60,r+8)),ae.style.left=`${Math.round(Math.max(12,Math.min(o,innerWidth-l-12)))}px`,ae.style.top=`${Math.round(u)}px`}function $n(e){const t=ae.querySelector(".q-note");if(!t||!O)return;const n=f.frames.find(i=>i.id===O.fid)?.kind==="folder",a=Object.keys(O.pending).length+(O.text?1:0);t.innerHTML=e?`<span>${L(e)}</span>`:(O.held||!n)&&a?`<span>Only on screen</span><button class="q-send" data-q="send" title="Loop can't change this in the code by itself. Ask the agent to make it real">Send to agent</button>`:"",Bt()}function Ln(e,t){if(!O)return;const{el:n}=O,a=(s,o)=>{n.style.setProperty(s,o),O.pending[s]=o};if(!O.base){const s=O,o=n.getAttribute("style");O.base=!0,setTimeout(()=>{s.base=!1},1500),(s.held||f.frames.find(r=>r.id===s.fid)?.kind!=="folder")&&G("Edited style",()=>{o==null?s.el.removeAttribute("style"):s.el.setAttribute("style",o),s.pending={},Pe(),O===s&&bt()},()=>{})}e==="border-color"&&!parseFloat(n.ownerDocument.defaultView.getComputedStyle(n).borderTopWidth)&&(a("border-width","1px"),a("border-style","solid")),a(e,t),Pe();const i=f.frames.find(s=>s.id===O.fid)?.kind==="folder";clearTimeout(O.t),i?O.t=setTimeout(hr,380):$n()}async function hr(){const e=O;if(!e||!Object.keys(e.pending).length)return;const t=e.pending;e.pending={};const n=e.el.isConnected?await We(e.fid,e.el):null;if(!n){e.pending={...t,...e.pending},e.held=!0,O===e&&$n();return}const{src:a,N:i}=n,s=i.attrs.find(l=>l.name==="style"),o=new Map;for(const l of(s?.value||"").split(";")){const d=l.indexOf(":");d>0&&o.set(l.slice(0,d).trim().toLowerCase(),l.slice(d+1).trim())}for(const[l,d]of Object.entries(t))o.set(l,d);"background-color"in t&&o.get("background")==="none"&&o.delete("background");const r=[...o].map(([l,d])=>`${l}: ${d}`).join("; ").replace(/"/g,"'");let c;if(s&&s.va>=0&&s.q)c={a:s.va,b:s.vb,before:a.slice(s.va,s.vb),text:s.q==='"'?r:r.replace(/'/g,'"')};else if(s)c={a:s.a,b:s.b,before:a.slice(s.a,s.b),text:`style="${r}"`};else{const l=a[i.openEnd-2]==="/"?i.openEnd-2:i.openEnd-1;c={a:l,b:l,before:"",text:` style="${r}"`}}try{await lt(e.fid,[c],"Edited style"),O===e&&$n("Saved")}catch(l){y(l.message)}}async function ed(e){const t=Object.entries(e.pending).map(([a,i])=>`${a}: ${i}`).join("; "),n=[e.text&&`Change this text from "${e.text.from.slice(0,300)}" to "${e.text.to.slice(0,600)}".`,t&&`Set these on this element: ${t}.`].filter(Boolean);n.length&&(e.pending={},e.text=null,e.held=!1,Ve(),await mr(e.fid,e.el,e.desc,`${n.join(" ")} Make it in the source and change nothing else.`))}ae.addEventListener("pointerdown",e=>e.stopPropagation()),ae.addEventListener("input",e=>{const t=e.target.closest("[data-q]");if(!(!t||!O)&&t.type==="color"){const n=t.closest(".q-sw");n.classList.remove("none"),n.querySelector("i").style.background=t.value,Ln(t.dataset.q,t.value)}}),ae.addEventListener("change",e=>{const t=e.target.closest("input[data-q]");t&&t.value.trim()!==""&&!isNaN(+t.value)&&Ln(t.dataset.q,`${Math.max(0,Math.min(400,Math.round(+t.value)))}px`)}),ae.addEventListener("keydown",e=>{if(e.stopPropagation(),(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="z"){e.preventDefault(),e.target.blur?.(),e.shiftKey?Qn():Va();return}if(e.key==="Escape")return e.target.blur?.(),Ve();if(e.key==="Enter")return e.target.blur?.();const t=e.target.closest("input[data-q]");t&&(e.key==="ArrowUp"||e.key==="ArrowDown")&&(e.preventDefault(),t.value=Math.max(0,Math.min(400,(parseInt(t.value)||0)+(e.key==="ArrowUp"?1:-1)*(e.shiftKey?10:1))),Ln(t.dataset.q,`${t.value}px`))}),ae.addEventListener("pointerdown",e=>{const t=e.target.closest("[data-scrub]");if(!t||!O)return;e.preventDefault();const n=t.parentElement.querySelector("input"),a=parseInt(n.value)||0,i=e.clientX;t.setPointerCapture(e.pointerId),document.body.classList.add("scrubbing");const s=r=>{const c=Math.max(0,Math.min(400,Math.round(a+(r.clientX-i)/2*(r.shiftKey?10:1))));String(c)!==n.value&&(n.value=c,Ln(t.dataset.scrub,`${c}px`))},o=()=>{t.removeEventListener("pointermove",s),document.body.classList.remove("scrubbing")};t.addEventListener("pointermove",s),t.addEventListener("pointerup",o,{once:!0}),t.addEventListener("pointercancel",o,{once:!0})}),ae.addEventListener("click",e=>{const t=e.target.closest("[data-pick]");if(t&&O)return ii(t);const n=e.target.closest("button[data-q]");if(!n)return;if(n.dataset.q==="comment")return ea();if(n.dataset.q==="delete")return ms();const a=e.target.closest("[data-pick]");if(a&&O)return ii(a);if(O)if(n.dataset.q==="text"){const{fid:i,el:s}=O;kn(i,s)}else n.dataset.q==="send"&&ed(O)});const Ce=document.createElement("div");Ce.id="cpick",Ce.hidden=!0,document.body.appendChild(Ce);let Q=null;const td=(e,t,n)=>{const a=i=>{const s=(i+e/60)%6;return n-n*t*Math.max(0,Math.min(s,4-s,1))};return[a(5),a(3),a(1)].map(i=>Math.round(i*255))},nd=e=>"#"+e.map(t=>t.toString(16).padStart(2,"0")).join("");function ps(e){const t=/^#?([0-9a-f]{6})$/i.exec(e||"");if(!t)return{h:0,s:0,v:1};const n=parseInt(t[1],16),a=(n>>16&255)/255,i=(n>>8&255)/255,s=(n&255)/255,o=Math.max(a,i,s),r=o-Math.min(a,i,s);return{h:r?o===a?((i-s)/r+6)%6*60:o===i?((s-a)/r+2)*60:((a-i)/r+4)*60:0,s:o?r/o:0,v:o}}function ad(e){const t=new Map;for(const n of[...e.body.querySelectorAll("*")].slice(0,1500)){const a=e.defaultView.getComputedStyle(n);for(const i of[a.color,a.backgroundColor,a.borderTopWidth!=="0px"?a.borderTopColor:""]){const s=ai(i);s&&t.set(s,(t.get(s)||0)+1)}}return[...t].sort((n,a)=>a[1]-n[1]).slice(0,14).map(n=>n[0])}function ii(e){if(Q?.btn===e)return Ft();Ft();const t=e.dataset.val||"#ffffff";Q={prop:e.dataset.pick,btn:e,...ps(t)};const n=(()=>{try{return ad(O.el.ownerDocument)}catch{return[]}})();Ce.innerHTML=`<div class="cp-sv"><i></i></div><div class="cp-hue"><i></i></div>
80
89
  <div class="cp-row"><span class="cp-now"></span><input class="cp-hex" spellcheck="false" maxlength="7">${e.dataset.pick==="frame-fill"?'<button class="cp-none" title="No fill: the frame shows the canvas behind it">No fill</button>':e.dataset.pick==="background-color"?'<button class="cp-none" title="No fill: whatever is behind it shows through">No fill</button>':e.dataset.pick==="border-color"?'<button class="cp-none" title="Remove the border">No border</button>':""}</div>
81
- ${n.length?`<div class="cp-label">On this page</div><div class="cp-used">${n.map(r=>`<button data-c="${r}" style="background:${r}" title="${r}"></button>`).join("")}</div>`:""}`,be.hidden=!1,Ri(!0);const i=e.getBoundingClientRect(),s=be.offsetWidth,a=be.offsetHeight;let o=i.bottom+8;o+a>innerHeight-12&&(o=i.top-a-8),be.style.left=`${Math.round(Math.max(12,Math.min(i.left-8,innerWidth-s-12)))}px`,be.style.top=`${Math.round(Math.max(12,o))}px`,e.classList.add("on")}function Ht(){G&&(G.prop==="frame-fill"&&Do(),G.btn?.classList.remove("on"),G=null,be.hidden=!0)}let zt=null;function zo(e){const t=u.frames.find(n=>n.id===I);t&&((!zt||zt.id!==t.id)&&(zt={id:t.id,before:t.fill||null}),t.fill=e,Q(t),clearTimeout(zt.t),zt.t=setTimeout(()=>w("PATCH",`/__loop/api/frames/${t.id}`,{fill:e}).catch(n=>b(n.message)),250))}function Do(){const e=zt;if(zt=null,!e)return;const t=u.frames.find(s=>s.id===e.id),n=t?.fill||null;if(n===e.before)return;const i=s=>{const a=u.frames.find(o=>o.id===e.id);return a&&(a.fill=s||void 0,Q(a),He()),w("PATCH",`/__loop/api/frames/${e.id}`,{fill:s})};Z("Frame fill",()=>i(e.before),()=>i(n))}function Ri(e){if(!G)return;const t=dc(cc(G.h,G.s,G.v));be.querySelector(".cp-sv").style.background=`linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(${G.h}, 100%, 50%))`,Object.assign(be.querySelector(".cp-sv i").style,{left:`${G.s*100}%`,top:`${(1-G.v)*100}%`,background:t}),Object.assign(be.querySelector(".cp-hue i").style,{left:`${G.h/360*100}%`,background:`hsl(${G.h}, 100%, 50%)`}),be.querySelector(".cp-now").style.background=t;const n=be.querySelector(".cp-hex");if(document.activeElement!==n&&(n.value=t.toUpperCase()),e)return;const i=G.btn;if(i.classList.remove("none"),i.querySelector("i").style.background=t,i.dataset.val=t,G.prop==="frame-fill"){const s=i.querySelector("span");return s&&(s.textContent=t.toUpperCase()),zo(t)}hn(G.prop,t)}be.addEventListener("pointerdown",e=>{e.stopPropagation();const t=e.target.closest(".cp-sv, .cp-hue");if(!t||!G)return;e.preventDefault(),t.setPointerCapture(e.pointerId);const n=s=>{const a=t.getBoundingClientRect(),o=Math.max(0,Math.min(1,(s.clientX-a.left)/a.width)),r=Math.max(0,Math.min(1,(s.clientY-a.top)/a.height));t.classList.contains("cp-hue")?G.h=o*360:(G.s=o,G.v=1-r),Ri()};n(e);const i=()=>t.removeEventListener("pointermove",n);t.addEventListener("pointermove",n),t.addEventListener("pointerup",i,{once:!0})}),be.addEventListener("click",e=>{if(e.target.closest(".cp-none")&&G?.prop==="frame-fill"){zo("none"),Ht(),He();return}if(e.target.closest(".cp-none")&&G){const n=G.btn,i=G.prop==="border-color";hn(i?"border-style":"background","none"),n.classList.add("none"),n.dataset.val="",n.querySelector("i").style.background="",Ht();return}const t=e.target.closest("[data-c]");t&&G&&(Object.assign(G,Ys(t.dataset.c)),Ri())}),be.addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Escape"&&Ht(),(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="z"&&(e.preventDefault(),e.target.blur?.(),e.shiftKey?Nn():_i())}),be.addEventListener("input",e=>{if(!e.target.classList.contains("cp-hex")||!G)return;const t=e.target.value.trim(),n=/^#?([0-9a-f]{6})$/i.exec(t);n&&(Object.assign(G,Ys("#"+n[1])),Ri())}),addEventListener("pointerdown",e=>{G&&!e.target.closest("#cpick, [data-pick]")&&Ht()},!0);async function Oo(){if(!$||!k())return;const{frameId:e,els:t}=$,n=[],i=[];for(const r of t){const l=r.isConnected?await ze(e,r):null;if(l){const{src:c,N:f}=l;let d=f.a,p=f.b;const h=c.lastIndexOf(`
82
- `,d-1)+1,g=c.indexOf(`
83
- `,p);/^[ \t]*$/.test(c.slice(h,d))&&/^[ \t]*$/.test(c.slice(p,g<0?c.length:g))&&(d=h,p=g<0?c.length:g+1),n.push({a:d,b:p,before:c.slice(d,p),text:""})}else i.push(r)}n.sort((r,l)=>r.a-l.a||l.b-r.b);const s=n.filter((r,l)=>!n.slice(0,l).some(c=>c.a<=r.a&&c.b>=r.b)),a=t.map(Ii),o=t.length===1?rt(t[0]):`${t.length} layers`;if(Ye(),i.length){const r=i.map(l=>[l,l.parentNode,l.nextSibling]);i.forEach(l=>l.remove()),Z(`Delete ${o}`,()=>r.forEach(([l,c,f])=>c?.insertBefore(l,f)),()=>{}),uc(e,i[0],a)}if(s.length)try{await Je(e,s,`Delete ${o}`)}catch(r){b(r.message)}}function uc(e,t,n){const i=document.createElement("div");i.id="del-ask",i.innerHTML="<span>This is drawn by the page's own script, so it's only hidden for now</span><button>Have the agent remove it</button>",document.querySelector("#del-ask")?.remove(),document.body.appendChild(i),i.querySelector("button").onclick=async()=>{i.remove(),await Io(e,t,n[0],`Remove ${n.length===1?"this element":`these ${n.length} elements`} from the page, in the source. Change nothing else.`)},setTimeout(()=>i.remove(),8e3)}function pc(e){if($?.frameId!==e||!O||O.fid!==e)return;const t=le(e);if(!t||t.location.href==="about:blank"||!t.body?.children.length)return;const n=t.querySelector(O.sel);if(!n)return ne();const i=O.pending;$.els=[n],O.el=n;for(const[s,a]of Object.entries(i))n.style.setProperty(s,a);Ae(),qt()}function Ks(e){if(e=e.filter(t=>u.frames.find(n=>n.id===t)),e.length===1)return ie(e[0]);I=null,K.clear(),e.forEach(t=>K.add(t));for(const t of u.frames)Q(t);He(),Wn()}function mc(e){const t=new Set(K.size?K:I?[I]:[]);t.has(e)?t.delete(e):t.add(e),Ks([...t])}const Vs=e=>{const t=Math.min(...e.map(i=>i.x)),n=Math.min(...e.map(i=>i.y));return{x:t,y:n,w:Math.max(...e.map(i=>i.x+i.w))-t,h:Math.max(...e.map(i=>i.y+i.h))-n}};async function xe(e){for(const[t,n]of Object.entries(e)){const i=u.frames.find(s=>s.id===t);i&&(Object.assign(i,n),Q(i))}gn(),Sn(),await Promise.all(Object.entries(e).map(([t,n])=>w("PATCH",`/__loop/api/frames/${t}`,n)))}const Ro={KeyA:"left",KeyD:"right",KeyW:"top",KeyS:"bottom",KeyH:"hcenter",KeyV:"vcenter"};function No(e){const t=[...K].map(o=>u.frames.find(r=>r.id===o)).filter(Boolean);if(t.length<2)return;const n=Vs(t),i={},s={};for(const o of t)i[o.id]={x:o.x,y:o.y};if(e==="hdist"||e==="vdist")return gc(e,t,n,i);ge=null,Ni();for(const o of t){const r={...i[o.id]};e==="left"?r.x=n.x:e==="right"?r.x=n.x+n.w-o.w:e==="hcenter"?r.x=Math.round(n.x+n.w/2-o.w/2):e==="top"?r.y=n.y:e==="bottom"?r.y=n.y+n.h-o.h:e==="vcenter"&&(r.y=Math.round(n.y+n.h/2-o.h/2)),s[o.id]=r}xe(s);const a={left:"Align left",right:"Align right",hcenter:"Align centres",top:"Align top",bottom:"Align bottom",vcenter:"Align middles",hdist:"Distribute horizontally",vdist:"Distribute vertically"}[e];Z(a,()=>xe(i),()=>xe(s))}async function hc(e){const t=e.map(_t).filter(Boolean);await Promise.all(e.map(i=>w("DELETE",`/__loop/api/frames/${i}`)));const n={frames:t.flatMap(i=>i.frames),comments:t.flatMap(i=>i.comments)};Z(`Delete ${e.length} frames`,()=>je(n),()=>Promise.all(e.map(i=>w("DELETE",`/__loop/api/frames/${i}`)))),K.clear(),Wn(),b(`Deleted ${e.length} frames \u2014 \u2318Z to undo`,2600)}let ge=null;function gc(e,t,n,i){const s=e==="hdist"?"x":"y",a=e==="hdist"?"w":"h",o=[...t].sort((c,f)=>c[s]-f[s]);let r=((s==="x"?n.w:n.h)-o.reduce((c,f)=>c+f[a],0))/Math.max(1,o.length-1);r<40&&(r=80),ge={k:s,size:a,ids:o.map(c=>c.id),start:o[0][s],before:i,after:null,gap:Math.round(r)};const l=ge;Yt(l.gap,!0),Z(e==="hdist"?"Distribute horizontally":"Distribute vertically",()=>xe(l.before),()=>xe(l.after)),Ni()}function yc(e){const t=ge,n={};let i=t.start;for(const s of t.ids){const a=u.frames.find(o=>o.id===s);a&&(n[s]={...t.before[s],[t.k]:Math.round(i)},i+=a[t.size]+e)}return n}function Yt(e,t){if(!ge)return;e=Math.max(0,Math.round(e)),ge.gap=e;const n=yc(e);if(t)ge.after=n,xe(n);else{for(const[o,r]of Object.entries(n)){const l=u.frames.find(c=>c.id===o);l&&(Object.assign(l,r),Q(l))}gn(),Sn()}const i=m("#align-bar"),s=i.querySelector(".ab-range"),a=i.querySelector(".ab-val");s&&(s.max=Math.max(800,e*2),s.value=e),a&&document.activeElement!==a&&(a.value=e)}function Ni(){const e=m("#align-bar").querySelector(".ab-spacing");if(!e||(e.hidden=!ge,!ge))return;e.querySelector(".ab-scrub").innerHTML=ge.k==="x"?'<svg viewBox="0 0 24 24"><path d="M3 12h18M7 8l-4 4 4 4M17 8l4 4-4 4"/></svg>':'<svg viewBox="0 0 24 24"><path d="M12 3v18M8 7l4-4 4 4M8 17l4 4 4-4"/></svg>';const t=e.querySelector(".ab-range"),n=e.querySelector(".ab-val");t.max=Math.max(800,ge.gap*2),t.value=ge.gap,document.activeElement!==n&&(n.value=ge.gap),gn()}const vc={left:'<path d="M4 3v18"/><rect x="7" y="6" width="11" height="4" rx="1"/><rect x="7" y="14" width="7" height="4" rx="1"/>',hcenter:'<path d="M12 3v18"/><rect x="5" y="6" width="14" height="4" rx="1"/><rect x="8" y="14" width="8" height="4" rx="1"/>',right:'<path d="M20 3v18"/><rect x="6" y="6" width="11" height="4" rx="1"/><rect x="10" y="14" width="7" height="4" rx="1"/>',top:'<path d="M3 4h18"/><rect x="6" y="7" width="4" height="11" rx="1"/><rect x="14" y="7" width="4" height="7" rx="1"/>',vcenter:'<path d="M3 12h18"/><rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="8" width="4" height="8" rx="1"/>',bottom:'<path d="M3 20h18"/><rect x="6" y="6" width="4" height="11" rx="1"/><rect x="14" y="10" width="4" height="7" rx="1"/>',hdist:'<path d="M4 4v16M20 4v16"/><rect x="9" y="7" width="6" height="10" rx="1"/>',vdist:'<path d="M4 4h16M4 20h16"/><rect x="7" y="9" width="10" height="6" rx="1"/>'},bc={left:"Align left (\u2325A)",hcenter:"Align horizontal centres (\u2325H)",right:"Align right (\u2325D)",top:"Align top (\u2325W)",vcenter:"Align vertical centres (\u2325V)",bottom:"Align bottom (\u2325S)",hdist:"Distribute horizontally",vdist:"Distribute vertically"};function Wn(){const e=m("#align-bar");if(!u||K.size<2||!k()||X){e.hidden=!0;return}if(!e.dataset.ready){e.innerHTML='<span class="ab-count"></span><span class="ab-sep"></span>'+["left","hcenter","right","|","top","vcenter","bottom","|","hdist","vdist"].map(s=>s==="|"?'<span class="ab-sep"></span>':`<button data-align="${s}" title="${bc[s]}"><svg viewBox="0 0 24 24">${vc[s]}</svg></button>`).join("")+'<span class="ab-spacing" hidden><span class="ab-sep"></span><span class="ab-scrub" title="Drag left or right to change the spacing"></span><input class="ab-range" type="range" min="0" max="800" step="1" title="Drag to spread them out or pull them closer"><label class="ab-num" title="Space between frames"><input class="ab-val" inputmode="numeric"><small>px</small></label></span>';const t=e.querySelector(".ab-range"),n=e.querySelector(".ab-val"),i=e.querySelector(".ab-scrub");t.addEventListener("input",()=>Yt(+t.value,!1)),t.addEventListener("change",()=>Yt(+t.value,!0)),n.addEventListener("keydown",s=>{s.stopPropagation(),s.key==="Enter"&&(Yt(+n.value||0,!0),n.blur()),s.key==="Escape"&&n.blur()}),n.addEventListener("change",()=>Yt(+n.value||0,!0)),i.addEventListener("pointerdown",s=>{if(!ge)return;s.preventDefault(),i.setPointerCapture(s.pointerId);const a=s.clientX,o=ge.gap,r=c=>Yt(o+(c.clientX-a)*2,!1),l=()=>{i.removeEventListener("pointermove",r),i.removeEventListener("pointerup",l),Yt(ge.gap,!0)};i.addEventListener("pointermove",r),i.addEventListener("pointerup",l)}),e.addEventListener("pointerdown",s=>s.stopPropagation()),e.addEventListener("click",s=>{const a=s.target.closest("[data-align]");a&&No(a.dataset.align)}),e.dataset.ready="1"}e.querySelector(".ab-count").textContent=`${K.size} frames`,e.querySelectorAll('[data-align$="dist"]').forEach(t=>t.disabled=K.size<2),ge&&(ge.ids.length!==K.size||ge.ids.some(t=>!K.has(t)))&&(ge=null),Ni(),e.hidden=!1,gn()}function gn(){const e=m("#align-bar");if(e.hidden||K.size<2||!u)return;const t=[...K].map(o=>u.frames.find(r=>r.id===o)).filter(Boolean).map(Oe);if(!t.length)return;const n=Vs(t),i=y.x+(n.x+n.w/2)*y.z,s=y.y+n.y*y.z-34,a=e.offsetWidth||360;e.style.left=`${Math.max(12,Math.min(i-a/2,innerWidth-a-12))}px`,e.style.top=`${Math.max(60,s-46)}px`}const Bo=6,Bi=e=>[e.x,e.x+e.w/2,e.x+e.w],Fi=e=>[e.y,e.y+e.h/2,e.y+e.h];function Fo(e){const t=e instanceof Set?e:new Set([e]);return u.frames.filter(n=>!t.has(n.id)).map(n=>Oe(n))}function yn(e,t,n){let i=null;for(const s of e)for(const a of t){const o=a-s;Math.abs(o)<=n&&(!i||Math.abs(o)<Math.abs(i.d))&&(i={d:o,at:a})}return i}function Wo(e,t,n,i){const s=[],a=[e,...t],o=.5/y.z;if(n){const r=a.filter(l=>Bi(l).some(c=>Math.abs(c-n.at)<o));s.push({x1:n.at,y1:Math.min(...r.map(l=>l.y)),x2:n.at,y2:Math.max(...r.map(l=>l.y+l.h))})}if(i){const r=a.filter(l=>Fi(l).some(c=>Math.abs(c-i.at)<o));s.push({x1:Math.min(...r.map(l=>l.x)),y1:i.at,x2:Math.max(...r.map(l=>l.x+l.w)),y2:i.at})}return s}function Xs(e,t){const n=Fo(t),i=Bo/y.z,s=yn(Bi(e),n.flatMap(Bi),i),a=yn(Fi(e),n.flatMap(Fi),i),o={...e,x:e.x+(s?.d||0),y:e.y+(a?.d||0)};return{dx:s?.d||0,dy:a?.d||0,guides:Wo(o,n,s,a)}}function wc(e,t,n="se"){const i=Fo(t),s=Bo/y.z,a=i.flatMap(Bi),o=i.flatMap(Fi),r={...e};let l=null,c=null;return n.includes("e")?(l=yn([e.x+e.w],a,s),l&&(r.w=e.w+l.d)):n.includes("w")&&(l=yn([e.x],a,s),l&&(r.x=e.x+l.d,r.w=e.w-l.d)),n.includes("s")?(c=yn([e.y+e.h],o,s),c&&(r.h=e.h+c.d)):n.includes("n")&&(c=yn([e.y],o,s),c&&(r.y=e.y+c.d,r.h=e.h-c.d)),{rect:r,guides:Wo(r,i,l,c)}}function vt(e){const t=m("#guides");t.innerHTML=e.map(n=>`<line x1="${n.x1}" y1="${n.y1}" x2="${n.x2}" y2="${n.y2}"/>`).join("")}const Wi=T("freeze");function xc(e){const t=H.get(e),n=le(e);if(!t||t.parked||!n?.documentElement||n.location.href==="about:blank")throw new Error("Bring the frame into view first, so it is loaded");const i=t.iframe.contentWindow,s=x=>{try{const M=new URL(x,n.baseURI);return M.origin===location.origin?M.pathname+M.search+M.hash:M.href}catch{return x}},a=(x,M)=>x.replace(/url\(\s*(['"]?)([^'")]+)\1\s*\)/g,(C,B,P)=>/^(data:|blob:|#)/.test(P)?C:`url("${s(new URL(P,M).href)}")`);let o="";const r=(x,M=0)=>{let C;try{C=x.cssRules}catch{x.href&&(o+=`@import url("${s(x.href)}");
84
- `);return}if(x.disabled||!C)return;const B=x.media?.mediaText;B&&M===0&&x.ownerNode?.tagName==="LINK"&&(o+=`@media ${B} {
85
- `);for(const P of C)P.type===CSSRule.IMPORT_RULE&&P.styleSheet&&M<4?r(P.styleSheet,M+1):o+=a(P.cssText,x.href||n.baseURI)+`
86
- `;B&&M===0&&x.ownerNode?.tagName==="LINK"&&(o+=`}
87
- `)};for(const x of[...n.styleSheets,...n.adoptedStyleSheets||[]])r(x);const l=n.documentElement.cloneNode(!0),c=n.querySelectorAll("input, textarea, select"),f=l.querySelectorAll("input, textarea, select");c.forEach((x,M)=>{const C=f[M];C&&(x.tagName==="TEXTAREA"?C.textContent=x.value:x.tagName==="SELECT"?[...x.options].forEach((B,P)=>C.options[P]?.toggleAttribute("selected",B.selected)):/^(checkbox|radio)$/.test(x.type)?C.toggleAttribute("checked",x.checked):/^(password|file)$/.test(x.type)||C.setAttribute("value",x.value))});const d=n.querySelectorAll("canvas"),p=l.querySelectorAll("canvas");d.forEach((x,M)=>{const C=n.createElement("img");for(const P of p[M].attributes)C.setAttribute(P.name,P.value);try{C.src=x.toDataURL("image/png")}catch{}const B=x.getBoundingClientRect();x.getAttribute("style")||C.setAttribute("style",`width:${B.width}px;height:${B.height}px`),p[M].replaceWith(C)});const h=n.documentElement.querySelectorAll("*"),g=l.querySelectorAll("*");h.length===g.length&&h.forEach((x,M)=>{(x.scrollTop||x.scrollLeft)&&g[M].setAttribute("data-loop-scroll",`${x.scrollLeft},${x.scrollTop}`)}),l.querySelectorAll('script, noscript, base, link[rel="stylesheet"], link[rel="preload"], link[rel="modulepreload"], link[rel="prefetch"], style').forEach(x=>x.remove()),l.querySelectorAll("*").forEach(x=>{for(const M of[...x.attributes])(/^on/i.test(M.name)||/^(href|src|action)$/i.test(M.name)&&/^\s*javascript:/i.test(M.value))&&x.removeAttribute(M.name)});let v=l.querySelector("head");v||(v=n.createElement("head"),l.prepend(v));const S=i.location.pathname+i.location.search,A=`scrollTo(${Math.round(i.scrollX)},${Math.round(i.scrollY)});document.querySelectorAll('[data-loop-scroll]').forEach(e=>{const[x,y]=e.dataset.loopScroll.split(',');e.scrollLeft=+x;e.scrollTop=+y});addEventListener('click',e=>{if(e.target.closest('a[href]'))e.preventDefault()},true);addEventListener('submit',e=>e.preventDefault(),true)`;return v.insertAdjacentHTML("afterbegin",`<meta charset="utf-8"><base href="${L(S)}"><meta name="loop-frozen" content="${Date.now()}"><style>${o.replace(/<\/style/gi,"<\\/style")}</style>`),l.querySelector("body")?.insertAdjacentHTML("beforeend",`<script>addEventListener('load',()=>{${A}})<\/script>`),`<!doctype html>
88
- `+l.outerHTML}async function ji(e){const t=u.frames.find(i=>i.id===e);if(!t)return;if(t.kind==="frozen")return b("This frame is already frozen");let n;try{n=xc(e)}catch(i){return b(i.message)}try{const i=await w("POST",`/__loop/api/frames/${e}/freeze`,{html:n,from:si(H.get(e))});let s=null;if(Z("Freeze frame",async()=>{s=_t(i.id)||s,await w("DELETE",`/__loop/api/frames/${i.id}`)},()=>je(s||{frames:[i]})),E)return b("Frozen copy added next to this frame");u.frames.find(a=>a.id===i.id)?(ie(i.id),Tt(i.id)):Ze=i.id,b("Frozen: this copy keeps the screen as it is now")}catch(i){b(i.message)}}async function jo(e){const t=u.frames.find(n=>n.id===e);if(t?.from)try{const n=await w("POST","/__loop/api/frames",{route:t.from,name:t.name.replace(/ · frozen( \d+)?$/,""),w:t.w,h:t.h,near:t.id,dup:!0});u.frames.find(i=>i.id===n.id)?(ie(n.id),Tt(n.id)):Ze=n.id}catch(n){b(n.message)}}const Kt=e=>{const t=Math.min(e.w,e.h),n=Math.max(e.w,e.h);return t>=320&&t<=500&&n>=560&&n<=1e3&&n/t>=1.5},Us=["qwertyuiop","asdfghjkl","zxcvbnm"];function Yo(e,t){const n=e.autoKb,i=Kt(t)&&(!!t.keyboard||!!n);if(e.el.classList.toggle("kb-on",i),!i)return;const s=t.w>t.h,a=n==="num"?"num":"abc";let o=e.el.querySelector(".kb");if(o||(o=document.createElement("div"),o.className="kb",e.el.querySelector(".frame-body").appendChild(o)),o.dataset.kind!==a){o.dataset.kind=a;const r=l=>[...l].map(c=>`<span class="k">${c}</span>`).join("");o.innerHTML=a==="num"?[["1",""],["2","ABC"],["3","DEF"],["4","GHI"],["5","JKL"],["6","MNO"],["7","PQRS"],["8","TUV"],["9","WXYZ"],[".",null],["0",""],["\u232B",null]].reduce((l,c,f)=>((l[Math.floor(f/3)]||=[]).push(c),l),[]).map(l=>`<div class="kb-row">${l.map(([c,f])=>`<span class="k${f==null?" fn plain":""}"><b>${c}</b>${f?`<i>${f}</i>`:""}</span>`).join("")}</div>`).join(""):`<div class="kb-bar"><span>I</span><span>The</span><span>I\u2019m</span></div>
89
- <div class="kb-row">${r(Us[0])}</div><div class="kb-row r2">${r(Us[1])}</div>
90
- <div class="kb-row"><span class="k fn">\u21E7</span>${r(Us[2])}<span class="k fn">\u232B</span></div>
91
- <div class="kb-row"><span class="k fn">123</span><span class="k fn">\u263A</span><span class="k sp">space</span><span class="k fn ret">return</span></div>`}o.classList.toggle("num",a==="num"),o.classList.toggle("land",s)}function kc(e){if(!e||e.disabled||e.readOnly)return null;const t=e.tagName,n=(e.getAttribute?.("type")||"text").toLowerCase(),i=(e.getAttribute?.("inputmode")||"").toLowerCase();return i==="none"?null:t==="TEXTAREA"||e.isContentEditable?"abc":t!=="INPUT"||/^(checkbox|radio|range|button|submit|reset|file|color|date|time|datetime-local|month|week|image|hidden)$/.test(n)?null:/^(numeric|decimal|tel)$/.test(i)||/^(number|tel)$/.test(n)?"num":"abc"}function $c(e,t,n){const i=()=>{const s=u?.frames.find(o=>o.id===n);if(!s||!Kt(s))return;const a=ve?.fid===n?null:kc(e.document.activeElement);t.autoKb!==a&&(t.autoKb=a,Yo(t,s),a&&setTimeout(()=>{try{e.document.activeElement?.scrollIntoView({block:"center",behavior:"smooth"})}catch{}},60),E?.fid===n&&setTimeout(()=>it(n),80))};e.addEventListener("focusin",i),e.addEventListener("focusout",()=>setTimeout(i,0))}async function Yi(e){const t=u.frames.find(i=>i.id===e);if(!t)return;if(!Kt(t))return b("The keyboard is for phone-sized frames");const n=!t.keyboard;try{await w("PATCH",`/__loop/api/frames/${e}`,{keyboard:n}),Z(n?"Show keyboard":"Hide keyboard",()=>w("PATCH",`/__loop/api/frames/${e}`,{keyboard:!n}),()=>w("PATCH",`/__loop/api/frames/${e}`,{keyboard:n}))}catch(i){b(i.message)}}let E=null;const jn=(()=>{try{return new Set(JSON.parse(localStorage.getItem("loop.stageNoDevice")||"[]"))}catch{return new Set}})(),Zs=e=>{const t=Math.min(e.w,e.h),n=Math.max(e.w,e.h);return!Kt(e)&&t>=700&&t<=1100&&n>=1e3&&n<=1400&&n/t>=1.2&&n/t<=1.65&&!(e.w===1280&&e.h===800)},Yn=e=>Kt(e)||Zs(e),Ko=e=>Yn(e)&&!jn.has(e.id);let Vo=0;function et(e,t=420){const n={...y},i=performance.now(),s=++Vo,a=o=>{if(s!==Vo)return;const r=Math.min(1,(o-i)/t),l=r<.5?4*r*r*r:1-Math.pow(-2*r+2,3)/2;y={x:n.x+(e.x-n.x)*l,y:n.y+(e.y-n.y)*l,z:n.z+(e.z-n.z)*l},se(),r<1&&requestAnimationFrame(a)};requestAnimationFrame(a)}function vn(e){const t=Ko(e),n=t?Zs(e)?34:22:0,i=H.get(e.id)?.el.querySelector(":scope > .opt-strip"),s=84+(i?i.offsetHeight+44:0)+(_?.fid===e.id?_.el.offsetHeight+18:0),a=96,r=Math.max(.04,Math.min((innerWidth-40*2)/(e.w+n*2),(innerHeight-s-a)/(e.h+n*2),2)),l=E.zoom==="100"?1:r;return{z:l,x:innerWidth/2-(e.x+e.w/2)*l,y:s+(innerHeight-s-a)/2-(e.y+e.h/2)*l}}function Vt(e){const t=u.frames.find(n=>n.id===e);t&&(E||(E={prev:{...y},zoom:"fit"}),document.querySelectorAll(".frame.staged").forEach(n=>n.classList.remove("staged","device","tablet")),E.fid=e,ie(null),J(),ne(),Va(),Xe(),Pe(),Ye(),Ht(),Y.hidden=!0,ve&&zi(!1),Gn?.(),document.body.classList.add("staging"),Kn(),et(vn(t)),Ie&&Ts(e))}function bt(){if(!E)return;_&&(_.staged=!1,Xe(!0));const e=E.prev;if(document.querySelectorAll(".frame.staged").forEach(t=>t.classList.remove("staged","device","landscape","tablet")),document.body.classList.remove("staging"),m("#stage-bar")?.remove(),E=null,Gs(),de){de=null,ot();for(const t of u.frames)Q(t)}et(e,380)}function Xo(e){return!!e&&Yn(e)&&(E?E.fid===e.id:Ie)}function Gs(){for(const[e,t]of H)try{t.iframe.contentDocument?.documentElement.classList.toggle("loop-touch",Xo(u.frames.find(n=>n.id===e)))}catch{}}function Qs(){return[...u.frames].sort((e,t)=>Math.abs(e.y-t.y)<200?e.x-t.x:e.y-t.y)}function Kn(){const e=u.frames.find(l=>l.id===E.fid);if(!e)return bt();const t=H.get(e.id),n=Zs(e),i=Yn(e),s=Ko(e);t?.el.classList.add("staged"),t?.el.classList.toggle("device",s),t?.el.classList.toggle("tablet",s&&n),t?.el.classList.toggle("landscape",e.w>e.h),Gs();let a=m("#stage-bar");a||(a=document.createElement("div"),a.id="stage-bar",document.body.appendChild(a),a.addEventListener("pointerdown",l=>l.stopPropagation()),a.addEventListener("click",Tc));const o=Qs(),r=o.findIndex(l=>l.id===e.id);a.innerHTML=`
92
- ${i?`<button class="sb-btn${s?" on":""}" data-sb="device" title="Show it inside ${n?"an iPad":"an iPhone"}"><span class="sb-dev${e.w>e.h?" side":""}">${T(n?"tablet":"phone")}</span></button>
93
- ${k()?`<button class="sb-btn" data-sb="rotate" title="Turn it ${e.w>e.h?"upright":"on its side"} (R)">${Cc}</button>`:""}`:""}
94
- ${e.kind!=="frozen"&&k()?`<button class="sb-btn" data-sb="freeze" title="Freeze a copy of it as it is now (\u21E7F)">${Wi}</button>`:""}
95
- ${k()&&["route","url","folder"].includes(e.kind)&&!e.image&&!e.sizeOf?`<button class="sb-btn" data-sb="sizes" title="See it at phone, tablet and desktop size, side by side">${Mc}</button>`:""}
96
- ${k()?'<button class="sb-fit" data-sb="fit" hidden><i></i><span>Doesn\u2019t fit</span><b>Make it fit</b></button>':""}
97
- <button class="sb-exit" data-sb="exit" title="Exit stage (Esc)">${T("x")}<span>Exit</span></button>`;for(const l of[250,900,2e3])setTimeout(Zo,l)}function Uo(e){try{const t=H.get(e.id)?.iframe.contentDocument,n=t?.documentElement;if(!n||!t.body)return 0;const i=Math.max(n.scrollWidth,t.body.scrollWidth)-n.clientWidth;return i>4?Math.round(i):0}catch{return 0}}function Zo(){const e=m("#stage-bar .sb-fit"),t=E&&u.frames.find(i=>i.id===E.fid);if(!e||!t)return;const n=u.live[t.id]||t.kind==="frozen"?0:Uo(t);e.hidden=!n,e.dataset.over=n,e.title=`The page is ${n}px wider than this ${t.w}\xD7${t.h} frame. Ask the agent to make it fit this size.`}async function Lc(){const e=E&&u.frames.find(s=>s.id===E.fid),t=e&&Uo(e);if(!t)return Zo();const n={id:Jn(),frameId:e.id,author:{name:V.name,color:V.color},anchor:Mn(e.id,{scope:"frame",x:0,y:0}),text:`This screen doesn\u2019t fit at ${e.w}\xD7${e.h}: the page runs ${t}px wider than the frame. Make it responsive at this size, and keep it looking the same at the sizes it already works at.`},i=gi(n);try{const s=await w("POST","/__loop/api/comments",n);s?.id&&s.id!==n.id&&i(),m("#stage-bar .sb-fit").hidden=!0,b("Asked the agent to make it fit")}catch(s){i(),b(s.message)}}const Cc='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 3.5v5h-5"/></svg>',Mc='<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="2.5" y="5" width="12" height="9" rx="1.5"/><rect x="12" y="8" width="6" height="10" rx="1.2"/><rect x="17" y="11" width="4.5" height="8" rx="1"/></svg>';async function Ec(e){try{const t=await w("POST",`/__loop/api/frames/${e.id}/sizes`);bt(),setTimeout(()=>Ge(!0,[e.id,...t.frames]),450),t.existing||b("The same screen at the other sizes, live. Comment on whichever one breaks.",3e3)}catch(t){b(t.message)}}async function Go(){const e=E&&u.frames.find(s=>s.id===E.fid);if(!e||!Yn(e)||!k())return;const t={w:e.w,h:e.h,x:e.x,y:e.y},n={w:e.h,h:e.w,x:Math.round(e.x+(e.w-e.h)/2),y:Math.round(e.y+(e.h-e.w)/2)},i=s=>(Object.assign(e,s),Q(e),E?.fid===e.id&&(Kn(),et(vn(e),320)),w("PATCH",`/__loop/api/frames/${e.id}`,s).catch(a=>b(a.message)));Z("Rotate frame",()=>i(t),()=>i(n)),i(n)}function Sc(e){if(!E)return;const t=Qs(),n=t.findIndex(i=>i.id===E.fid);t.length>1&&Vt(t[(n+e+t.length)%t.length].id)}function Tc(e){const t=e.target.closest("[data-sb]");if(!t||!E)return;const n=u.frames.find(o=>o.id===E.fid);if(!n)return;const i=t.dataset.sb,s=Qs(),a=s.findIndex(o=>o.id===n.id);if(i==="exit")return bt();if(i==="prev"||i==="next"){const o=s[(a+(i==="next"?1:-1)+s.length)%s.length];return Vt(o.id)}if(i==="device"){jn.has(n.id)?jn.delete(n.id):jn.add(n.id);try{localStorage.setItem("loop.stageNoDevice",JSON.stringify([...jn]))}catch{}return Kn(),et(vn(n),300)}if(i==="keyboard")return Yi(n.id);if(i==="rotate")return Go();if(i==="fit")return Lc();if(i==="sizes")return Ec(n);if(i==="freeze")return ji(n.id);if(i==="zoom")return E.zoom=E.zoom==="fit"?"100":"fit",Kn(),et(vn(n),320)}addEventListener("keydown",e=>{if(!(!E||Et()||e.metaKey||e.ctrlKey)&&((e.key==="ArrowRight"||e.key==="ArrowLeft")&&(e.preventDefault(),Sc(e.key==="ArrowRight"?1:-1)),e.key.toLowerCase()==="r"&&!e.shiftKey&&!e.altKey)){const t=u.frames.find(n=>n.id===E.fid);t&&Yn(t)&&k()&&(e.preventDefault(),e.stopImmediatePropagation(),Go())}}),addEventListener("resize",()=>{if(E){const e=u.frames.find(t=>t.id===E.fid);e&&(y=vn(e),se())}});const ke=document.createElement("div");ke.id="edge",ke.hidden=!0,document.body.appendChild(ke),ke.innerHTML=`<button class="eg-btn" data-eg="stage">${T("stage")}<span></span></button>`;let Dt=null,Xt=null,Ki=!1,Js=0;const De={x:-1,y:-1},bn=52;function Ot(e){const t=Oe(e),n=y.z;return{l:y.x+t.x*n,t:y.y+t.y*n,w:t.w*n,h:t.h*n}}function Ac(){if(!u)return null;if(E)return E.fid;if(ae||document.body.classList.contains("versions-on"))return null;for(let e=u.frames.length-1;e>=0;e--){const t=Ot(u.frames[e]),n=Math.max(t.t,bn);if(De.x>=t.l-6&&De.x<=t.l+t.w+6&&De.y>=Math.max(t.t-44,0)&&De.y<=Math.min(n+110,t.t+t.h))return u.frames[e].id}return!K.size&&I||de||null}function Vi(){const e=Ac();e?(clearTimeout(Xt),Xt=null,Dt=e):Dt&&!Xt&&!Ki&&(Xt=setTimeout(()=>{Xt=null,Ki||(Dt=null,Vn())},380)),Vn()}function Vn(){const e=Dt&&u?.frames.find(f=>f.id===Dt),t=!1,n=e&&Ot(e);if(!e||E||n.w<72||n.t+n.h<bn+30||n.t>innerHeight-40||n.l>innerWidth-40||n.l+n.w<40){ke.hidden=!0;return}ke.hidden=!1,ke.classList.toggle("exit",t),ke.classList.toggle("compact",!t&&n.w<200);const i=ke.querySelector('[data-eg="stage"]');Le(i.lastChild,t?"Exit stage":"Stage"),i.dataset.tip="Stage: focus on this frame";const s=ke.offsetWidth,a=ke.offsetHeight;let o=n.t-12*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1)-a/2;const r=o<bn;r&&(o=Math.max(n.t+8,bn+4));const l=r?-8:parseFloat(getComputedStyle(i).paddingRight)||0;let c=Math.min(n.l+n.w-s+l,innerWidth-s-12);c=Math.max(c,n.l),ke.classList.toggle("inside",r),ke.style.left=`${Math.round(c)}px`,ke.style.top=`${Math.round(o)}px`;for(const[f,d]of H){const p=d.el.querySelector(":scope > .opt-strip, :scope > .ver-strip");if(!p)continue;const h=u.frames.find(x=>x.id===f);if(!h)continue;const g=Ot(h),v=p.offsetHeight,S=g.t-34-v,A=S<bn+4?Math.min(bn+4-S,Math.max(0,g.h-20)):0;p.style.translate=A?`0 ${A/y.z}px`:""}}addEventListener("pointermove",e=>{De.x=e.clientX,De.y=e.clientY,Nr(),Js||(Js=requestAnimationFrame(()=>{Js=0,Vi()}))},{capture:!0,passive:!0}),ke.addEventListener("pointerenter",()=>{Ki=!0,clearTimeout(Xt),Xt=null}),ke.addEventListener("pointerleave",()=>{Ki=!1,Vi()}),ke.addEventListener("pointerdown",e=>e.stopPropagation()),ke.addEventListener("click",async e=>{!e.target.closest('[data-eg="stage"]')||!Dt||(E?.fid===Dt?bt():Vt(Dt))});const Xi=new Set;function Qo(e,t=0){if(!Xi.has(e)){if((ae||E||N||ve)&&t<40)return setTimeout(()=>Qo(e,t+1),250);setTimeout(()=>{!Xi.has(e)&&u.sections.some(n=>n.id===e)&&(Xi.add(e),Jo(e))},t?0:500)}}function Jo(e){const t=u.sections.find(d=>d.id===e),n=t&&u.comments.find(d=>d.id===t.optionsFor),i=n&&u.frames.find(d=>d.id===n.frameId);if(!t||!i||E||N)return;const s=Math.min(i.x,t.x),a=Math.min(i.y,t.y)-40,o=Math.max(i.x+i.w,t.x+t.w),r=Math.max(i.y+i.h,t.y+t.h),l={x:y.x+s*y.z,y:y.y+a*y.z},c={x:y.x+o*y.z,y:y.y+r*y.z};if(l.x>=0&&l.y>=50&&c.x<=innerWidth&&c.y<=innerHeight-70&&(o-s)*y.z>innerWidth*.45)return;const f=Math.min(1,(innerWidth-160)/(o-s),(innerHeight-240)/(r-a));et({z:f,x:(innerWidth-(o-s)*f)/2-s*f,y:120+(innerHeight-240-(r-a)*f)/2-a*f},520)}function wn(e){const t=y.z;return t<.33||e.w*t<300&&e.h*t<300}let Ui={fid:null,t:0},Ut=null;function _c(e,t){const n=Se&&u.sections.find(s=>s.id===Se),i=n?Un(n).map(s=>s.id):K.size?[...K]:I?[I]:[];if(!i.length&&!n)return!1;Ut||={from:Object.fromEntries(i.map(s=>{const a=u.frames.find(o=>o.id===s);return[s,{x:a.x,y:a.y}]})),sec:n&&{id:n.id,x:n.x,y:n.y}};for(const s of Object.keys(Ut.from)){const a=u.frames.find(o=>o.id===s);a&&(a.x+=e,a.y+=t,Q(a))}return n&&Ut.sec&&(n.x+=e,n.y+=t,Nt()),Ce(),Vn(),Wn(),clearTimeout(Ut.t),Ut.t=setTimeout(()=>{const s=Ut;Ut=null;const a=Object.fromEntries(Object.keys(s.from).map(f=>{const d=u.frames.find(p=>p.id===f);return[f,{x:d.x,y:d.y}]})),o=s.from,r=s.sec&&u.sections.find(f=>f.id===s.sec.id),l=r&&{x:r.x,y:r.y},c=s.sec&&{x:s.sec.x,y:s.sec.y};xe(a),r&&w("PATCH",`/__loop/api/sections/${r.id}`,l).catch(()=>{}),Z("Nudge",()=>Promise.all([xe(o),r&&wt(r.id,c)]),()=>Promise.all([xe(a),r&&wt(r.id,l)]))},400),!0}const Rt=m("#sections"),Xn=new Map;let Se=null,Zi={id:null,t:0};const ea=e=>({...e,...Xn.get(e.id)||{}}),Gi=(e,t)=>{const n=t.x+t.w/2,i=t.y+t.h/2;return n>=e.x&&n<=e.x+e.w&&i>=e.y&&i<=e.y+e.h},Un=e=>u.frames.filter(t=>Gi(e,t));function er(){if(!u)return;const e=y.z,t=(u.sections||[]).map(ea);for(const n of u.frames){const i=H.get(n.id);if(!i)continue;const s=n.w*e,a=Oe(n),o=t.some(r=>Gi(r,a)&&(a.y-r.y)*e<24);i.el.classList.toggle("narrow",s<200),i.el.classList.toggle("noname",s<34||o)}for(const n of t){const i=Rt.querySelector(`.section[data-id="${n.id}"]`);i&&(i.classList.toggle("noname",n.w*e<48),i.classList.remove("lift"))}}function Nt(){const e=u.sections||[],t=new Set(e.map(n=>n.id));Rt.querySelectorAll(".section").forEach(n=>{t.has(n.dataset.id)||n.remove()}),Se&&!t.has(Se)&&(Se=null);for(const n of e){const i=ea(n);let s=Rt.querySelector(`.section[data-id="${i.id}"]`);if(!s){s=document.createElement("div"),s.className="section",s.dataset.id=i.id,s.innerHTML=`<div class="sec-label"><span class="sec-name"></span><button class="sec-more" title="Section options"><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="3.5" cy="8" r="1.3"/><circle cx="8" cy="8" r="1.3"/><circle cx="12.5" cy="8" r="1.3"/></svg></button></div>${["n","s","e","w","ne","nw","se","sw"].map(c=>`<div class="srz rz-${c}" data-dir="${c}"></div>`).join("")}`,Rt.appendChild(s);const r=s.querySelector(".sec-more"),l=i.id;r.addEventListener("pointerdown",c=>c.stopPropagation()),r.addEventListener("click",c=>{c.stopPropagation(),Ic(l,r)})}Object.assign(s.style,{left:`${i.x}px`,top:`${i.y}px`,width:`${i.w}px`,height:`${i.h}px`}),s.style.setProperty("--sw",`${i.w}px`);const a=s.querySelector(".sec-name");a.querySelector("input")||Le(a,i.name),s.classList.toggle("selected",Se===i.id);const o=i.optionsFor&&u.comments.find(r=>r.id===i.optionsFor);s.classList.toggle("making",!!o&&(ci(o.id)==="working"||u.frames.some(r=>r.building&&r.optionOf?.cid===o.id)))}er()}function Qi(e){(I||K.size||de)&&ie(null),Se=e,Nt()}function tr(e,t){const n=u.sections.find(i=>i.id===e);ae={type:"smove",sid:e,sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,moved:!1,from:Object.fromEntries(Un(n).map(i=>[i.id,{x:i.x,y:i.y}]))},q.classList.add("dragging"),q.setPointerCapture(t.pointerId)}function Pc(e,t){const n=u.sections.find(i=>i.id===e);ae={type:"sresize",sid:e,dir:t.target.dataset.dir||"se",sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,w:n.w,h:n.h},q.classList.add("dragging"),q.setPointerCapture(t.pointerId)}function wt(e,t){const n=u.sections.find(i=>i.id===e);return n&&(Object.assign(n,t),Nt()),w("PATCH",`/__loop/api/sections/${e}`,t)}async function qc(e){try{const t=await w("POST","/__loop/api/sections",e);u.sections.find(n=>n.id===t.id)||u.sections.push(t),Z("Add section",()=>w("DELETE",`/__loop/api/sections/${t.id}`),()=>je({sections:[t]})),Qi(t.id)}catch(t){b(t.message)}}const ue=document.createElement("div");ue.id="sec-menu",ue.className="menu",ue.hidden=!0,document.body.appendChild(ue);function Ic(e,t){if(!ue.hidden&&ue._for===e){ue.hidden=!0;return}const n=u.sections.find(l=>l.id===e);if(!n||!k())return;const i=Un(n).length,s=`${i} frame${i===1?"":"s"}`;ue._for=e,ue.innerHTML=i?`<button class="menu-item" data-sm="keep"><span><b>Remove section</b><small>Its ${s} stay${i===1?"s":""} on the canvas</small></span></button>
98
- <button class="menu-item danger" data-sm="all"><span><b>Delete section and its ${s}</b><small>Everything inside it goes too</small></span></button>`:'<button class="menu-item" data-sm="keep"><span><b>Delete section</b><small>It has no frames in it</small></span></button>',ue.hidden=!1;const a=t.getBoundingClientRect(),o=ue.offsetWidth,r=ue.offsetHeight;ue.style.left=`${Math.round(Math.max(12,Math.min(a.left,innerWidth-o-12)))}px`,ue.style.top=`${Math.round(a.bottom+6+r>innerHeight-12?Math.max(12,a.top-r-6):a.bottom+6)}px`}ue.addEventListener("pointerdown",e=>e.stopPropagation()),ue.addEventListener("click",e=>{const t=e.target.closest("[data-sm]");if(!t)return;const n=ue._for;ue.hidden=!0,(t.dataset.sm==="all"?Hc(n):nr(n)).catch(i=>b(i.message))}),addEventListener("pointerdown",e=>{!ue.hidden&&!e.target.closest("#sec-menu, .sec-more")&&(ue.hidden=!0)},!0),addEventListener("keydown",e=>{e.key==="Escape"&&!ue.hidden&&(ue.hidden=!0,e.stopPropagation())},!0);async function Hc(e){const t=u.sections.find(o=>o.id===e);if(!t)return;const n={...t},i=Un(t).map(o=>o.id),s=i.map(_t).filter(Boolean),a=()=>Promise.all([...i.map(o=>w("DELETE",`/__loop/api/frames/${o}`).catch(()=>{})),w("DELETE",`/__loop/api/sections/${e}`).catch(()=>{})]);Se=null,await a(),Z("Delete section and its frames",()=>je({frames:s.flatMap(o=>o.frames),comments:s.flatMap(o=>o.comments),sections:[n]}),a),b(`Deleted \u201C${n.name}\u201D and ${i.length} frame${i.length===1?"":"s"} \xB7 \u2318Z to undo`,2800)}async function nr(e){const t=u.sections.find(i=>i.id===e);if(!t)return;const n={...t};Se=null,await w("DELETE",`/__loop/api/sections/${e}`),Z("Delete section",()=>je({sections:[n]}),()=>w("DELETE",`/__loop/api/sections/${e}`)),b(`Removed \u201C${n.name}\u201D (its frames stay) \xB7 \u2318Z to undo`,2600)}function zc(e){const t=Rt.querySelector(`.section[data-id="${e}"] .sec-name`),n=u.sections.find(o=>o.id===e);if(!t||!n)return;const i=document.createElement("input");i.className="rename",i.value=n.name,t.replaceChildren(i),i.focus(),i.select(),i.addEventListener("pointerdown",o=>o.stopPropagation());let s=!1;const a=o=>{if(s)return;s=!0;const r=i.value.trim(),l=n.name;t.textContent=o&&r?r:l,o&&r&&r!==l&&(wt(e,{name:r}),Z("Rename section",()=>wt(e,{name:l}),()=>wt(e,{name:r})))};i.addEventListener("keydown",o=>{o.stopPropagation(),o.key==="Enter"&&a(!0),o.key==="Escape"&&a(!1)}),i.addEventListener("blur",()=>a(!0))}let _=null;const xn=e=>{const t=Ji(e);return t.length?[...t,{id:"",now:!0,label:t[t.length-1].last,at:Date.now(),thumb:null}]:[]};function ir(e,t){if(_?.fid===e&&t==null)return Xe();Xe();const n=H.get(e),i=u.frames.find(r=>r.id===e);if(!n||!i||!xn(e).length)return;N&&Zt(),Dc(e),ne(),Pe();const s=E?.fid===e;Vt(e);const a=document.createElement("div");a.className="ver-strip top",a.innerHTML='<div class="vt-row"></div><div class="vt-acts"></div>',document.body.appendChild(a),_={fid:e,pin:t??null,hover:null,now:null,el:a,key:"",akey:"",back:null,staged:!s};const o=a.querySelector(".vt-row");a.addEventListener("pointerdown",r=>r.stopPropagation()),o.addEventListener("wheel",r=>{(Math.abs(r.deltaX)>Math.abs(r.deltaY)||r.shiftKey)&&r.stopPropagation()},{passive:!0}),a.addEventListener("click",r=>{const l=r.target.closest("[data-vs]"),c=r.target.closest("[data-v]");if(l)return Oc(l.dataset.vs);c&&(_.pin=c.dataset.v===""||_.pin===c.dataset.v?null:c.dataset.v,_.hover=null,kn(),Zn())}),kn(),Zn(),o.scrollLeft=o.scrollWidth,et(vn(i)),w("POST",`/__loop/api/frames/${e}/versions`).then(r=>{_?.el===a&&(_.now=r.now,kn())}).catch(()=>{})}function Uc(){const e=u.frames.find(o=>o.id===_.fid);if(!e)return;const t=Ot(e),n=64+_.el.offsetHeight+44,i=t.l<12||t.l+Math.min(t.w,_.el.offsetWidth)>innerWidth-12;if(t.t>=n&&t.t<innerHeight-160&&!i)return;const s=y.z,a={z:s,x:i?Math.max(24,(innerWidth-e.w*s)/2)-e.x*s:y.x,y:n-e.y*s};_.back={from:{...y},to:a},et(a,320)}function Dc(e){const t=W&&u.comments.find(n=>n.id===W);t&&t.frameId!==e&&J()}function kn(){if(!_)return;const{fid:e,el:t}=_,n=u.frames.find(f=>f.id===e),i=xn(e);if(!n||!i.length)return Xe();_.pin&&!i.some(f=>f.id===_.pin)&&(_.pin=null);const s=n.w/n.h,a=52,o=Math.round(Math.min(104,Math.max(32,a*s))),r=i.map((f,d)=>{const p=f.now?_.now:f.thumb;return`<button class="vt${(f.now?!_.pin:_.pin===f.id)?" on":""}" data-v="${f.id}"><span class="vt-img" style="width:${o}px;height:${a}px">${p?`<img src="${L(p)}" alt="" draggable="false">`:""}</span><span class="vt-n">${d+1}</span></button>`}).join(""),l=t.querySelector(".vt-row");if(_.key!==r){const f=l.scrollLeft;_.key=r,l.innerHTML=r,l.scrollLeft=f}const c=_.pin&&k()?`<button class="vt-go" data-vs="back" title="Go back to this version (the one you are on is kept)">${T("undo")}<span>Go back</span></button><button class="vt-btn" data-vs="dup" title="Make this version its own frame">${Pn.copy}</button>`:"";if(_.akey!==c){_.akey=c;const f=t.querySelector(".vt-acts");f.innerHTML=c,f.hidden=!c}sr(),Vn()}const Zc=T("layers");function sr(){if(!_)return;const e=xn(_.fid),t=_.hover!=null?_.hover:_.pin,n=t?e.findIndex(o=>o.id===t):e.length-1,i=e[n];if(!i)return;const s=`<b>${i.now?"Now":`v${n+1}`}</b><span>${L(i.label||"")}</span>${i.now?"":`<time>${jt(i.at)}</time>`}`,a=_.el.querySelector(".vt-cap");a&&a._h!==s&&(a._h=s,a.innerHTML=s,a.title=i.label||"")}function Zn(){if(!_)return;sr();const{fid:e}=_,t=H.get(e),n=u.frames.find(p=>p.id===e);if(!t||!n)return;const i=_.hover!=null?_.hover:_.pin,s=t.el.querySelector(".frame-body");let a=s.querySelector(":scope > .ver-prev");const o=i?xn(e).find(p=>p.id===i):null;if(t.el.classList.toggle("previewing",!!o),!o){a&&(a.classList.remove("on"),setTimeout(()=>{a.classList.contains("on")||a.remove()},180));return}a||(a=document.createElement("div"),a.className="ver-prev",a.innerHTML='<img alt="" draggable="false"><iframe title=""></iframe>',s.appendChild(a),a.offsetWidth),a.classList.add("on");const r=a.querySelector("img"),l=a.querySelector("iframe"),c=`/__loop/hist/${o.id}/${encodeURIComponent(n.entry||"index.html")}`;o.thumb?(r.getAttribute("src")!==o.thumb&&(r.src=o.thumb),r.hidden=!1):r.hidden=!0;const f=_.pin===o.id,d=f||!o.thumb;a.classList.toggle("live",f),d?l.dataset.src!==c&&(l.dataset.src=c,l.classList.remove("ready"),a.classList.add("loading"),l.onload=()=>{l.classList.add("ready"),a.classList.remove("loading")},l.src=c):(a.classList.remove("loading"),l.dataset.src&&(l.dataset.src="",l.classList.remove("ready"),l.src="about:blank")),a.classList.toggle("bare",!o.thumb)}function Xe(e){if(!_)return;const{fid:t,el:n,back:i,staged:s}=_;_=null,n.remove(),s&&E?.fid===t&&!e&&setTimeout(()=>{_||bt()},0);const a=H.get(t);a?.el.classList.remove("previewing"),a?.el.querySelector(".frame-body > .ver-prev")?.remove(),i&&!e&&Math.abs(y.x-i.to.x)<2&&Math.abs(y.y-i.to.y)<2&&Math.abs(y.z-i.to.z)<.004&&et(i.from,300)}async function Oc(e){if(!_)return;const{fid:t,pin:n}=_,i=xn(t),s=i.findIndex(o=>o.id===n),a=u.frames.find(o=>o.id===t);if(e==="close")return Xe();if(e==="stack")return Xe(!0),Rc(t,n);if(!(s<0))try{if(e==="back")await w("POST",`/__loop/api/frames/${t}/versions/restore`,{id:n}),Xe(),b("Back to that version. The one you were on is kept.",3200);else if(e==="dup"){const o=await w("POST",`/__loop/api/frames/${t}/versions/duplicate`,{id:n,name:`${a?.name||"Frame"} \xB7 v${s+1}`});Xe(!0),u.frames.find(r=>r.id===o.id)?(ie(o.id),Tt(o.id)):Ze=o.id,b("That version is now its own frame")}}catch(o){b(o.message)}}addEventListener("keydown",e=>{if(!_||N||Et()||e.metaKey||e.ctrlKey)return;if(e.key==="Escape"){e.stopPropagation(),e.preventDefault(),_.pin?(_.pin=null,kn(),Zn()):Xe();return}if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.stopPropagation(),e.preventDefault();const t=xn(_.fid),n=_.pin?t.findIndex(o=>o.id===_.pin):t.length-1,i=t[Math.max(0,Math.min(t.length-1,n+(e.key==="ArrowRight"?1:-1)))];_.pin=i.now?null:i.id,_.hover=null,kn(),Zn();const s=_.el.querySelector(".vt-row"),a=s.querySelector(".vt.on");a&&(s.scrollLeft=Math.max(0,Math.min(a.offsetLeft-(s.clientWidth-a.offsetWidth)/2,s.scrollWidth)))},!0);let N=null;function Ji(e){const t=u.frames.find(i=>i.id===e),n=[...u.comments.filter(i=>i.frameId===e&&i.snapshot&&!i.local&&i.status!=="working"&&i.status!=="queued").map(i=>({id:i.id,at:i.startedAt||i.createdAt,thumb:i.snapThumb,what:i.kind==="create"?"Created":i.text})),...(t?.restores||[]).map(i=>({id:i.id,at:i.at,thumb:i.thumb,what:i.what||"Went back to an earlier version"}))].sort((i,s)=>i.at-s.at);return n.map((i,s)=>({id:i.id,thumb:i.thumb,at:s?n[s-1].at:i.at,label:s?n[s-1].what:"Original",last:n[n.length-1].what}))}function Rc(e,t){const n=u.frames.find(x=>x.id===e),i=n&&Ji(e).slice(-11);if(!n||!i.length||N)return;E&&bt(),J(),ne(),Pe(),ie(null),Va(),Xe(!0);const s=Ot(n),a=132,o=96,r=Math.min((innerWidth-200)/n.w,(innerHeight-a-o)/n.h,1.2),l=n.w*r,c=n.h*r,f=(innerWidth-l)/2,d=a+(innerHeight-a-o-c)/2,p=[...i,{id:"",now:!0,label:i[i.length-1].last,at:Date.now(),thumb:null}].reverse(),h=t?Math.max(0,p.findIndex(x=>x.id===t)):0,g=document.createElement("div");g.id="versions",g.innerHTML=`<div class="vs-rig" style="left:${f}px;top:${d}px;width:${l}px;height:${c}px">
99
- ${p.map((x,M)=>`<div class="vs-layer${M===h?" front":""}" data-i="${M}">${x.thumb?`<img src="${L(x.thumb)}" alt="" draggable="false">`:""}</div>`).join("")}
90
+ ${n.length?`<div class="cp-label">On this page</div><div class="cp-used">${n.map(r=>`<button data-c="${r}" style="background:${r}" title="${r}"></button>`).join("")}</div>`:""}`,Ce.hidden=!1,si(!0);const a=e.getBoundingClientRect(),i=Ce.offsetWidth,s=Ce.offsetHeight;let o=a.bottom+8;o+s>innerHeight-12&&(o=a.top-s-8),Ce.style.left=`${Math.round(Math.max(12,Math.min(a.left-8,innerWidth-i-12)))}px`,Ce.style.top=`${Math.round(Math.max(12,o))}px`,e.classList.add("on")}function Ft(){Q&&(Q.prop==="frame-fill"&&yr(),Q.btn?.classList.remove("on"),Q=null,Ce.hidden=!0)}let Wt=null;function gr(e){const t=f.frames.find(n=>n.id===_);t&&((!Wt||Wt.id!==t.id)&&(Wt={id:t.id,before:t.fill||null}),t.fill=e,J(t),clearTimeout(Wt.t),Wt.t=setTimeout(()=>w("PATCH",`/__loop/api/frames/${t.id}`,{fill:e}).catch(n=>y(n.message)),250))}function yr(){const e=Wt;if(Wt=null,!e)return;const t=f.frames.find(i=>i.id===e.id),n=t?.fill||null;if(n===e.before)return;const a=i=>{const s=f.frames.find(o=>o.id===e.id);return s&&(s.fill=i||void 0,J(s),Fe()),w("PATCH",`/__loop/api/frames/${e.id}`,{fill:i})};G("Frame fill",()=>a(e.before),()=>a(n))}function si(e){if(!Q)return;const t=nd(td(Q.h,Q.s,Q.v));Ce.querySelector(".cp-sv").style.background=`linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(${Q.h}, 100%, 50%))`,Object.assign(Ce.querySelector(".cp-sv i").style,{left:`${Q.s*100}%`,top:`${(1-Q.v)*100}%`,background:t}),Object.assign(Ce.querySelector(".cp-hue i").style,{left:`${Q.h/360*100}%`,background:`hsl(${Q.h}, 100%, 50%)`}),Ce.querySelector(".cp-now").style.background=t;const n=Ce.querySelector(".cp-hex");if(document.activeElement!==n&&(n.value=t.toUpperCase()),e)return;const a=Q.btn;if(a.classList.remove("none"),a.querySelector("i").style.background=t,a.dataset.val=t,Q.prop==="frame-fill"){const i=a.querySelector("span");return i&&(i.textContent=t.toUpperCase()),gr(t)}Ln(Q.prop,t)}Ce.addEventListener("pointerdown",e=>{e.stopPropagation();const t=e.target.closest(".cp-sv, .cp-hue");if(!t||!Q)return;e.preventDefault(),t.setPointerCapture(e.pointerId);const n=i=>{const s=t.getBoundingClientRect(),o=Math.max(0,Math.min(1,(i.clientX-s.left)/s.width)),r=Math.max(0,Math.min(1,(i.clientY-s.top)/s.height));t.classList.contains("cp-hue")?Q.h=o*360:(Q.s=o,Q.v=1-r),si()};n(e);const a=()=>t.removeEventListener("pointermove",n);t.addEventListener("pointermove",n),t.addEventListener("pointerup",a,{once:!0})}),Ce.addEventListener("click",e=>{if(e.target.closest(".cp-none")&&Q?.prop==="frame-fill"){gr("none"),Ft(),Fe();return}if(e.target.closest(".cp-none")&&Q){const n=Q.btn,a=Q.prop==="border-color";Ln(a?"border-style":"background","none"),n.classList.add("none"),n.dataset.val="",n.querySelector("i").style.background="",Ft();return}const t=e.target.closest("[data-c]");t&&Q&&(Object.assign(Q,ps(t.dataset.c)),si())}),Ce.addEventListener("keydown",e=>{e.stopPropagation(),e.key==="Escape"&&Ft(),(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="z"&&(e.preventDefault(),e.target.blur?.(),e.shiftKey?Qn():Va())}),Ce.addEventListener("input",e=>{if(!e.target.classList.contains("cp-hex")||!Q)return;const t=e.target.value.trim(),n=/^#?([0-9a-f]{6})$/i.exec(t);n&&(Object.assign(Q,ps("#"+n[1])),si())}),addEventListener("pointerdown",e=>{Q&&!e.target.closest("#cpick, [data-pick]")&&Ft()},!0);async function ms(){if(!x||!$())return;const{frameId:e,els:t}=x,n=[],a=[];for(const r of t){const c=r.isConnected?await We(e,r):null;if(c){const{src:l,N:d}=c;let u=d.a,p=d.b;const h=l.lastIndexOf(`
91
+ `,u-1)+1,g=l.indexOf(`
92
+ `,p);/^[ \t]*$/.test(l.slice(h,u))&&/^[ \t]*$/.test(l.slice(p,g<0?l.length:g))&&(u=h,p=g<0?l.length:g+1),n.push({a:u,b:p,before:l.slice(u,p),text:""})}else a.push(r)}n.sort((r,c)=>r.a-c.a||c.b-r.b);const i=n.filter((r,c)=>!n.slice(0,c).some(l=>l.a<=r.a&&l.b>=r.b)),s=t.map(ta),o=t.length===1?Ye(t[0]):`${t.length} layers`;if(Ve(),a.length){const r=a.map(c=>[c,c.parentNode,c.nextSibling]);a.forEach(c=>c.remove()),G(`Delete ${o}`,()=>r.forEach(([c,l,d])=>l?.insertBefore(c,d)),()=>{}),id(e,a[0],s)}if(i.length)try{await lt(e,i,`Delete ${o}`)}catch(r){y(r.message)}}function id(e,t,n){const a=document.createElement("div");a.id="del-ask",a.innerHTML="<span>Hidden for now. The page\u2019s code draws it.</span><button>Remove it for real</button>",document.querySelector("#del-ask")?.remove(),document.body.appendChild(a),a.querySelector("button").onclick=async()=>{a.remove(),await mr(e,t,n[0],`Remove ${n.length===1?"this element":`these ${n.length} elements`} from the page, in the source. Change nothing else.`)},setTimeout(()=>a.remove(),8e3)}function sd(e){if(x?.frameId!==e||!O||O.fid!==e)return;const t=de(e);if(!t||t.location.href==="about:blank"||!t.body?.children.length)return;const n=t.querySelector(O.sel);if(!n)return te();const a=O.pending;x.els=[n],O.el=n;for(const[i,s]of Object.entries(a))n.style.setProperty(i,s);Pe(),bt()}function hs(e){if(e=e.filter(t=>f.frames.find(n=>n.id===t)),e.length===1)return Z(e[0]);_=null,Y.clear(),e.forEach(t=>Y.add(t));for(const t of f.frames)J(t);Fe(),oa()}function od(e){const t=new Set(Y.size?Y:_?[_]:[]);t.has(e)?t.delete(e):t.add(e),hs([...t])}const gs=e=>{const t=Math.min(...e.map(a=>a.x)),n=Math.min(...e.map(a=>a.y));return{x:t,y:n,w:Math.max(...e.map(a=>a.x+a.w))-t,h:Math.max(...e.map(a=>a.y+a.h))-n}};async function Se(e){for(const[t,n]of Object.entries(e)){const a=f.frames.find(i=>i.id===t);a&&(Object.assign(a,n),J(a))}Cn(),Nn(),await Promise.all(Object.entries(e).map(([t,n])=>w("PATCH",`/__loop/api/frames/${t}`,n)))}const br={KeyA:"left",KeyD:"right",KeyW:"top",KeyS:"bottom",KeyH:"hcenter",KeyV:"vcenter"};function vr(e){const t=[...Y].map(o=>f.frames.find(r=>r.id===o)).filter(Boolean);if(t.length<2)return;const n=gs(t),a={},i={};for(const o of t)a[o.id]={x:o.x,y:o.y};if(e==="hdist"||e==="vdist")return rd(e,t,n,a);be=null,oi();for(const o of t){const r={...a[o.id]};e==="left"?r.x=n.x:e==="right"?r.x=n.x+n.w-o.w:e==="hcenter"?r.x=Math.round(n.x+n.w/2-o.w/2):e==="top"?r.y=n.y:e==="bottom"?r.y=n.y+n.h-o.h:e==="vcenter"&&(r.y=Math.round(n.y+n.h/2-o.h/2)),i[o.id]=r}Se(i);const s={left:"Align left",right:"Align right",hcenter:"Align centres",top:"Align top",bottom:"Align bottom",vcenter:"Align middles",hdist:"Distribute horizontally",vdist:"Distribute vertically"}[e];G(s,()=>Se(a),()=>Se(i))}async function wr(e){const t=e.map(yt).filter(Boolean);await Promise.all(e.map(a=>w("DELETE",`/__loop/api/frames/${a}`)));const n={frames:t.flatMap(a=>a.frames),comments:t.flatMap(a=>a.comments)};G(`Delete ${e.length} frames`,()=>He(n),()=>Promise.all(e.map(a=>w("DELETE",`/__loop/api/frames/${a}`)))),Y.clear(),oa(),y(`Deleted ${e.length} frames \u2014 \u2318Z to undo`,2600)}let be=null;function rd(e,t,n,a){const i=e==="hdist"?"x":"y",s=e==="hdist"?"w":"h",o=[...t].sort((l,d)=>l[i]-d[i]);let r=((i==="x"?n.w:n.h)-o.reduce((l,d)=>l+d[s],0))/Math.max(1,o.length-1);r<40&&(r=80),be={k:i,size:s,ids:o.map(l=>l.id),start:o[0][i],before:a,after:null,gap:Math.round(r)};const c=be;Jt(c.gap,!0),G(e==="hdist"?"Distribute horizontally":"Distribute vertically",()=>Se(c.before),()=>Se(c.after)),oi()}function ld(e){const t=be,n={};let a=t.start;for(const i of t.ids){const s=f.frames.find(o=>o.id===i);s&&(n[i]={...t.before[i],[t.k]:Math.round(a)},a+=s[t.size]+e)}return n}function Jt(e,t){if(!be)return;e=Math.max(0,Math.round(e)),be.gap=e;const n=ld(e);if(t)be.after=n,Se(n);else{for(const[o,r]of Object.entries(n)){const c=f.frames.find(l=>l.id===o);c&&(Object.assign(c,r),J(c))}Cn(),Nn()}const a=m("#align-bar"),i=a.querySelector(".ab-range"),s=a.querySelector(".ab-val");i&&(i.max=Math.max(800,e*2),i.value=e),s&&document.activeElement!==s&&(s.value=e)}function oi(){const e=m("#align-bar").querySelector(".ab-spacing");if(!e||(e.hidden=!be,!be))return;e.querySelector(".ab-scrub").innerHTML=be.k==="x"?'<svg viewBox="0 0 24 24"><path d="M3 12h18M7 8l-4 4 4 4M17 8l4 4-4 4"/></svg>':'<svg viewBox="0 0 24 24"><path d="M12 3v18M8 7l4-4 4 4M8 17l4 4 4-4"/></svg>';const t=e.querySelector(".ab-range"),n=e.querySelector(".ab-val");t.max=Math.max(800,be.gap*2),t.value=be.gap,document.activeElement!==n&&(n.value=be.gap),Cn()}const cd={left:'<path d="M4 3v18"/><rect x="7" y="6" width="11" height="4" rx="1"/><rect x="7" y="14" width="7" height="4" rx="1"/>',hcenter:'<path d="M12 3v18"/><rect x="5" y="6" width="14" height="4" rx="1"/><rect x="8" y="14" width="8" height="4" rx="1"/>',right:'<path d="M20 3v18"/><rect x="6" y="6" width="11" height="4" rx="1"/><rect x="10" y="14" width="7" height="4" rx="1"/>',top:'<path d="M3 4h18"/><rect x="6" y="7" width="4" height="11" rx="1"/><rect x="14" y="7" width="4" height="7" rx="1"/>',vcenter:'<path d="M3 12h18"/><rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="8" width="4" height="8" rx="1"/>',bottom:'<path d="M3 20h18"/><rect x="6" y="6" width="4" height="11" rx="1"/><rect x="14" y="10" width="4" height="7" rx="1"/>',hdist:'<path d="M4 4v16M20 4v16"/><rect x="9" y="7" width="6" height="10" rx="1"/>',vdist:'<path d="M4 4h16M4 20h16"/><rect x="7" y="9" width="10" height="6" rx="1"/>'},dd={left:"Align left (\u2325A)",hcenter:"Align horizontal centres (\u2325H)",right:"Align right (\u2325D)",top:"Align top (\u2325W)",vcenter:"Align vertical centres (\u2325V)",bottom:"Align bottom (\u2325S)",hdist:"Distribute horizontally",vdist:"Distribute vertically"};function oa(){const e=m("#align-bar");if(!f||Y.size<2||!$()||X){e.hidden=!0;return}if(!e.dataset.ready){e.innerHTML='<span class="ab-count"></span><span class="ab-sep"></span>'+["left","hcenter","right","|","top","vcenter","bottom","|","hdist","vdist"].map(i=>i==="|"?'<span class="ab-sep"></span>':`<button data-align="${i}" title="${dd[i]}"><svg viewBox="0 0 24 24">${cd[i]}</svg></button>`).join("")+'<span class="ab-spacing" hidden><span class="ab-sep"></span><span class="ab-scrub" title="Drag left or right to change the spacing"></span><input class="ab-range" type="range" min="0" max="800" step="1" title="Drag to spread them out or pull them closer"><label class="ab-num" title="Space between frames"><input class="ab-val" inputmode="numeric"><small>px</small></label></span>';const t=e.querySelector(".ab-range"),n=e.querySelector(".ab-val"),a=e.querySelector(".ab-scrub");t.addEventListener("input",()=>Jt(+t.value,!1)),t.addEventListener("change",()=>Jt(+t.value,!0)),n.addEventListener("keydown",i=>{i.stopPropagation(),i.key==="Enter"&&(Jt(+n.value||0,!0),n.blur()),i.key==="Escape"&&n.blur()}),n.addEventListener("change",()=>Jt(+n.value||0,!0)),a.addEventListener("pointerdown",i=>{if(!be)return;i.preventDefault(),a.setPointerCapture(i.pointerId);const s=i.clientX,o=be.gap,r=l=>Jt(o+(l.clientX-s)*2,!1),c=()=>{a.removeEventListener("pointermove",r),a.removeEventListener("pointerup",c),Jt(be.gap,!0)};a.addEventListener("pointermove",r),a.addEventListener("pointerup",c)}),e.addEventListener("pointerdown",i=>i.stopPropagation()),e.addEventListener("click",i=>{const s=i.target.closest("[data-align]");s&&vr(s.dataset.align)}),e.dataset.ready="1"}e.querySelector(".ab-count").textContent=`${Y.size} frames`,e.querySelectorAll('[data-align$="dist"]').forEach(t=>t.disabled=Y.size<2),be&&(be.ids.length!==Y.size||be.ids.some(t=>!Y.has(t)))&&(be=null),oi(),e.hidden=!1,Cn()}function Cn(){const e=m("#align-bar");if(e.hidden||Y.size<2||!f)return;const t=[...Y].map(o=>f.frames.find(r=>r.id===o)).filter(Boolean).map(De);if(!t.length)return;const n=gs(t),a=b.x+(n.x+n.w/2)*b.z,i=b.y+n.y*b.z-34,s=e.offsetWidth||360;e.style.left=`${Math.max(12,Math.min(a-s/2,innerWidth-s-12))}px`,e.style.top=`${Math.max(60,i-46)}px`}const xr=6,ri=e=>[e.x,e.x+e.w/2,e.x+e.w],li=e=>[e.y,e.y+e.h/2,e.y+e.h];function kr(e){const t=e instanceof Set?e:new Set([e]);return f.frames.filter(n=>!t.has(n.id)).map(n=>De(n))}function Mn(e,t,n){let a=null;for(const i of e)for(const s of t){const o=s-i;Math.abs(o)<=n&&(!a||Math.abs(o)<Math.abs(a.d))&&(a={d:o,at:s})}return a}function $r(e,t,n,a){const i=[],s=[e,...t],o=.5/b.z;if(n){const r=s.filter(c=>ri(c).some(l=>Math.abs(l-n.at)<o));i.push({x1:n.at,y1:Math.min(...r.map(c=>c.y)),x2:n.at,y2:Math.max(...r.map(c=>c.y+c.h))})}if(a){const r=s.filter(c=>li(c).some(l=>Math.abs(l-a.at)<o));i.push({x1:Math.min(...r.map(c=>c.x)),y1:a.at,x2:Math.max(...r.map(c=>c.x+c.w)),y2:a.at})}return i}function ys(e,t){const n=kr(t),a=xr/b.z,i=Mn(ri(e),n.flatMap(ri),a),s=Mn(li(e),n.flatMap(li),a),o={...e,x:e.x+(i?.d||0),y:e.y+(s?.d||0)};return{dx:i?.d||0,dy:s?.d||0,guides:$r(o,n,i,s)}}function fd(e,t,n="se"){const a=kr(t),i=xr/b.z,s=a.flatMap(ri),o=a.flatMap(li),r={...e};let c=null,l=null;return n.includes("e")?(c=Mn([e.x+e.w],s,i),c&&(r.w=e.w+c.d)):n.includes("w")&&(c=Mn([e.x],s,i),c&&(r.x=e.x+c.d,r.w=e.w-c.d)),n.includes("s")?(l=Mn([e.y+e.h],o,i),l&&(r.h=e.h+l.d)):n.includes("n")&&(l=Mn([e.y],o,i),l&&(r.y=e.y+l.d,r.h=e.h-l.d)),{rect:r,guides:$r(r,a,c,l)}}function At(e){const t=m("#guides");t.innerHTML=e.map(n=>`<line x1="${n.x1}" y1="${n.y1}" x2="${n.x2}" y2="${n.y2}"/>`).join("")}const ci=A("freeze");function Lr(e){const t=D.get(e),n=de(e);if(!t||t.parked||!n?.documentElement||n.location.href==="about:blank")throw new Error("Bring the frame into view first, so it is loaded");const a=t.iframe.contentWindow,i=k=>{try{const M=new URL(k,n.baseURI);return M.origin===location.origin?M.pathname+M.search+M.hash:M.href}catch{return k}},s=(k,M)=>k.replace(/url\(\s*(['"]?)([^'")]+)\1\s*\)/g,(E,N,q)=>/^(data:|blob:|#)/.test(q)?E:`url("${i(new URL(q,M).href)}")`);let o="";const r=(k,M=0)=>{let E;try{E=k.cssRules}catch{k.href&&(o+=`@import url("${i(k.href)}");
93
+ `);return}if(k.disabled||!E)return;const N=k.media?.mediaText;N&&M===0&&k.ownerNode?.tagName==="LINK"&&(o+=`@media ${N} {
94
+ `);for(const q of E)q.type===CSSRule.IMPORT_RULE&&q.styleSheet&&M<4?r(q.styleSheet,M+1):o+=s(q.cssText,k.href||n.baseURI)+`
95
+ `;N&&M===0&&k.ownerNode?.tagName==="LINK"&&(o+=`}
96
+ `)};for(const k of[...n.styleSheets,...n.adoptedStyleSheets||[]])r(k);const c=n.documentElement.cloneNode(!0),l=n.querySelectorAll("input, textarea, select"),d=c.querySelectorAll("input, textarea, select");l.forEach((k,M)=>{const E=d[M];E&&(k.tagName==="TEXTAREA"?E.textContent=k.value:k.tagName==="SELECT"?[...k.options].forEach((N,q)=>E.options[q]?.toggleAttribute("selected",N.selected)):/^(checkbox|radio)$/.test(k.type)?E.toggleAttribute("checked",k.checked):/^(password|file)$/.test(k.type)||E.setAttribute("value",k.value))});const u=n.querySelectorAll("canvas"),p=c.querySelectorAll("canvas");u.forEach((k,M)=>{const E=n.createElement("img");for(const q of p[M].attributes)E.setAttribute(q.name,q.value);try{E.src=k.toDataURL("image/png")}catch{}const N=k.getBoundingClientRect();k.getAttribute("style")||E.setAttribute("style",`width:${N.width}px;height:${N.height}px`),p[M].replaceWith(E)});const h=n.documentElement.querySelectorAll("*"),g=c.querySelectorAll("*");h.length===g.length&&h.forEach((k,M)=>{(k.scrollTop||k.scrollLeft)&&g[M].setAttribute("data-loop-scroll",`${k.scrollLeft},${k.scrollTop}`)}),c.querySelectorAll('script, noscript, base, link[rel="stylesheet"], link[rel="preload"], link[rel="modulepreload"], link[rel="prefetch"], style').forEach(k=>k.remove()),c.querySelectorAll("*").forEach(k=>{for(const M of[...k.attributes])(/^on/i.test(M.name)||/^(href|src|action)$/i.test(M.name)&&/^\s*javascript:/i.test(M.value))&&k.removeAttribute(M.name)});let v=c.querySelector("head");v||(v=n.createElement("head"),c.prepend(v));const T=a.location.pathname+a.location.search,C=`scrollTo(${Math.round(a.scrollX)},${Math.round(a.scrollY)});document.querySelectorAll('[data-loop-scroll]').forEach(e=>{const[x,y]=e.dataset.loopScroll.split(',');e.scrollLeft=+x;e.scrollTop=+y});addEventListener('click',e=>{if(e.target.closest('a[href]'))e.preventDefault()},true);addEventListener('submit',e=>e.preventDefault(),true)`;return v.insertAdjacentHTML("afterbegin",`<meta charset="utf-8"><base href="${L(T)}"><meta name="loop-frozen" content="${Date.now()}"><style>${o.replace(/<\/style/gi,"<\\/style")}</style>`),c.querySelector("body")?.insertAdjacentHTML("beforeend",`<script>addEventListener('load',()=>{${C}})<\/script>`),`<!doctype html>
97
+ `+c.outerHTML}async function ud(e){const t=f.frames.find(a=>a.id===e);if(!t)return;let n;try{n=Lr(e)}catch(a){return y(a.message)}try{const a=De(t),i=await w("POST",`/__loop/api/frames/${e}/freeze`,{html:n,from:Dn(D.get(e)),editable:!0,x:a.x+a.w+80,y:a.y});let s=null;G("Editable copy",async()=>{s=yt(i.id)||s,await w("DELETE",`/__loop/api/frames/${i.id}`)},()=>He(s||{frames:[i]})),f.frames.find(o=>o.id===i.id)?(Z(i.id),St(i.id)):Ue=i.id,y("Editable copy beside it. Changes stay in the copy; ask the agent to make it real when it is right.",3400)}catch(a){y(a.message)}}async function ra(e){const t=f.frames.find(a=>a.id===e);if(!t)return;if(t.kind==="frozen")return y("This frame is already frozen");let n;try{n=Lr(e)}catch(a){return y(a.message)}try{const a=await w("POST",`/__loop/api/frames/${e}/freeze`,{html:n,from:Dn(D.get(e))});let i=null;if(G("Freeze frame",async()=>{i=yt(a.id)||i,await w("DELETE",`/__loop/api/frames/${a.id}`)},()=>He(i||{frames:[a]})),S)return y("Frozen copy added next to this frame");f.frames.find(s=>s.id===a.id)?(Z(a.id),St(a.id)):Ue=a.id,y("Frozen: this copy keeps the screen as it is now")}catch(a){y(a.message)}}async function Cr(e){const t=f.frames.find(n=>n.id===e);if(t?.from)try{const n=await w("POST","/__loop/api/frames",{route:t.from,name:t.name.replace(/ · frozen( \d+)?$/,""),w:t.w,h:t.h,near:t.id,dup:!0});f.frames.find(a=>a.id===n.id)?(Z(n.id),St(n.id)):Ue=n.id}catch(n){y(n.message)}}const en=e=>{const t=Math.min(e.w,e.h),n=Math.max(e.w,e.h);return t>=320&&t<=500&&n>=560&&n<=1e3&&n/t>=1.5},bs=["qwertyuiop","asdfghjkl","zxcvbnm"];function Mr(e,t){const n=e.autoKb,a=en(t)&&(!!t.keyboard||!!n);if(e.el.classList.toggle("kb-on",a),!a)return;const i=t.w>t.h,s=n==="num"?"num":"abc";let o=e.el.querySelector(".kb");if(o||(o=document.createElement("div"),o.className="kb",e.el.querySelector(".frame-body").appendChild(o)),o.dataset.kind!==s){o.dataset.kind=s;const r=c=>[...c].map(l=>`<span class="k">${l}</span>`).join("");o.innerHTML=s==="num"?[["1",""],["2","ABC"],["3","DEF"],["4","GHI"],["5","JKL"],["6","MNO"],["7","PQRS"],["8","TUV"],["9","WXYZ"],[".",null],["0",""],["\u232B",null]].reduce((c,l,d)=>((c[Math.floor(d/3)]||=[]).push(l),c),[]).map(c=>`<div class="kb-row">${c.map(([l,d])=>`<span class="k${d==null?" fn plain":""}"><b>${l}</b>${d?`<i>${d}</i>`:""}</span>`).join("")}</div>`).join(""):`<div class="kb-bar"><span>I</span><span>The</span><span>I\u2019m</span></div>
98
+ <div class="kb-row">${r(bs[0])}</div><div class="kb-row r2">${r(bs[1])}</div>
99
+ <div class="kb-row"><span class="k fn">\u21E7</span>${r(bs[2])}<span class="k fn">\u232B</span></div>
100
+ <div class="kb-row"><span class="k fn">123</span><span class="k fn">\u263A</span><span class="k sp">space</span><span class="k fn ret">return</span></div>`}o.classList.toggle("num",s==="num"),o.classList.toggle("land",i)}function pd(e){if(!e||e.disabled||e.readOnly)return null;const t=e.tagName,n=(e.getAttribute?.("type")||"text").toLowerCase(),a=(e.getAttribute?.("inputmode")||"").toLowerCase();return a==="none"?null:t==="TEXTAREA"||e.isContentEditable?"abc":t!=="INPUT"||/^(checkbox|radio|range|button|submit|reset|file|color|date|time|datetime-local|month|week|image|hidden)$/.test(n)?null:/^(numeric|decimal|tel)$/.test(a)||/^(number|tel)$/.test(n)?"num":"abc"}function md(e,t,n){const a=()=>{const i=f?.frames.find(o=>o.id===n);if(!i||!en(i))return;const s=xe?.fid===n?null:pd(e.document.activeElement);t.autoKb!==s&&(t.autoKb=s,Mr(t,i),s&&setTimeout(()=>{try{e.document.activeElement?.scrollIntoView({block:"center",behavior:"smooth"})}catch{}},60),S?.fid===n&&setTimeout(()=>ut(n),80))};e.addEventListener("focusin",a),e.addEventListener("focusout",()=>setTimeout(a,0))}async function di(e){const t=f.frames.find(a=>a.id===e);if(!t)return;if(!en(t))return y("The keyboard is for phone-sized frames");const n=!t.keyboard;try{await w("PATCH",`/__loop/api/frames/${e}`,{keyboard:n}),G(n?"Show keyboard":"Hide keyboard",()=>w("PATCH",`/__loop/api/frames/${e}`,{keyboard:!n}),()=>w("PATCH",`/__loop/api/frames/${e}`,{keyboard:n}))}catch(a){y(a.message)}}let S=null;const la=(()=>{try{return new Set(JSON.parse(localStorage.getItem("loop.stageNoDevice")||"[]"))}catch{return new Set}})(),hd=[[744,1133],[768,1024],[810,1080],[820,1180],[834,1112],[834,1194],[800,1280],[1024,1366],[1032,1376]],vs=e=>{const t=Math.min(e.w,e.h),n=Math.max(e.w,e.h);return!en(e)&&!(e.w===1280&&e.h===800)&&hd.some(([a,i])=>Math.abs(a-t)<=2&&Math.abs(i-n)<=2)},ca=e=>en(e)||vs(e),Er=e=>ca(e)&&!la.has(e.id);let Sr=0;function ct(e,t=420){const n={...b},a=performance.now(),i=++Sr,s=o=>{if(i!==Sr)return;const r=Math.min(1,(o-a)/t),c=r<.5?4*r*r*r:1-Math.pow(-2*r+2,3)/2;b={x:n.x+(e.x-n.x)*c,y:n.y+(e.y-n.y)*c,z:n.z+(e.z-n.z)*c},ie(),r<1&&requestAnimationFrame(s)};requestAnimationFrame(s)}function En(e){const t=Er(e),n=t?vs(e)?34:22:0,a=D.get(e.id)?.el.querySelector(":scope > .opt-strip"),i=84+(a?a.offsetHeight+44:0)+(P?.fid===e.id?P.el.offsetHeight+18:0),s=96,r=Math.max(.04,Math.min((innerWidth-40*2)/(e.w+n*2),(innerHeight-i-s)/(e.h+n*2),2)),c=S.zoom==="100"?1:r;return{z:c,x:innerWidth/2-(e.x+e.w/2)*c,y:i+(innerHeight-i-s)/2-(e.y+e.h/2)*c}}function vt(e){const t=f.frames.find(n=>n.id===e);t&&(S||(S={prev:{...b},zoom:"fit"}),document.querySelectorAll(".frame.staged").forEach(n=>n.classList.remove("staged","device","tablet")),S.fid=e,Z(null),ee(),te(),xo(),nt(),Re(),Ve(),Ft(),V.hidden=!0,xe&&ni(!1),ma?.(),document.body.classList.add("staging"),da(),ct(En(t)),Be&&Gi(e))}function dt(){if(!S)return;P&&(P.staged=!1,nt(!0));const e=S.prev;if(document.querySelectorAll(".frame.staged").forEach(t=>t.classList.remove("staged","device","landscape","tablet")),document.body.classList.remove("staging"),m("#stage-bar")?.remove(),S=null,ws(),fe){fe=null,ht();for(const t of f.frames)J(t)}ct(e,380)}function Tr(e){return!!e&&ca(e)&&(S?S.fid===e.id:Be)}function ws(){for(const[e,t]of D)try{t.iframe.contentDocument?.documentElement.classList.toggle("loop-touch",Tr(f.frames.find(n=>n.id===e)))}catch{}}function xs(){return[...f.frames].sort((e,t)=>Math.abs(e.y-t.y)<200?e.x-t.x:e.y-t.y)}function da(){const e=f.frames.find(c=>c.id===S.fid);if(!e)return dt();const t=D.get(e.id),n=vs(e),a=ca(e),i=Er(e);t?.el.classList.add("staged"),t?.el.classList.toggle("device",i),t?.el.classList.toggle("tablet",i&&n),t?.el.classList.toggle("landscape",e.w>e.h),ws();let s=m("#stage-bar");s||(s=document.createElement("div"),s.id="stage-bar",document.body.appendChild(s),s.addEventListener("pointerdown",c=>c.stopPropagation()),s.addEventListener("click",wd));const o=xs(),r=o.findIndex(c=>c.id===e.id);s.innerHTML=`
101
+ ${a?`<button class="sb-btn${i?" on":""}" data-sb="device" title="Show it inside ${n?"an iPad":"an iPhone"}"><span class="sb-dev${e.w>e.h?" side":""}">${A(n?"tablet":"phone")}</span></button>
102
+ ${$()?`<button class="sb-btn" data-sb="rotate" title="Turn it ${e.w>e.h?"upright":"on its side"} (R)">${yd}</button>`:""}`:""}
103
+ ${e.kind!=="frozen"&&$()?`<button class="sb-btn" data-sb="freeze" title="Freeze a copy of it as it is now (\u21E7F)">${ci}</button>`:""}
104
+ ${$()&&["route","url","folder"].includes(e.kind)&&!e.image&&!e.sizeOf?`<button class="sb-btn" data-sb="sizes" title="See it at phone, tablet and desktop size, side by side">${bd}</button>`:""}
105
+ ${$()?'<button class="sb-fit" data-sb="fit" hidden><i></i><span>Doesn\u2019t fit</span><b>Make it fit</b></button>':""}
106
+ <button class="sb-exit" data-sb="exit" title="Exit stage (Esc)">${A("x")}<span>Exit</span></button>`;for(const c of[250,900,2e3])setTimeout(_r,c)}function Ar(e){try{const t=D.get(e.id)?.iframe.contentDocument,n=t?.documentElement;if(!n||!t.body)return 0;const a=Math.max(n.scrollWidth,t.body.scrollWidth)-n.clientWidth;return a>4?Math.round(a):0}catch{return 0}}function _r(){const e=m("#stage-bar .sb-fit"),t=S&&f.frames.find(a=>a.id===S.fid);if(!e||!t)return;const n=f.live[t.id]||t.kind==="frozen"?0:Ar(t);e.hidden=!n,e.dataset.over=n,e.title=`The page is ${n}px wider than this ${t.w}\xD7${t.h} frame. Ask the agent to make it fit this size.`}async function gd(){const e=S&&f.frames.find(i=>i.id===S.fid),t=e&&Ar(e);if(!t)return _r();const n={id:ga(),frameId:e.id,author:{name:U.name,color:U.color},anchor:On(e.id,{scope:"frame",x:0,y:0}),text:`This screen doesn\u2019t fit at ${e.w}\xD7${e.h}: the page runs ${t}px wider than the frame. Make it responsive at this size, and keep it looking the same at the sizes it already works at.`},a=Pa(n);try{const i=await w("POST","/__loop/api/comments",n);i?.id&&i.id!==n.id&&a(),m("#stage-bar .sb-fit").hidden=!0,y("Asked the agent to make it fit")}catch(i){a(),y(i.message)}}const yd='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20.5 12a8.5 8.5 0 1 1-2.6-6.1"/><path d="M20.5 3.5v5h-5"/></svg>',bd='<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="2.5" y="5" width="12" height="9" rx="1.5"/><rect x="12" y="8" width="6" height="10" rx="1.2"/><rect x="17" y="11" width="4.5" height="8" rx="1"/></svg>';async function Pr(e){try{const t=await w("POST",`/__loop/api/frames/${e.id}/sizes`);dt(),setTimeout(()=>Oe(!0,[e.id,...t.frames]),450),t.existing||y("The same screen at the other sizes, live. Comment on whichever one breaks.",3e3)}catch(t){y(t.message)}}async function qr(){const e=S&&f.frames.find(i=>i.id===S.fid);if(!e||!ca(e)||!$())return;const t={w:e.w,h:e.h,x:e.x,y:e.y},n={w:e.h,h:e.w,x:Math.round(e.x+(e.w-e.h)/2),y:Math.round(e.y+(e.h-e.w)/2)},a=i=>(Object.assign(e,i),J(e),S?.fid===e.id&&(da(),ct(En(e),320)),w("PATCH",`/__loop/api/frames/${e.id}`,i).catch(s=>y(s.message)));G("Rotate frame",()=>a(t),()=>a(n)),a(n)}function vd(e){const t=S&&f.frames.find(l=>l.id===S.fid);if(!t)return;const n=l=>({x:l.x+l.w/2,y:l.y+l.h/2}),a=n(t),i=e==="left"||e==="right",s=e==="right"||e==="down"?1:-1,o=f.frames.filter(l=>l.id!==t.id).map(l=>{const d=n(l);return{f:l,along:(i?d.x-a.x:d.y-a.y)*s,side:Math.abs(i?d.y-a.y:d.x-a.x)}}),c=o.filter(l=>l.along>1).sort((l,d)=>l.along+2*l.side-(d.along+2*d.side))[0]||o.sort((l,d)=>l.along+2*l.side-(d.along+2*d.side))[0];c&&vt(c.f.id)}function Od(e){if(!S)return;const t=xs(),n=t.findIndex(a=>a.id===S.fid);t.length>1&&vt(t[(n+e+t.length)%t.length].id)}function wd(e){const t=e.target.closest("[data-sb]");if(!t||!S)return;const n=f.frames.find(o=>o.id===S.fid);if(!n)return;const a=t.dataset.sb,i=xs(),s=i.findIndex(o=>o.id===n.id);if(a==="exit")return dt();if(a==="prev"||a==="next"){const o=i[(s+(a==="next"?1:-1)+i.length)%i.length];return vt(o.id)}if(a==="device"){la.has(n.id)?la.delete(n.id):la.add(n.id);try{localStorage.setItem("loop.stageNoDevice",JSON.stringify([...la]))}catch{}return da(),ct(En(n),300)}if(a==="keyboard")return di(n.id);if(a==="rotate")return qr();if(a==="fit")return gd();if(a==="sizes")return Pr(n);if(a==="freeze")return ra(n.id);if(a==="zoom")return S.zoom=S.zoom==="fit"?"100":"fit",da(),ct(En(n),320)}addEventListener("keydown",e=>{if(!S||Ot()||e.metaKey||e.ctrlKey)return;const t={ArrowRight:"right",ArrowLeft:"left",ArrowUp:"up",ArrowDown:"down"}[e.key];if(t&&(e.preventDefault(),vd(t)),e.key.toLowerCase()==="r"&&!e.shiftKey&&!e.altKey){const n=f.frames.find(a=>a.id===S.fid);n&&ca(n)&&$()&&(e.preventDefault(),e.stopImmediatePropagation(),qr())}}),addEventListener("resize",()=>{if(S){const e=f.frames.find(t=>t.id===S.fid);e&&(b=En(e),ie())}});const Te=document.createElement("div");Te.id="edge",Te.hidden=!0,document.body.appendChild(Te),Te.innerHTML=`<button class="eg-btn" data-eg="stage">${A("stage")}<span></span></button>`;let _t=null,tn=null,fi=!1,ks=0;const je={x:-1,y:-1},Sn=52;function jt(e){const t=De(e),n=b.z;return{l:b.x+t.x*n,t:b.y+t.y*n,w:t.w*n,h:t.h*n}}function xd(){if(!f)return null;if(S)return S.fid;if(se||document.body.classList.contains("versions-on"))return null;for(let e=f.frames.length-1;e>=0;e--){const t=jt(f.frames[e]),n=Math.max(t.t,Sn);if(je.x>=t.l-6&&je.x<=t.l+t.w+6&&je.y>=Math.max(t.t-44,0)&&je.y<=Math.min(n+110,t.t+t.h))return f.frames[e].id}return!Y.size&&_||fe||null}function ui(){const e=xd();e?(clearTimeout(tn),tn=null,_t=e):_t&&!tn&&!fi&&(tn=setTimeout(()=>{tn=null,fi||(_t=null,fa())},380)),fa()}function fa(){const e=_t&&f?.frames.find(d=>d.id===_t),t=!1,n=e&&jt(e);if(!e||S||n.w<72||n.t+n.h<Sn+30||n.t>innerHeight-40||n.l>innerWidth-40||n.l+n.w<40){Te.hidden=!0;return}Te.hidden=!1,Te.classList.toggle("exit",t),Te.classList.toggle("compact",!t&&n.w<200);const a=Te.querySelector('[data-eg="stage"]');$e(a.lastChild,t?"Exit stage":"Stage"),a.dataset.tip="Stage: focus on this frame (S)";const i=Te.offsetWidth,s=Te.offsetHeight;let o=n.t-12*(parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--lz"))||1)-s/2;const r=o<Sn;r&&(o=Math.max(n.t+8,Sn+4));const c=r?-8:parseFloat(getComputedStyle(a).paddingRight)||0;let l=Math.min(n.l+n.w-i+c,innerWidth-i-12);l=Math.max(l,n.l),Te.classList.toggle("inside",r),Te.style.left=`${Math.round(l)}px`,Te.style.top=`${Math.round(o)}px`;for(const[d,u]of D){const p=u.el.querySelector(":scope > .opt-strip, :scope > .ver-strip");if(!p)continue;const h=f.frames.find(k=>k.id===d);if(!h)continue;const g=jt(h),v=p.offsetHeight,T=g.t-34-v,C=T<Sn+4?Math.min(Sn+4-T,Math.max(0,g.h-20)):0;p.style.translate=C?`0 ${C/b.z}px`:""}}addEventListener("pointermove",e=>{je.x=e.clientX,je.y=e.clientY,Cl(),ks||(ks=requestAnimationFrame(()=>{ks=0,ui()}))},{capture:!0,passive:!0}),Te.addEventListener("pointerenter",()=>{fi=!0,clearTimeout(tn),tn=null}),Te.addEventListener("pointerleave",()=>{fi=!1,ui()}),Te.addEventListener("pointerdown",e=>e.stopPropagation()),Te.addEventListener("click",async e=>{!e.target.closest('[data-eg="stage"]')||!_t||(S?.fid===_t?dt():vt(_t))});const pi=new Set;function Dr(e,t=0){if(!pi.has(e)){if((se||S||F||xe)&&t<40)return setTimeout(()=>Dr(e,t+1),250);setTimeout(()=>{!pi.has(e)&&f.sections.some(n=>n.id===e)&&(pi.add(e),Ir(e))},t?0:500)}}function Ir(e){const t=f.sections.find(u=>u.id===e),n=t&&f.comments.find(u=>u.id===t.optionsFor),a=n&&f.frames.find(u=>u.id===n.frameId);if(!t||!a||S||F)return;const i=Math.min(a.x,t.x),s=Math.min(a.y,t.y)-40,o=Math.max(a.x+a.w,t.x+t.w),r=Math.max(a.y+a.h,t.y+t.h),c={x:b.x+i*b.z,y:b.y+s*b.z},l={x:b.x+o*b.z,y:b.y+r*b.z};if(c.x>=0&&c.y>=50&&l.x<=innerWidth&&l.y<=innerHeight-70&&(o-i)*b.z>innerWidth*.45)return;const d=Math.min(1,(innerWidth-160)/(o-i),(innerHeight-240)/(r-s));ct({z:d,x:(innerWidth-(o-i)*d)/2-i*d,y:120+(innerHeight-240-(r-s)*d)/2-s*d},520)}function Tn(e){const t=b.z;return t<.33||e.w*t<300&&e.h*t<300}let mi={fid:null,t:0},nn=null;function kd(e,t){const n=ke&&f.sections.find(i=>i.id===ke),a=n?an(n).map(i=>i.id):Y.size?[...Y]:_?[_]:[];if(!a.length&&!n)return!1;nn||={from:Object.fromEntries(a.map(i=>{const s=f.frames.find(o=>o.id===i);return[i,{x:s.x,y:s.y}]})),sec:n&&{id:n.id,x:n.x,y:n.y}};for(const i of Object.keys(nn.from)){const s=f.frames.find(o=>o.id===i);s&&(s.x+=e,s.y+=t,J(s))}return n&&nn.sec&&(n.x+=e,n.y+=t,wt()),_e(),fa(),oa(),clearTimeout(nn.t),nn.t=setTimeout(()=>{const i=nn;nn=null;const s=Object.fromEntries(Object.keys(i.from).map(d=>{const u=f.frames.find(p=>p.id===d);return[d,{x:u.x,y:u.y}]})),o=i.from,r=i.sec&&f.sections.find(d=>d.id===i.sec.id),c=r&&{x:r.x,y:r.y},l=i.sec&&{x:i.sec.x,y:i.sec.y};Se(s),r&&w("PATCH",`/__loop/api/sections/${r.id}`,c).catch(()=>{}),G("Nudge",()=>Promise.all([Se(o),r&&Pt(r.id,l)]),()=>Promise.all([Se(s),r&&Pt(r.id,c)]))},400),!0}const Kt=m("#sections"),ua=new Map;let ke=null,hi={id:null,t:0};const $s=e=>({...e,...ua.get(e.id)||{}}),An=(e,t)=>{const n=Math.min(t.x+t.w,e.x+e.w)-Math.max(t.x,e.x),a=Math.min(t.y+t.h,e.y+e.h)-Math.max(t.y,e.y);return n>0&&a>0&&n*a>t.w*t.h*.5};function gi(e){for(const t of f.frames)D.get(t.id)?.el.classList.toggle("joining",!!e&&!t.parent&&An(e,De(t)))}const an=e=>f.frames.filter(t=>An(e,t));function Hr(){if(!f)return;const e=b.z,t=(f.sections||[]).map($s);for(const n of f.frames){const a=D.get(n.id);if(!a)continue;const i=n.w*e,s=De(n),o=t.some(r=>An(r,s)&&(s.y-r.y)*e<24);a.el.classList.toggle("narrow",i<200),a.el.classList.toggle("noname",i<34||o)}for(const n of t){const a=Kt.querySelector(`.section[data-id="${n.id}"]`);a&&(a.classList.toggle("noname",n.w*e<48),a.classList.remove("lift"))}}function wt(){const e=f.sections||[],t=new Set(e.map(n=>n.id));Kt.querySelectorAll(".section").forEach(n=>{t.has(n.dataset.id)||n.remove()}),ke&&!t.has(ke)&&(ke=null);for(const n of e){const a=$s(n);let i=Kt.querySelector(`.section[data-id="${a.id}"]`);if(!i){i=document.createElement("div"),i.className="section",i.dataset.id=a.id,i.innerHTML=`<div class="sec-label"><span class="sec-name"></span><button class="sec-more" title="Section options"><svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="3.5" cy="8" r="1.3"/><circle cx="8" cy="8" r="1.3"/><circle cx="12.5" cy="8" r="1.3"/></svg></button></div>${["n","s","e","w","ne","nw","se","sw"].map(l=>`<div class="srz rz-${l}" data-dir="${l}"></div>`).join("")}`,Kt.appendChild(i);const r=i.querySelector(".sec-more"),c=a.id;r.addEventListener("pointerdown",l=>l.stopPropagation()),r.addEventListener("click",l=>{l.stopPropagation(),Cd(c,r)})}Object.assign(i.style,{left:`${a.x}px`,top:`${a.y}px`,width:`${a.w}px`,height:`${a.h}px`}),i.style.setProperty("--sw",`${a.w}px`);const s=i.querySelector(".sec-name");s.classList.contains("editing-name")||$e(s,a.name),i.classList.toggle("selected",ke===a.id);const o=a.optionsFor&&f.comments.find(r=>r.id===a.optionsFor);i.classList.toggle("making",!!o&&(Ca(o.id)==="working"||f.frames.some(r=>r.building&&r.optionOf?.cid===o.id)))}Hr()}function yi(e){(_||Y.size||fe)&&Z(null),ke=e,wt()}function zr(e,t){const n=f.sections.find(a=>a.id===e);se={type:"smove",sid:e,sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,moved:!1,from:Object.fromEntries(an(n).map(a=>[a.id,{x:a.x,y:a.y}]))},I.classList.add("dragging"),I.setPointerCapture(t.pointerId)}function $d(e,t){const n=f.sections.find(a=>a.id===e);se={type:"sresize",sid:e,dir:t.target.dataset.dir||"se",sx:t.clientX,sy:t.clientY,x0:n.x,y0:n.y,w:n.w,h:n.h},I.classList.add("dragging"),I.setPointerCapture(t.pointerId)}function Pt(e,t){const n=f.sections.find(a=>a.id===e);return n&&(Object.assign(n,t),wt()),w("PATCH",`/__loop/api/sections/${e}`,t)}async function Ld(e){try{const t=await w("POST","/__loop/api/sections",e);f.sections.find(n=>n.id===t.id)||f.sections.push(t),G("Add section",()=>w("DELETE",`/__loop/api/sections/${t.id}`),()=>He({sections:[t]})),yi(t.id)}catch(t){y(t.message)}}const me=document.createElement("div");me.id="sec-menu",me.className="menu",me.hidden=!0,document.body.appendChild(me);function Cd(e,t){if(!me.hidden&&me._for===e){me.hidden=!0;return}const n=f.sections.find(c=>c.id===e);if(!n||!$())return;const a=an(n).length,i=`${a} frame${a===1?"":"s"}`;me._for=e,me.innerHTML=a?`<button class="menu-item" data-sm="keep"><span><b>Unsection</b><small>Its ${i} stay${a===1?"s":""} on the canvas \xB7 ${we.shift}${we.cmd}S</small></span></button>
107
+ <button class="menu-item danger" data-sm="all"><span><b>Delete section and its ${i}</b><small>Everything inside it goes too</small></span></button>`:'<button class="menu-item" data-sm="keep"><span><b>Delete section</b><small>It has no frames in it</small></span></button>',me.hidden=!1;const s=t.getBoundingClientRect(),o=me.offsetWidth,r=me.offsetHeight;me.style.left=`${Math.round(Math.max(12,Math.min(s.left,innerWidth-o-12)))}px`,me.style.top=`${Math.round(s.bottom+6+r>innerHeight-12?Math.max(12,s.top-r-6):s.bottom+6)}px`}me.addEventListener("pointerdown",e=>e.stopPropagation()),me.addEventListener("click",e=>{const t=e.target.closest("[data-sm]");if(!t)return;const n=me._for;me.hidden=!0,(t.dataset.sm==="all"?Or(n):bi(n)).catch(a=>y(a.message))}),addEventListener("pointerdown",e=>{!me.hidden&&!e.target.closest("#sec-menu, .sec-more")&&(me.hidden=!0)},!0),addEventListener("keydown",e=>{e.key==="Escape"&&!me.hidden&&(me.hidden=!0,e.stopPropagation())},!0);async function Or(e){const t=f.sections.find(o=>o.id===e);if(!t)return;const n={...t},a=an(t).map(o=>o.id),i=a.map(yt).filter(Boolean),s=()=>Promise.all([...a.map(o=>w("DELETE",`/__loop/api/frames/${o}`).catch(()=>{})),w("DELETE",`/__loop/api/sections/${e}`).catch(()=>{})]);ke=null,await s(),G("Delete section and its frames",()=>He({frames:i.flatMap(o=>o.frames),comments:i.flatMap(o=>o.comments),sections:[n]}),s),y(`Deleted \u201C${n.name}\u201D and ${a.length} frame${a.length===1?"":"s"} \xB7 \u2318Z to undo`,2800)}async function bi(e){const t=f.sections.find(a=>a.id===e);if(!t)return;const n={...t};ke=null,await w("DELETE",`/__loop/api/sections/${e}`),G("Delete section",()=>He({sections:[n]}),()=>w("DELETE",`/__loop/api/sections/${e}`)),y(`Removed \u201C${n.name}\u201D (its frames stay) \xB7 \u2318Z to undo`,2600)}function Rr(e){const t=Kt.querySelector(`.section[data-id="${e}"] .sec-name`),n=f.sections.find(a=>a.id===e);!t||!n||Xs(t,n.name,a=>{if(a){const i=n.name;Pt(e,{name:a}),G("Rename section",()=>Pt(e,{name:i}),()=>Pt(e,{name:a}))}ke===e&&(ke=null,wt())})}let P=null;const _n=e=>{const t=vi(e);return t.length?[...t,{id:"",now:!0,label:t[t.length-1].last,at:Date.now(),thumb:null}]:[]};function Ls(e,t){if(P?.fid===e&&t==null)return nt();nt();const n=D.get(e),a=f.frames.find(r=>r.id===e);if(!n||!a||!_n(e).length)return;F&&sn(),Md(e),te(),Re();const i=S?.fid===e;vt(e);const s=document.createElement("div");s.className="ver-strip top",s.innerHTML='<div class="vt-row"></div><div class="vt-acts"></div>',document.body.appendChild(s),P={fid:e,pin:t??null,hover:null,now:null,el:s,key:"",akey:"",back:null,staged:!i};const o=s.querySelector(".vt-row");s.addEventListener("pointerdown",r=>r.stopPropagation()),o.addEventListener("wheel",r=>{(Math.abs(r.deltaX)>Math.abs(r.deltaY)||r.shiftKey)&&r.stopPropagation()},{passive:!0}),s.addEventListener("click",r=>{const c=r.target.closest("[data-vs]"),l=r.target.closest("[data-v]");if(c)return Ed(c.dataset.vs);l&&(P.pin=l.dataset.v===""||P.pin===l.dataset.v?null:l.dataset.v,P.hover=null,Pn(),pa())}),Pn(),pa(),o.scrollLeft=o.scrollWidth,ct(En(a)),w("POST",`/__loop/api/frames/${e}/versions`).then(r=>{P?.el===s&&(P.now=r.now,Pn())}).catch(()=>{})}function Rd(){const e=f.frames.find(o=>o.id===P.fid);if(!e)return;const t=jt(e),n=64+P.el.offsetHeight+44,a=t.l<12||t.l+Math.min(t.w,P.el.offsetWidth)>innerWidth-12;if(t.t>=n&&t.t<innerHeight-160&&!a)return;const i=b.z,s={z:i,x:a?Math.max(24,(innerWidth-e.w*i)/2)-e.x*i:b.x,y:n-e.y*i};P.back={from:{...b},to:s},ct(s,320)}function Md(e){const t=j&&f.comments.find(n=>n.id===j);t&&t.frameId!==e&&ee()}function Pn(){if(!P)return;const{fid:e,el:t}=P,n=f.frames.find(d=>d.id===e),a=_n(e);if(!n||!a.length)return nt();P.pin&&!a.some(d=>d.id===P.pin)&&(P.pin=null);const i=n.w/n.h,s=52,o=Math.round(Math.min(104,Math.max(32,s*i))),r=a.map((d,u)=>{const p=d.now?P.now:d.thumb;return`<button class="vt${(d.now?!P.pin:P.pin===d.id)?" on":""}" data-v="${d.id}"><span class="vt-img" style="width:${o}px;height:${s}px">${p?`<img src="${L(p)}" alt="" draggable="false">`:""}</span><span class="vt-n">${u+1}</span></button>`}).join(""),c=t.querySelector(".vt-row");if(P.key!==r){const d=c.scrollLeft;P.key=r,c.innerHTML=r,c.scrollLeft=d}const l=P.pin&&$()?`<button class="vt-go" data-vs="back" title="Go back to this version (the one you are on is kept)">${A("undo")}<span>Go back</span></button><button class="vt-btn" data-vs="dup" title="Make this version its own frame">${Wn.copy}</button>`:"";if(P.akey!==l){P.akey=l;const d=t.querySelector(".vt-acts");d.innerHTML=l,d.hidden=!l}Nr(),fa()}const Nd=A("layers");function Nr(){if(!P)return;const e=_n(P.fid),t=P.hover!=null?P.hover:P.pin,n=t?e.findIndex(o=>o.id===t):e.length-1,a=e[n];if(!a)return;const i=`<b>${a.now?"Now":`v${n+1}`}</b><span>${L(a.label||"")}</span>${a.now?"":`<time>${Ut(a.at)}</time>`}`,s=P.el.querySelector(".vt-cap");s&&s._h!==i&&(s._h=i,s.innerHTML=i,s.title=a.label||"")}function pa(){if(!P)return;Nr();const{fid:e}=P,t=D.get(e),n=f.frames.find(p=>p.id===e);if(!t||!n)return;const a=P.hover!=null?P.hover:P.pin,i=t.el.querySelector(".frame-body");let s=i.querySelector(":scope > .ver-prev");const o=a?_n(e).find(p=>p.id===a):null;if(t.el.classList.toggle("previewing",!!o),!o){s&&(s.classList.remove("on"),setTimeout(()=>{s.classList.contains("on")||s.remove()},180));return}s||(s=document.createElement("div"),s.className="ver-prev",s.innerHTML='<img alt="" draggable="false"><iframe title=""></iframe>',i.appendChild(s),s.offsetWidth),s.classList.add("on");const r=s.querySelector("img"),c=s.querySelector("iframe"),l=`/__loop/hist/${o.id}/${encodeURIComponent(n.entry||"index.html")}`;o.thumb?(r.getAttribute("src")!==o.thumb&&(r.src=o.thumb),r.hidden=!1):r.hidden=!0;const d=P.pin===o.id,u=d||!o.thumb;s.classList.toggle("live",d),u?c.dataset.src!==l&&(c.dataset.src=l,c.classList.remove("ready"),s.classList.add("loading"),c.onload=()=>{c.classList.add("ready"),s.classList.remove("loading")},c.src=l):(s.classList.remove("loading"),c.dataset.src&&(c.dataset.src="",c.classList.remove("ready"),c.src="about:blank")),s.classList.toggle("bare",!o.thumb)}function nt(e){if(!P)return;const{fid:t,el:n,back:a,staged:i}=P;P=null,n.remove(),i&&S?.fid===t&&!e&&setTimeout(()=>{P||dt()},0);const s=D.get(t);s?.el.classList.remove("previewing"),s?.el.querySelector(".frame-body > .ver-prev")?.remove(),a&&!e&&Math.abs(b.x-a.to.x)<2&&Math.abs(b.y-a.to.y)<2&&Math.abs(b.z-a.to.z)<.004&&ct(a.from,300)}async function Ed(e){if(!P)return;const{fid:t,pin:n}=P,a=_n(t),i=a.findIndex(o=>o.id===n),s=f.frames.find(o=>o.id===t);if(e==="close")return nt();if(e==="stack")return nt(!0),Sd(t,n);if(!(i<0))try{if(e==="back")await w("POST",`/__loop/api/frames/${t}/versions/restore`,{id:n}),nt(),y("Back to that version. The one you were on is kept.",3200);else if(e==="dup"){const o=await w("POST",`/__loop/api/frames/${t}/versions/duplicate`,{id:n,name:`${s?.name||"Frame"} \xB7 v${i+1}`});nt(!0),f.frames.find(r=>r.id===o.id)?(Z(o.id),St(o.id)):Ue=o.id,y("That version is now its own frame")}}catch(o){y(o.message)}}addEventListener("keydown",e=>{if(!P||F||Ot()||e.metaKey||e.ctrlKey)return;if(e.key==="Escape"){e.stopPropagation(),e.preventDefault(),P.pin?(P.pin=null,Pn(),pa()):nt();return}if(e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;e.stopPropagation(),e.preventDefault();const t=_n(P.fid),n=P.pin?t.findIndex(o=>o.id===P.pin):t.length-1,a=t[Math.max(0,Math.min(t.length-1,n+(e.key==="ArrowRight"?1:-1)))];P.pin=a.now?null:a.id,P.hover=null,Pn(),pa();const i=P.el.querySelector(".vt-row"),s=i.querySelector(".vt.on");s&&(i.scrollLeft=Math.max(0,Math.min(s.offsetLeft-(i.clientWidth-s.offsetWidth)/2,i.scrollWidth)))},!0);let F=null;function vi(e){const t=f.frames.find(a=>a.id===e),n=[...f.comments.filter(a=>a.frameId===e&&a.snapshot&&!a.local&&a.status!=="working"&&a.status!=="queued").map(a=>({id:a.id,at:a.startedAt||a.createdAt,thumb:a.snapThumb,what:a.kind==="create"?"Created":a.text})),...(t?.restores||[]).map(a=>({id:a.id,at:a.at,thumb:a.thumb,what:a.what||"Went back to an earlier version"}))].sort((a,i)=>a.at-i.at);return n.map((a,i)=>({id:a.id,thumb:a.thumb,at:i?n[i-1].at:a.at,label:i?n[i-1].what:"Original",last:n[n.length-1].what}))}function Sd(e,t){const n=f.frames.find(k=>k.id===e),a=n&&vi(e).slice(-11);if(!n||!a.length||F)return;S&&dt(),ee(),te(),Re(),Z(null),xo(),nt(!0);const i=jt(n),s=132,o=96,r=Math.min((innerWidth-200)/n.w,(innerHeight-s-o)/n.h,1.2),c=n.w*r,l=n.h*r,d=(innerWidth-c)/2,u=s+(innerHeight-s-o-l)/2,p=[...a,{id:"",now:!0,label:a[a.length-1].last,at:Date.now(),thumb:null}].reverse(),h=t?Math.max(0,p.findIndex(k=>k.id===t)):0,g=document.createElement("div");g.id="versions",g.innerHTML=`<div class="vs-rig" style="left:${d}px;top:${u}px;width:${c}px;height:${l}px">
108
+ ${p.map((k,M)=>`<div class="vs-layer${M===h?" front":""}" data-i="${M}">${k.thumb?`<img src="${L(k.thumb)}" alt="" draggable="false">`:""}</div>`).join("")}
100
109
  <div class="vs-live"><iframe title="" style="width:${n.w}px;height:${n.h}px;transform:scale(${r})"></iframe></div></div>
101
- <div class="vs-bar"></div>`,document.body.appendChild(g),document.body.classList.add("versions-on"),N={fid:e,layers:p,el:g,at:h,liveT:null};const v=g.querySelector(".vs-rig");v.style.transform=`translate(${s.l-f}px, ${s.t-d}px) scale(${s.w/l})`,requestAnimationFrame(()=>requestAnimationFrame(()=>{N?.el===g&&(v.style.transform="",g.classList.add("open"),ta())})),w("POST",`/__loop/api/frames/${e}/versions`).then(x=>{!N||N.el!==g||(x.now&&rr(0,x.now),or())}).catch(x=>{N?.el===g&&(N.failed=x.message,g.classList.add("failed"),ar())}),g.addEventListener("pointerdown",x=>x.stopPropagation());let S=0,A=0;g.addEventListener("wheel",x=>{x.preventDefault(),x.stopPropagation(),S+=Math.abs(x.deltaY)>=Math.abs(x.deltaX)?x.deltaY:x.deltaX;const M=performance.now();Math.abs(S)>40&&M-A>170&&(es(S>0?1:-1),S=0,A=M)},{passive:!1}),g.addEventListener("click",x=>{const M=x.target.closest("[data-vc]");if(M)return Nc(M.dataset.vc);if(x.target.closest(".vs-bar, .vs-live"))return;const C=x.target.closest(".vs-layer");if(C){+C.dataset.i!==N.at&&(N.at=+C.dataset.i,ta());return}Zt()})}function es(e){if(!N)return;const t=Math.max(0,Math.min(N.layers.length-1,N.at+e));t!==N.at&&(N.at=t,ta())}function ta(){if(!N)return;const{el:e,layers:t,at:n,fid:i}=N,s=u.frames.find(c=>c.id===i);e.querySelectorAll(".vs-layer").forEach(c=>{const f=+c.dataset.i-n,d=f<0||f>3;c.classList.toggle("front",f===0),c.classList.toggle("gone",d),c.style.transform=f<0?"translate3d(0, 48px, 260px)":`translate3d(0, ${-f*22}px, ${-f*150}px)`,c.style.opacity=d?"0":"1",c.style.filter=f>0&&!d?`brightness(${(1-f*.09).toFixed(2)})`:"",c.style.zIndex=String(100-Math.abs(f))}),ar();const a=e.querySelector(".vs-live"),o=a.querySelector("iframe"),r=t[n];if(a.classList.remove("ready"),clearTimeout(N.liveT),!s||!r)return;const l=r.now?`/__loop/f/${s.id}/${encodeURIComponent(s.entry||"index.html")}?_v=${Date.now()}`:`/__loop/hist/${r.id}/${encodeURIComponent(s.entry||"index.html")}`;N.liveT=setTimeout(()=>{N?.el!==e||N.at!==n||(o.onload=()=>{N?.el===e&&N.at===n&&a.classList.add("ready")},o.src=l)},460)}function ar(){if(!N)return;const{el:e,layers:t,at:n}=N,i=t.length,s=t[n],a=s.now?"Now":`v${i-n}`;e.querySelector(".vs-bar").innerHTML=`
102
- <button class="sb-btn" data-vc="older" title="Older version (\u2190)" ${n>=i-1?"disabled":""}>${T("left")}</button>
103
- <div class="vs-pos"><b>${a}</b><span>${i-n} of ${i}</span></div>
104
- <button class="sb-btn" data-vc="newer" title="Newer version (\u2192)" ${n<=0?"disabled":""}>${T("right")}</button>
110
+ <div class="vs-bar"></div>`,document.body.appendChild(g),document.body.classList.add("versions-on"),F={fid:e,layers:p,el:g,at:h,liveT:null};const v=g.querySelector(".vs-rig");v.style.transform=`translate(${i.l-d}px, ${i.t-u}px) scale(${i.w/c})`,requestAnimationFrame(()=>requestAnimationFrame(()=>{F?.el===g&&(v.style.transform="",g.classList.add("open"),Cs())})),w("POST",`/__loop/api/frames/${e}/versions`).then(k=>{!F||F.el!==g||(k.now&&Wr(0,k.now),Fr())}).catch(k=>{F?.el===g&&(F.failed=k.message,g.classList.add("failed"),Br())}),g.addEventListener("pointerdown",k=>k.stopPropagation());let T=0,C=0;g.addEventListener("wheel",k=>{k.preventDefault(),k.stopPropagation(),T+=Math.abs(k.deltaY)>=Math.abs(k.deltaX)?k.deltaY:k.deltaX;const M=performance.now();Math.abs(T)>40&&M-C>170&&(wi(T>0?1:-1),T=0,C=M)},{passive:!1}),g.addEventListener("click",k=>{const M=k.target.closest("[data-vc]");if(M)return Td(M.dataset.vc);if(k.target.closest(".vs-bar, .vs-live"))return;const E=k.target.closest(".vs-layer");if(E){+E.dataset.i!==F.at&&(F.at=+E.dataset.i,Cs());return}sn()})}function wi(e){if(!F)return;const t=Math.max(0,Math.min(F.layers.length-1,F.at+e));t!==F.at&&(F.at=t,Cs())}function Cs(){if(!F)return;const{el:e,layers:t,at:n,fid:a}=F,i=f.frames.find(l=>l.id===a);e.querySelectorAll(".vs-layer").forEach(l=>{const d=+l.dataset.i-n,u=d<0||d>3;l.classList.toggle("front",d===0),l.classList.toggle("gone",u),l.style.transform=d<0?"translate3d(0, 48px, 260px)":`translate3d(0, ${-d*22}px, ${-d*150}px)`,l.style.opacity=u?"0":"1",l.style.filter=d>0&&!u?`brightness(${(1-d*.09).toFixed(2)})`:"",l.style.zIndex=String(100-Math.abs(d))}),Br();const s=e.querySelector(".vs-live"),o=s.querySelector("iframe"),r=t[n];if(s.classList.remove("ready"),clearTimeout(F.liveT),!i||!r)return;const c=r.now?`/__loop/f/${i.id}/${encodeURIComponent(i.entry||"index.html")}?_v=${Date.now()}`:`/__loop/hist/${r.id}/${encodeURIComponent(i.entry||"index.html")}`;F.liveT=setTimeout(()=>{F?.el!==e||F.at!==n||(o.onload=()=>{F?.el===e&&F.at===n&&s.classList.add("ready")},o.src=c)},460)}function Br(){if(!F)return;const{el:e,layers:t,at:n}=F,a=t.length,i=t[n],s=i.now?"Now":`v${a-n}`;e.querySelector(".vs-bar").innerHTML=`
111
+ <button class="sb-btn" data-vc="older" title="Older version (\u2190)" ${n>=a-1?"disabled":""}>${A("left")}</button>
112
+ <div class="vs-pos"><b>${s}</b><span>${a-n} of ${a}</span></div>
113
+ <button class="sb-btn" data-vc="newer" title="Newer version (\u2192)" ${n<=0?"disabled":""}>${A("right")}</button>
105
114
  <span class="sb-sep"></span>
106
- <div class="vs-what" title="${L(s.label||"")}"><span>${N.failed?`The pictures could not be made (${L(N.failed)})`:L(s.label||"")}</span>${s.now?"":`<time>${jt(s.at)}</time>`}</div>
107
- ${k()&&!s.now?`<span class="sb-sep"></span>
108
- <button class="sb-tog" data-vc="restore" title="Go back to this version (the one you are on is kept)">${T("undo")}<span>Go back to it</span></button>
109
- <button class="sb-btn" data-vc="duplicate" title="Make this version its own frame on the canvas">${T("copy")}</button>`:""}
115
+ <div class="vs-what" title="${L(i.label||"")}"><span>${F.failed?`The pictures could not be made (${L(F.failed)})`:L(i.label||"")}</span>${i.now?"":`<time>${Ut(i.at)}</time>`}</div>
116
+ ${$()&&!i.now?`<span class="sb-sep"></span>
117
+ <button class="sb-tog" data-vc="restore" title="Go back to this version (the one you are on is kept)">${A("undo")}<span>Go back to it</span></button>
118
+ <button class="sb-btn" data-vc="duplicate" title="Make this version its own frame on the canvas">${A("copy")}</button>`:""}
110
119
  <span class="sb-sep"></span>
111
- <button class="sb-btn" data-vc="exit" title="Close (esc)">${T("x")}</button>`}async function Nc(e){if(!N)return;const t=N.at,n=N.layers[t],i=N.layers.length,s=N.fid,a=u.frames.find(o=>o.id===s);if(e==="exit")return Zt();if(e==="older")return es(1);if(e==="newer")return es(-1);if(!(!n||n.now))try{if(e==="duplicate"){const o=await w("POST",`/__loop/api/frames/${s}/versions/duplicate`,{id:n.id,name:`${a?.name||"Frame"} \xB7 v${i-t}`});Zt(!0),u.frames.find(r=>r.id===o.id)?(ie(o.id),Tt(o.id)):Ze=o.id,b(`v${i-t} is now its own frame`)}else e==="restore"&&(await w("POST",`/__loop/api/frames/${s}/versions/restore`,{id:n.id}),Zt(),b(`Back to v${i-t}. The version you were on is kept.`,3200))}catch(o){b(o.message)}}function or(){if(!N)return;const e=Ji(N.fid);N.layers.forEach((t,n)=>{const i=!t.now&&e.find(s=>s.id===t.id)?.thumb;i&&rr(n,i)})}function rr(e,t){const n=N?.el.querySelector(`.vs-layer[data-i="${e}"]`);if(!n)return;let i=n.querySelector("img");i||(i=document.createElement("img"),i.alt="",i.draggable=!1,n.appendChild(i)),i.getAttribute("src")!==t&&(i.src=t)}function Zt(e){if(!N)return;const{el:t,fid:n}=N;clearTimeout(N.liveT),N=null;const i=u.frames.find(a=>a.id===n),s=t.querySelector(".vs-rig");if(t.classList.remove("open"),t.classList.add("closing"),i&&s&&!e){const a=Ot(i),o=parseFloat(s.style.left),r=parseFloat(s.style.top),l=parseFloat(s.style.width);s.style.transform=`translate(${a.l-o}px, ${a.t-r}px) scale(${a.w/l})`}document.body.classList.remove("versions-on"),setTimeout(()=>t.remove(),380)}addEventListener("keydown",e=>{N&&(e.key==="Escape"?(e.stopPropagation(),e.preventDefault(),Zt()):/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&!Et()&&(e.stopPropagation(),e.preventDefault(),es(e.key==="ArrowLeft"||e.key==="ArrowUp"?1:-1)))},!0),addEventListener("resize",()=>Zt());let Gt=null;async function ts(e,t){try{const n=H.get(e),i=n&&!n.parked?si(n):n?.resume,s=await w("POST",`/__loop/api/frames/${e}/duplicate`,{...t?{x:Math.round(t.x),y:Math.round(t.y)}:{},...i?{route:i}:{}});let a=null;Z("Duplicate frame",async()=>{a=_t(s.id)||a,await w("DELETE",`/__loop/api/frames/${s.id}`)},()=>je(a||{frames:[s]})),u.frames.find(o=>o.id===s.id)?(ie(s.id),Tt(s.id)):Ze=s.id}catch(n){b(n.message)}}addEventListener("keydown",e=>{e.key==="Alt"&&q.classList.add("alt")}),addEventListener("keydown",e=>{const t=document.activeElement,n=Et()&&(t.value??t.textContent??"").trim();if(e.key!=="Enter"||!e[lt]||n||!k())return;const i=[...document.querySelectorAll('.pin.needs[data-act="background"], .wait-pill')];if(!i.length)return;const s=(o=>{const r=o.getBoundingClientRect();return r.right>0&&r.bottom>0&&r.left<innerWidth&&r.top<innerHeight?Math.hypot(r.left+r.width/2-innerWidth/2,r.top+r.height/2-innerHeight/2):1/0}),a=i.find(o=>o.dataset.key===W)||i.filter(o=>s(o)<1/0).sort((o,r)=>s(o)-s(r))[0];a&&(e.preventDefault(),(a.querySelector(".pin-act")||a.querySelector("button"))?.click())}),addEventListener("keyup",e=>{e.key==="Alt"&&q.classList.remove("alt")}),addEventListener("blur",()=>q.classList.remove("alt"));const Bc=[["Tools",[["V","Select: frames, and the elements inside them"],["Click, then click again","Select an element, then the one inside it, level by level"],["Hold \u2318","Reach the exact element under the pointer, however deep"],["\u2190 \u2192 \u2191 \u2193 on an element","Move it past its neighbour, following its layout"],["Drag a selected element","Drop it in any gap, in any container; out of the frame makes it a frame of its own"],["\u2318-drag a selected element","Place it freely: it leaves the layout and stays where you put it"],["\u2318D on an element","Duplicate it, right after itself"],["I","Interact: click, type and scroll in the pages"],["Scroll in a frame you\u2019re using","Up/down scrolls its page; sideways moves the canvas"],["H / hold Space","Pan"],["F","Frame (presets, or drag to draw)"],["\u21E7S","Section: drag a region that holds frames"],["C","Comment (click = pin, drag = area)"],["C, then hold \u2318","Comment on a block: hover to outline it, click to comment"],["\u21E7C","Hide / show comments"],["D","Deep select: pick exact elements (\u21E7 for more)"],["P","Draw"],["E","Erase marks"],["N","Describe a frame for the agent"]]],["Edit",[["\u2318Z","Undo"],["\u21E7\u2318Z / Ctrl Y","Redo"],["\u2325 drag title","Duplicate frame"],["\u2318C / \u2318V","Copy / paste frame"],["\u2318D","Duplicate in place"],["\u21E7\u2318C","Copy a frame as an image"],["Drop / \u2318V","Put an image, a web address or an HTML file on the canvas"],["\u21E7F","Freeze a copy (keeps this moment)"],["K","Phone keyboard on / off"],["\u21E7 click / drag box","Select several frames"],["\u2318A","Select all frames"],["\u2325A \u2325H \u2325D","Align left / centre / right"],["\u2325W \u2325V \u2325S","Align top / middle / bottom"],["Delete","Delete selected frame"],["Double-click title","Rename frame"],["Click the size by a title","Size & device presets"],["Esc","Close / deselect"]]],["View",[["Pinch / \u2318 scroll","Zoom"],["Scroll","Pan"],["\u21E71","Fit everything"],["\u21E72","Zoom to the selection"],["Arrows / \u21E7 arrows","Nudge the selection 1px / 10px"],["\u21E7 drag","Move straight across or up/down"],["\u23180","Zoom to 100%"],["+ / \u2212","Zoom in / out"]]],["Comments",[["\u21B5","Send to the agent"],["\u21E7\u21B5","New line"],["?","This list"]]]];function lr(e){let t=m("#shortcuts");t||(t=document.createElement("div"),t.id="shortcuts",t.className="modal",t.hidden=!0,t.innerHTML=`<div class="modal-card sc-card"><div class="modal-head"><span>Keyboard shortcuts</span><button class="icon-btn" data-close>\xD7</button></div>
112
- <div class="sc-grid">${Bc.map(([n,i])=>`<div><div class="sc-group">${n}</div>${i.map(([s,a])=>`<div class="sc-row"><span>${L(a)}</span><span class="sc-keys">${s.split(" / ").map(o=>`<kbd>${L(o)}</kbd>`).join(" ")}</span></div>`).join("")}</div>`).join("")}</div>
113
- <div class="sc-tips"><div class="sc-group">Tips</div><button class="sc-tip" data-tip="deep"><span><b>Go straight to it</b>Hold \u2318 to pick whatever is under the pointer, however deep</span><em>Show</em></button></div></div>`,document.body.appendChild(t),t.querySelector('[data-tip="deep"]').addEventListener("click",()=>{t.hidden=!0,Mo(innerWidth/2-136,innerHeight/2-120,!0)}),t.addEventListener("pointerdown",n=>{(n.target===t||n.target.closest("[data-close]"))&&(t.hidden=!0)})),t.hidden=e===void 0?!t.hidden:!e}addEventListener("keydown",e=>{Et()||(e.key==="?"?(e.preventDefault(),lr()):e.key==="Escape"&&m("#shortcuts")&&!m("#shortcuts").hidden&&lr(!1))});function cr(e){const t=u.frames.find(i=>i.id===I),n=e.value.trim();if(t&&n&&n!==t.name){const i=t.name,s=t.id;t.name=n,Q(t),w("PATCH",`/__loop/api/frames/${s}`,{name:n}).catch(a=>b(a.message)),Z("Rename frame",()=>At(s,{name:i}),()=>At(s,{name:n}))}}m("#frame-panel").addEventListener("change",e=>{e.target.id==="fp-name"&&cr(e.target)}),m("#frame-panel").addEventListener("keydown",e=>{e.target.id==="fp-name"&&e.key==="Enter"&&(cr(e.target),e.target.blur())},!0),m("#history-btn").addEventListener("click",e=>{e.stopPropagation(),Fc()});async function Fc(e){let t=m("#hist-pop");if(t&&e!==!0){t.remove();return}t||(t=document.createElement("div"),t.id="hist-pop",document.body.appendChild(t),t.addEventListener("pointerdown",o=>o.stopPropagation())),t.innerHTML='<div class="hp-head">Canvas history</div><div class="hp-list"><div class="hp-empty">Loading\u2026</div></div>';const n=m("#history-btn").getBoundingClientRect();t.style.left=`${n.left}px`,t.style.top=`${n.bottom+8}px`;let i=[];try{i=(await w("GET","/__loop/api/canvas-history")).items}catch(o){b(o.message)}const s=o=>{const r=new Date(o);return(new Date().toDateString()===r.toDateString()?"":r.toLocaleDateString([],{month:"short",day:"numeric"})+", ")+r.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})},a=o=>o==="before restoring"?"Before a restore":o==="before a change"?"Before frames or comments went":"";t.querySelector(".hp-list").innerHTML=i.length?i.map(o=>`<div class="hp-row"><span><b>${s(o.at)}</b><small>${a(o.label)?`${a(o.label)} \xB7 `:""}${o.frames} frame${o.frames===1?"":"s"}, ${o.comments} comment${o.comments===1?"":"s"}${o.names.length?` \xB7 ${L(o.names.join(", "))}`:""}</small></span><button data-restore="${o.id}">Restore</button></div>`).join(""):'<div class="hp-empty">Nothing kept yet. Loop keeps the canvas as it was before frames or comments go, and every ten minutes while you work.</div>',t.querySelectorAll("[data-restore]").forEach(o=>o.addEventListener("click",async()=>{try{const r=await w("POST",`/__loop/api/canvas-history/${o.dataset.restore}/restore`);t.remove(),b(`Restored (${r.frames} frames). What was there before is in the history too.`,3200)}catch(r){b(r.message)}}))}addEventListener("pointerdown",e=>{const t=m("#hist-pop");t&&!t.contains(e.target)&&!e.target.closest("#history-btn")&&t.remove()}),m("#canvas-name").addEventListener("click",()=>{const e=m("#canvas-name");if(!k()||X||e.querySelector("input"))return;const t=document.createElement("input");t.className="canvas-rename",t.value=u.name,t.spellcheck=!1,e.replaceChildren(t),t.focus(),t.select();const n=i=>{const s=t.value.trim();if(e.textContent=i&&s?s:u.name,i&&s&&s!==u.name){const a=u.name;u.name=s,w("POST","/__loop/api/settings",{name:s}).catch(o=>b(o.message)),Z("Rename canvas",()=>w("POST","/__loop/api/settings",{name:a}),()=>w("POST","/__loop/api/settings",{name:s}))}};t.addEventListener("keydown",i=>{i.stopPropagation(),i.key==="Enter"&&t.blur(),i.key==="Escape"&&(t.value=u.name,t.blur())}),t.addEventListener("blur",()=>n(!0))}),addEventListener("resize",()=>Ce()),Ml(),we("select"),se(),hr();const Ue=document.createElement("div");Ue.id="tip",Ue.hidden=!0,document.body.appendChild(Ue);let Qt=null,na=null,ia=0;function Gn(){clearTimeout(na),na=null,Qt&&!Ue.hidden&&(ia=Date.now()),Qt=null,Ue.hidden=!0}function Wc(e,t){if(!e.isConnected)return Gn();const n=/^(.*\S)\s+\(([^()]{1,14})\)$/.exec(t);Ue.innerHTML=n?`${L(n[1])}<kbd>${L(n[2])}</kbd>`:L(t),Ue.hidden=!1;const i=e.getBoundingClientRect(),s=Ue.offsetWidth,a=Ue.offsetHeight,o=i.bottom+8+a<innerHeight-6&&i.top<innerHeight*.6;Ue.style.left=`${Math.round(Math.max(8,Math.min(i.left+i.width/2-s/2,innerWidth-s-8)))}px`,Ue.style.top=`${Math.round(o?i.bottom+8:i.top-a-8)}px`,Ue.classList.toggle("up",!o)}document.addEventListener("pointerover",e=>{const t=e.target.closest?.("[title]:not(iframe), [data-tip]");if(t===Qt||(Gn(),!t||e.pointerType==="touch"))return;t.title&&(t.dataset.tip=t.title,!t.getAttribute("aria-label")&&!t.textContent.trim()&&t.setAttribute("aria-label",t.title),t.removeAttribute("title"));const n=t.dataset.tip;n&&(Qt=t,na=setTimeout(()=>Wc(t,n),Date.now()-ia<700?0:260))},!0),document.addEventListener("pointerout",e=>{Qt&&!Qt.contains(e.relatedTarget)&&Gn()},!0);for(const e of["pointerdown","wheel","keydown"])addEventListener(e,()=>{Qt&&(Gn(),ia=0)},{capture:!0,passive:!0});
120
+ <button class="sb-btn" data-vc="exit" title="Close (esc)">${A("x")}</button>`}async function Td(e){if(!F)return;const t=F.at,n=F.layers[t],a=F.layers.length,i=F.fid,s=f.frames.find(o=>o.id===i);if(e==="exit")return sn();if(e==="older")return wi(1);if(e==="newer")return wi(-1);if(!(!n||n.now))try{if(e==="duplicate"){const o=await w("POST",`/__loop/api/frames/${i}/versions/duplicate`,{id:n.id,name:`${s?.name||"Frame"} \xB7 v${a-t}`});sn(!0),f.frames.find(r=>r.id===o.id)?(Z(o.id),St(o.id)):Ue=o.id,y(`v${a-t} is now its own frame`)}else e==="restore"&&(await w("POST",`/__loop/api/frames/${i}/versions/restore`,{id:n.id}),sn(),y(`Back to v${a-t}. The version you were on is kept.`,3200))}catch(o){y(o.message)}}function Fr(){if(!F)return;const e=vi(F.fid);F.layers.forEach((t,n)=>{const a=!t.now&&e.find(i=>i.id===t.id)?.thumb;a&&Wr(n,a)})}function Wr(e,t){const n=F?.el.querySelector(`.vs-layer[data-i="${e}"]`);if(!n)return;let a=n.querySelector("img");a||(a=document.createElement("img"),a.alt="",a.draggable=!1,n.appendChild(a)),a.getAttribute("src")!==t&&(a.src=t)}function sn(e){if(!F)return;const{el:t,fid:n}=F;clearTimeout(F.liveT),F=null;const a=f.frames.find(s=>s.id===n),i=t.querySelector(".vs-rig");if(t.classList.remove("open"),t.classList.add("closing"),a&&i&&!e){const s=jt(a),o=parseFloat(i.style.left),r=parseFloat(i.style.top),c=parseFloat(i.style.width);i.style.transform=`translate(${s.l-o}px, ${s.t-r}px) scale(${s.w/c})`}document.body.classList.remove("versions-on"),setTimeout(()=>t.remove(),380)}addEventListener("keydown",e=>{F&&(e.key==="Escape"?(e.stopPropagation(),e.preventDefault(),sn()):/^Arrow(Left|Right|Up|Down)$/.test(e.key)&&!Ot()&&(e.stopPropagation(),e.preventDefault(),wi(e.key==="ArrowLeft"||e.key==="ArrowUp"?1:-1)))},!0),addEventListener("resize",()=>sn());let Xe=null;async function qn(e,t){try{const n=D.get(e),a=n&&!n.parked?Dn(n):n?.resume,i=await w("POST",`/__loop/api/frames/${e}/duplicate`,{...t?{x:Math.round(t.x),y:Math.round(t.y)}:{},...a?{route:a}:{}});let s=null;G("Duplicate frame",async()=>{s=yt(i.id)||s,await w("DELETE",`/__loop/api/frames/${i.id}`)},()=>He(s||{frames:[i]})),f.frames.find(o=>o.id===i.id)?(Z(i.id),St(i.id)):Ue=i.id}catch(n){y(n.message)}}addEventListener("keydown",e=>{e.key==="Alt"&&I.classList.add("alt")}),addEventListener("keydown",e=>{const t=document.activeElement,n=Ot()&&(t.value??t.textContent??"").trim();if(e.key!=="Enter"||!e[rt]||n||!$())return;const a=[...document.querySelectorAll('.pin.needs[data-act="background"], .wait-pill')];if(!a.length)return;const i=(o=>{const r=o.getBoundingClientRect();return r.right>0&&r.bottom>0&&r.left<innerWidth&&r.top<innerHeight?Math.hypot(r.left+r.width/2-innerWidth/2,r.top+r.height/2-innerHeight/2):1/0}),s=a.find(o=>o.dataset.key===j)||a.filter(o=>i(o)<1/0).sort((o,r)=>i(o)-i(r))[0];s&&(e.preventDefault(),(s.querySelector(".pin-act")||s.querySelector("button"))?.click())}),addEventListener("keyup",e=>{e.key==="Alt"&&I.classList.remove("alt")}),addEventListener("blur",()=>I.classList.remove("alt"));const Ad=[["Tools",[["V","Select: frames, and the elements inside them"],["Click","Select the thing under the pointer: a button, a card, an image, a text"],["Click again / Esc","One level in / one level out"],["Hold \u2318","Reach the exact element under the pointer, however deep"],["\u2190 \u2192 \u2191 \u2193 on an element","Move it past its neighbour, following its layout"],["Drag a selected element","Drop it in any gap, in any container; out of the frame makes it a frame of its own"],["\u2318-drag a selected element","Place it freely: it leaves the layout and stays where you put it"],["\u2318D on an element","Duplicate it, right after itself"],["X","Interact: click, type and scroll in the pages"],["Scroll in a frame you\u2019re using","Up/down scrolls its page; sideways moves the canvas"],["H / hold Space","Pan"],["F","Frame (presets, or drag to draw)"],["S","Open the selected frame on stage (S again to leave)"],["\u21E7\u2318S","Unsection: remove the section, keep its frames"],["\u21E7\u2318F","Unframe: remove the frame, keep what is inside"],["\u21E7S","Section: drag a region that holds frames"],["C","Comment (click = pin, drag = area)"],["C, then hold \u2318","Comment on a block: hover to outline it, click to comment"],["\u21E7C","Hide / show comments"],["D","Deep select: pick exact elements (\u21E7 for more)"],["P","Draw"],["E","Erase marks"],["N","Describe a frame for the agent"]]],["Edit",[["\u2318Z","Undo"],["\u21E7\u2318Z / Ctrl Y","Redo"],["\u2325 drag title","Duplicate frame"],["\u2318C / \u2318V","Copy / paste frame"],["\u2318D","Duplicate in place"],["\u21E7\u2318C","Copy a frame as an image"],["\u21E7\u2318L","Copy a link to the frame or element"],["Right-click","Everything you can do with what is under the pointer"],["Drop / \u2318V","Put an image, a web address or an HTML file on the canvas"],["\u21E7F","Freeze a copy (keeps this moment)"],["K","Phone keyboard on / off"],["\u21E7 click / drag box","Select several frames"],["\u2318A","Select all frames"],["\u2325A \u2325H \u2325D","Align left / centre / right"],["\u2325W \u2325V \u2325S","Align top / middle / bottom"],["Delete","Delete selected frame"],["Double-click title","Rename frame"],["Click the size by a title","Size & device presets"],["Esc","Close / deselect"]]],["View",[["Pinch / \u2318 scroll","Zoom"],["Scroll","Pan"],["\u21E71","Fit everything"],["\u21E72","Zoom to the selection"],["Arrows / \u21E7 arrows","Nudge the selection 1px / 10px"],["\u21E7 drag","Move straight across or up/down"],["\u23180","Zoom to 100%"],["+ / \u2212","Zoom in / out"]]],["Comments",[["\u21B5","Send to the agent"],["\u21E7\u21B5","New line"],["?","This list"]]]];function Ms(e){let t=m("#shortcuts");t||(t=document.createElement("div"),t.id="shortcuts",t.className="modal",t.hidden=!0,t.innerHTML=`<div class="modal-card sc-card"><div class="modal-head"><span>Keyboard shortcuts</span><button class="icon-btn" data-close>\xD7</button></div>
121
+ <div class="sc-grid">${Ad.map(([n,a])=>`<div><div class="sc-group">${n}</div>${a.map(([i,s])=>`<div class="sc-row"><span>${L(s)}</span><span class="sc-keys">${i.split(" / ").map(o=>`<kbd>${L(o)}</kbd>`).join(" ")}</span></div>`).join("")}</div>`).join("")}</div>
122
+ <div class="sc-tips"><div class="sc-group">Tips</div><button class="sc-tip" data-tip="deep"><span><b>Go straight to it</b>Hold \u2318 to pick whatever is under the pointer, however deep</span><em>Show</em></button></div></div>`,document.body.appendChild(t),t.querySelector('[data-tip="deep"]').addEventListener("click",()=>{t.hidden=!0,tr(innerWidth/2-136,innerHeight/2-120,!0)}),t.addEventListener("pointerdown",n=>{(n.target===t||n.target.closest("[data-close]"))&&(t.hidden=!0)})),t.hidden=e===void 0?!t.hidden:!e}addEventListener("keydown",e=>{Ot()||(e.key==="?"?(e.preventDefault(),Ms()):e.key==="Escape"&&m("#shortcuts")&&!m("#shortcuts").hidden&&Ms(!1))});function jr(e){const t=f.frames.find(a=>a.id===_),n=e.value.trim();if(t&&n&&n!==t.name){const a=t.name,i=t.id;t.name=n,J(t),w("PATCH",`/__loop/api/frames/${i}`,{name:n}).catch(s=>y(s.message)),G("Rename frame",()=>Rt(i,{name:a}),()=>Rt(i,{name:n}))}}m("#frame-panel").addEventListener("change",e=>{e.target.id==="fp-name"&&jr(e.target)}),m("#frame-panel").addEventListener("keydown",e=>{e.target.id==="fp-name"&&e.key==="Enter"&&(jr(e.target),e.target.blur())},!0),m("#history-btn").addEventListener("click",e=>{e.stopPropagation(),Kr()});async function Kr(e){let t=m("#hist-pop");if(t&&e!==!0){t.remove();return}t||(t=document.createElement("div"),t.id="hist-pop",document.body.appendChild(t),t.addEventListener("pointerdown",o=>o.stopPropagation())),t.innerHTML='<div class="hp-head">Canvas history</div><div class="hp-list"><div class="hp-empty">Loading\u2026</div></div>';const n=m("#history-btn").getBoundingClientRect();t.style.left=`${n.left}px`,t.style.top=`${n.bottom+8}px`;let a=[];try{a=(await w("GET","/__loop/api/canvas-history")).items}catch(o){y(o.message)}const i=o=>{const r=new Date(o);return(new Date().toDateString()===r.toDateString()?"":r.toLocaleDateString([],{month:"short",day:"numeric"})+", ")+r.toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})},s=o=>o==="before restoring"?"Before a restore":o==="before a change"?"Before frames or comments went":"";t.querySelector(".hp-list").innerHTML=a.length?a.map(o=>`<div class="hp-row"><span><b>${i(o.at)}</b><small>${s(o.label)?`${s(o.label)} \xB7 `:""}${o.frames} frame${o.frames===1?"":"s"}, ${o.comments} comment${o.comments===1?"":"s"}${o.names.length?` \xB7 ${L(o.names.join(", "))}`:""}</small></span><button data-restore="${o.id}">Restore</button></div>`).join(""):'<div class="hp-empty">Nothing kept yet. Loop keeps the canvas as it was before frames or comments go, and every ten minutes while you work.</div>',t.querySelectorAll("[data-restore]").forEach(o=>o.addEventListener("click",async()=>{try{const r=await w("POST",`/__loop/api/canvas-history/${o.dataset.restore}/restore`);t.remove(),y(`Restored (${r.frames} frames). What was there before is in the history too.`,3200)}catch(r){y(r.message)}}))}addEventListener("pointerdown",e=>{const t=m("#hist-pop");t&&!t.contains(e.target)&&!e.target.closest("#history-btn")&&t.remove()}),m("#canvas-name").addEventListener("click",()=>{const e=m("#canvas-name");if(!$()||X||e.querySelector("input"))return;const t=document.createElement("input");t.className="canvas-rename",t.value=f.name,t.spellcheck=!1,e.replaceChildren(t),t.focus(),t.select();const n=a=>{const i=t.value.trim();if(e.textContent=a&&i?i:f.name,a&&i&&i!==f.name){const s=f.name;f.name=i,w("POST","/__loop/api/settings",{name:i}).catch(o=>y(o.message)),G("Rename canvas",()=>w("POST","/__loop/api/settings",{name:s}),()=>w("POST","/__loop/api/settings",{name:i}))}};t.addEventListener("keydown",a=>{a.stopPropagation(),a.key==="Enter"&&t.blur(),a.key==="Escape"&&(t.value=f.name,t.blur())}),t.addEventListener("blur",()=>n(!0))}),addEventListener("resize",()=>_e()),pc(),Ee("select"),ie(),Gr();const at=document.createElement("div");at.id="tip",at.hidden=!0,document.body.appendChild(at);let on=null,Es=null,Ss=0;function ma(){clearTimeout(Es),Es=null,on&&!at.hidden&&(Ss=Date.now()),on=null,at.hidden=!0}function _d(e,t){if(!e.isConnected)return ma();const n=/^(.*\S)\s+\(([^()]{1,14})\)$/.exec(t);at.innerHTML=n?`${L(n[1])}<kbd>${L(n[2])}</kbd>`:L(t),at.hidden=!1;const a=e.getBoundingClientRect(),i=at.offsetWidth,s=at.offsetHeight,o=a.bottom+8+s<innerHeight-6&&a.top<innerHeight*.6;at.style.left=`${Math.round(Math.max(8,Math.min(a.left+a.width/2-i/2,innerWidth-i-8)))}px`,at.style.top=`${Math.round(o?a.bottom+8:a.top-s-8)}px`,at.classList.toggle("up",!o)}document.addEventListener("pointerover",e=>{const t=e.target.closest?.("[title]:not(iframe), [data-tip]");if(t===on||(ma(),!t||e.pointerType==="touch"))return;t.title&&(t.dataset.tip=t.title,!t.getAttribute("aria-label")&&!t.textContent.trim()&&t.setAttribute("aria-label",t.title),t.removeAttribute("title"));const n=t.dataset.tip;n&&(on=t,Es=setTimeout(()=>_d(t,n),Date.now()-Ss<700?0:260))},!0),document.addEventListener("pointerout",e=>{on&&!on.contains(e.relatedTarget)&&ma()},!0);for(const e of["pointerdown","wheel","keydown"])addEventListener(e,()=>{on&&(ma(),Ss=0)},{capture:!0,passive:!0});