Humuhumu33 commited on
Commit
3e4ec4c
Β·
verified Β·
1 Parent(s): 643981a

APP-EXODUS E3 prep: backfill 16 current b/ bodies to sha256 mirror (mirror-first before any CAS exodus)

Browse files
sha256/026c320b1e9de27af7ac42d21d1544035c409fb4c1912507bac0eb28811ca34e ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // messenger-skin.mjs β€” bakes the SLACK re-tone as the messenger default (aubergine chrome + a floating,
2
+ // inset content pane; see the data-skin="slack" block in messenger-skins) and applies the hi-DPI /
3
+ // high-FPS perf layer. No picker / no toggle. Additive + guarded. Escape hatch: set localStorage
4
+ // "holo.skin" to graphite | warm | contrast | light (or "" to remove) to override the default.
5
+
6
+ (function () {
7
+ if (!document.querySelector("link[data-holo-skins]")) {
8
+ const l = document.createElement("link"); l.rel = "stylesheet"; l.href = new URL("./messenger-skins.css?v=d76d596376d1", import.meta.url); l.setAttribute("data-holo-skins", "1"); document.head.appendChild(l);
9
+ }
10
+ let skin = "whatsapp";
11
+ try { const s = localStorage.getItem("holo.skin"); if (s) skin = s; } catch {}
12
+ // ?skin=aim β€” the AIM opt-in for THIS visit (session-only; the saved default is untouched)
13
+ try { const q = new URLSearchParams(location.search).get("skin"); if (q) skin = q; } catch {}
14
+ if (skin) document.documentElement.setAttribute("data-skin", skin); else document.documentElement.removeAttribute("data-skin");
15
+ // the AIM experience layer (buddy list Β· sign-on Β· away Β· door sounds, A0-A5) rides ONLY its own skin β€”
16
+ // every other skin pays nothing. Lazy + fail-soft, the holo-msg-mount idiom.
17
+ if (skin === "aim") { try { import("./holo-aim.mjs?v=aim1").catch(() => {}); } catch {} }
18
+ // remove any lingering picker + its persisted flag from earlier ?skins=1 sessions
19
+ try { localStorage.removeItem("holo.skins"); } catch {}
20
+ try { const p = document.querySelector(".holo-skin-pick"); if (p) p.remove(); } catch {}
21
+ })();
22
+
23
+ // ── UX ENHANCER (whatsapp-ux-v1) β€” additive, guarded, DOM-only. Two WhatsApp-desktop niceties the compiled
24
+ // bundle can't get surgically: (1) a DRAG-RESIZE divider between the chat list and the conversation, persisted
25
+ // per device; (2) CLICK-AWAY / tap-outside close for the composer "+" attach sheet and the emoji popover (the
26
+ // message + row menus already close on outside-click via the bundle; these two didn't). Everything here is
27
+ // idempotent and fail-open β€” if the DOM shape ever changes, it simply does nothing.
28
+ (function () {
29
+ const root = document.documentElement, LS_W = "holo.side.w";
30
+ const MIN = 260, MAXPX = 560, MAXPCT = 0.46;
31
+ const applyWidth = (px) => { if (px == null) root.style.removeProperty("--holo-side-w"); else root.style.setProperty("--holo-side-w", px + "px"); };
32
+ // returning users reopen at their chosen width (set before first paint)
33
+ try { const v = parseFloat(localStorage.getItem(LS_W)); if (v > 0) applyWidth(v); } catch {}
34
+
35
+ const container = () => document.querySelector(".holo-wa-root .cs-main-container");
36
+ const sidebar = () => document.querySelector(".holo-wa-root .cs-sidebar.cs-sidebar--left");
37
+
38
+ function ensureHandle() {
39
+ if (window.innerWidth < 900) return; // desktop only
40
+ const c = container(); if (!c) return;
41
+ if (c.querySelector(":scope > .holo-side-resize")) return; // already mounted
42
+ const h = document.createElement("div");
43
+ h.className = "holo-side-resize"; h.title = "Drag to resize, double-click to reset"; h.setAttribute("aria-hidden", "true");
44
+ c.appendChild(h);
45
+ let startX = 0, startW = 0, raf = 0, pending = 0;
46
+ const maxW = () => Math.min(MAXPX, Math.round((c.clientWidth || window.innerWidth) * MAXPCT));
47
+ const onMove = (e) => {
48
+ pending = Math.max(MIN, Math.min(maxW(), startW + (e.clientX - startX)));
49
+ if (!raf) raf = requestAnimationFrame(() => { raf = 0; applyWidth(pending); });
50
+ };
51
+ const onUp = () => {
52
+ document.removeEventListener("pointermove", onMove);
53
+ document.removeEventListener("pointerup", onUp);
54
+ document.body.classList.remove("holo-side-dragging");
55
+ h.classList.remove("holo-drag");
56
+ if (raf) { cancelAnimationFrame(raf); raf = 0; }
57
+ applyWidth(pending);
58
+ try { localStorage.setItem(LS_W, String(pending)); } catch {}
59
+ };
60
+ h.addEventListener("pointerdown", (e) => {
61
+ if (e.button !== 0) return;
62
+ e.preventDefault();
63
+ const sb = sidebar(); if (!sb) return;
64
+ startX = e.clientX; startW = Math.round(sb.getBoundingClientRect().width); pending = startW;
65
+ document.body.classList.add("holo-side-dragging"); h.classList.add("holo-drag");
66
+ document.addEventListener("pointermove", onMove);
67
+ document.addEventListener("pointerup", onUp);
68
+ });
69
+ h.addEventListener("dblclick", (e) => { e.preventDefault(); applyWidth(null); try { localStorage.removeItem(LS_W); } catch {} }); // reset to default
70
+ }
71
+
72
+ const boot = () => {
73
+ ensureHandle();
74
+ try { new MutationObserver(() => ensureHandle()).observe(document.body, { childList: true, subtree: true }); } catch {}
75
+ window.addEventListener("resize", ensureHandle, { passive: true });
76
+ };
77
+ if (document.body) boot(); else window.addEventListener("DOMContentLoaded", boot, { once: true });
78
+
79
+ // (2) click-away close for the two composer popovers. They close cleanly through the app's OWN Escape handler,
80
+ // so dispatch Escape on an outside pointerdown. pointerdown fires BEFORE React's onClick, and skipping the
81
+ // composer icons (the triggers) avoids the toggle-reopen race.
82
+ document.addEventListener("pointerdown", (e) => {
83
+ const pop = document.querySelector(".holo-attach-menu, .holo-emoji-pop");
84
+ if (!pop) return; // nothing open
85
+ if (pop.contains(e.target)) return; // clicked inside β†’ keep open
86
+ if (e.target.closest && e.target.closest(".holo-c-icon")) return; // a composer trigger β†’ let it toggle
87
+ try { document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true })); } catch {}
88
+ }, true);
89
+ })();
90
+
91
+ // ── AUDITED E2E STACK (whatsapp-e2e-voz) β€” activate the additive vodozemac Olm/Megolm engine as an OPT-IN
92
+ // (window.HoloMsg). Importing only DEFINES the door; the 393 KB crypto wasm + the spine load on FIRST USE,
93
+ // so the default holo-seal door pays nothing and is entirely untouched. Nothing calls HoloMsg yet β€” this
94
+ // just makes the audited Double-Ratchet engine LIVE-CAPABLE; the UI opt-in (?e2e=voz) is the next step.
95
+ try { import("./holo-msg-mount.mjs").catch(() => {}); } catch {}
sha256/28186f18edebe4a990c721dc98594d94f74ab02b8eea40d67b04a4b7b777be7f ADDED
@@ -0,0 +1 @@
 
 
1
+ import{$ as I,B as z,Ca as fe,H as te,I as ne,Ib as Le,J as ae,Ja as pe,Ma as Re,Pa as w,Qa as ge,Sa as O,X as oe,aa as m,ab as ve,b as ee,ba as R,bb as A,ca as F,cb as Te,da as x,ea as le,ga as se,ha as ie,ia as re,k as D,kb as Ee,la as ce,nb as B,o as $,rb as Ce,sa as ue,sb as ye,ta as me,ub as H,va as de,wa as he,ya as be}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as Ve}from"./chunk-EJ2FITLI.js";import{b as Ue}from"./chunk-SQE76S5B.js";var e=Ue(Ve(),1);var T={ref:null,position:"bottom",width:120,height:80,border:1,borderRadius:4,padding:4,gap:16,imageFit:"contain",vignette:!0,hidden:!1,showToggle:!1},Y=t=>({...T,...t});function xe(){let{thumbnails:t}=w();return Y(t)}var E=t=>F($,t),u=t=>E(F("thumbnail",t)),De=A("VideoThumbnail",e.createElement("path",{d:"M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"})),Fe=A("UnknownThumbnail",e.createElement("path",{d:"M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"}));function Oe({slide:t,render:n,rect:o,imageFit:l}){var r;let d=(r=n.thumbnail)===null||r===void 0?void 0:r.call(n,{slide:t,render:n,rect:o,imageFit:l});if(d)return d;let p={render:n,rect:o,imageFit:l};if(t.thumbnail)return e.createElement(H,{slide:{src:t.thumbnail},...p});if(ce(t))return e.createElement(H,{slide:t,...p});let h=m(u(oe));return t.type==="video"?e.createElement(e.Fragment,null,t.poster&&e.createElement(H,{slide:{src:t.poster},...p}),e.createElement(De,{className:h})):e.createElement(Fe,{className:h})}var Be=x("active"),X=x("fadein"),K=x("fadeout"),Xe=x("placeholder"),Ne="delay",Pe="duration";function Ke({slide:t,index:n,onClick:o,fadeIn:l,fadeOut:r,placeholder:d,onLoseFocus:p}){let h=e.useRef(null),{render:g,styles:C,labels:s}=w(),{slides:b,globalIndex:U}=O(),{getOwnerDocument:M}=pe(),{width:L,height:_,imageFit:N}=xe(),P={width:L,height:_},S=n===U,k=B(p);return e.useEffect(()=>{r&&M().activeElement===h.current&&k()},[r,k,M]),e.createElement("button",{ref:h,type:"button",className:I(m(z),m(u()),S&&m(u(Be())),l&&m(u(X())),r&&m(u(K())),d&&m(u(Xe()))),style:{...l?{[R(u(X(Pe)))]:`${l.duration}ms`,[R(u(X(Ne)))]:`${l.delay}ms`}:null,...r?{[R(u(K(Pe)))]:`${r.duration}ms`,[R(u(K(Ne)))]:`${r.delay}ms`}:null,...C.thumbnail},onClick:o,"aria-current":S?!0:void 0,"aria-label":se(s,b,n)},t&&Oe({slide:t,render:g,rect:P,imageFit:N}))}function Se(t){return["top","bottom"].includes(t)}function ke(t,n){return n+2*(t.border+t.padding)+t.gap}function Ye(t){let{thumbnail:n,poster:o}=t||{thumbnail:"placeholder"};return typeof n=="string"&&n||typeof o=="string"&&o||t&&de(t)||void 0}function Ie({visible:t,containerRef:n}){let o=e.useRef(null),l=Ce(),{publish:r,subscribe:d}=Re(),{carousel:p,styles:h,labels:g}=w(),{slides:C,globalIndex:s,animation:b}=O(),{registerSensors:U,subscribeSensors:M}=ye();Le(M);let L=xe(),{position:_,width:N,height:P,border:S,borderStyle:k,borderColor:j,borderRadius:G,padding:W,gap:q,vignette:_e}=L,i=b?.duration!==void 0&&b?.increment||0,J=b?.duration||0,{prepareAnimation:$e}=Ee(o,a=>({keyframes:Se(_)?[{transform:`translateX(${(l?-1:1)*ke(L,N)*i+a}px)`},{transform:"translateX(0)"}]:[{transform:`translateY(${ke(L,P)*i+a}px)`},{transform:"translateY(0)"}],duration:J,easing:b?.easing})),Q=B(()=>{let a=0;if(n.current&&o.current){let c=n.current.getBoundingClientRect(),v=o.current.getBoundingClientRect();a=Se(_)?v.left-c.left-(c.width-v.width)/2:v.top-c.top-(c.height-v.height)/2}$e(a)});e.useEffect(()=>ie(d(ae,Q)),[d,Q]);let f=be(p,C),Z=[];if(ue(C))for(let a=s-f-Math.abs(i);a<=s+f+Math.abs(i);a+=1){let v=p.finite&&(a<0||a>C.length-1)||i<0&&a<s-f||i>0&&a>s+f?null:me(C,a),y=[`${a}`,Ye(v)].filter(Boolean).join("|");Z.push({key:y,index:a,slide:v})}let ze=a=>()=>{a>s?r(ne,{count:a-s}):a<s&&r(te,{count:s-a})};return e.createElement("div",{className:I(m(E("container")),m(z)),style:{...t?null:{display:"none"},...N!==T.width?{[R(u("width"))]:`${N}px`}:null,...P!==T.height?{[R(u("height"))]:`${P}px`}:null,...S!==T.border?{[R(u("border"))]:`${S}px`}:null,...k?{[R(u("border_style"))]:k}:null,...j?{[R(u("border_color"))]:j}:null,...G!==T.borderRadius?{[R(u("border_radius"))]:`${G}px`}:null,...W!==T.padding?{[R(u("padding"))]:`${W}px`}:null,...q!==T.gap?{[R(u("gap"))]:`${q}px`}:null,...h.thumbnailsContainer}},e.createElement("nav",{ref:o,style:h.thumbnailsTrack,className:I(m(E("track")),m(z)),"aria-label":le(g,"Thumbnails"),tabIndex:-1,...U},Z.map(({key:a,index:c,slide:v})=>{let y=J/Math.abs(i||1),Ae=i>0&&c>s+f-i&&c<=s+f||i<0&&c<s-f-i&&c>=s-f?{duration:y,delay:((i>0?c-(s+f-i):s-f-i-c)-1)*y}:void 0,He=i>0&&c<s-f||i<0&&c>s+f?{duration:y,delay:(i>0?i-(s-f-c):-i-(c-(s+f)))*y}:void 0;return e.createElement(Ke,{key:a,index:c,slide:v,fadeIn:Ae,fadeOut:He,placeholder:!v,onClick:ze(c),onLoseFocus:()=>{var V;return(V=o.current)===null||V===void 0?void 0:V.focus()}})})),_e&&e.createElement("div",{className:m(E("vignette"))}))}var we=e.createContext(null),je=re("useThumbnails","ThumbnailsContext",we);function Ge({children:t,...n}){let{ref:o,position:l,hidden:r}=Y(n.thumbnails),[d,p]=e.useState(!r),h=e.useRef(null),g=e.useMemo(()=>({visible:d,show:()=>p(!0),hide:()=>p(!1)}),[d]);return e.useImperativeHandle(o,()=>g,[g]),e.createElement(ge,{...n},e.createElement(we.Provider,{value:g},e.createElement("div",{ref:h,className:I(m(E()),m(E(`${l}`)))},["start","top"].includes(l)&&e.createElement(Ie,{containerRef:h,visible:d}),e.createElement("div",{className:m(E("wrapper"))},t),["end","bottom"].includes(l)&&e.createElement(Ie,{containerRef:h,visible:d}))))}var Me=()=>e.createElement(e.Fragment,null,e.createElement("path",{strokeWidth:2,stroke:"currentColor",strokeLinejoin:"round",fill:"none",d:"M3 5l18 0l0 14l-18 0l0-14z"}),e.createElement("path",{d:"M5 14h4v3h-4zM10 14h4v3h-4zM15 14h4v3h-4z"})),We=A("ThumbnailsVisible",Me()),qe=Te("ThumbnailsHidden",Me());function Je(){let{visible:t,show:n,hide:o}=je(),{render:l}=w();return l.buttonThumbnails?e.createElement(e.Fragment,null,l.buttonThumbnails({visible:t,show:n,hide:o})):e.createElement(ve,{label:t?"Hide thumbnails":"Show thumbnails",icon:t?We:qe,renderIcon:t?l.iconThumbnailsVisible:l.iconThumbnailsHidden,onClick:t?o:n})}function et({augment:t,contains:n,append:o,addParent:l}){t(({thumbnails:d,toolbar:p,...h})=>{let g=Y(d);return{toolbar:he(p,$,g.showToggle?e.createElement(Je,null):null),thumbnails:g,...h}});let r=fe($,Ge);n(D)?o(D,r):l(ee,r)}export{et as default};
sha256/2a19268225fab8e102982de6e490c3e3468bedcfe368407aaa3525b78eb7cf34 ADDED
@@ -0,0 +1 @@
 
 
1
+ import"./chunk-SQE76S5B.js";var D=typeof TextEncoder<"u"?new TextEncoder:null;async function b(o){let c=await crypto.subtle.digest("SHA-256",D.encode(o));return[...new Uint8Array(c)].map(y=>y.toString(16).padStart(2,"0")).join("")}var S=o=>b(JSON.stringify([o.v,o.kind,o.text||"",o.bg||"",o.caption||"",o.dataUrl||"",o.at,o.ttl,o.author,o.name||""]));async function O({hd:o=null,now:c=()=>Date.now(),ttlMs:y=864e5}={}){if(o=o||(typeof window<"u"?window.HoloDirect:null),!o||!o.onStory)throw new Error("status needs the HoloDirect story rail");let d=o.mySign?await o.mySign():null,T=()=>{try{return(localStorage.getItem("holo.direct.name")||"").trim()||null}catch{return null}},i=null;try{i=await(await navigator.storage.getDirectory()).getDirectoryHandle("holo-status",{create:!0})}catch{}let a=new Map,g=new Set,l=()=>{for(let t of g)try{t()}catch{}},f=t=>t&&t.at+(t.ttl||y)>c();async function w(t){if(a.set(t.id,t),i)try{let n=await(await i.getFileHandle(t.id,{create:!0})).createWritable();await n.write(JSON.stringify(t)),await n.close()}catch{}}async function h(t){if(a.delete(t),i)try{await i.removeEntry(t)}catch{}}if(i)try{for await(let[t,e]of i.entries())try{let n=JSON.parse(await(await e.getFile()).text());f(n)?a.set(n.id,n):await i.removeEntry(t)}catch{}}catch{}async function A({kind:t,dataUrl:e=null,text:n=null,bg:r=null,caption:u=null}){if(t!=="photo"&&t!=="text")return{ok:!1,error:"kind must be photo|text"};if(t==="photo"&&(!e||String(e).length>2e5))return{ok:!1,error:"photo missing or too large \u2014 downscale to \u22641080px JPEG first"};if(t==="text"&&!(n||"").trim())return{ok:!1,error:"text story needs text"};let s={v:1,kind:t,dataUrl:t==="photo"?e:null,text:n?String(n).slice(0,700):null,bg:r||null,caption:u?String(u).slice(0,700):null,at:c(),ttl:y,author:d,name:T()};s.id=await S(s),await w({...s,mine:!0,seen:!0,viewers:{}}),l();let m={sent:0,contacts:0};try{m=await o.postStory(s)}catch{}return{ok:!0,id:s.id,...m}}async function p({contactId:t,sign:e,frame:n}){if(n.t==="story"){let r=n.story;if(!r||r.v!==1||r.author!==e||!f(r)||String(r.dataUrl||"").length>2e5||String(r.text||"").length>700||await S(r)!==r.id||a.has(r.id))return;await w({...r,authorCid:t||null,mine:!1,seen:!1,viewers:{}}),l()}else if(n.t==="story-ack"){let r=a.get(n.id);r&&r.mine&&e&&(r.viewers[e]=n.ts||c(),await w(r),l())}else if(n.t==="story-revoke"){let r=a.get(n.id);r&&r.author===e&&!r.mine&&(await h(n.id),l())}}o.onStory(t=>{p(t).catch(()=>{})});function x(){let t=new Map;for(let n of a.values()){if(!f(n))continue;let r=n.mine?"me":n.author;(t.get(r)||t.set(r,[]).get(r)).push(n)}for(let n of t.values())n.sort((r,u)=>r.at-u.at);let e=[...t.entries()].sort(([n,r],[u,s])=>n==="me"?-1:u==="me"?1:s[s.length-1].at-r[r.length-1].at);return new Map(e)}let _=()=>{let t=0;for(let e of a.values())f(e)&&!e.mine&&!e.seen&&t++;return t};async function E(t){let e=a.get(t);if(!(!e||e.mine||e.seen)){e.seen=!0,await w(e),l();try{await o.storyCtl(e.authorCid||e.author,{t:"story-ack",id:t,ts:c()})}catch{}}}async function M(t){let e=a.get(t);if(!e||!e.mine)return{ok:!1,error:"not yours"};await h(t),l();try{await o.storyFan({t:"story-revoke",id:t,ts:c()})}catch{}return{ok:!0}}let X=t=>{let e=a.get(t);return e&&e.mine?Object.entries(e.viewers).map(([n,r])=>({sign:n,ts:r})):[]},k=setInterval(()=>{let t=0;for(let[e,n]of a)f(n)||(h(e),t++);t&&l()},6e4);return{post:A,feed:x,unseenCount:_,markSeen:E,revoke:M,viewersOf:X,mySign:d,onChange:t=>(g.add(t),()=>g.delete(t)),_ingest:p,destroy:()=>{clearInterval(k),g.clear()}}}var v=null;function C(o){return v=v||O(o)}export{O as createStatusEngine,C as getStatusEngine};
sha256/304e4bf228c2aeade13b288617aab175a53d04f8ea3d305dc65a92c8973cc3df ADDED
@@ -0,0 +1 @@
 
 
1
+ import{Pa as w,Sa as p,ab as m,bb as v,j as s,la as u,wa as f}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as L}from"./chunk-EJ2FITLI.js";import{b as g}from"./chunk-SQE76S5B.js";var d=g(L(),1);var x={download:void 0},D=e=>({...x,...e});function I(e){if(!e)return;let n=/filename\*\s*=\s*UTF-8''([^;]+)/i.exec(e);if(n)try{let l=decodeURIComponent(n[1].trim());if(l)return l}catch{}let o=/filename\s*=\s*("[^"]*"|[^;]+)/i.exec(e);return o?.[1].trim().replace(/^"(.*)"$/,"$1")||void 0}function U(e){var n,o;return(o=(n=/^content-disposition:(.*)$/im.exec(e.getAllResponseHeaders()))===null||n===void 0?void 0:n[1])!==null&&o!==void 0?o:null}function _(e,n){let o=new XMLHttpRequest;o.open("GET",e),o.responseType="blob",o.onload=()=>{i(o.response,n||I(U(o)))},o.onerror=()=>{console.error("Failed to download file")},o.send()}function y(e){let n=new XMLHttpRequest;n.open("HEAD",e,!1);try{n.send()}catch{}return n.status>=200&&n.status<=299}function r(e){try{e.dispatchEvent(new MouseEvent("click"))}catch{let o=document.createEvent("MouseEvents");o.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(o)}}function i(e,n){let o=document.createElement("a");o.rel="noopener",o.download=n||"",o.download||(o.target="_blank"),typeof e=="string"?(o.href=e,o.origin!==window.location.origin?y(o.href)?_(e,n):(o.target="_blank",r(o)):r(o)):(o.href=URL.createObjectURL(e),setTimeout(()=>URL.revokeObjectURL(o.href),3e4),setTimeout(()=>r(o),0))}var k=v("DownloadIcon",d.createElement("path",{d:"M18 15v3H6v-3H4v3c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-3h-2zm-1-4-1.41-1.41L13 12.17V4h-2v8.17L8.41 9.59 7 11l5 5 5-5z"}));function F(){let{render:e,on:n,download:o}=w(),{download:l}=D(o),{currentSlide:t,currentIndex:b}=p();if(e.buttonDownload)return d.createElement(d.Fragment,null,e.buttonDownload());let c=t&&(t.downloadUrl||typeof t.download=="string"&&t.download||typeof t.download=="object"&&t.download.url||u(t)&&t.src)||void 0,h=l?t?.download!==!1:!!c,E=()=>{if(t&&c){let a=t.downloadFilename||typeof t.download=="object"&&t.download.filename||void 0;i(c,a)}},R=()=>{var a;t&&((l||E)({slide:t,saveAs:i}),(a=n.download)===null||a===void 0||a.call(n,{index:b}))};return d.createElement(m,{label:"Download",icon:k,renderIcon:e.iconDownload,disabled:!h,onClick:R})}function T({augment:e}){e(({toolbar:n,download:o,...l})=>({toolbar:f(n,s,d.createElement(F,null)),download:D(o),...l}))}export{T as default};
sha256/3fd2a00105ad0e8f01109dce52ff4c7a0cc6c9444532b0453ed9d770cce2d3a4 ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
3
+ <title>HOLOGRAM</title>
4
+ <style>html,body{margin:0;height:100%;background:#101010;color:#eee;font:15px/1.5 system-ui,sans-serif}
5
+ .boot{display:grid;place-items:center;height:100%;text-align:center;gap:.6rem}
6
+ .boot small{color:#888}.boot b{font-size:1.1rem;font-weight:700}</style>
7
+ <script>
8
+ // The ΞΊ-Jellyfin wrapper (SHIP D1/D2/D3): register OUR Service Worker at THIS app's scope
9
+ // (/Q/apps/jellyfin/ live Β· / in the harness) β€” it becomes the media server β€” then hand off to
10
+ // jellyfin-web. Evict any foreign SW (jellyfin-web ships its own PWA worker at /web/ that would hijack
11
+ // the scope). The built SW is a CLASSIC script (Firefox has no module SWs; evicted imports 404) β€” so no
12
+ // { type:"module" } here. Same-origin only; degrades to a message if SWs are unavailable.
13
+ (function () {
14
+ var base = location.pathname.replace(/index\.html$/, ""); // this app's root = the SW scope
15
+ var swUrl = base + "holo-jellyfin-sw.js";
16
+ var mine = function (u) { return /holo-jellyfin-sw/.test(u || ""); };
17
+ function fail(m) { document.title = "SW FAILED: " + m; var e = document.getElementById("msg"); if (e) e.textContent = "Couldn’t start the media server: " + m; }
18
+ if (!("serviceWorker" in navigator)) { return fail("this browser has no Service Workers"); }
19
+ var ctl = navigator.serviceWorker.controller;
20
+ if (ctl && mine(ctl.scriptURL)) { location.replace(base + "web/index.html"); return; } // already ours β†’ go
21
+ navigator.serviceWorker.getRegistrations()
22
+ .then(function (rs) { return Promise.all(rs.filter(function (r) { return !mine(r.active && r.active.scriptURL); }).map(function (r) { return r.unregister(); })); })
23
+ .then(function () { return navigator.serviceWorker.register(swUrl, { scope: base }); })
24
+ .then(function (reg) {
25
+ var go = function () { location.replace(base + "web/index.html"); };
26
+ if (reg.active && navigator.serviceWorker.controller) return go();
27
+ navigator.serviceWorker.addEventListener("controllerchange", go);
28
+ var w = reg.installing || reg.waiting || reg.active;
29
+ if (w) w.addEventListener("statechange", function (e) { if (e.target.state === "activated") setTimeout(go, 60); });
30
+ setTimeout(go, 2500); // belt-and-braces: control usually lands < 1s
31
+ })
32
+ .catch(function (e) { fail(e && e.message || String(e)); });
33
+ })();
34
+ </script></head>
35
+ <body><div class="boot"><b>HOLOGRAM</b><small id="msg">Starting your media server…</small></div></body></html>
sha256/65a4954f079070d79a8687acb55ef9927de74599bbdc0afbc8400cb4b0d75fac ADDED
@@ -0,0 +1,1309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{a as o}from"./chunk-SQE76S5B.js";var a=o((exports,module)=>{(()=>{"use strict";var __webpack_modules__={"./src/index.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
2
+ exports.__esModule = true;
3
+ exports.Zuck = void 0;
4
+ var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
5
+ var options_1 = __webpack_require__(/*! ./options */ "./src/options.ts");
6
+ var modal_1 = __webpack_require__(/*! ./modal */ "./src/modal.ts");
7
+ var Zuck = function (timeline, options) {
8
+ if (!timeline.id) {
9
+ timeline.setAttribute('id', (0, utils_1.generateId)());
10
+ }
11
+ var id = timeline.id;
12
+ var _a = (0, options_1.loadOptions)(options), option = _a.option, callbackOption = _a.callback, templateOption = _a.template, languageOption = _a.language;
13
+ var data = option('stories') || [];
14
+ var internalData = {};
15
+ /* data functions */
16
+ var saveLocalData = function (key, data) {
17
+ try {
18
+ if (option('localStorage') && (0, utils_1.hasWindow)()) {
19
+ var keyName = "zuck-".concat(id, "-").concat(key);
20
+ window.localStorage[keyName] = JSON.stringify(data);
21
+ }
22
+ }
23
+ catch (e) { }
24
+ };
25
+ var getLocalData = function (key) {
26
+ if (option('localStorage') && (0, utils_1.hasWindow)()) {
27
+ var keyName = "zuck-".concat(id, "-").concat(key);
28
+ return window.localStorage[keyName]
29
+ ? JSON.parse(window.localStorage[keyName])
30
+ : undefined;
31
+ }
32
+ else {
33
+ return undefined;
34
+ }
35
+ };
36
+ internalData.seenItems = getLocalData('seenItems') || {};
37
+ var playVideoItem = function (storyViewer, elements, unmute) {
38
+ var itemElement = elements === null || elements === void 0 ? void 0 : elements[1];
39
+ var itemPointer = elements === null || elements === void 0 ? void 0 : elements[0];
40
+ if (!itemElement || !itemPointer) {
41
+ return false;
42
+ }
43
+ var cur = internalData.currentVideoElement;
44
+ if (cur) {
45
+ cur.pause();
46
+ }
47
+ if (itemElement.getAttribute('data-type') === 'video') {
48
+ var video_1 = itemElement.querySelector('video');
49
+ if (!video_1) {
50
+ internalData.currentVideoElement = undefined;
51
+ return false;
52
+ }
53
+ var setDuration = function () {
54
+ var duration = video_1.duration;
55
+ var itemPointerProgress = itemPointer.querySelector('.progress');
56
+ if (+video_1.dataset.length) {
57
+ duration = +video_1.dataset.length;
58
+ }
59
+ if (duration && itemPointerProgress) {
60
+ itemPointerProgress.style.animationDuration = "".concat(duration, "s");
61
+ }
62
+ };
63
+ setDuration();
64
+ video_1.addEventListener('loadedmetadata', setDuration);
65
+ internalData.currentVideoElement = video_1;
66
+ video_1.play();
67
+ try {
68
+ unmuteVideoItem(video_1, storyViewer);
69
+ }
70
+ catch (e) {
71
+ console.warn('Could not unmute video', unmute);
72
+ }
73
+ }
74
+ else {
75
+ internalData.currentVideoElement = undefined;
76
+ }
77
+ };
78
+ var findStoryIndex = function (id) {
79
+ return data.findIndex(function (item) { return item.id === id; });
80
+ };
81
+ var pauseVideoItem = function () {
82
+ var video = internalData.currentVideoElement;
83
+ if (video) {
84
+ try {
85
+ video.pause();
86
+ }
87
+ catch (e) { }
88
+ }
89
+ };
90
+ var unmuteVideoItem = function (video, storyViewer) {
91
+ video.muted = false;
92
+ video.volume = 1.0;
93
+ video.removeAttribute('muted');
94
+ video.play();
95
+ if (video.paused) {
96
+ video.muted = true;
97
+ video.play();
98
+ }
99
+ if (storyViewer) {
100
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
101
+ }
102
+ };
103
+ var parseItems = function (story, forceUpdate) {
104
+ var storyId = (story === null || story === void 0 ? void 0 : story.getAttribute('data-id')) || '';
105
+ var storyIndex = findStoryIndex(storyId);
106
+ var storyItems = document.querySelectorAll("#".concat(id, " [data-id=\\"").concat(storyId, "\\"] .items > li"));
107
+ var items = [];
108
+ if (!option('reactive') || forceUpdate) {
109
+ storyItems.forEach(function (_a) {
110
+ var firstElementChild = _a.firstElementChild;
111
+ var a = firstElementChild;
112
+ var img = a === null || a === void 0 ? void 0 : a.firstElementChild;
113
+ var li = a === null || a === void 0 ? void 0 : a.parentElement;
114
+ var item = {
115
+ id: (a === null || a === void 0 ? void 0 : a.getAttribute('data-id')) || (li === null || li === void 0 ? void 0 : li.getAttribute('data-id')),
116
+ src: a === null || a === void 0 ? void 0 : a.getAttribute('href'),
117
+ length: (0, utils_1.safeNum)(a === null || a === void 0 ? void 0 : a.getAttribute('data-length')),
118
+ type: a === null || a === void 0 ? void 0 : a.getAttribute('data-type'),
119
+ time: (a === null || a === void 0 ? void 0 : a.getAttribute('data-time')) || (li === null || li === void 0 ? void 0 : li.getAttribute('data-time')),
120
+ link: (a === null || a === void 0 ? void 0 : a.getAttribute('data-link')) || '',
121
+ linkText: a === null || a === void 0 ? void 0 : a.getAttribute('data-linkText'),
122
+ preview: img === null || img === void 0 ? void 0 : img.getAttribute('src'),
123
+ seen: li === null || li === void 0 ? void 0 : li.classList.contains('seen')
124
+ };
125
+ var all = a === null || a === void 0 ? void 0 : a.attributes;
126
+ var reserved = [
127
+ 'data-id',
128
+ 'href',
129
+ 'data-length',
130
+ 'data-type',
131
+ 'data-time',
132
+ 'data-link',
133
+ 'data-linkText'
134
+ ];
135
+ if (all) {
136
+ for (var z = 0; z < all.length; z++) {
137
+ if (reserved.indexOf(all[z].nodeName) === -1) {
138
+ item[all[z].nodeName.replace('data-', '')] = all === null || all === void 0 ? void 0 : all[z].nodeValue;
139
+ }
140
+ }
141
+ }
142
+ // destruct the remaining attributes as options
143
+ items.push(item);
144
+ });
145
+ data[storyIndex].items = items;
146
+ var callback = callbackOption('onDataUpdate');
147
+ if (callback) {
148
+ callback(data, function () { });
149
+ }
150
+ }
151
+ };
152
+ var parseStory = function (story) {
153
+ var _a, _b;
154
+ var storyId = (story === null || story === void 0 ? void 0 : story.getAttribute('data-id')) || '';
155
+ var storyIndex = findStoryIndex(storyId);
156
+ var seen = false;
157
+ if (internalData.seenItems[storyId]) {
158
+ seen = true;
159
+ }
160
+ try {
161
+ var storyData = {};
162
+ if (storyIndex !== -1) {
163
+ storyData = data[storyIndex];
164
+ }
165
+ storyData.id = storyId;
166
+ storyData.photo = story === null || story === void 0 ? void 0 : story.getAttribute('data-photo');
167
+ storyData.name = (_a = story === null || story === void 0 ? void 0 : story.querySelector('.name')) === null || _a === void 0 ? void 0 : _a.innerText;
168
+ storyData.link = (_b = story === null || story === void 0 ? void 0 : story.querySelector('.item-link')) === null || _b === void 0 ? void 0 : _b.getAttribute('href');
169
+ storyData.lastUpdated = (0, utils_1.safeNum)((story === null || story === void 0 ? void 0 : story.getAttribute('data-last-updated')) ||
170
+ (story === null || story === void 0 ? void 0 : story.getAttribute('data-time')));
171
+ storyData.seen = seen;
172
+ if (!storyData.items) {
173
+ storyData.items = [];
174
+ }
175
+ if (storyIndex === -1) {
176
+ data.push(storyData);
177
+ }
178
+ else {
179
+ data[storyIndex] = storyData;
180
+ }
181
+ }
182
+ catch (e) {
183
+ data[storyIndex] = {
184
+ items: []
185
+ };
186
+ }
187
+ if (story) {
188
+ story.onclick = function (e) {
189
+ e.preventDefault();
190
+ modal.show(storyId);
191
+ };
192
+ }
193
+ var callback = callbackOption('onDataUpdate');
194
+ if (callback) {
195
+ callback(data, function () { });
196
+ }
197
+ };
198
+ var add = function (data, append) {
199
+ var _a, _b, _c, _d;
200
+ var storyId = data['id'] || '';
201
+ var storyEl = document.querySelector("#".concat(id, " [data-id=\\"").concat(storyId, "\\"]"));
202
+ var items = data['items'];
203
+ var story = null;
204
+ var preview = undefined;
205
+ if (items === null || items === void 0 ? void 0 : items[0]) {
206
+ preview = ((_a = items === null || items === void 0 ? void 0 : items[0]) === null || _a === void 0 ? void 0 : _a.preview) || '';
207
+ }
208
+ if (internalData.seenItems[storyId] === true) {
209
+ data.seen = true;
210
+ }
211
+ if (data) {
212
+ data.currentPreview = preview;
213
+ }
214
+ if (!storyEl) {
215
+ var storyItem = document.createElement('div');
216
+ storyItem.innerHTML = templateOption('timelineItem')(data);
217
+ story = storyItem.firstElementChild;
218
+ }
219
+ else {
220
+ story = storyEl;
221
+ }
222
+ if (data.seen === false) {
223
+ internalData.seenItems[storyId] = false;
224
+ saveLocalData('seenItems', internalData.seenItems);
225
+ }
226
+ story === null || story === void 0 ? void 0 : story.setAttribute('data-id', storyId);
227
+ if (data['photo']) {
228
+ story === null || story === void 0 ? void 0 : story.setAttribute('data-photo', data['photo']);
229
+ }
230
+ story === null || story === void 0 ? void 0 : story.setAttribute('data-time', (_b = data['time']) === null || _b === void 0 ? void 0 : _b.toString());
231
+ if (data['lastUpdated']) {
232
+ story === null || story === void 0 ? void 0 : story.setAttribute('data-last-updated', (_c = data['lastUpdated']) === null || _c === void 0 ? void 0 : _c.toString());
233
+ }
234
+ else {
235
+ story === null || story === void 0 ? void 0 : story.setAttribute('data-last-updated', (_d = data['time']) === null || _d === void 0 ? void 0 : _d.toString());
236
+ }
237
+ parseStory(story);
238
+ if (!storyEl && !option('reactive')) {
239
+ if (append) {
240
+ timeline.appendChild(story);
241
+ }
242
+ else {
243
+ (0, utils_1.prepend)(timeline, story);
244
+ }
245
+ }
246
+ items === null || items === void 0 ? void 0 : items.forEach(function (item) {
247
+ addItem(storyId, item, append);
248
+ });
249
+ if (!append) {
250
+ updateStorySeenPosition();
251
+ }
252
+ };
253
+ var update = add;
254
+ var next = function () {
255
+ modal.next();
256
+ };
257
+ var remove = function (storyId) {
258
+ var _a;
259
+ var story = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"]"));
260
+ (_a = story === null || story === void 0 ? void 0 : story.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(story);
261
+ };
262
+ var addItem = function (storyId, data, append) {
263
+ var story = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"]"));
264
+ if (!option('reactive')) {
265
+ var li = document.createElement('li');
266
+ var el = story === null || story === void 0 ? void 0 : story.querySelectorAll('.items')[0];
267
+ if (data['id']) {
268
+ li.className = data['seen'] ? 'seen' : '';
269
+ li.setAttribute('data-id', data['id']);
270
+ }
271
+ li.innerHTML = templateOption('timelineStoryItem')(data);
272
+ if (append) {
273
+ el === null || el === void 0 ? void 0 : el.appendChild(li);
274
+ }
275
+ else {
276
+ (0, utils_1.prepend)(el, li);
277
+ }
278
+ }
279
+ parseItems(story);
280
+ };
281
+ var removeItem = function (storyId, itemId) {
282
+ var _a;
283
+ var item = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"] [data-id=\\"").concat(itemId, "\\"]"));
284
+ if (!option('reactive')) {
285
+ (_a = item === null || item === void 0 ? void 0 : item.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(item);
286
+ data.forEach(function (story) {
287
+ if (story.id === storyId) {
288
+ story.items = story.items.filter(function (item) { return item.id !== itemId; });
289
+ }
290
+ });
291
+ }
292
+ };
293
+ var nextItem = function (direction, event) {
294
+ var currentStory = internalData.currentStory;
295
+ var currentStoryIndex = findStoryIndex(internalData.currentStory);
296
+ var currentItem = data[currentStoryIndex].currentItem;
297
+ var storyViewer = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(currentStory, "\\"]"));
298
+ var directionNumber = direction === 'previous' ? -1 : 1;
299
+ if (!storyViewer) {
300
+ return false;
301
+ }
302
+ var currentItemElements = storyViewer.querySelectorAll("[data-index=\\"".concat(currentItem, "\\"]"));
303
+ var currentPointer = currentItemElements[0];
304
+ var currentItemElement = currentItemElements[1];
305
+ var navigateItem = currentItem + directionNumber;
306
+ var nextItems = storyViewer.querySelectorAll("[data-index=\\"".concat(navigateItem, "\\"]"));
307
+ var nextPointer = nextItems[0];
308
+ var nextItem = nextItems[1];
309
+ if (storyViewer && nextPointer && nextItem) {
310
+ var navigateItemCallback = function () {
311
+ if (direction === 'previous') {
312
+ currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.remove('seen');
313
+ currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.remove('seen');
314
+ }
315
+ else {
316
+ currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.add('seen');
317
+ currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.add('seen');
318
+ }
319
+ currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.remove('active');
320
+ currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.remove('active');
321
+ nextPointer === null || nextPointer === void 0 ? void 0 : nextPointer.classList.remove('seen');
322
+ nextPointer === null || nextPointer === void 0 ? void 0 : nextPointer.classList.add('active');
323
+ nextItem === null || nextItem === void 0 ? void 0 : nextItem.classList.remove('seen');
324
+ nextItem === null || nextItem === void 0 ? void 0 : nextItem.classList.add('active');
325
+ storyViewer
326
+ .querySelectorAll('.time')
327
+ .forEach(function (el) {
328
+ el.innerText = (0, utils_1.timeAgo)(Number(nextItem.getAttribute('data-time')), option('language'));
329
+ });
330
+ data[currentStoryIndex].currentItem =
331
+ data[currentStoryIndex].currentItem + directionNumber;
332
+ var nextVideo = nextItem.querySelector('video');
333
+ if (nextVideo) {
334
+ nextVideo.currentTime = 0;
335
+ }
336
+ playVideoItem(storyViewer, nextItems, event);
337
+ };
338
+ var callback = callbackOption('onNavigateItem');
339
+ callback = !callback
340
+ ? callbackOption('onNextItem')
341
+ : callbackOption('onNavigateItem');
342
+ callback(currentStory, nextItem.getAttribute('data-story-id'), navigateItemCallback);
343
+ }
344
+ else if (storyViewer) {
345
+ if (direction !== 'previous') {
346
+ modal.next();
347
+ }
348
+ }
349
+ return true;
350
+ };
351
+ var navigateItem = nextItem;
352
+ var updateStorySeenPosition = function () {
353
+ document
354
+ .querySelectorAll("#".concat(id, " .story.seen"))
355
+ .forEach(function (el) {
356
+ var storyId = el === null || el === void 0 ? void 0 : el.getAttribute('data-id');
357
+ var storyIndex = findStoryIndex(storyId);
358
+ if (storyId) {
359
+ var newData = data[storyIndex];
360
+ var timeline_1 = el === null || el === void 0 ? void 0 : el.parentNode;
361
+ if (!option('reactive') && timeline_1) {
362
+ timeline_1.removeChild(el);
363
+ }
364
+ update(newData, true);
365
+ }
366
+ });
367
+ };
368
+ var init = function () {
369
+ if (timeline && timeline.querySelector('.story')) {
370
+ timeline.querySelectorAll('.story').forEach(function (story) {
371
+ parseStory(story);
372
+ parseItems(story);
373
+ });
374
+ }
375
+ if (option('backNative') && (0, utils_1.hasWindow)()) {
376
+ if (window.location.hash === "#!".concat(id)) {
377
+ window.location.hash = '';
378
+ }
379
+ window.addEventListener('popstate', function () {
380
+ if (window.location.hash !== "#!".concat(id)) {
381
+ window.location.hash = '';
382
+ }
383
+ }, false);
384
+ }
385
+ if (!option('reactive')) {
386
+ var seenItems_1 = getLocalData('seenItems');
387
+ if (seenItems_1) {
388
+ Object.entries(seenItems_1).forEach(function (_a) {
389
+ var key = _a[1];
390
+ if (key && data[key]) {
391
+ data[key].seen = seenItems_1[key] ? true : false;
392
+ }
393
+ });
394
+ }
395
+ }
396
+ option('stories').forEach(function (item) {
397
+ add(item, true);
398
+ });
399
+ updateStorySeenPosition();
400
+ var avatars = option('avatars') ? 'user-icon' : 'story-preview';
401
+ var list = option('list') ? 'list' : 'carousel';
402
+ var rtl = option('rtl') ? 'rtl' : '';
403
+ timeline.className += " stories ".concat(avatars, " ").concat(list, " ").concat("".concat(option('skin')).toLowerCase(), " ").concat(rtl);
404
+ return {
405
+ id: id,
406
+ option: option,
407
+ callback: callbackOption,
408
+ template: templateOption,
409
+ language: languageOption,
410
+ navigateItem: navigateItem,
411
+ saveLocalData: saveLocalData,
412
+ getLocalData: getLocalData,
413
+ data: data,
414
+ internalData: internalData,
415
+ add: add,
416
+ update: update,
417
+ next: next,
418
+ remove: remove,
419
+ addItem: addItem,
420
+ removeItem: removeItem,
421
+ nextItem: nextItem,
422
+ findStoryIndex: findStoryIndex,
423
+ updateStorySeenPosition: updateStorySeenPosition,
424
+ playVideoItem: playVideoItem,
425
+ pauseVideoItem: pauseVideoItem,
426
+ unmuteVideoItem: unmuteVideoItem
427
+ };
428
+ };
429
+ var zuck = init();
430
+ var modal = (0, modal_1.modal)(zuck);
431
+ return zuck;
432
+ };
433
+ exports.Zuck = Zuck;
434
+ exports["default"] = exports.Zuck;
435
+
436
+
437
+ //# sourceURL=webpack://Zuck/./src/index.ts?`)}),"./src/modal.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
438
+ exports.__esModule = true;
439
+ exports.modal = void 0;
440
+ var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
441
+ var modal = function (zuck) {
442
+ var id = zuck.id;
443
+ var modalZuckContainer = document.querySelector('#zuck-modal');
444
+ if (!modalZuckContainer && !zuck.hasModal) {
445
+ zuck.hasModal = true;
446
+ modalZuckContainer = document.createElement('div');
447
+ modalZuckContainer.id = 'zuck-modal';
448
+ if (zuck.option('cubeEffect')) {
449
+ modalZuckContainer.className = 'with-cube';
450
+ }
451
+ modalZuckContainer.innerHTML = '<div id="zuck-modal-content"></div>';
452
+ modalZuckContainer.style.display = 'none';
453
+ modalZuckContainer.setAttribute('tabIndex', '1');
454
+ modalZuckContainer.onkeyup = function (_a) {
455
+ var keyCode = _a.keyCode;
456
+ var code = keyCode;
457
+ if (code === 27) {
458
+ modalZuckContainer.modal.close();
459
+ }
460
+ else if (code === 13 || code === 32) {
461
+ modalZuckContainer.modal.next();
462
+ }
463
+ };
464
+ if (zuck.option('openEffect')) {
465
+ modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.add('with-effects');
466
+ }
467
+ if (zuck.option('rtl')) {
468
+ modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.add('rtl');
469
+ }
470
+ (0, utils_1.onTransitionEnd)(modalZuckContainer, function () {
471
+ var modalContent = document.querySelector('#zuck-modal-content');
472
+ if (modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.contains('closed')) {
473
+ if (modalContent) {
474
+ modalContent.innerHTML = '';
475
+ }
476
+ modalZuckContainer.style.display = 'none';
477
+ modalZuckContainer.classList.remove('closed');
478
+ modalZuckContainer.classList.remove('animated');
479
+ }
480
+ });
481
+ document.body.appendChild(modalZuckContainer);
482
+ }
483
+ var translate = function (element, to, duration, ease) {
484
+ var _a;
485
+ if (to === undefined || (to && isNaN(to))) {
486
+ return;
487
+ }
488
+ var direction = to > 0 ? 1 : -1;
489
+ var modalWidth = ((_a = document.querySelector('#zuck-modal')) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 1;
490
+ var to3d = (Math.abs(to) / modalWidth) * 90 * direction;
491
+ if (zuck.option('cubeEffect')) {
492
+ var scaling = to3d === 0 ? 'scale(0.95)' : 'scale(0.930,0.930)';
493
+ var modalContent = document.querySelector('#zuck-modal-content');
494
+ if (modalContent) {
495
+ modalContent.style.transform = scaling;
496
+ }
497
+ if (to3d < -90 || to3d > 90) {
498
+ return false;
499
+ }
500
+ }
501
+ var transform = !zuck.option('cubeEffect')
502
+ ? "translate3d(".concat(to, "px, 0, 0)")
503
+ : "rotateY(".concat(to3d, "deg)");
504
+ if (element) {
505
+ if (ease) {
506
+ element.style.transitionTimingFunction = ease;
507
+ }
508
+ element.style.transitionDuration = "".concat(duration, "ms");
509
+ element.style.transform = transform;
510
+ }
511
+ };
512
+ var fullScreen = function (elem, cancel) {
513
+ var anyDocument = document;
514
+ var anyElem = elem;
515
+ try {
516
+ if (cancel) {
517
+ if (anyDocument.fullscreenElement ||
518
+ anyDocument.webkitFullscreenElement ||
519
+ anyDocument.mozFullScreenElement ||
520
+ anyDocument.msFullscreenElement) {
521
+ if (anyDocument.exitFullscreen) {
522
+ anyDocument.exitFullscreen()["catch"](function () { });
523
+ }
524
+ else if (anyDocument.mozCancelFullScreen) {
525
+ anyDocument.mozCancelFullScreen()["catch"](function () { });
526
+ }
527
+ }
528
+ }
529
+ else {
530
+ if (anyElem.requestFullscreen) {
531
+ anyElem.requestFullscreen();
532
+ }
533
+ else if (anyElem.msRequestFullscreen) {
534
+ anyElem.msRequestFullscreen();
535
+ }
536
+ else if (anyElem.mozRequestFullScreen) {
537
+ anyElem.mozRequestFullScreen();
538
+ }
539
+ else if (anyElem.webkitRequestFullscreen) {
540
+ anyElem.webkitRequestFullscreen();
541
+ }
542
+ }
543
+ }
544
+ catch (e) {
545
+ console.warn("[Zuck.js] Can't access fullscreen");
546
+ }
547
+ };
548
+ var moveStoryItem = function (direction) {
549
+ var modalContainer = document.querySelector('#zuck-modal');
550
+ var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
551
+ var target = '';
552
+ var useless = '';
553
+ var transform = 0;
554
+ var slideItems = {
555
+ previous: document.querySelector('#zuck-modal .story-viewer.previous'),
556
+ next: document.querySelector('#zuck-modal .story-viewer.next'),
557
+ viewing: document.querySelector('#zuck-modal .story-viewer.viewing')
558
+ };
559
+ if ((!slideItems.previous && !direction) ||
560
+ (!slideItems.next && direction)) {
561
+ if (!zuck.option('rtl')) {
562
+ return false;
563
+ }
564
+ }
565
+ if (!direction) {
566
+ target = 'previous';
567
+ useless = 'next';
568
+ }
569
+ else {
570
+ target = 'next';
571
+ useless = 'previous';
572
+ }
573
+ var transitionTime = 600;
574
+ if (zuck.option('cubeEffect')) {
575
+ if (target === 'previous') {
576
+ transform = (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth);
577
+ }
578
+ else if (target === 'next') {
579
+ transform = (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth) * -1;
580
+ }
581
+ }
582
+ else {
583
+ transform = (0, utils_1.findPos)(slideItems[target])[0] * -1;
584
+ }
585
+ translate(modalSlider, transform, transitionTime, null);
586
+ setTimeout(function () {
587
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
588
+ // set page data when transition complete
589
+ if (zuck.option('rtl')) {
590
+ var tmp = target;
591
+ target = useless;
592
+ useless = tmp;
593
+ }
594
+ if (target !== '' && slideItems[target] && useless !== '') {
595
+ var currentStory = (_a = slideItems[target]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-story-id');
596
+ zuck.internalData.currentStory = currentStory;
597
+ var oldStory = document.querySelector("#zuck-modal .story-viewer.".concat(useless));
598
+ if (oldStory) {
599
+ (_b = oldStory === null || oldStory === void 0 ? void 0 : oldStory.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(oldStory);
600
+ }
601
+ if (slideItems.viewing) {
602
+ (_c = slideItems.viewing) === null || _c === void 0 ? void 0 : _c.classList.add('stopped');
603
+ (_d = slideItems.viewing) === null || _d === void 0 ? void 0 : _d.classList.add(useless);
604
+ (_e = slideItems.viewing) === null || _e === void 0 ? void 0 : _e.classList.remove('viewing');
605
+ }
606
+ if (slideItems[target]) {
607
+ (_f = slideItems[target]) === null || _f === void 0 ? void 0 : _f.classList.remove('stopped');
608
+ (_g = slideItems[target]) === null || _g === void 0 ? void 0 : _g.classList.remove(target);
609
+ (_h = slideItems[target]) === null || _h === void 0 ? void 0 : _h.classList.add('viewing');
610
+ }
611
+ var newTimelineItem = getStoryMorningGlory(target);
612
+ if (newTimelineItem) {
613
+ createStoryViewer(newTimelineItem, target);
614
+ }
615
+ var storyId = zuck.internalData.currentStory;
616
+ var storyIndex = zuck.findStoryIndex(storyId);
617
+ var storyWrap = document.querySelector("#zuck-modal [data-story-id=\\"".concat(storyId, "\\"]"));
618
+ var items = undefined;
619
+ if (storyWrap) {
620
+ items = storyWrap.querySelectorAll('[data-index].active');
621
+ var duration = (_j = items === null || items === void 0 ? void 0 : items[0]) === null || _j === void 0 ? void 0 : _j.firstElementChild;
622
+ zuck.data[storyIndex].currentItem = (0, utils_1.safeNum)((_k = items === null || items === void 0 ? void 0 : items[0]) === null || _k === void 0 ? void 0 : _k.getAttribute('data-index'));
623
+ if (items === null || items === void 0 ? void 0 : items[0]) {
624
+ items[0].innerHTML = zuck.template('viewerItemPointerProgress')(duration.style.cssText);
625
+ (0, utils_1.onAnimationEnd)(duration, function () {
626
+ zuck.nextItem();
627
+ });
628
+ }
629
+ }
630
+ translate(modalSlider, 0, 0, null);
631
+ if (items) {
632
+ var storyViewer = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(currentStory, "\\"]"));
633
+ zuck.playVideoItem(storyViewer, items);
634
+ }
635
+ zuck.callback('onView')(zuck.internalData.currentStory);
636
+ }
637
+ }, transitionTime + 50);
638
+ };
639
+ var createStoryViewer = function (storyData, className, forcePlay) {
640
+ var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
641
+ var storyItems = storyData['items'];
642
+ storyData.time = storyItems && (storyItems === null || storyItems === void 0 ? void 0 : storyItems[0]['time']);
643
+ var htmlItems = '';
644
+ var pointerItems = '';
645
+ var storyId = storyData['id'];
646
+ var slides = document.createElement('div');
647
+ var currentItem = storyData['currentItem'] || 0;
648
+ var exists = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(storyId, "\\"]"));
649
+ if (exists) {
650
+ return false;
651
+ }
652
+ slides.className = 'slides';
653
+ storyItems.forEach(function (item, i) {
654
+ if (currentItem > i) {
655
+ storyData.items[i].seen = true;
656
+ item.seen = true;
657
+ }
658
+ pointerItems += zuck.template('viewerItemPointer')(i, currentItem, item);
659
+ htmlItems += zuck.template('viewerItemBody')(i, currentItem, item);
660
+ });
661
+ slides.innerHTML = htmlItems;
662
+ var video = slides.querySelector('video');
663
+ var addMuted = function (video) {
664
+ if (video.muted) {
665
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('muted');
666
+ }
667
+ else {
668
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('muted');
669
+ }
670
+ };
671
+ if (video) {
672
+ video.onwaiting = function () {
673
+ if (video.paused) {
674
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('paused');
675
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('loading');
676
+ }
677
+ };
678
+ video.onplay = function () {
679
+ addMuted(video);
680
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('stopped');
681
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
682
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('loading');
683
+ };
684
+ video.onload =
685
+ video.onplaying =
686
+ video.oncanplay =
687
+ function () {
688
+ addMuted(video);
689
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('loading');
690
+ };
691
+ video.onvolumechange = function () {
692
+ addMuted(video);
693
+ };
694
+ }
695
+ var storyViewerWrap = document.createElement('div');
696
+ storyViewerWrap.innerHTML = zuck.template('viewerItem')(storyData, storyItems[currentItem]);
697
+ var storyViewer = storyViewerWrap.firstElementChild;
698
+ var storyViewerPointerWrap = storyViewer.querySelector('.slides-pointers .wrap');
699
+ storyViewer.className = "story-viewer muted ".concat(className, " ").concat(!forcePlay ? 'stopped' : '', " ").concat(zuck.option('backButton') ? 'with-back-button' : '');
700
+ if (storyId) {
701
+ storyViewer.setAttribute('data-story-id', storyId);
702
+ }
703
+ if (storyViewerPointerWrap) {
704
+ storyViewerPointerWrap.innerHTML = pointerItems;
705
+ }
706
+ storyViewer
707
+ .querySelectorAll('.close, .back')
708
+ .forEach(function (el) {
709
+ el.onclick = function (e) {
710
+ e.preventDefault();
711
+ modalZuckContainer.modal.close();
712
+ };
713
+ });
714
+ storyViewer.appendChild(slides);
715
+ if (className === 'viewing') {
716
+ zuck.playVideoItem(storyViewer, storyViewer.querySelectorAll("[data-index=\\"".concat(currentItem, "\\"].active")), undefined);
717
+ }
718
+ storyViewer
719
+ .querySelectorAll('.slides-pointers [data-index] > .progress')
720
+ .forEach(function (el) {
721
+ (0, utils_1.onAnimationEnd)(el, function () {
722
+ zuck.nextItem(undefined);
723
+ });
724
+ });
725
+ if (!modalSlider) {
726
+ return;
727
+ }
728
+ if (className === 'previous') {
729
+ (0, utils_1.prepend)(modalSlider, storyViewer);
730
+ }
731
+ else {
732
+ modalSlider.appendChild(storyViewer);
733
+ }
734
+ };
735
+ var createStoryTouchEvents = function (modalSlider) {
736
+ var modalContainer = document.querySelector('#zuck-modal');
737
+ var enableMouseEvents = true;
738
+ var position = null;
739
+ var touchOffset = null;
740
+ var isScrolling = null;
741
+ var delta = null;
742
+ var timer = undefined;
743
+ var nextTimer = undefined;
744
+ var touchStart = function (event) {
745
+ var storyViewer = document.querySelector('#zuck-modal .viewing');
746
+ var storyViewerWrap = document.querySelector('#zuck-modal .story-viewer');
747
+ if (event.target.nodeName === 'A') {
748
+ return;
749
+ }
750
+ var touches = event.touches
751
+ ? event.touches[0]
752
+ : event;
753
+ var pos = (0, utils_1.findPos)(document.querySelector('#zuck-modal .story-viewer.viewing'));
754
+ if (modalContainer) {
755
+ modalContainer.slideWidth = storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth;
756
+ modalContainer.slideHeight = storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetHeight;
757
+ }
758
+ position = {
759
+ x: pos[0],
760
+ y: pos[1]
761
+ };
762
+ var clientX = touches.clientX;
763
+ var clientY = touches.clientY;
764
+ touchOffset = {
765
+ x: clientX,
766
+ y: clientY,
767
+ time: Date.now(),
768
+ valid: true
769
+ };
770
+ if (clientY < 80 || clientY > (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideHeight) - 80) {
771
+ touchOffset.valid = false;
772
+ }
773
+ else {
774
+ event.preventDefault();
775
+ isScrolling = undefined;
776
+ delta = {};
777
+ if (enableMouseEvents) {
778
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mousemove', touchMove);
779
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mouseup', touchEnd);
780
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mouseleave', touchEnd);
781
+ }
782
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchmove', touchMove);
783
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchend', touchEnd);
784
+ if (storyViewer) {
785
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('paused');
786
+ }
787
+ zuck.pauseVideoItem();
788
+ timer = setTimeout(function () {
789
+ if (storyViewer) {
790
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('longPress');
791
+ }
792
+ }, 600);
793
+ nextTimer = setTimeout(function () {
794
+ clearInterval(nextTimer);
795
+ nextTimer = undefined;
796
+ }, 250);
797
+ }
798
+ };
799
+ var touchMove = function (event) {
800
+ var touches = event.touches
801
+ ? event.touches[0]
802
+ : event;
803
+ var clientX = touches.clientX;
804
+ var clientY = touches.clientY;
805
+ if (touchOffset && touchOffset.valid) {
806
+ delta = {
807
+ x: clientX - touchOffset.x,
808
+ y: clientY - touchOffset.y
809
+ };
810
+ if (typeof isScrolling === 'undefined') {
811
+ isScrolling = !!(isScrolling || Math.abs(delta.x) < Math.abs(delta.y));
812
+ }
813
+ if (!isScrolling && touchOffset) {
814
+ event.preventDefault();
815
+ translate(modalSlider, (0, utils_1.safeNum)(position === null || position === void 0 ? void 0 : position.x) + (0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x), 0, null);
816
+ }
817
+ }
818
+ };
819
+ var touchEnd = function (event) {
820
+ var storyViewer = document.querySelector('#zuck-modal .viewing');
821
+ var lastTouchOffset = touchOffset;
822
+ var duration = touchOffset ? Date.now() - touchOffset.time : undefined;
823
+ var isValid = (Number(duration) < 300 && Math.abs((0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x)) > 25) ||
824
+ Math.abs((0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x)) > (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth) / 3;
825
+ var direction = (0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x) < 0;
826
+ var index = direction
827
+ ? document.querySelector('#zuck-modal .story-viewer.next')
828
+ : document.querySelector('#zuck-modal .story-viewer.previous');
829
+ var isOutOfBounds = (direction && !index) || (!direction && !index);
830
+ if (touchOffset && !touchOffset.valid) {
831
+ }
832
+ else {
833
+ if (delta) {
834
+ if (!isScrolling) {
835
+ if (isValid && !isOutOfBounds) {
836
+ moveStoryItem(direction);
837
+ }
838
+ else {
839
+ translate(modalSlider, (0, utils_1.safeNum)(position === null || position === void 0 ? void 0 : position.x), 300);
840
+ }
841
+ }
842
+ touchOffset = undefined;
843
+ if (enableMouseEvents) {
844
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mousemove', touchMove);
845
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mouseup', touchEnd);
846
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mouseleave', touchEnd);
847
+ }
848
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('touchmove', touchMove);
849
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('touchend', touchEnd);
850
+ }
851
+ var video = zuck.internalData.currentVideoElement;
852
+ if (timer) {
853
+ clearInterval(timer);
854
+ }
855
+ if (storyViewer) {
856
+ zuck.playVideoItem(storyViewer, storyViewer.querySelectorAll('.active'), undefined);
857
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('longPress');
858
+ storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
859
+ }
860
+ if (nextTimer) {
861
+ clearInterval(nextTimer);
862
+ nextTimer = undefined;
863
+ var navigateItem = function () {
864
+ if (!direction) {
865
+ if ((0, utils_1.safeNum)(lastTouchOffset === null || lastTouchOffset === void 0 ? void 0 : lastTouchOffset.x) > document.body.offsetWidth / 3 ||
866
+ !zuck.option('previousTap')) {
867
+ if (zuck.option('rtl')) {
868
+ zuck.navigateItem('previous', event);
869
+ }
870
+ else {
871
+ zuck.navigateItem('next', event);
872
+ }
873
+ }
874
+ else {
875
+ if (zuck.option('rtl')) {
876
+ zuck.navigateItem('next', event);
877
+ }
878
+ else {
879
+ zuck.navigateItem('previous', event);
880
+ }
881
+ }
882
+ }
883
+ };
884
+ var storyViewerViewing = document.querySelector('#zuck-modal .viewing');
885
+ if (storyViewerViewing && video) {
886
+ if (storyViewerViewing === null || storyViewerViewing === void 0 ? void 0 : storyViewerViewing.classList.contains('muted')) {
887
+ zuck.unmuteVideoItem(video, storyViewerViewing);
888
+ }
889
+ else {
890
+ navigateItem();
891
+ }
892
+ }
893
+ else {
894
+ navigateItem();
895
+ return false;
896
+ }
897
+ }
898
+ }
899
+ };
900
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchstart', touchStart);
901
+ if (enableMouseEvents) {
902
+ modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mousedown', touchStart);
903
+ }
904
+ };
905
+ var getStoryMorningGlory = function (what) {
906
+ // my wife told me to stop singing Wonderwall. I SAID MAYBE.
907
+ var currentStory = zuck.internalData.currentStory;
908
+ if (currentStory && what !== '') {
909
+ var element = document.querySelector("#".concat(id, " [data-id=\\"").concat(currentStory, "\\"]"));
910
+ var foundStory = what === 'previous'
911
+ ? element.previousElementSibling
912
+ : element.nextElementSibling;
913
+ if (foundStory) {
914
+ var storyId = foundStory.getAttribute('data-id');
915
+ var storyIndex = zuck.findStoryIndex(storyId);
916
+ var data = zuck.data[storyIndex] || false;
917
+ return data;
918
+ }
919
+ }
920
+ return false;
921
+ };
922
+ var show = function (storyId) {
923
+ var modalContainer = document.querySelector('#zuck-modal');
924
+ var callback = function () {
925
+ var modalContent = document.querySelector('#zuck-modal-content');
926
+ modalContent.innerHTML = "<div id=\\"zuck-modal-slider-".concat(id, "\\" class=\\"slider\\"></div>");
927
+ if (!modalContent || !storyId) {
928
+ return;
929
+ }
930
+ var storyIndex = zuck.findStoryIndex(storyId);
931
+ var storyData = zuck.data[storyIndex];
932
+ var currentItem = storyData.currentItem || 0;
933
+ var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
934
+ createStoryTouchEvents(modalSlider);
935
+ zuck.internalData.currentStory = storyId;
936
+ storyData.currentItem = currentItem;
937
+ if (zuck.option('backNative') && (0, utils_1.hasWindow)()) {
938
+ window.location.hash = "#!".concat(id);
939
+ }
940
+ var previousItemData = getStoryMorningGlory('previous');
941
+ if (previousItemData) {
942
+ createStoryViewer(previousItemData, 'previous');
943
+ }
944
+ createStoryViewer(storyData, 'viewing', true);
945
+ var nextItemData = getStoryMorningGlory('next');
946
+ if (nextItemData) {
947
+ createStoryViewer(nextItemData, 'next');
948
+ }
949
+ if (zuck.option('autoFullScreen')) {
950
+ modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.add('fullscreen');
951
+ }
952
+ var tryFullScreen = function () {
953
+ if ((modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.contains('fullscreen')) &&
954
+ zuck.option('autoFullScreen') &&
955
+ document.body.offsetWidth <= 1024) {
956
+ fullScreen(modalContainer);
957
+ }
958
+ modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.focus();
959
+ };
960
+ var storyViewerWrap = document.querySelector('#zuck-modal .story-viewer');
961
+ if (zuck.option('openEffect') && modalContainer) {
962
+ var storyEl = document.querySelector("#".concat(id, " [data-id=\\"").concat(storyId, "\\"] .item-preview"));
963
+ var pos = (0, utils_1.findPos)(storyEl);
964
+ modalContainer.style.marginLeft = "".concat(pos[0] + (0, utils_1.safeNum)(storyEl === null || storyEl === void 0 ? void 0 : storyEl.offsetWidth) / 2, "px");
965
+ modalContainer.style.marginTop = "".concat(pos[1] + (0, utils_1.safeNum)(storyEl === null || storyEl === void 0 ? void 0 : storyEl.offsetHeight) / 2, "px");
966
+ modalContainer.style.display = 'block';
967
+ modalContainer.slideWidth = (storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth) || 0;
968
+ setTimeout(function () {
969
+ modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.add('animated');
970
+ }, 10);
971
+ setTimeout(function () {
972
+ tryFullScreen();
973
+ }, 300); // because effects
974
+ }
975
+ else {
976
+ if (modalContainer) {
977
+ modalContainer.style.display = 'block';
978
+ modalContainer.slideWidth = (storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth) || 0;
979
+ }
980
+ tryFullScreen();
981
+ }
982
+ zuck.callback('onView')(storyId);
983
+ };
984
+ zuck.callback('onOpen')(storyId, callback);
985
+ };
986
+ var next = function () {
987
+ var callback = function () {
988
+ var lastStory = zuck.internalData.currentStory;
989
+ var lastStoryIndex = zuck.findStoryIndex(lastStory);
990
+ var lastStoryTimelineElement = document.querySelector("#".concat(id, " [data-id=\\"").concat(lastStory, "\\"]"));
991
+ if (lastStoryTimelineElement) {
992
+ lastStoryTimelineElement === null || lastStoryTimelineElement === void 0 ? void 0 : lastStoryTimelineElement.classList.add('seen');
993
+ zuck.data[lastStoryIndex].seen = true;
994
+ zuck.internalData.seenItems[lastStory] = true;
995
+ zuck.saveLocalData('seenItems', zuck.internalData.seenItems);
996
+ zuck.updateStorySeenPosition();
997
+ }
998
+ var stories = document.querySelector('#zuck-modal .story-viewer.next');
999
+ if (!stories) {
1000
+ modalZuckContainer.modal.close();
1001
+ }
1002
+ else {
1003
+ if (zuck.option('rtl')) {
1004
+ moveStoryItem(false);
1005
+ }
1006
+ else {
1007
+ moveStoryItem(true);
1008
+ }
1009
+ }
1010
+ };
1011
+ zuck.callback('onEnd')(zuck.internalData.currentStory, callback);
1012
+ };
1013
+ var close = function () {
1014
+ var modalContainer = document.querySelector('#zuck-modal');
1015
+ var modalContent = document.querySelector('#zuck-modal-content');
1016
+ var callback = function () {
1017
+ if (zuck.option('backNative') && (0, utils_1.hasWindow)()) {
1018
+ window.location.hash = '';
1019
+ }
1020
+ fullScreen(modalContainer, true);
1021
+ if (modalContainer) {
1022
+ if (zuck.option('openEffect')) {
1023
+ modalContainer.classList.add('closed');
1024
+ }
1025
+ else {
1026
+ if (modalContent) {
1027
+ modalContent.innerHTML = '';
1028
+ }
1029
+ modalContainer.style.display = 'none';
1030
+ }
1031
+ }
1032
+ };
1033
+ zuck.callback('onClose')(zuck.internalData.currentStory, callback);
1034
+ };
1035
+ modalZuckContainer.modal = {
1036
+ show: show,
1037
+ next: next,
1038
+ close: close
1039
+ };
1040
+ return modalZuckContainer.modal;
1041
+ };
1042
+ exports.modal = modal;
1043
+
1044
+
1045
+ //# sourceURL=webpack://Zuck/./src/modal.ts?`)}),"./src/options.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
1046
+ exports.__esModule = true;
1047
+ exports.loadOptions = exports.option = exports.optionsDefault = void 0;
1048
+ var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
1049
+ var optionsDefault = function (option) { return ({
1050
+ rtl: false,
1051
+ skin: 'snapgram',
1052
+ avatars: true,
1053
+ stories: [],
1054
+ backButton: true,
1055
+ backNative: false,
1056
+ paginationArrows: false,
1057
+ previousTap: true,
1058
+ autoFullScreen: false,
1059
+ openEffect: true,
1060
+ cubeEffect: false,
1061
+ list: false,
1062
+ localStorage: true,
1063
+ callbacks: {
1064
+ onOpen: function (storyId, callback) {
1065
+ // on open story viewer
1066
+ callback();
1067
+ },
1068
+ onView: function (storyId, callback) {
1069
+ // on view story
1070
+ callback === null || callback === void 0 ? void 0 : callback();
1071
+ },
1072
+ onEnd: function (storyId, callback) {
1073
+ // on end story
1074
+ callback();
1075
+ },
1076
+ onClose: function (storyId, callback) {
1077
+ // on close story viewer
1078
+ callback();
1079
+ },
1080
+ onNextItem: function (storyId, nextStoryId, callback) {
1081
+ // on navigate item of story
1082
+ callback();
1083
+ },
1084
+ onNavigateItem: function (storyId, nextStoryId, callback) {
1085
+ // use to update state on your reactive framework
1086
+ callback();
1087
+ },
1088
+ onDataUpdate: function (data, callback) {
1089
+ // use to update state on your reactive framework
1090
+ callback();
1091
+ }
1092
+ },
1093
+ template: {
1094
+ timelineItem: function (itemData) {
1095
+ return "\\n <div class=\\"story ".concat(itemData['seen'] === true ? 'seen' : '', "\\">\\n <a class=\\"item-link\\" ").concat(itemData['link'] ? "href=\\"".concat(itemData['link'] || '', "\\"") : '', ">\\n <span class=\\"item-preview\\">\\n <img lazy=\\"eager\\" src=\\"").concat(option('avatars') || !itemData['currentPreview']
1096
+ ? itemData['photo']
1097
+ : itemData['currentPreview'], "\\" />\\n </span>\\n <span class=\\"info\\" itemProp=\\"author\\" itemScope itemType=\\"http://schema.org/Person\\">\\n <strong class=\\"name\\" itemProp=\\"name\\">").concat(itemData['name'], "</strong>\\n <span class=\\"time\\">").concat((0, utils_1.timeAgo)(itemData['lastUpdated'] || itemData['time'], option('language')) || '', "</span>\\n </span>\\n </a>\\n\\n <ul class=\\"items\\"></ul>\\n </div>");
1098
+ },
1099
+ timelineStoryItem: function (itemData) {
1100
+ var reserved = [
1101
+ 'id',
1102
+ 'seen',
1103
+ 'src',
1104
+ 'link',
1105
+ 'linkText',
1106
+ 'loop',
1107
+ 'time',
1108
+ 'type',
1109
+ 'length',
1110
+ 'preview'
1111
+ ];
1112
+ var attributes = "";
1113
+ for (var dataKey in itemData) {
1114
+ if (reserved.indexOf(dataKey) === -1) {
1115
+ if (itemData[dataKey] !== undefined && itemData[dataKey] !== false) {
1116
+ attributes += " data-".concat(dataKey, "=\\"").concat(itemData[dataKey], "\\"");
1117
+ }
1118
+ }
1119
+ }
1120
+ reserved.forEach(function (dataKey) {
1121
+ if (itemData[dataKey] !== undefined && itemData[dataKey] !== false) {
1122
+ attributes += " data-".concat(dataKey, "=\\"").concat(itemData[dataKey], "\\"");
1123
+ }
1124
+ });
1125
+ return "<a href=\\"".concat(itemData['src'], "\\" ").concat(attributes, ">\\n <img loading=\\"auto\\" src=\\"").concat(itemData['preview'], "\\" />\\n </a>");
1126
+ },
1127
+ viewerItem: function (storyData, currentStoryItem) {
1128
+ return "<div class=\\"story-viewer\\">\\n <div class=\\"head\\">\\n <div class=\\"left\\">\\n ".concat(option('backButton') ? '<a class="back">&lsaquo;</a>' : '', "\\n\\n <span class=\\"item-preview\\">\\n <img lazy=\\"eager\\" class=\\"profilePhoto\\" src=\\"").concat(storyData['photo'], "\\" />\\n </span>\\n\\n <div class=\\"info\\">\\n <strong class=\\"name\\">").concat(storyData['name'], "</strong>\\n <span class=\\"time\\">").concat((0, utils_1.timeAgo)(storyData['time'], option('language')) || '', "</span>\\n </div>\\n </div>\\n\\n <div class=\\"right\\">\\n <span class=\\"time\\">\\n ").concat((0, utils_1.timeAgo)(currentStoryItem['time'], option('language')) ||
1129
+ '', "\\n </span>\\n <span class=\\"loading\\"></span>\\n <a class=\\"close\\" tabIndex=\\"2\\">&times;</a>\\n </div>\\n </div>\\n\\n <div class=\\"slides-pointers\\">\\n <div class=\\"wrap\\"></div>\\n </div>\\n\\n ").concat(option('paginationArrows')
1130
+ ? "\\n <div class=\\"slides-pagination\\">\\n <span class=\\"previous\\">&lsaquo;</span>\\n <span class=\\"next\\">&rsaquo;</span>\\n </div>"
1131
+ : '', "\\n </div>");
1132
+ },
1133
+ viewerItemPointerProgress: function (style) {
1134
+ return "<span class=\\"progress\\" style=\\"".concat(style, "\\"></span>");
1135
+ },
1136
+ viewerItemPointer: function (index, currentIndex, item) {
1137
+ return "<span\\n class=\\"\\n ".concat(currentIndex === index ? 'active' : '', "\\n ").concat(item['seen'] === true ? 'seen' : '', "\\n \\"\\n data-index=\\"").concat(index, "\\" data-item-id=\\"").concat(item['id'], "\\">\\n ").concat(option('template')['viewerItemPointerProgress']("animation-duration:".concat((0, utils_1.safeNum)(item['length']) ? item['length'] : '3', "s")), "\\n </span>");
1138
+ },
1139
+ viewerItemBody: function (index, currentIndex, item) {
1140
+ return "<div\\n class=\\"\\n item\\n ".concat(item['seen'] === true ? 'seen' : '', "\\n ").concat(currentIndex === index ? 'active' : '', "\\n \\"\\n data-time=\\"").concat(item['time'], "\\"\\n data-type=\\"").concat(item['type'], "\\"\\n data-index=\\"").concat(index, "\\"\\n data-item-id=\\"").concat(item['id'], "\\">\\n ").concat(item['type'] === 'video'
1141
+ ? "<video class=\\"media\\" data-length=\\"".concat(item.length, "\\" ").concat(item.loop ? 'loop' : '', " muted webkit-playsinline playsinline preload=\\"auto\\" src=\\"").concat(item['src'], "\\" ").concat(item['type'], "></video>\\n <b class=\\"tip muted\\">").concat(option('language')['unmute'], "</b>")
1142
+ : "<img loading=\\"auto\\" class=\\"media\\" src=\\"".concat(item['src'], "\\" ").concat(item['type'], " />\\n "), "\\n\\n ").concat(item['link']
1143
+ ? "<a class=\\"tip link\\" href=\\"".concat(item['link'], "\\" rel=\\"noopener\\" target=\\"_blank\\">\\n ").concat(item['linkText'] || option('language')['visitLink'], "\\n </a>")
1144
+ : '', "\\n </div>");
1145
+ }
1146
+ },
1147
+ language: {
1148
+ unmute: 'Touch to unmute',
1149
+ keyboardTip: 'Press space to see next',
1150
+ visitLink: 'Visit link',
1151
+ time: {
1152
+ ago: 'ago',
1153
+ hour: 'hour ago',
1154
+ hours: 'hours ago',
1155
+ minute: 'minute ago',
1156
+ minutes: 'minutes ago',
1157
+ fromnow: 'from now',
1158
+ seconds: 'seconds ago',
1159
+ yesterday: 'yesterday',
1160
+ tomorrow: 'tomorrow',
1161
+ days: 'days ago'
1162
+ }
1163
+ }
1164
+ }); };
1165
+ exports.optionsDefault = optionsDefault;
1166
+ var option = function (options, _name) {
1167
+ var self = function (name) {
1168
+ return typeof (options === null || options === void 0 ? void 0 : options[name]) !== 'undefined'
1169
+ ? options === null || options === void 0 ? void 0 : options[name]
1170
+ : (0, exports.optionsDefault)(self)[name];
1171
+ };
1172
+ return self(_name);
1173
+ };
1174
+ exports.option = option;
1175
+ var loadOptions = function (options) {
1176
+ return {
1177
+ option: function (name) {
1178
+ return (0, exports.option)(options, name);
1179
+ },
1180
+ callback: function (name) {
1181
+ var customOpts = (0, exports.option)(options, 'callbacks');
1182
+ return typeof customOpts[name] !== undefined
1183
+ ? customOpts[name]
1184
+ : (0, exports.option)(undefined, 'callbacks')[name];
1185
+ },
1186
+ template: function (name) {
1187
+ var customOpts = (0, exports.option)(options, 'template');
1188
+ return typeof customOpts[name] !== undefined
1189
+ ? customOpts[name]
1190
+ : (0, exports.option)(undefined, 'template')[name];
1191
+ },
1192
+ language: function (name) {
1193
+ var customOpts = (0, exports.option)(options, 'language');
1194
+ return typeof customOpts[name] !== undefined
1195
+ ? customOpts[name]
1196
+ : (0, exports.option)(undefined, 'language')[name];
1197
+ }
1198
+ };
1199
+ };
1200
+ exports.loadOptions = loadOptions;
1201
+
1202
+
1203
+ //# sourceURL=webpack://Zuck/./src/options.ts?`)}),"./src/utils.ts":((__unused_webpack_module,exports)=>{eval(`
1204
+ exports.__esModule = true;
1205
+ exports.timeAgo = exports.findPos = exports.generateId = exports.prepend = exports.onTransitionEnd = exports.onAnimationEnd = exports.safeNum = exports.hasWindow = void 0;
1206
+ var hasWindow = function () {
1207
+ return typeof window !== 'undefined';
1208
+ };
1209
+ exports.hasWindow = hasWindow;
1210
+ var safeNum = function (num) {
1211
+ return num ? Number(num) : 0;
1212
+ };
1213
+ exports.safeNum = safeNum;
1214
+ var onAnimationEnd = function (el, func) {
1215
+ el.addEventListener('animationend', func);
1216
+ };
1217
+ exports.onAnimationEnd = onAnimationEnd;
1218
+ var onTransitionEnd = function (el, func) {
1219
+ if (!el.transitionEndEvent) {
1220
+ el.transitionEndEvent = true;
1221
+ el.addEventListener('transitionend', func);
1222
+ }
1223
+ };
1224
+ exports.onTransitionEnd = onTransitionEnd;
1225
+ var prepend = function (parent, child) {
1226
+ if (!child || !parent) {
1227
+ return;
1228
+ }
1229
+ if (parent === null || parent === void 0 ? void 0 : parent.firstChild) {
1230
+ parent.insertBefore(child, parent === null || parent === void 0 ? void 0 : parent.firstChild);
1231
+ }
1232
+ else {
1233
+ parent.appendChild(child);
1234
+ }
1235
+ };
1236
+ exports.prepend = prepend;
1237
+ var generateId = function () {
1238
+ return 'stories-' + Math.random().toString(36).substr(2, 9);
1239
+ };
1240
+ exports.generateId = generateId;
1241
+ var findPos = function (obj, offsetY, offsetX, stop) {
1242
+ var curleft = 0;
1243
+ var curtop = 0;
1244
+ if (obj) {
1245
+ if (obj.offsetParent) {
1246
+ do {
1247
+ curleft += obj.offsetLeft;
1248
+ curtop += obj.offsetTop;
1249
+ if (obj === stop) {
1250
+ break;
1251
+ }
1252
+ } while ((obj = obj.offsetParent));
1253
+ }
1254
+ if (offsetY) {
1255
+ curtop = curtop - offsetY;
1256
+ }
1257
+ if (offsetX) {
1258
+ curleft = curleft - offsetX;
1259
+ }
1260
+ }
1261
+ return [curleft, curtop];
1262
+ };
1263
+ exports.findPos = findPos;
1264
+ var timeAgo = function (time, languageObject) {
1265
+ var language = (languageObject === null || languageObject === void 0 ? void 0 : languageObject.time) || undefined;
1266
+ var timeNumber = time instanceof Date ? time.getTime() : (0, exports.safeNum)(time) * 1000;
1267
+ var dateObj = new Date(timeNumber);
1268
+ var dateStr = dateObj.getTime();
1269
+ var seconds = (new Date().getTime() - dateStr) / 1000;
1270
+ var formats = [
1271
+ [60, " ".concat((language === null || language === void 0 ? void 0 : language.seconds) || ''), 1],
1272
+ [120, "1 ".concat((language === null || language === void 0 ? void 0 : language.minute) || ''), ''],
1273
+ [3600, " ".concat((language === null || language === void 0 ? void 0 : language.minutes) || ''), 60],
1274
+ [7200, "1 ".concat((language === null || language === void 0 ? void 0 : language.hour) || ''), ''],
1275
+ [86400, " ".concat((language === null || language === void 0 ? void 0 : language.hours) || ''), 3600],
1276
+ [172800, " ".concat((language === null || language === void 0 ? void 0 : language.yesterday) || ''), ''],
1277
+ [604800, " ".concat((language === null || language === void 0 ? void 0 : language.days) || ''), 86400]
1278
+ ];
1279
+ var currentFormat = 1;
1280
+ if (seconds < 0) {
1281
+ seconds = Math.abs(seconds);
1282
+ currentFormat = 2;
1283
+ }
1284
+ var result = false;
1285
+ formats.forEach(function (format) {
1286
+ var formatKey = format[0];
1287
+ if (seconds < formatKey && !result) {
1288
+ if (typeof format[2] === 'string') {
1289
+ result = format[currentFormat];
1290
+ }
1291
+ else if (format !== null) {
1292
+ result = Math.floor(seconds / format[2]) + format[1];
1293
+ }
1294
+ }
1295
+ });
1296
+ if (!result) {
1297
+ var day = dateObj.getDate();
1298
+ var month = dateObj.getMonth();
1299
+ var year = dateObj.getFullYear();
1300
+ return "".concat(day, "/").concat(month + 1, "/").concat(year);
1301
+ }
1302
+ else {
1303
+ return result;
1304
+ }
1305
+ };
1306
+ exports.timeAgo = timeAgo;
1307
+
1308
+
1309
+ //# sourceURL=webpack://Zuck/./src/utils.ts?`)})},__webpack_module_cache__={};function __webpack_require__(n){var t=__webpack_module_cache__[n];if(t!==void 0)return t.exports;var e=__webpack_module_cache__[n]={exports:{}};return __webpack_modules__[n](e,e.exports,__webpack_require__),e.exports}var __webpack_exports__=__webpack_require__("./src/index.ts");exports.Zuck=__webpack_exports__.default})()});export default a();
sha256/6ff8513d484fcf377d948147762b83dafd3cdefd3d48d4333669407808a7653c ADDED
The diff for this file is too large to render. See raw diff
 
sha256/7c0ac719466c48d161fba6b77fdcee5a6c017f9d540da575f23191ddbc97d982 ADDED
The diff for this file is too large to render. See raw diff
 
sha256/929cb2072b4084ca0195c2c0cb65190340c29e62c6b5c50dc1cebf8b788f6eca ADDED
@@ -0,0 +1 @@
 
 
1
+ import{$ as lt,A as nt,B as ot,Ca as ft,Cb as K,F as it,G as ct,Ja as gt,Pa as T,Q as at,S as rt,Sa as B,_ as st,aa as W,ab as wt,bb as tt,ha as ut,ia as ht,ib as X,jb as pt,ka as J,la as N,ma as Q,nb as L,p as q,qa as dt,ub as $,wa as mt,xb as vt}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as Pt}from"./chunk-EJ2FITLI.js";import{b as It}from"./chunk-SQE76S5B.js";var e=It(Pt(),1);var Mt={minZoom:1,maxZoomPixelRatio:1,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:500,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,pinchZoomV4:!1,scrollToZoom:!1,maxZoom:8};function _t(t){return Math.min(Math.max(t,Number.EPSILON),1)}function Ct(t){let{minZoom:n,...i}={...Mt,...t};return{minZoom:_t(n),...i}}function kt(t,n,i,o){let c=e.useRef(void 0),l=e.useRef(void 0),{zoom:u}=T().animation,s=pt(),h=L(()=>{var d,g,r;if((d=c.current)===null||d===void 0||d.cancel(),c.current=void 0,l.current&&o?.current){try{c.current=(r=(g=o.current).animate)===null||r===void 0?void 0:r.call(g,[{transform:l.current},{transform:`scale(${t}) translateX(${n}px) translateY(${i}px)`}],{duration:s?0:u??500,easing:c.current?"ease-out":"ease-in-out"})}catch(R){console.error(R)}l.current=void 0,c.current&&(c.current.onfinish=()=>{c.current=void 0})}});return X(h,[t,n,i,h]),e.useCallback(()=>{l.current=o?.current?window.getComputedStyle(o.current).transform:void 0},[o])}function yt(t,n){let{on:i}=T(),o=L(()=>{var c;n||(c=i.zoom)===null||c===void 0||c.call(i,{zoom:t})});e.useEffect(o,[t,o])}function G(){let{zoom:t}=T();return Ct(t)}function Dt(t,n){var i;let o=typeof t=="function"?(i=t(n))!==null&&i!==void 0?i:Mt.maxZoom:t;return Math.max(o,1)}function Ot(t,n){var i,o;let c={width:0,height:0},l={width:0,height:0},{currentSlide:u}=B(),{imageFit:s}=T().carousel,{maxZoomPixelRatio:h,maxZoom:d}=G();if(t&&u){let r={...u,...n};if(N(r)){let R=Q(r,s),m=Math.max(...(((i=r.srcSet)===null||i===void 0?void 0:i.map(v=>v.width))||[]).concat(r.width?[r.width]:[])),w=Math.max(...(((o=r.srcSet)===null||o===void 0?void 0:o.map(v=>v.height))||[]).concat(r.height?[r.height]:[]));m>0&&w>0&&t.width>0&&t.height>0&&(l=R?{width:Math.round(Math.min(m,t.width/t.height*w)),height:Math.round(Math.min(w,t.height/t.width*m))}:{width:m,height:w},l={width:l.width*h,height:l.height*h},c=R?{width:Math.min(t.width,l.width,m),height:Math.min(t.height,l.height,w)}:{width:Math.round(Math.min(t.width,t.height/w*m,m)),height:Math.round(Math.min(t.height,t.width/m*w,w))})}else t.width>0&&t.height>0&&(n&&n.width>0&&n.height>0?c={width:Math.min(t.width,n.width),height:Math.min(t.height,n.height)}:c={width:t.width,height:t.height})}let g=u&&c.width?N(u)?Math.max(J(l.width/c.width,5),1):Dt(d,u):1;return{imageRect:c,maxZoom:g}}function Rt(t,n){return Math.hypot(t.clientX-n.clientX,t.clientY-n.clientY)}function Zt(t,n,i=100,o=2){return t*Math.min(1+Math.abs(n/i),o)**Math.sign(n)}function Lt(t,n,i,o,c,l,u,s,h){let d=e.useRef([]),g=e.useRef(0),r=e.useRef(void 0),{globalIndex:R}=B(),{getOwnerWindow:m}=gt(),{containerRef:w,subscribeSensors:v}=K(),{keyboardMoveDistance:C,zoomInMultiplier:k,wheelZoomDistanceFactor:x,scrollToZoom:M,doubleTapDelay:Z,doubleClickDelay:b,doubleClickMaxStops:S,pinchZoomDistanceFactor:p,pinchZoomV4:I}=G(),Y=e.useCallback(a=>{if(w.current){let{pageX:f,pageY:E}=a,{scrollX:P,scrollY:_}=m(),{left:O,top:F,width:H,height:V}=w.current.getBoundingClientRect();return[f-O-P-H/2,E-F-_-V/2]}return[]},[w,m]),y=L(a=>{let{key:f,metaKey:E,ctrlKey:P}=a,_=E||P,O=()=>{a.preventDefault(),a.stopPropagation()};if(t>1){let F=(H,V)=>{O(),s(H,V)};f==="ArrowDown"?F(0,C):f==="ArrowUp"?F(0,-C):f==="ArrowLeft"?F(-C,0):f==="ArrowRight"&&F(C,0)}f==="+"||_&&f==="="?(O(),c()):f==="-"||_&&f==="_"?(O(),l()):_&&f==="0"&&(O(),u(1))}),D=L(a=>{if((a.ctrlKey||M)&&Math.abs(a.deltaY)>Math.abs(a.deltaX)){a.stopPropagation(),u(Zt(t,-a.deltaY,x),!0,...Y(a));return}t>1&&(a.stopPropagation(),M||s(a.deltaX,a.deltaY))}),A=e.useCallback(a=>{let f=d.current;f.splice(0,f.length,...f.filter(E=>E.pointerId!==a.pointerId))},[]),z=e.useCallback(a=>{A(a),a.persist(),d.current.push(a)},[A]),j=L(a=>{var f;let E=d.current;if(a.pointerType==="mouse"&&a.buttons>1||!(!((f=h?.current)===null||f===void 0)&&f.contains(a.target)))return;t>1&&a.stopPropagation();let{timeStamp:P}=a;if(E.length===0&&P-g.current<(a.pointerType==="touch"?Z:b)){g.current=0;let _=t>=1?t!==i?t*Math.max(i**(1/S),k):1:t!==n?t/Math.max(n**(-1/S),k):1;u(_,!1,...Y(a))}else g.current=P;if(z(a),E.length===2){let _=Rt(E[0],E[1]);r.current={previousDistance:_,initialDistance:Math.max(_,1),initialZoom:t}}}),xt=L(a=>{let f=d.current,E=f.find(P=>P.pointerId===a.pointerId);if(f.length===2&&r.current){a.stopPropagation(),z(a);let P=Rt(f[0],f[1]),_=I?r.current.initialZoom/r.current.initialDistance*P:Zt(t,P-r.current.previousDistance,p);u(_,!0,...f.map(O=>Y(O)).reduce((O,F)=>F.map((H,V)=>O[V]+H/2))),r.current.previousDistance=P;return}t>1&&(a.stopPropagation(),E&&(f.length===1&&s((E.clientX-a.clientX)/t,(E.clientY-a.clientY)/t),z(a)))}),St=e.useCallback(a=>{let f=d.current;f.length===2&&f.find(E=>E.pointerId===a.pointerId)&&(r.current=void 0),A(a)},[A]),U=e.useCallback(()=>{let a=d.current;a.splice(0,a.length),g.current=0,r.current=void 0},[]);vt(v,j,xt,St,o),e.useEffect(U,[R,U]),e.useEffect(()=>o?()=>{}:ut(U,v(at,y),v(rt,D)),[o,v,U,y,D])}function Yt(t,n,i){let[o,c]=e.useState(1),[l,u]=e.useState(0),[s,h]=e.useState(0),d=kt(o,l,s,i),{currentSlide:g,globalIndex:r}=B(),{containerRect:R,slideRect:m}=K(),{minZoom:w,zoomInMultiplier:v}=G(),C=g&&N(g)?g.src:void 0,k=!i?.current;X(()=>{c(1),u(0),h(0)},[r,C]);let x=e.useCallback((p,I,Y)=>{let y=Y||o,D=l-(p||0),A=s-(I||0),z=(t.width*y-m.width)/2/y,j=(t.height*y-m.height)/2/y;u(Math.min(Math.abs(D),Math.max(z,0))*Math.sign(D)),h(Math.min(Math.abs(A),Math.max(j,0))*Math.sign(A))},[o,l,s,m,t.width,t.height]),M=e.useCallback((p,I,Y,y)=>{let D=J(p+.01<n?p-.01>w?p:w:n,5);I||d(),x(Y?Y*(1/o-1/D):0,y?y*(1/o-1/D):0,D),c(D)},[o,w,n,x,d]),Z=L(()=>{o>1&&(o>n&&M(n,!0),x())});X(Z,[R.width,R.height,Z]);let b=e.useCallback(()=>{let p=o*v;M(o<1&&p>1?1:p)},[o,v,M]),S=e.useCallback(()=>{let p=o/v;M(o>1&&p<1?1:p)},[o,v,M]);return{zoom:o,offsetX:l,offsetY:s,disabled:k,changeOffsets:x,changeZoom:M,zoomIn:b,zoomOut:S}}var Et=e.createContext(null),et=ht("useZoom","ZoomControllerContext",Et);function Ft({children:t}){let[n,i]=e.useState(),{slideRect:o}=K(),{ref:c,minZoom:l}=G(),{imageRect:u,maxZoom:s}=Ot(o,n?.imageDimensions),{zoom:h,offsetX:d,offsetY:g,disabled:r,changeZoom:R,changeOffsets:m,zoomIn:w,zoomOut:v}=Yt(u,s,n?.zoomWrapperRef);yt(h,r),Lt(h,l,s,r,w,v,R,m,n?.zoomWrapperRef);let C=e.useMemo(()=>({zoom:h,minZoom:l,maxZoom:s,offsetX:d,offsetY:g,disabled:r,zoomIn:w,zoomOut:v,changeZoom:R}),[h,l,s,d,g,r,w,v,R]);e.useImperativeHandle(c,()=>C,[C]);let k=e.useMemo(()=>({...C,setZoomWrapper:i}),[C,i]);return e.createElement(Et.Provider,{value:k},t)}var Tt=tt("ZoomIn",e.createElement(e.Fragment,null,e.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),e.createElement("path",{d:"M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"}))),At=tt("ZoomOut",e.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"})),bt=e.forwardRef(function({zoomIn:n,onLoseFocus:i},o){let c=e.useRef(!1),l=e.useRef(!1),{zoom:u,minZoom:s,maxZoom:h,zoomIn:d,zoomOut:g,disabled:r}=et(),{render:R}=T(),m=r||(n?u>=h:u<=s);return e.useEffect(()=>{m&&c.current&&l.current&&i(),m||(c.current=!0)},[m,i]),e.createElement(wt,{ref:o,disabled:m,label:n?"Zoom in":"Zoom out",icon:n?Tt:At,renderIcon:n?R.iconZoomIn:R.iconZoomOut,onClick:n?d:g,onFocus:()=>{l.current=!0},onBlur:()=>{l.current=!1}})});function Xt(){let t=e.useRef(null),n=e.useRef(null),{focus:i}=K(),o=e.useCallback(u=>{var s,h;!((s=u.current)===null||s===void 0)&&s.disabled?i():(h=u.current)===null||h===void 0||h.focus()},[i]),c=e.useCallback(()=>o(t),[o]),l=e.useCallback(()=>o(n),[o]);return e.createElement(e.Fragment,null,e.createElement(bt,{zoomIn:!0,ref:t,onLoseFocus:l}),e.createElement(bt,{ref:n,onLoseFocus:c}))}function Nt(){let{render:t}=T(),n=et();return t.buttonZoom?e.createElement(e.Fragment,null,t.buttonZoom(n)):e.createElement(Xt,null)}function zt(t){var n;return(((n=t.srcSet)===null||n===void 0?void 0:n.length)||0)>0}function Ht({current:t,preload:n},{type:i,source:o}){switch(i){case"fetch":return t?{current:t,preload:o}:{current:o};case"done":return o===n?{current:o}:{current:t,preload:n};default:throw new Error(st)}}function Vt(t){var n,i;let[{current:o,preload:c},l]=e.useReducer(Ht,{}),{slide:u,rect:s,imageFit:h,render:d,interactive:g}=t,r=u.srcSet.sort((b,S)=>b.width-S.width),R=(n=u.width)!==null&&n!==void 0?n:r[r.length-1].width,m=(i=u.height)!==null&&i!==void 0?i:r[r.length-1].height,w=Q(u,h),v=Math.max(...r.map(b=>b.width)),C=Math.min((w?Math.max:Math.min)(s.width,R*(s.height/m)),v),k=dt(),x=L(()=>{var b;let S=(b=r.find(p=>p.width>=C*k))!==null&&b!==void 0?b:r[r.length-1];(!o||r.findIndex(p=>p.src===o)<r.findIndex(p=>p===S))&&l({type:"fetch",source:S.src})});X(x,[s.width,s.height,k,x]);let M=L(b=>l({type:"done",source:b})),Z={WebkitTransform:g?"initial":"translateZ(0)"};return w||Object.assign(Z,s.width/s.height<R/m?{width:"100%",height:"auto"}:{width:"auto",height:"100%"}),e.createElement(e.Fragment,null,c&&c!==o&&e.createElement($,{key:"preload",...t,offset:void 0,slide:{...u,src:c,srcSet:void 0},style:{position:"absolute",visibility:"hidden",...Z},onLoad:()=>M(c),render:{...d,iconLoading:()=>null,iconError:()=>null}}),o&&e.createElement($,{key:"current",...t,slide:{...u,src:o,srcSet:void 0},style:Z}))}function Wt({render:t,slide:n,offset:i,rect:o}){var c;let[l,u]=e.useState(),s=e.useRef(null),h=N(n),{zoom:d,maxZoom:g,offsetX:r,offsetY:R,setZoomWrapper:m}=et(),w=d>1,{carousel:v,on:C}=T(),{currentIndex:k}=B();X(()=>{if(i!==0||h||!s.current)return()=>{};let M=()=>{let b=s.current;if(!b)return;let S=0,p=0;for(let I of b.children)I instanceof HTMLElement&&(S=Math.max(S,I.offsetWidth),p=Math.max(p,I.offsetHeight));u(I=>I&&I.width===S&&I.height===p?I:{width:S,height:p})};if(M(),typeof ResizeObserver>"u")return()=>{};let Z=new ResizeObserver(M);for(let b of s.current.children)Z.observe(b);return()=>Z.disconnect()},[i,h,o]),X(()=>i===0?(m({zoomWrapperRef:s,imageDimensions:l}),()=>m(void 0)):()=>{},[i,l,m]);let x=(c=t.slide)===null||c===void 0?void 0:c.call(t,{slide:n,offset:i,rect:o,zoom:d,maxZoom:g});if(!x&&h){let M={slide:n,offset:i,rect:o,render:t,imageFit:v.imageFit,imageProps:v.imageProps,onClick:i===0?()=>{var Z;return(Z=C.click)===null||Z===void 0?void 0:Z.call(C,{index:k})}:void 0};x=zt(n)?e.createElement(Vt,{...M,slide:n,interactive:w,rect:i===0?{width:o.width*d,height:o.height*d}:o}):e.createElement($,{onLoad:Z=>u({width:Z.naturalWidth,height:Z.naturalHeight}),...M})}return x?e.createElement("div",{ref:s,className:lt(W(nt),W(ot),W(it),w&&W(ct)),style:i===0?{transform:`scale(${d}) translateX(${r}px) translateY(${R}px)`}:void 0},x):null}var Ut=({augment:t,addModule:n})=>{t(({zoom:i,toolbar:o,render:c,controller:l,...u})=>{let s=Ct(i);return{zoom:s,toolbar:mt(o,q,e.createElement(Nt,null)),render:{...c,slide:h=>{var d,g;return N(h.slide)||h.slide.type!=null&&(!((d=s.supports)===null||d===void 0)&&d.includes(h.slide.type))?e.createElement(Wt,{render:c,...h}):(g=c.slide)===null||g===void 0?void 0:g.call(c,h)}},controller:{...l,preventDefaultWheelY:s.scrollToZoom},...u}}),n(ft(q,Ft))};export{Ut as default};
sha256/946dd4ca8e36408f3e5da27813cdafad3908e2a3466dc86e82eff442de4b813f ADDED
The diff for this file is too large to render. See raw diff
 
sha256/9ffc94e11c78fbe6b940bc04ac92f0f12238cf7ce82b5092c53d5761146a50df ADDED
The diff for this file is too large to render. See raw diff
 
sha256/ba0a74a49b10960552dd4778d210a152990ee94b69a2847699c630f94f87182d ADDED
@@ -0,0 +1 @@
 
 
1
+ import{a as _n}from"./chunk-SXSU3V5W.js";import{a as mn}from"./chunk-EJ2FITLI.js";import{b as _t}from"./chunk-SQE76S5B.js";var n=_t(mn(),1);var Ve="carousel",$e="controller",vt="navigation",Lt="no-scroll",Ie="portal",gt="root",Fe="toolbar",vn="captions",Ln="counter",gn="download",Nn="fullscreen",In="inline",Cn="share",Pn="slideshow",Sn="thumbnails",On="zoom",fe="loading",Nt="playing",Re="error",Ee="complete",It="placeholder",ae=e=>`active-slide-${e}`,Tn=ae(fe),xn=ae(Nt),bn=ae(Re),wn=ae(Ee),An="fullsize",Ge="flex_center",Ct="no_scroll",He="no_scroll_padding",Ce="slide",Pt="slide_wrapper",yn="slide_wrapper_interactive",q="prev",Q="next",Ke="swipe",ee="close",Be="onPointerDown",Xe="onPointerMove",Ye="onPointerUp",ze="onPointerLeave",je="onPointerCancel",Ze="onKeyDown",St="onKeyUp",qe="onWheel",Ot="Escape",Tt="ArrowLeft",xt="ArrowRight",bt="button",Pe="icon",Qe="contain",Je="cover",wt="Unknown action type";var Gt=_t(_n(),1),Ht="yarl__";function z(...e){return e.filter(Boolean).join(" ")}function P(e){return`${Ht}${e}`}function F(e){return`--${Ht}${e}`}function pe(e,t){return`${e}${t?`_${t}`:""}`}function at(e){return t=>pe(e,t)}function ne(e,t){var o;return(o=e?.[t])!==null&&o!==void 0?o:t}function ko(e,t){return ne(e,t)}function Mn(e,t,o){return ne(e,"{index} of {total}").replace(/\{index}/g,`${st(o,t.length)+1}`).replace(/\{total}/g,`${t.length}`)}function Kt(...e){return()=>{e.forEach(t=>{t()})}}function j(e,t,o){return()=>{let r=n.useContext(o);if(!r)throw new Error(`${e} must be used within a ${t}.Provider`);return r}}function it(){return typeof window<"u"}function Dn(e,t=0){let o=10**t;return Math.round((e+Number.EPSILON)*o)/o}function Bt(e){return e.type===void 0||e.type==="image"}function Un(e,t){return e.imageFit===Je||e.imageFit!==Qe&&t===Je}function Te(e){return typeof e=="string"?Number.parseInt(e,10):e}function Oe(e){if(typeof e=="number")return{pixel:e};if(typeof e=="string"){let t=Te(e);return e.endsWith("%")?{percent:t}:{pixel:t}}return{pixel:0}}function Wn(e,t){let o=Oe(t),r=o.percent!==void 0?e.width/100*o.percent:o.pixel;return{width:Math.max(e.width-2*r,0),height:Math.max(e.height-2*r,0)}}function Vo(){return(it()?window?.devicePixelRatio:void 0)||1}function st(e,t){return t>0?(e%t+t)%t:0}function Xt(e){return e.length>0}function Yt(e,t){return e[st(t,e.length)]}function ot(e,t){return Xt(e)?Yt(e,t):void 0}function kn(e){return Bt(e)?e.src:void 0}function $o(e,t,o){if(!o)return e;let{buttons:r,...c}=e,a=r.findIndex(s=>s===t),i=n.isValidElement(o)?n.cloneElement(o,{key:t},null):o;if(a>=0){let s=[...r];return s.splice(a,1,i),{buttons:s,...c}}return{buttons:[i,...r],...c}}function Fo(){let e=t=>{t.stopPropagation()};return{onPointerDown:e,onKeyDown:e,onWheel:e}}function Vn(e,t,o=0){return Math.min(e.preload,Math.max(e.finite?t.length-1:Math.floor(t.length/2),o))}var $n=Number(n.version.split(".")[0])>=19;function Fn(e){return{inert:$n?e:e?"":void 0}}function Gn(e){e.scrollTop}var rt={open:!1,close:()=>{},index:0,slides:[],render:{},plugins:[],toolbar:{buttons:[ee]},labels:{},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},carousel:{finite:!1,preload:2,padding:"16px",spacing:"30%",imageFit:Qe,imageProps:{}},controller:{ref:null,focus:!0,aria:!1,touchAction:"none",closeOnPullUp:!1,closeOnPullDown:!1,closeOnBackdropClick:!1,closeOnEscape:!0,preventDefaultWheelX:!0,preventDefaultWheelY:!1,disableSwipeNavigation:!1},portal:{},noScroll:{disabled:!1},on:{},styles:{},className:""};function oe(e,t){return{name:e,component:t}}function U(e,t){return{module:e,children:t}}function zt(e,t,o){return e.module.name===t?o(e):e.children?[U(e.module,e.children.flatMap(r=>{var c;return(c=zt(r,t,o))!==null&&c!==void 0?c:[]}))]:[e]}function ie(e,t,o){return e.flatMap(r=>{var c;return(c=zt(r,t,o))!==null&&c!==void 0?c:[]})}function Hn(e,t=[],o=[]){let r=e,c=p=>{let E=[...r];for(;E.length>0;){let u=E.pop();if(u?.module.name===p)return!0;u?.children&&E.push(...u.children)}return!1},a=(p,E)=>{if(p===""){r=[U(E,r)];return}r=ie(r,p,u=>[U(E,[u])])},i=(p,E)=>{r=ie(r,p,u=>[U(u.module,[U(E,u.children)])])},s=(p,E,u)=>{r=ie(r,p,N=>{var I;return[U(N.module,[...u?[U(E)]:[],...(I=N.children)!==null&&I!==void 0?I:[],...u?[]:[U(E)]])]})},d=(p,E,u)=>{r=ie(r,p,N=>[...u?[U(E)]:[],N,...u?[]:[U(E)]])},f=p=>{i($e,p)},h=(p,E)=>{r=ie(r,p,u=>[U(E,u.children)])},m=p=>{r=ie(r,p,E=>E.children)},R=p=>{o.push(p)};return t.forEach(p=>{p({contains:c,addParent:a,append:i,addChild:s,addSibling:d,addModule:f,replace:h,remove:m,augment:R})}),{config:r,augmentation:p=>o.reduce((E,u)=>u(E),p)}}var jt=n.createContext(null),Zt=j("useA11yContext","A11yContext",jt);function Kn({children:e}){let[t,o]=n.useState(!1),[r,c]=n.useState(!1),a=n.useMemo(()=>({focusWithin:t,trackFocusWithin:(s,d)=>{let f=h=>m=>{var R;m.currentTarget.contains(m.relatedTarget)||o(h),(R=h?s:d)===null||R===void 0||R(m)};return{onFocus:f(!0),onBlur:f(!1)}},autoPlaying:r,setAutoPlaying:c}),[t,r]);return n.createElement(jt.Provider,{value:a},e)}var qt=n.createContext(null),lt=j("useDocument","DocumentContext",qt);function Bn({nodeRef:e,children:t}){let o=n.useMemo(()=>{let r=a=>{var i;return((i=a||e.current)===null||i===void 0?void 0:i.ownerDocument)||document};return{getOwnerDocument:r,getOwnerWindow:a=>{var i;return((i=r(a))===null||i===void 0?void 0:i.defaultView)||window}}},[e]);return n.createElement(qt.Provider,{value:o},t)}var Qt=n.createContext(null),xe=j("useEvents","EventsContext",Qt);function Xn({children:e}){let[t]=n.useState({});n.useEffect(()=>()=>{Object.keys(t).forEach(r=>delete t[r])},[t]);let o=n.useMemo(()=>{let r=(i,s)=>{var d;(d=t[i])===null||d===void 0||d.splice(0,t[i].length,...t[i].filter(f=>f!==s))};return{publish:(...[i,s])=>{var d;(d=t[i])===null||d===void 0||d.forEach(f=>f(s))},subscribe:(i,s)=>(t[i]||(t[i]=[]),t[i].push(s),()=>r(i,s)),unsubscribe:r}},[t]);return n.createElement(Qt.Provider,{value:o},e)}var Jt=n.createContext(null),he=j("useLightboxProps","LightboxPropsContext",Jt);function Yn({children:e,...t}){return n.createElement(Jt.Provider,{value:t},e)}var en=n.createContext(null),be=j("useLightboxState","LightboxStateContext",en),tn=n.createContext(null),zn=j("useLightboxDispatch","LightboxDispatchContext",tn);function jn(e,t){switch(t.type){case"swipe":{let{slides:o}=e,r=t?.increment||0,c=e.globalIndex+r,a=st(c,o.length),i=ot(o,a),s=r||t.duration!==void 0?{increment:r,duration:t.duration,easing:t.easing}:void 0;return{slides:o,currentIndex:a,globalIndex:c,currentSlide:i,animation:s}}case"update":return t.slides!==e.slides||t.index!==e.currentIndex?{slides:t.slides,currentIndex:t.index,globalIndex:t.index,currentSlide:ot(t.slides,t.index)}:e;default:throw new Error(wt)}}function Zn({slides:e,index:t,children:o}){let[r,c]=n.useReducer(jn,{slides:e,currentIndex:t,globalIndex:t,currentSlide:ot(e,t)}),[a,i]=n.useState(e),[s,d]=n.useState(t);(e!==a||t!==s)&&(i(e),d(t),c({type:"update",slides:e,index:t}));let f=n.useMemo(()=>({...r,state:r,dispatch:c}),[r,c]);return n.createElement(tn.Provider,{value:c},n.createElement(en.Provider,{value:f},o))}var nn=n.createContext(null),qn=j("useRTLContext","RTLContext",nn);function Qn({isRTL:e,children:t}){let o=n.useMemo(()=>({isRTL:e}),[e]);return n.createElement(nn.Provider,{value:o},t)}var on=n.createContext(null),we=j("useTimeouts","TimeoutsContext",on);function Jn({children:e}){let[t]=n.useState([]);n.useEffect(()=>()=>{t.forEach(r=>window.clearTimeout(r)),t.splice(0,t.length)},[t]);let o=n.useMemo(()=>{let r=i=>{t.splice(0,t.length,...t.filter(s=>s!==i))};return{setTimeout:(i,s)=>{let d=window.setTimeout(()=>{r(d),i()},s);return t.push(d),d},clearTimeout:i=>{i!==void 0&&(r(i),window.clearTimeout(i))}}},[t]);return n.createElement(on.Provider,{value:o},e)}var rn=n.forwardRef(function({label:t,className:o,icon:r,renderIcon:c,onClick:a,style:i,...s},d){let{styles:f,labels:h}=he(),m=ne(h,t);return n.createElement("button",{ref:d,type:"button",title:m,"aria-label":m,className:z(P(bt),o),onClick:a,style:{...i,...f.button},...s},c?c():n.createElement(r,{className:P(Pe),style:f.icon}))});function cn(e,t){let o=r=>n.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false",...r},t);return o.displayName=e,o}function me(e,t){return cn(e,n.createElement("g",{fill:"currentColor"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t))}function Go(e,t){return cn(e,n.createElement(n.Fragment,null,n.createElement("defs",null,n.createElement("mask",{id:"strike"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"white"}),n.createElement("path",{d:"M0 0L24 24",stroke:"black",strokeWidth:4}))),n.createElement("path",{d:"M0.70707 2.121320L21.878680 23.292883",stroke:"currentColor",strokeWidth:2}),n.createElement("g",{fill:"currentColor",mask:"url(#strike)"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t)))}var eo=me("Close",n.createElement("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})),to=me("Previous",n.createElement("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})),no=me("Next",n.createElement("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})),oo=me("Loading",n.createElement(n.Fragment,null,Array.from({length:8}).map((e,t,o)=>n.createElement("line",{key:t,x1:"12",y1:"6.5",x2:"12",y2:"1.8",strokeLinecap:"round",strokeWidth:"2.6",stroke:"currentColor",strokeOpacity:1/o.length*(t+1),transform:`rotate(${360/o.length*t}, 12, 12)`})))),ro=me("Error",n.createElement("path",{d:"M21.9,21.9l-8.49-8.49l0,0L3.59,3.59l0,0L2.1,2.1L0.69,3.51L3,5.83V19c0,1.1,0.9,2,2,2h13.17l2.31,2.31L21.9,21.9z M5,18 l3.5-4.5l2.5,3.01L12.17,15l3,3H5z M21,18.17L5.83,3H19c1.1,0,2,0.9,2,2V18.17z"})),Ae=it()?n.useLayoutEffect:n.useEffect;function an(){let[e,t]=n.useState(!1);return n.useEffect(()=>{var o,r;let c=(o=window.matchMedia)===null||o===void 0?void 0:o.call(window,"(prefers-reduced-motion: reduce)");t(c?.matches);let a=i=>t(i.matches);return(r=c?.addEventListener)===null||r===void 0||r.call(c,"change",a),()=>{var i;return(i=c?.removeEventListener)===null||i===void 0?void 0:i.call(c,"change",a)}},[]),e}function co(e){let t=0,o=0,r=0,a=window.getComputedStyle(e).transform.match(/matrix.*\((.+)\)/);if(a){let i=a[1].split(",").map(Te);i.length===6?(t=i[4],o=i[5]):i.length===16&&(t=i[12],o=i[13],r=i[14])}return{x:t,y:o,z:r}}function At(e,t){let o=n.useRef(void 0),r=n.useRef(void 0),c=an();return Ae(()=>{var a,i,s;if(e.current&&o.current!==void 0&&!c){let{keyframes:d,duration:f,easing:h,onfinish:m}=t(o.current,e.current.getBoundingClientRect(),co(e.current))||{};if(d&&f){(a=r.current)===null||a===void 0||a.cancel(),r.current=void 0;try{r.current=(s=(i=e.current).animate)===null||s===void 0?void 0:s.call(i,d,{duration:f,easing:h})}catch(R){console.error(R)}r.current&&(r.current.onfinish=()=>{r.current=void 0,m?.()})}}o.current=void 0}),{prepareAnimation:a=>{o.current=a},isAnimationPlaying:()=>{var a;return((a=r.current)===null||a===void 0?void 0:a.playState)==="running"}}}function sn(){let e=n.useRef(null),t=n.useRef(void 0),[o,r]=n.useState();return{setContainerRef:n.useCallback(a=>{e.current=a,t.current&&(t.current.disconnect(),t.current=void 0);let i=()=>{if(a){let s=window.getComputedStyle(a),d=f=>parseFloat(f)||0;r({width:Math.round(a.clientWidth-d(s.paddingLeft)-d(s.paddingRight)),height:Math.round(a.clientHeight-d(s.paddingTop)-d(s.paddingBottom))})}else r(void 0)};i(),a&&typeof ResizeObserver<"u"&&(t.current=new ResizeObserver(i),t.current.observe(a))},[]),containerRef:e,containerRect:o}}function Se(){let e=n.useRef(void 0),{setTimeout:t,clearTimeout:o}=we();return n.useCallback((r,c)=>{o(e.current),e.current=t(r,c>0?c:0)},[t,o])}function A(e){let t=n.useRef(e);return Ae(()=>{t.current=e}),n.useCallback((...o)=>{var r;return(r=t.current)===null||r===void 0?void 0:r.call(t,...o)},[])}function yt(e,t){typeof e=="function"?e(t):e&&(e.current=t)}function ct(e,t){return n.useMemo(()=>e==null&&t==null?null:o=>{yt(e,o),yt(t,o)},[e,t])}function ao(e,t=!1){let o=n.useRef(!1);Ae(()=>{t&&o.current&&(o.current=!1,e())},[t,e]);let r=n.useCallback(()=>{o.current=!0},[]),c=n.useCallback(()=>{o.current=!1},[]);return{onFocus:r,onBlur:c}}function ut(){return qn().isRTL}function io(){let[e]=n.useState({}),t=n.useCallback((c,a)=>{var i;(i=e[c])===null||i===void 0||i.forEach(s=>{a.isPropagationStopped()||s(a)})},[e]),o=n.useMemo(()=>({onPointerDown:c=>t(Be,c),onPointerMove:c=>t(Xe,c),onPointerUp:c=>t(Ye,c),onPointerLeave:c=>t(ze,c),onPointerCancel:c=>t(je,c),onKeyDown:c=>t(Ze,c),onKeyUp:c=>t(St,c),onWheel:c=>t(qe,c)}),[t]),r=n.useCallback((c,a)=>(e[c]||(e[c]=[]),e[c].unshift(a),()=>{let i=e[c];i&&i.splice(0,i.length,...i.filter(s=>s!==a))}),[e]);return{registerSensors:o,subscribeSensors:r}}function Mt(e,t){let o=n.useRef(0),r=Se(),c=A((...a)=>{o.current=Date.now(),e(a)});return n.useCallback((...a)=>{r(()=>{c(a)},t-(Date.now()-o.current))},[t,c,r])}var et=at("slide"),tt=at("slide_image");function so({slide:e,offset:t,render:o,rect:r,imageFit:c,imageProps:a,onClick:i,onLoad:s,onError:d,style:f}){var h,m,R,p,E,u,N,I;let[S,b]=n.useState(fe),{publish:w}=xe(),{setTimeout:T}=we(),D=n.useRef(null);n.useEffect(()=>{t===0&&w(ae(S))},[t,S,w]);let O=A(C=>{("decode"in C?C.decode():Promise.resolve()).catch(()=>{}).then(()=>{C.parentNode&&(b(Ee),T(()=>{s?.(C)},0))})}),y=n.useCallback(C=>{D.current=C,C?.complete&&O(C)},[O]),_=n.useCallback(C=>{O(C.currentTarget)},[O]),V=A(()=>{b(Re),d?.()}),H=Un(e,c),B=(C,re)=>Number.isFinite(C)?C:re,v=B(Math.max(...((m=(h=e.srcSet)===null||h===void 0?void 0:h.map(C=>C.width))!==null&&m!==void 0?m:[]).concat(e.width?[e.width]:[]).filter(Boolean)),((R=D.current)===null||R===void 0?void 0:R.naturalWidth)||0),g=B(Math.max(...((E=(p=e.srcSet)===null||p===void 0?void 0:p.map(C=>C.height))!==null&&E!==void 0?E:[]).concat(e.height?[e.height]:[]).filter(Boolean)),((u=D.current)===null||u===void 0?void 0:u.naturalHeight)||0),L=v&&g?{maxWidth:`min(${v}px, 100%)`,maxHeight:`min(${g}px, 100%)`}:{maxWidth:"100%",maxHeight:"100%"},M=(N=e.srcSet)===null||N===void 0?void 0:N.slice().sort((C,re)=>C.width-re.width).map(C=>`${C.src} ${C.width}w`).join(", "),W=()=>r&&!H&&e.width&&e.height?r.height/e.height*e.width:Number.MAX_VALUE,J=M&&r&&it()?`${Math.round(Math.min(W(),r.width))}px`:void 0,{style:se,className:ye,...Z}=(typeof a=="function"?a(e):a)||{};return n.createElement(n.Fragment,null,n.createElement("img",{ref:y,onLoad:_,onError:V,onClick:i,draggable:!1,className:z(P(tt()),H&&P(tt("cover")),S!==Ee&&P(tt("loading")),ye),style:{...L,...f,...se},...Z,alt:(I=e.alt)!==null&&I!==void 0?I:"",sizes:J,srcSet:M,src:e.src}),S!==Ee&&n.createElement("div",{className:P(et(It))},S===fe&&(o?.iconLoading?o.iconLoading():n.createElement(oo,{className:z(P(Pe),P(et(fe)))})),S===Re&&(o?.iconError?o.iconError():n.createElement(ro,{className:z(P(Pe),P(et(Re)))}))))}var lo=n.forwardRef(function({className:t,children:o,onFocus:r,onBlur:c,...a},i){let s=n.useRef(null),[d,f]=n.useState(!1),{trackFocusWithin:h}=Zt(),m=A(()=>{if(s.current){let R=window.getComputedStyle(s.current).direction==="rtl";R!==d&&f(R)}});return n.useEffect(m),n.createElement(Bn,{nodeRef:s},n.createElement(Qn,{isRTL:d},n.createElement("div",{ref:ct(i,s),className:z(P("root"),t),...h(r,c),...a},o)))}),k;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL",e[e.ANIMATION=3]="ANIMATION"})(k||(k={}));function uo(e,t,o,r,c){n.useEffect(()=>c?()=>{}:Kt(e(Be,t),e(Xe,o),e(Ye,r),e(ze,r),e(je,r)),[e,t,o,r,c])}var K;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL"})(K||(K={}));var nt=30;function fo({disableSwipeNavigation:e,closeOnBackdropClick:t},o,r,c,a,i,s,d,f,h,m,R,p,E,u,N){let I=n.useRef(0),S=n.useRef([]),b=n.useRef(void 0),w=n.useRef(0),T=n.useRef(K.NONE),D=n.useCallback(v=>{b.current===v.pointerId&&(b.current=void 0,T.current=K.NONE);let g=S.current;g.splice(0,g.length,...g.filter(L=>L.pointerId!==v.pointerId))},[]),O=n.useCallback(v=>{D(v),v.persist(),S.current.push(v)},[D]),y=n.useCallback(v=>S.current.find(({pointerId:g})=>v.pointerId===g),[]),_=A(v=>{O(v)}),V=(v,g)=>m&&v>g||h&&v<-g,H=A(v=>{let g=y(v);if(g)if(b.current===v.pointerId){let L=Date.now()-w.current,M=I.current;T.current===K.SWIPE?Math.abs(M)>.3*c||Math.abs(M)>5&&L<a?d(M,L):f(M):T.current===K.PULL&&(V(M,2*nt)?E(M,L):u(M)),I.current=0,T.current=K.NONE}else{let{target:L}=v;t&&L instanceof HTMLElement&&L===g.target&&(L.classList.contains(P(Ce))||L.classList.contains(P(Pt)))&&N()}D(v)}),B=A(v=>{let g=y(v);if(g){let L=b.current===v.pointerId;if(v.buttons===0){L&&I.current!==0?H(v):D(g);return}let M=v.clientX-g.clientX,W=v.clientY-g.clientY;if(b.current===void 0){let J=se=>{O(v),b.current=v.pointerId,w.current=Date.now(),T.current=se};Math.abs(M)>Math.abs(W)&&Math.abs(M)>nt&&r(M)?e||(J(K.SWIPE),i()):Math.abs(W)>Math.abs(M)&&V(W,nt)&&(J(K.PULL),R())}else L&&(T.current===K.SWIPE?(I.current=M,s(M)):T.current===K.PULL&&(I.current=W,p(W)))}});uo(o,_,B,H)}function Ro({preventDefaultWheelX:e,preventDefaultWheelY:t}){let o=n.useRef(null),r=A(c=>{let a=Math.abs(c.deltaX)>Math.abs(c.deltaY);(a&&e||!a&&t||c.ctrlKey)&&c.preventDefault()});return n.useCallback(c=>{var a;c?c.addEventListener("wheel",r,{passive:!1}):(a=o.current)===null||a===void 0||a.removeEventListener("wheel",r),o.current=c},[r])}function Eo(e,t,o,r,c,a,i,s,d){let f=n.useRef(0),h=n.useRef(0),m=n.useRef(void 0),R=n.useRef(void 0),p=n.useRef(0),E=n.useRef(void 0),u=n.useRef(0),{setTimeout:N,clearTimeout:I}=we(),S=n.useCallback(()=>{m.current&&(I(m.current),m.current=void 0)},[I]),b=n.useCallback(()=>{R.current&&(I(R.current),R.current=void 0)},[I]),w=A(()=>{e!==k.SWIPE&&(f.current=0,u.current=0,S(),b())});n.useEffect(w,[e,w]);let T=A(O=>{R.current=void 0,f.current===O&&d(f.current)}),D=A(O=>{if(O.ctrlKey||Math.abs(O.deltaY)>Math.abs(O.deltaX))return;let y=_=>{p.current=_,I(E.current),E.current=_>0?N(()=>{p.current=0,E.current=void 0},300):void 0};if(e===k.NONE){if(Math.abs(O.deltaX)<=1.2*Math.abs(p.current)){y(O.deltaX);return}if(!o(-O.deltaX))return;if(h.current+=O.deltaX,S(),Math.abs(h.current)>30)h.current=0,y(0),u.current=Date.now(),a();else{let _=h.current;m.current=N(()=>{m.current=void 0,_===h.current&&(h.current=0)},c)}}else if(e===k.SWIPE){let _=f.current-O.deltaX;if(_=Math.min(Math.abs(_),r)*Math.sign(_),f.current=_,i(_),b(),Math.abs(_)>.2*r){y(O.deltaX),s(_,Date.now()-u.current);return}R.current=N(()=>T(_),2*c)}else y(O.deltaX)});n.useEffect(()=>t(qe,D),[t,D])}var Dt=at("container"),ln=n.createContext(null),_e=j("useController","ControllerContext",ln);function po({children:e,...t}){var o;let{carousel:r,animation:c,controller:a,on:i,styles:s,render:d}=t,{closeOnPullUp:f,closeOnPullDown:h,preventDefaultWheelX:m,preventDefaultWheelY:R}=a,[p,E]=n.useState(),u=be(),N=zn(),[I,S]=n.useState(k.NONE),b=n.useRef(0),w=n.useRef(0),T=n.useRef(1),{registerSensors:D,subscribeSensors:O}=io(),{subscribe:y,publish:_}=xe(),V=Se(),H=Se(),B=Se(),{containerRef:v,setContainerRef:g,containerRect:L}=sn(),M=ct(Ro({preventDefaultWheelX:m,preventDefaultWheelY:R}),g),W=n.useRef(null),J=ct(W,void 0),{getOwnerDocument:se}=lt(),ye=ut(),Z=l=>(ye?-1:1)*(typeof l=="number"?l:1),C=A(()=>{var l;return(l=v.current)===null||l===void 0?void 0:l.focus()}),re=A(()=>t),dt=A(()=>u),ve=n.useCallback(l=>_(q,l),[_]),Le=n.useCallback(l=>_(Q,l),[_]),ce=n.useCallback(()=>_(ee),[_]),Me=l=>!(r.finite&&(Z(l)>0&&u.currentIndex===0||Z(l)<0&&u.currentIndex===u.slides.length-1)),ft=l=>{var x;b.current=l,(x=v.current)===null||x===void 0||x.style.setProperty(F("swipe_offset"),`${Math.round(l)}px`)},De=l=>{var x,$;w.current=l,T.current=(()=>{let ue=h&&l>0?l:f&&l<0?-l:0;return Math.min(Math.max(Dn(1-ue/60*(1-.5),2),.5),1)})(),(x=v.current)===null||x===void 0||x.style.setProperty(F("pull_offset"),`${Math.round(l)}px`),($=v.current)===null||$===void 0||$.style.setProperty(F("pull_opacity"),`${T.current}`)},{prepareAnimation:fn}=At(W,(l,x,$)=>{if(W.current&&L)return{keyframes:[{transform:`translate(0, ${l.rect.y-x.y+$.y}px)`,opacity:l.opacity},{transform:"translate(0, 0)",opacity:1}],duration:l.duration,easing:c.easing.fade}}),Rt=(l,x)=>{if(f||h){De(l);let $=0;W.current&&($=c.fade*(x?2:1),fn({rect:W.current.getBoundingClientRect(),opacity:T.current,duration:$})),B(()=>{De(0),S(k.NONE)},$),S(k.ANIMATION),x||ce()}},{prepareAnimation:Rn,isAnimationPlaying:En}=At(W,(l,x,$)=>{var X;if(W.current&&L&&(!((X=u.animation)===null||X===void 0)&&X.duration)){let G=Oe(r.spacing),ue=(G.percent?G.percent*L.width/100:G.pixel)||0;return{keyframes:[{transform:`translate(${Z(u.globalIndex-l.index)*(L.width+ue)+l.rect.x-x.x+$.x}px, 0)`},{transform:"translate(0, 0)"}],duration:u.animation.duration,easing:u.animation.easing}}}),le=A(l=>{var x,$;let X=l.offset||0,G=X?c.swipe:(x=c.navigation)!==null&&x!==void 0?x:c.swipe,ue=!X&&!En()?c.easing.navigation:c.easing.swipe,{direction:ge}=l,Ne=($=l.count)!==null&&$!==void 0?$:1,Ue=k.ANIMATION,Y=G*Ne;if(!ge){let de=L?.width,mt=l.duration||0,ke=de?G/de*Math.abs(X):G;Ne!==0?(mt<ke?Y=Y/ke*Math.max(mt,ke/5):de&&(Y=G/de*(de-Math.abs(X))),ge=Z(X)>0?q:Q):Y=G/2}let We=0;ge===q?Me(Z(1))?We=-Ne:(Ue=k.NONE,Y=G):ge===Q&&(Me(Z(-1))?We=Ne:(Ue=k.NONE,Y=G)),Y=Math.round(Y),H(()=>{ft(0),S(k.NONE)},Y),W.current&&Rn({rect:W.current.getBoundingClientRect(),index:u.globalIndex}),S(Ue),_(Ke,{type:"swipe",increment:We,duration:Y,easing:ue})});n.useEffect(()=>{var l,x;!((l=u.animation)===null||l===void 0)&&l.increment&&(!((x=u.animation)===null||x===void 0)&&x.duration)&&V(()=>N({type:"swipe",increment:0}),u.animation.duration)},[u.animation,N,V]);let Et=[O,Me,L?.width||0,c.swipe,()=>S(k.SWIPE),l=>ft(l),(l,x)=>le({offset:l,duration:x,count:1}),l=>le({offset:l,count:0})],pn=[()=>{h&&S(k.PULL)},l=>De(l),l=>Rt(l),l=>Rt(l,!0)];fo(a,...Et,f,h,...pn,ce),Eo(I,...Et);let pt=A(()=>{a.focus&&se().querySelector(`.${P(Ie)} .${P(Dt())}`)&&C()});n.useEffect(pt,[pt]);let ht=A(()=>{var l;(l=i.view)===null||l===void 0||l.call(i,{index:u.currentIndex})});n.useEffect(ht,[u.globalIndex,ht]),n.useEffect(()=>Kt(y(q,l=>le({direction:q,...l})),y(Q,l=>le({direction:Q,...l})),y(Ke,l=>N(l))),[y,le,N]);let hn=n.useMemo(()=>({prev:ve,next:Le,close:ce,focus:C,slideRect:L?Wn(L,r.padding):{width:0,height:0},containerRect:L||{width:0,height:0},subscribeSensors:O,containerRef:v,setCarouselRef:J,toolbarWidth:p,setToolbarWidth:E}),[ve,Le,ce,C,O,L,v,J,p,E,r.padding]);return n.useImperativeHandle(a.ref,()=>({prev:ve,next:Le,close:ce,focus:C,getLightboxProps:re,getLightboxState:dt}),[ve,Le,ce,C,re,dt]),n.createElement("div",{ref:M,className:z(P(Dt()),P(Ge)),style:{...I===k.SWIPE?{[F("swipe_offset")]:`${Math.round(b.current)}px`}:null,...I===k.PULL?{[F("pull_offset")]:`${Math.round(w.current)}px`,[F("pull_opacity")]:`${T.current}`}:null,...a.touchAction!=="none"?{[F("controller_touch_action")]:a.touchAction}:null,...s.container},tabIndex:-1,...D},L&&n.createElement(ln.Provider,{value:hn},e,(o=d.controls)===null||o===void 0?void 0:o.call(d)))}var ho=oe($e,po);function te(e){return pe(Ve,e)}function Ut(e){return pe(Ce,e)}function mo({slide:e,offset:t}){let o=n.useRef(null),{currentIndex:r,slides:c}=be(),{slideRect:a,focus:i}=_e(),{render:s,carousel:{imageFit:d,imageProps:f},on:{click:h},styles:{slide:m},labels:R}=he(),{getOwnerDocument:p}=lt(),E=t!==0;n.useEffect(()=>{var N;E&&(!((N=o.current)===null||N===void 0)&&N.contains(p().activeElement))&&i()},[E,i,p]);let u=()=>{var N,I,S,b;let w=(N=s.slide)===null||N===void 0?void 0:N.call(s,{slide:e,offset:t,rect:a});return!w&&Bt(e)&&(w=n.createElement(so,{slide:e,offset:t,render:s,rect:a,imageFit:d,imageProps:f,onClick:E?void 0:()=>h?.({index:r})})),w?n.createElement(n.Fragment,null,(I=s.slideHeader)===null||I===void 0?void 0:I.call(s,{slide:e}),((S=s.slideContainer)!==null&&S!==void 0?S:(({children:T})=>T))({slide:e,children:w}),(b=s.slideFooter)===null||b===void 0?void 0:b.call(s,{slide:e})):null};return n.createElement("div",{ref:o,className:z(P(Ut()),!E&&P(Ut("current")),P(Ge)),...Fn(E),style:m,role:"group","aria-roledescription":ne(R,"Slide"),"aria-label":Mn(R,c,r+t)},u())}function _o(){let e=he().styles.slide;return n.createElement("div",{className:P(Ce),style:e})}function vo({carousel:e,labels:t}){let{slides:o,currentIndex:r,globalIndex:c}=be(),{setCarouselRef:a}=_e(),{autoPlaying:i,focusWithin:s}=Zt(),d=Oe(e.spacing),f=Oe(e.padding),h=Vn(e,o,1),m=[];if(Xt(o))for(let R=r-h;R<=r+h;R+=1){let p=Yt(o,R),E=c-r+R,u=e.finite&&(R<0||R>o.length-1);m.push(u?{key:E}:{key:[`${E}`,kn(p)].filter(Boolean).join("|"),offset:R-r,slide:p})}return n.createElement("div",{ref:a,className:z(P(te()),m.length>0&&P(te("with_slides"))),style:{[`${F(te("slides_count"))}`]:m.length,[`${F(te("spacing_px"))}`]:d.pixel||0,[`${F(te("spacing_percent"))}`]:d.percent||0,[`${F(te("padding_px"))}`]:f.pixel||0,[`${F(te("padding_percent"))}`]:f.percent||0},role:"region","aria-live":i&&!s?"off":"polite","aria-roledescription":ne(t,"Carousel"),"aria-label":ne(t,"Photo gallery")},m.map(({key:R,slide:p,offset:E})=>p?n.createElement(mo,{key:R,slide:p,offset:E}):n.createElement(_o,{key:R})))}var Lo=oe(Ve,vo);function un(){let{carousel:e}=he(),{slides:t,currentIndex:o}=be(),r=t.length===0||e.finite&&o===0,c=t.length===0||e.finite&&o===t.length-1;return{prevDisabled:r,nextDisabled:c}}function go(e){var t;let o=ut(),{publish:r}=xe(),{animation:c,controller:a}=he(),{prevDisabled:i,nextDisabled:s}=un(),d=((t=c.navigation)!==null&&t!==void 0?t:c.swipe)/2,f=Mt(()=>r(q),d),h=Mt(()=>r(Q),d),m=A(R=>{switch(R.key){case Ot:if(!a.closeOnEscape)return;r(ee);break;case Tt:(o?s:i)||(o?h:f)();break;case xt:(o?i:s)||(o?f:h)();break;default:return}R.stopPropagation()});n.useEffect(()=>e(Ze,m),[e,m])}function Wt({label:e,icon:t,renderIcon:o,action:r,onClick:c,disabled:a,style:i}){return n.createElement(rn,{label:e,icon:t,renderIcon:o,className:P(`navigation_${r}`),disabled:a,onClick:c,style:i,...ao(_e().focus,a)})}function No({render:{buttonPrev:e,buttonNext:t,iconPrev:o,iconNext:r},styles:c}){let{prev:a,next:i,subscribeSensors:s}=_e(),{prevDisabled:d,nextDisabled:f}=un();return go(s),n.createElement(n.Fragment,null,e?e():n.createElement(Wt,{label:"Previous",action:q,icon:to,renderIcon:o,style:c.navigationPrev,disabled:d,onClick:a}),t?t():n.createElement(Wt,{label:"Next",action:Q,icon:no,renderIcon:r,style:c.navigationNext,disabled:f,onClick:i}))}var Io=oe(vt,No),kt=P(Ct),Co=P(He);function Po(e){return"style"in e}function Vt(e,t,o){let r=window.getComputedStyle(e),c=o?"padding-left":"padding-right",a=o?r.paddingLeft:r.paddingRight,i=e.style.getPropertyValue(c);return e.style.setProperty(c,`${(Te(a)||0)+t}px`),()=>{i?e.style.setProperty(c,i):e.style.removeProperty(c)}}function So({noScroll:{disabled:e},children:t}){let o=ut(),{getOwnerDocument:r,getOwnerWindow:c}=lt();return n.useEffect(()=>{if(e)return()=>{};let a=[],i=c(),{body:s,documentElement:d}=r(),f=Math.round(i.innerWidth-d.clientWidth);if(f>0){a.push(Vt(s,f,o));let h=s.getElementsByTagName("*");for(let m=0;m<h.length;m+=1){let R=h[m];Po(R)&&i.getComputedStyle(R).getPropertyValue("position")==="fixed"&&!R.classList.contains(Co)&&a.push(Vt(R,f,o))}}return s.classList.add(kt),()=>{s.classList.remove(kt),a.forEach(h=>h())}},[o,e,r,c]),n.createElement(n.Fragment,null,t)}var Oo=oe(Lt,So);function $t(e){return pe(Ie,e)}function Ft(e,t,o){let r=e.getAttribute(t);return e.setAttribute(t,o),()=>{r?e.setAttribute(t,r):e.removeAttribute(t)}}function To({portal:{root:e,container:{className:t,style:o,...r}={}},animation:c,styles:a,className:i,on:s,close:d,labels:f,children:h}){let[m,R]=n.useState(!1),[p,E]=n.useState(!1),u=n.useRef([]),N=n.useRef(null),{setTimeout:I}=we(),{subscribe:S}=xe(),w=an()?0:c.fade;n.useEffect(()=>(R(!0),()=>{R(!1),E(!1)}),[]);let T=A(()=>{u.current.forEach(_=>_()),u.current=[]}),D=A(()=>{var _;E(!1),T(),(_=s.exiting)===null||_===void 0||_.call(s),I(()=>{var V;(V=s.exited)===null||V===void 0||V.call(s),d()},w)});n.useEffect(()=>S(ee,D),[S,D]);let O=A(_=>{var V,H,B;Gn(_),E(!0),(V=s.entering)===null||V===void 0||V.call(s);let v=(B=(H=_.parentNode)===null||H===void 0?void 0:H.children)!==null&&B!==void 0?B:[];for(let g=0;g<v.length;g+=1){let L=v[g];["TEMPLATE","SCRIPT","STYLE"].indexOf(L.tagName)===-1&&L!==_&&(u.current.push(Ft(L,"inert","")),u.current.push(Ft(L,"aria-hidden","true")))}u.current.push(()=>{var g,L;(L=(g=N.current)===null||g===void 0?void 0:g.focus)===null||L===void 0||L.call(g)}),I(()=>{var g;(g=s.entered)===null||g===void 0||g.call(s)},w)}),y=n.useCallback(_=>{_?O(_):T()},[O,T]);return m?(0,Gt.createPortal)(n.createElement(lo,{ref:y,className:z(i,t,P($t()),P(He),p&&P($t("open"))),"aria-modal":!0,role:"dialog","aria-label":ne(f,"Lightbox"),style:{...c.fade!==rt.animation.fade?{[F("fade_animation_duration")]:`${w}ms`}:null,...c.easing.fade!==rt.animation.easing.fade?{[F("fade_animation_timing_function")]:c.easing.fade}:null,...a.root,...o},onFocus:_=>{N.current||(N.current=_.relatedTarget)},...r},h),(typeof e=="function"?e():e)||document.body):null}var xo=oe(Ie,To);function bo({children:e}){return n.createElement(n.Fragment,null,e)}var wo=oe(gt,bo);function Ao(e){return pe(Fe,e)}function yo({toolbar:{buttons:e},render:{buttonClose:t,iconClose:o},styles:r}){let{close:c,setToolbarWidth:a}=_e(),{setContainerRef:i,containerRect:s}=sn();Ae(()=>{a(s?.width)},[a,s?.width]);let d=()=>t?t():n.createElement(rn,{key:ee,label:"Close",icon:eo,renderIcon:o,onClick:c});return n.createElement("div",{ref:i,style:r.toolbar,className:P(Ao())},e?.map(f=>f===ee?d():f))}var Mo=oe(Fe,yo);function dn(e,t){var o;return n.createElement(e.module.component,{key:e.module.name,...t},(o=e.children)===null||o===void 0?void 0:o.map(r=>dn(r,t)))}function Do(e,t={}){let{easing:o,...r}=e,{easing:c,...a}=t;return{easing:{...o,...c},...r,...a}}function Ho({carousel:e,animation:t,render:o,toolbar:r,controller:c,noScroll:a,on:i,plugins:s,slides:d,index:f,...h}){let{animation:m,carousel:R,render:p,toolbar:E,controller:u,noScroll:N,on:I,slides:S,index:b,plugins:w,...T}=rt,{config:D,augmentation:O}=Hn([U(xo,[U(Oo,[U(ho,[U(Lo),U(Mo),U(Io)])])])],s||w),y=O({animation:Do(m,t),carousel:{...R,...e},render:{...p,...o},toolbar:{...E,...r},controller:{...u,...c},noScroll:{...N,...a},on:{...I,...i},...T,...h});return y.open?n.createElement(Yn,{...y},n.createElement(Zn,{slides:d||S,index:Te(f||b)},n.createElement(Jn,null,n.createElement(Xn,null,n.createElement(Kn,null,dn(U(wo,D),y)))))):null}export{Ve as a,$e as b,vt as c,Lt as d,Ie as e,gt as f,Fe as g,vn as h,Ln as i,gn as j,Nn as k,In as l,Cn as m,Pn as n,Sn as o,On as p,fe as q,Nt as r,Re as s,Ee as t,It as u,ae as v,Tn as w,xn as x,bn as y,wn as z,An as A,Ge as B,Ct as C,He as D,Ce as E,Pt as F,yn as G,q as H,Q as I,Ke as J,ee as K,Be as L,Xe as M,Ye as N,ze as O,je as P,Ze as Q,St as R,qe as S,Ot as T,Tt as U,xt as V,bt as W,Pe as X,Qe as Y,Je as Z,wt as _,z as $,P as aa,F as ba,pe as ca,at as da,ne as ea,ko as fa,Mn as ga,Kt as ha,j as ia,it as ja,Dn as ka,Bt as la,Un as ma,Te as na,Oe as oa,Wn as pa,Vo as qa,st as ra,Xt as sa,Yt as ta,ot as ua,kn as va,$o as wa,Fo as xa,Vn as ya,Fn as za,Gn as Aa,rt as Ba,oe as Ca,U as Da,Hn as Ea,jt as Fa,Zt as Ga,Kn as Ha,qt as Ia,lt as Ja,Bn as Ka,Qt as La,xe as Ma,Xn as Na,Jt as Oa,he as Pa,Yn as Qa,en as Ra,be as Sa,tn as Ta,zn as Ua,Zn as Va,nn as Wa,qn as Xa,Qn as Ya,on as Za,we as _a,Jn as $a,rn as ab,me as bb,Go as cb,eo as db,to as eb,no as fb,oo as gb,ro as hb,Ae as ib,an as jb,At as kb,sn as lb,Se as mb,A as nb,yt as ob,ct as pb,ao as qb,ut as rb,io as sb,Mt as tb,so as ub,lo as vb,k as wb,uo as xb,fo as yb,Ro as zb,Eo as Ab,ln as Bb,_e as Cb,po as Db,ho as Eb,vo as Fb,Lo as Gb,un as Hb,go as Ib,Wt as Jb,No as Kb,Io as Lb,So as Mb,Oo as Nb,To as Ob,xo as Pb,bo as Qb,wo as Rb,yo as Sb,Mo as Tb,Ho as Ub};
sha256/bdb559bd0dec93fd70e9c1ed515bbd483ff4cadc8ce38df946983adca29c604e ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // holo-orb.js β€” THE canonical living Q orb (shared by the standalone Q chat and the messenger; the messenger's
2
+ // holo-q-orb-live.mjs re-exports this file). mountOrb(canvas, opts?) β†’ { stop, fallback, mode, ... } β€” the API is
3
+ // a superset of the original 54-line WebGL orb (opts optional, {stop,fallback} preserved), so existing callers
4
+ // are unaffected while every surface gains the enhanced renderer. Original preserved as holo-orb.js.pre-converge.bak.
5
+ //
6
+ // PRIMARY: a NATIVE-WebGPU raymarched volume rendered on a dedicated Web Worker via OffscreenCanvas. The render
7
+ // loop lives on the worker, PHYSICALLY off the main thread, so the orb stays glass-smooth and NEVER freezes even
8
+ // while the host's main thread is busy (React, Q inference, message churn). It binds the real GPU adapter
9
+ // (powerPreference:"high-performance", no fallback) β†’ 100% native WebGPU, and renders at native DPR Γ— SSAA for a
10
+ // crisp, hyper-real look. Fully self-contained: the worker is spawned from a Blob URL with inline WGSL β€” no deps,
11
+ // no import map, no extra files to serve, so it works in every environment (dev SPA and the real app alike).
12
+ //
13
+ // FALLBACK: the original self-contained WebGL2 wireframe icosphere (kept verbatim below), then a CSS/SVG orb.
14
+ // The gate is fail-closed and probe-before-transfer: the worker confirms a GPU adapter BEFORE the canvas is
15
+ // transferred, so a probe failure leaves the canvas reusable for the WebGL2 floor.
16
+ //
17
+ // mountOrb(canvas) β†’ { stop(), fallback:boolean, mode }
18
+
19
+ // ─────────────────────────────────────────────────────────────────────────────────────────────────────────
20
+ // WGSL β€” fullscreen-triangle vertex + a raymarched, noise-displaced SDF sphere with the OS brand spectrum
21
+ // (OKLAB-interpolated), a triangular lattice shell, thin-film iridescence, an inner living nebula, ACES filmic
22
+ // tonemap and temporal dither. Idle-animated (breath + spin + shimmer) so it's alive at rest with ZERO main-
23
+ // thread involvement. TERM-IDENTICAL to the native OS orb (usr/lib/holo/voice/holo-voice-orb-gpu.mjs): same
24
+ // march (72 steps / 4 octaves / radius 0.82 / freq 1.7 / glow 0.012), same full signal uniforms (level + bands
25
+ // + onset + energy + warm/dim/gold), same spin/swell/iridescence/nebula formulas β€” so the messenger's corner
26
+ // orb and the CEF home-tab orb are the SAME animation, pixel for pixel (minus the OS-only morph-form library).
27
+ // ─────────────────────────────────────────────────────────────────────────────────────────────────────────
28
+ const WGSL = `
29
+ struct U {
30
+ res: vec2f, time: f32, level: f32,
31
+ bass: f32, mid: f32, treble: f32, onset: f32,
32
+ energy: f32, warm: f32, dim: f32, gold: f32,
33
+ };
34
+ @group(0) @binding(0) var<uniform> u: U;
35
+
36
+ const STOPS = array<vec3f, 8>(
37
+ vec3f(1.0, 0.231, 0.42), vec3f(1.0, 0.62, 0.173), vec3f(1.0, 0.886, 0.29), vec3f(0.275, 0.878, 0.541),
38
+ vec3f(0.169, 0.831, 1.0), vec3f(0.357, 0.549, 1.0), vec3f(0.78, 0.482, 1.0), vec3f(1.0, 0.231, 0.42));
39
+
40
+ @vertex fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f {
41
+ var p = array<vec2f, 3>(vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0));
42
+ return vec4f(p[vi], 0.0, 1.0);
43
+ }
44
+ fn hash(p3i: vec3f) -> f32 { var p3 = fract(p3i * 0.1031); p3 = p3 + dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }
45
+ fn vnoise(x: vec3f) -> f32 {
46
+ let i = floor(x); let f = fract(x); let w = f * f * (3.0 - 2.0 * f);
47
+ let n000 = hash(i + vec3f(0.0,0.0,0.0)); let n100 = hash(i + vec3f(1.0,0.0,0.0));
48
+ let n010 = hash(i + vec3f(0.0,1.0,0.0)); let n110 = hash(i + vec3f(1.0,1.0,0.0));
49
+ let n001 = hash(i + vec3f(0.0,0.0,1.0)); let n101 = hash(i + vec3f(1.0,0.0,1.0));
50
+ let n011 = hash(i + vec3f(0.0,1.0,1.0)); let n111 = hash(i + vec3f(1.0,1.0,1.0));
51
+ let x00 = mix(n000,n100,w.x); let x10 = mix(n010,n110,w.x); let x01 = mix(n001,n101,w.x); let x11 = mix(n011,n111,w.x);
52
+ return mix(mix(x00,x10,w.y), mix(x01,x11,w.y), w.z) * 2.0 - 1.0;
53
+ }
54
+ fn fbm(p0: vec3f) -> f32 { var p = p0; var a = 0.5; var s = 0.0; for (var i = 0; i < 4; i = i + 1) { s = s + a * vnoise(p); p = p * 1.9; a = a * 0.5; } return s; }
55
+ fn srgb2lin(c: vec3f) -> vec3f { return select(c/12.92, pow((c+0.055)/1.055, vec3f(2.4)), c > vec3f(0.04045)); }
56
+ fn lin2srgb(c: vec3f) -> vec3f { let x = max(c, vec3f(0.0)); return select(x*12.92, 1.055*pow(x, vec3f(1.0/2.4))-0.055, x > vec3f(0.0031308)); }
57
+ fn lin2oklab(c: vec3f) -> vec3f {
58
+ let l = 0.4122214708*c.r + 0.5363325363*c.g + 0.0514459929*c.b;
59
+ let m = 0.2119034982*c.r + 0.6806995451*c.g + 0.1073969566*c.b;
60
+ let s = 0.0883024619*c.r + 0.2817188376*c.g + 0.6299787005*c.b;
61
+ let l_ = pow(max(l,0.0),1.0/3.0); let m_ = pow(max(m,0.0),1.0/3.0); let s_ = pow(max(s,0.0),1.0/3.0);
62
+ return vec3f(0.2104542553*l_+0.7936177850*m_-0.0040720468*s_, 1.9779984951*l_-2.4285922050*m_+0.4505937099*s_, 0.0259040371*l_+0.7827717662*m_-0.8086757660*s_);
63
+ }
64
+ fn oklab2srgb(c: vec3f) -> vec3f {
65
+ let l_ = c.x+0.3963377774*c.y+0.2158037573*c.z; let m_ = c.x-0.1055613458*c.y-0.0638541728*c.z; let s_ = c.x-0.0894841775*c.y-1.2914855480*c.z;
66
+ let l = l_*l_*l_; let m = m_*m_*m_; let s = s_*s_*s_;
67
+ let lin = vec3f(4.0767416621*l-3.3077115913*m+0.2309699292*s, -1.2684380046*l+2.6097574011*m-0.3413193965*s, -0.0041960863*l-0.7034186147*m+1.7076147010*s);
68
+ return lin2srgb(lin);
69
+ }
70
+ fn spec(t0: f32) -> vec3f { let t = fract(t0) * 7.0; let k = clamp(i32(floor(t)), 0, 6); let a = lin2oklab(srgb2lin(STOPS[k])); let b = lin2oklab(srgb2lin(STOPS[k+1])); return oklab2srgb(mix(a, b, fract(t))); }
71
+ fn sdf(p: vec3f) -> f32 {
72
+ let R = 0.82 + u.level * 0.05 + u.onset * 0.03 + sin(u.time * 0.6) * 0.012;
73
+ let warp = vec3f(u.time*0.05, u.time*0.06, u.time*0.07);
74
+ let disp = fbm(p * 1.7 + warp) * (0.07 + u.level * 0.20 + u.mid * 0.14 + u.bass * 0.10);
75
+ return length(p) - R - disp;
76
+ }
77
+ fn nrm(p: vec3f) -> vec3f { let e = vec2f(0.0012, 0.0); return normalize(vec3f(sdf(p+e.xyy)-sdf(p-e.xyy), sdf(p+e.yxy)-sdf(p-e.yxy), sdf(p+e.yyx)-sdf(p-e.yyx))); }
78
+ fn gline(x: f32) -> f32 { return smoothstep(0.42, 0.5, abs(fract(x) - 0.5)); }
79
+ fn ign(p: vec2f) -> f32 { return fract(52.9829189 * fract(dot(p, vec2f(0.06711056, 0.00583715)))); }
80
+ fn aces(x: vec3f) -> vec3f { let a=2.51; let b=0.03; let c=2.43; let d=0.59; let e=0.14; return clamp((x*(a*x+b))/(x*(c*x+d)+e), vec3f(0.0), vec3f(1.0)); }
81
+
82
+ @fragment fn fs(@builtin(position) fc: vec4f) -> @location(0) vec4f {
83
+ let uv = (fc.xy - 0.5 * u.res) / u.res.y;
84
+ let ro = vec3f(0.0, 0.0, 3.6);
85
+ let rd = normalize(vec3f(uv.x, -uv.y, -1.5));
86
+ let spin = u.time / 7.0 * (1.0 + u.level * 1.6 + u.treble * 1.4) * (0.4 + 0.6 * u.energy);
87
+ var t = 0.0; var glow = 0.0; var neb = 0.0; var hit = false; var hp = vec3f(0.0);
88
+ var omega = 1.2; var prevD = 1e9; var stepLen = 0.0;
89
+ for (var i = 0; i < 72; i = i + 1) {
90
+ let p = ro + rd * t; let d = sdf(p);
91
+ if (omega > 1.0 && (d + prevD) < stepLen) { t = t - stepLen; omega = 1.0; prevD = 1e9; continue; }
92
+ prevD = d;
93
+ glow = glow + 0.012 / (1.0 + d * d * 42.0);
94
+ if (d < 0.0) { neb = neb + (0.5 + 0.5 * fbm(p * 2.72 + vec3f(u.time * 0.09))) * 0.05; }
95
+ if (d < 0.0015) { hit = true; hp = p; break; }
96
+ stepLen = max(d * omega, 0.004); t = t + stepLen;
97
+ if (t > 6.0) { break; }
98
+ }
99
+ var col = vec3f(0.0); var alpha = 0.0;
100
+ if (hit) {
101
+ let n = nrm(hp);
102
+ let lon = atan2(n.x, n.z) / 6.2831853 + 0.5;
103
+ let lat = acos(clamp(n.y, -1.0, 1.0)) / 3.14159265;
104
+ let hue = lon + spin + 0.18 * n.y;
105
+ let base = spec(hue);
106
+ let fres = pow(1.0 - max(dot(n, -rd), 0.0), 2.5);
107
+ let ld = normalize(vec3f(-0.4, 0.7, 0.5));
108
+ let diff = 0.5 + 0.5 * max(dot(n, ld), 0.0);
109
+ let irid = spec(hue + fres * 0.30 + u.treble * 0.08);
110
+ let bodyHue = mix(base, irid, fres * 0.45);
111
+ let A = lon * 18.0; let B = lat * 11.0; let pf = sin(lat * 3.14159265);
112
+ let g = max(gline(B), max(gline(A + B * 0.5), gline(A - B * 0.5))) * pf;
113
+ let face = bodyHue * (0.28 + 0.30 * diff);
114
+ let dofs = 0.020 * (0.5 + fres);
115
+ let edgeRGB = vec3f(spec(hue - dofs).r, spec(hue).g, spec(hue + dofs).b);
116
+ let edge = (edgeRGB * 1.7 + vec3f(0.22, 0.22, 0.32)) * (0.7 + 0.6 * fres);
117
+ col = mix(face, edge, g) + bodyHue * fres * 0.55;
118
+ col = col * (0.9 + u.level * 0.45 + u.onset * 0.5);
119
+ alpha = max(g, 0.34 + 0.45 * fres);
120
+ }
121
+ let ncol = spec(spin + 0.55 + neb);
122
+ col = col + ncol * neb * (0.7 + u.level * 0.9 + u.bass * 0.8);
123
+ let gcol = spec(spin + 0.25);
124
+ col = col + gcol * glow * (0.6 + u.level * 1.0 + u.treble * 0.7);
125
+ alpha = max(alpha, clamp((glow + neb * 0.6) * 1.2, 0.0, 1.0));
126
+ if (u.gold > 0.0) { col = mix(col, vec3f(1.0, 0.78, 0.20) * (0.4 + 0.9 * length(col)), u.gold); }
127
+ col.r = col.r * (1.0 + u.warm * 0.10);
128
+ col.b = col.b * (1.0 - u.warm * 0.30);
129
+ col = col * (1.0 - u.dim * 0.4);
130
+ col = aces(col * 1.18);
131
+ col = col + (ign(fc.xy + u.time * 60.0) - 0.5) * (1.5 / 255.0);
132
+ col = clamp(col, vec3f(0.0), vec3f(1.0));
133
+ return vec4f(col * alpha, alpha);
134
+ }`;
135
+
136
+ // ── the worker body (classic worker, spawned from a Blob URL). WGSL is injected as a JS string literal so the
137
+ // whole thing is self-contained β€” nothing extra is fetched, so it runs in any serve environment. ──
138
+ const WORKER_BODY = [
139
+ "const WGSL = __WGSL__;",
140
+ "let dev=null, ctx=null, pipeline=null, bind=null, ubuf=null, uf=null, raf=0, running=false, dead=false, canvas=null;",
141
+ "let dpr=1, ssMax=1, scale=1, cssW=64, cssH=64;", // backing = css Γ— dpr Γ— scale; scale climbs to ssMax (SSAA) with headroom, drops under load β€” the native orb's ladder
142
+ "let mode=0, extLevel=-1, cur=0.0, gcur=0.0, dbg=false, fc=0, lastT=0, emaDt=0;", // mode: 0 idle Β· 1 listening Β· 2 thinking Β· 3 speaking. cur = eased base level; gcur = eased gold (mind-flare) wash; extLevel = live speech amplitude (0..1) or -1.
143
+ "const NOW=function(){return (typeof performance!=='undefined')?performance.now():Date.now();};",
144
+ "const RAF=(typeof requestAnimationFrame==='function')?requestAnimationFrame:function(f){return setTimeout(function(){f(NOW());},16);};",
145
+ "const CAF=(typeof cancelAnimationFrame==='function')?cancelAnimationFrame:clearTimeout;",
146
+ "function resize(){var s=dpr*scale;var w=Math.max(1,Math.round(cssW*s)),h=Math.max(1,Math.round(cssH*s)); if(canvas.width!==w||canvas.height!==h){canvas.width=w;canvas.height=h;}}",
147
+ // Q-state-reactive level, calibrated to the NATIVE orb's idle: at rest level eases to 0 (energy 1), so the
148
+ // idle animation is exactly the OS home-tab orb β€” breath sin(tΒ·0.6)Β·0.012, spin t/7, fbm skin 0.07. States
149
+ // modulate on top: listening = alert; thinking = livelier + the OS gold mind-flare wash; speaking = pulse to
150
+ // live amplitude (extLevel) or a synthetic speech cadence. cur/gcur ease so transitions read as intent.",
151
+ "function frame(){ if(!running||dead) return; var t=NOW()/1000; var base, osc, gold=0;",
152
+ " if(mode===2){ base=0.35; osc=0.10*Math.sin(t*3.4); gold=0.30+0.20*Math.sin(t*3.4); }",
153
+ " else if(mode===1){ base=0.22; osc=0.05*Math.sin(t*2.0); }",
154
+ " else if(mode===3){ base=0.32; osc=(extLevel>=0?0.0:0.30*Math.abs(Math.sin(t*6.5))); }",
155
+ " else { base=0.0; osc=0.0; }",
156
+ " var live=(extLevel>=0&&(mode===1||mode===3))?extLevel*0.6:0.0;", // REAL audio amplitude swells the orb (listening to you Β· speaking as Q)
157
+ " cur+=(base-cur)*0.06; gcur+=(gold-gcur)*0.08; var lvl=Math.max(0.0, cur+osc+live);",
158
+ " var now=NOW(); if(lastT){ emaDt=emaDt?emaDt*0.9+(now-lastT)*0.1:(now-lastT); } lastT=now;",
159
+ " if(((++fc)%24)===0&&emaDt>0){ var fps=1000/emaDt;", // frame-time adaptive resolution (the native ladder): drop fast under load, climb slow into SSAA headroom β†’ sharp AND never laggy
160
+ " if(fps<50&&scale>0.5){ scale=Math.max(0.5,scale-0.25); resize(); }",
161
+ " else if(fps>58&&scale<ssMax){ scale=Math.min(ssMax,scale+0.25); resize(); } }",
162
+ " if(dbg&&(fc%15)===0){ try{ self.postMessage({t:'lvl', v:lvl, mode:mode}); }catch(e){} }",
163
+ " uf[0]=canvas.width; uf[1]=canvas.height; uf[2]=t; uf[3]=lvl;",
164
+ " uf[4]=0; uf[5]=0; uf[6]=0; uf[7]=0; uf[8]=1; uf[9]=0; uf[10]=0; uf[11]=gcur;", // bass/mid/treble/onset idle at 0 and energy at 1 β€” the native orb's values when no live meter feeds it
165
+ " dev.queue.writeBuffer(ubuf,0,uf); var view; try{ view=ctx.getCurrentTexture().createView(); }catch(e){ raf=RAF(frame); return; } var enc=dev.createCommandEncoder(); var pass=enc.beginRenderPass({colorAttachments:[{view:view,clearValue:{r:0,g:0,b:0,a:0},loadOp:'clear',storeOp:'store'}]}); pass.setPipeline(pipeline); pass.setBindGroup(0,bind); pass.draw(3); pass.end(); dev.queue.submit([enc.finish()]); raf=RAF(frame); }",
166
+ "self.onmessage=async function(e){ var m=e.data||{}; try{",
167
+ " if(m.t==='probe'){ try{ if(!navigator.gpu) throw new Error('no gpu'); var a=await navigator.gpu.requestAdapter({powerPreference:'high-performance'}); if(!a) throw new Error('no adapter'); var d=await a.requestDevice(); if(d.destroy) d.destroy(); self.postMessage({t:'probe-ok'}); }catch(err){ self.postMessage({t:'fail',err:'probe: '+String(err&&err.message||err)}); } return; }",
168
+ " if(m.t==='init'){ try{",
169
+ " canvas=m.canvas; dpr=m.dpr||1; ssMax=m.ss||1; scale=1; cssW=m.cssW||64; cssH=m.cssH||64; dbg=!!m.debug;",
170
+ " var a=await navigator.gpu.requestAdapter({powerPreference:'high-performance'}); if(!a) throw new Error('no adapter'); dev=await a.requestDevice(); if(dev.lost) dev.lost.then(function(){dead=true;});",
171
+ " ctx=canvas.getContext('webgpu'); if(!ctx) throw new Error('no webgpu ctx'); var fmt=navigator.gpu.getPreferredCanvasFormat(); ctx.configure({device:dev,format:fmt,alphaMode:'premultiplied'});",
172
+ " uf=new Float32Array(12); ubuf=dev.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});",
173
+ " dev.pushErrorScope('validation'); var mod=dev.createShaderModule({code:WGSL});",
174
+ " pipeline=dev.createRenderPipeline({layout:'auto',vertex:{module:mod,entryPoint:'vs'},fragment:{module:mod,entryPoint:'fs',targets:[{format:fmt,blend:{color:{srcFactor:'one',dstFactor:'one-minus-src-alpha'},alpha:{srcFactor:'one',dstFactor:'one-minus-src-alpha'}}}]},primitive:{topology:'triangle-list'}});",
175
+ " var perr=await dev.popErrorScope(); if(perr) throw new Error('wgsl: '+perr.message);",
176
+ " bind=dev.createBindGroup({layout:pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:ubuf}}]});",
177
+ " resize(); running=true; raf=RAF(frame); self.postMessage({t:'ready'});",
178
+ " }catch(err){ self.postMessage({t:'fail',err:String(err&&err.message||err)}); } return; }",
179
+ " if(!canvas) return;",
180
+ " if(m.t==='size'){ cssW=m.cssW||cssW; cssH=m.cssH||cssH; dpr=m.dpr||dpr; resize(); }",
181
+ " else if(m.t==='sig'){ mode=m.mode||0; extLevel=(typeof m.level==='number'?m.level:-1); }",
182
+ " else if(m.t==='pause'){ if(running){ running=false; if(raf){ CAF(raf); raf=0; } } }", // off-screen/backgrounded β†’ halt the loop, KEEP the device (cheap resume)
183
+ " else if(m.t==='resume'){ if(!running && !dead && canvas){ running=true; raf=RAF(frame); } }",
184
+ " else if(m.t==='stop'){ running=false; if(raf){ CAF(raf); raf=0; } try{ if(dev&&dev.destroy) dev.destroy(); }catch(e){} }",
185
+ "}catch(err){ try{ self.postMessage({t:'fail',err:String(err&&err.message||err)}); }catch(e2){} } };",
186
+ ].join("\n");
187
+
188
+ const WORKER_SRC = WORKER_BODY.replace("__WGSL__", JSON.stringify(WGSL));
189
+
190
+ // mount the WebGPU worker orb. Returns a handle (sync) that upgrades async; on any failure it falls back to the
191
+ // WebGL2 wireframe on the SAME canvas (probe-before-transfer keeps the canvas reusable). Returns null only when
192
+ // the platform can't do OffscreenCanvas/Worker/WebGPU at all β†’ caller uses WebGL2 directly.
193
+ function mountGpuOrb(canvas, opts) {
194
+ opts = opts || {};
195
+ const ok = typeof navigator !== "undefined" && navigator.gpu &&
196
+ typeof OffscreenCanvas !== "undefined" && typeof Worker !== "undefined" &&
197
+ canvas && canvas.transferControlToOffscreen;
198
+ if (!ok) return null;
199
+
200
+ let worker = null, url = null, stopped = false, transferred = false, fellBack = null, timer = 0, ro = null, pendingSig = null, onQState = null;
201
+ const handle = { fallback: false, mode: "webgpu-worker",
202
+ pause() { // visibility budget: halt the render loop while unseen (keeps the device warm for an instant resume)
203
+ try { if (worker && !stopped) worker.postMessage({ t: "pause" }); } catch (e) {}
204
+ if (fellBack && fellBack.pause) { try { fellBack.pause(); } catch (e) {} }
205
+ },
206
+ resume() {
207
+ try { if (worker && !stopped) worker.postMessage({ t: "resume" }); } catch (e) {}
208
+ if (fellBack && fellBack.resume) { try { fellBack.resume(); } catch (e) {} }
209
+ },
210
+ stop() {
211
+ stopped = true; if (timer) { clearTimeout(timer); timer = 0; }
212
+ try { if (ro) ro.disconnect(); } catch (e) {}
213
+ try { if (typeof window !== "undefined" && onQState) window.removeEventListener("holo-q-state", onQState); } catch (e) {}
214
+ try { if (worker) { worker.postMessage({ t: "stop" }); worker.terminate(); } } catch (e) {}
215
+ try { if (url) URL.revokeObjectURL(url); } catch (e) {}
216
+ if (fellBack && fellBack.stop) { try { fellBack.stop(); } catch (e) {} }
217
+ } };
218
+
219
+ function toWebgl() {
220
+ if (timer) { clearTimeout(timer); timer = 0; }
221
+ try { if (worker) worker.terminate(); } catch (e) {}
222
+ if (stopped || transferred || fellBack) return; // transferred β†’ canvas burned, can't reuse (rare, post-probe only)
223
+ fellBack = mountWebglOrb(canvas); // same untouched canvas β†’ the proven WebGL2 wireframe
224
+ handle.mode = (fellBack && !fellBack.fallback) ? "webgl" : "none";
225
+ }
226
+
227
+ try { url = URL.createObjectURL(new Blob([WORKER_SRC], { type: "text/javascript" })); worker = new Worker(url); }
228
+ catch (e) { return mountWebglOrb(canvas); }
229
+
230
+ const dpr = () => Math.min((typeof window !== "undefined" && window.devicePixelRatio) || 1, 3); // full device DPR (cap 3) β€” a small corner orb is cheap, so every edge is razor-sharp
231
+ const cw = () => canvas.clientWidth || 64, ch = () => canvas.clientHeight || 64;
232
+
233
+ worker.onmessage = (e) => {
234
+ const m = e.data || {};
235
+ if (m.t === "probe-ok") {
236
+ if (stopped) return;
237
+ let off; try { off = canvas.transferControlToOffscreen(); transferred = true; }
238
+ catch (err) { toWebgl(); return; }
239
+ try { worker.postMessage({ t: "init", canvas: off, dpr: dpr(), ss: 2, cssW: cw(), cssH: ch(), debug: !!opts.debug }, [off]); } // ss = the SSAA ceiling the worker's ladder climbs to with fps headroom (starts at 1Γ— β€” instant first paint)
240
+ catch (err) { toWebgl(); }
241
+ } else if (m.t === "ready") { if (timer) { clearTimeout(timer); timer = 0; } if (pendingSig) { forwardSig(pendingSig.mode, pendingSig.level); pendingSig = null; } } // painting on the worker
242
+ else if (m.t === "lvl") { handle.level = m.v; handle.stateMode = m.mode; if (typeof handle.onLevel === "function") { try { handle.onLevel(m.v, m.mode); } catch (e) {} } } // optional debug readback (opts.debug)
243
+ else if (m.t === "fail") { toWebgl(); }
244
+ };
245
+ worker.onerror = () => toWebgl();
246
+ timer = setTimeout(toWebgl, 4500);
247
+ try { worker.postMessage({ t: "probe" }); } catch (e) { toWebgl(); }
248
+
249
+ if (typeof ResizeObserver !== "undefined") {
250
+ ro = new ResizeObserver(() => { if (transferred && worker && !stopped) { try { worker.postMessage({ t: "size", cssW: cw(), cssH: ch(), dpr: dpr() }); } catch (e) {} } });
251
+ try { ro.observe(canvas); } catch (e) {}
252
+ }
253
+
254
+ // ── Q-state reactivity: forward the global `holo-q-state` events to the worker (the messenger dispatches them
255
+ // when Q is thinking/listening/speaking), so the orb visibly REACTS instead of only idling. Buffered until the
256
+ // worker is live (pendingSig), and torn down with the orb (stop() removes the listener). ──
257
+ const MODE_MAP = { idle: 0, listening: 1, thinking: 2, speaking: 3 };
258
+ function forwardSig(modeNum, level) {
259
+ if (worker && transferred && !stopped) { try { worker.postMessage({ t: "sig", mode: modeNum, level: level }); } catch (e) {} }
260
+ else pendingSig = { mode: modeNum, level: level };
261
+ }
262
+ handle.signal = function (s) { s = s || {}; forwardSig(MODE_MAP[s.mode] || 0, (typeof s.level === "number") ? s.level : -1); };
263
+ onQState = (e) => handle.signal((e && e.detail) || {});
264
+ if (typeof window !== "undefined") { try { window.addEventListener("holo-q-state", onQState); } catch (e) {} }
265
+ return handle;
266
+ }
267
+
268
+ // ── VISIBILITY BUDGET (M5-L1) β€” the orb is a CONTINUOUS GPU raymarch; on a phone it must cost ~nothing when it
269
+ // can't be seen. The dominant case is the app/tab BACKGROUNDED β€” halt the loop on `visibilitychange`/document.hidden
270
+ // and resume on return. This is 100% reliable and self-correcting: the orb runs exactly as before whenever the app
271
+ // is foreground-visible, and goes idle (no rAF, no GPU) the moment it's backgrounded β€” the big battery/thermal win.
272
+ // prefers-reduced-motion β†’ paint one calm frame, then hold static (the base <img> behind the canvas carries the
273
+ // still orb, so it never goes blank). Fail-safe: any error leaves the orb running exactly as before β€” we never
274
+ // break the orb to save a frame. (Off-screen-while-foreground gating via IntersectionObserver is deferred to a
275
+ // later L1 pass, pending real-device verification β€” it can't be exercised in a throttled headless tab.)
276
+ function budgetByVisibility(canvas, h) {
277
+ try {
278
+ if (!h || typeof h.pause !== "function" || typeof h.resume !== "function") return h; // mode:"none" β†’ nothing to gate
279
+ if (typeof document === "undefined") return h;
280
+ const reduce = (typeof matchMedia === "function") && matchMedia("(prefers-reduced-motion: reduce)").matches;
281
+ if (reduce) {
282
+ const t = setTimeout(function () { try { h.pause(); } catch (e) {} }, 450); // one frame settles, then the still image holds
283
+ const os = h.stop && h.stop.bind(h);
284
+ h.stop = function () { try { clearTimeout(t); } catch (e) {} if (os) os(); };
285
+ return h;
286
+ }
287
+ let gone = false;
288
+ const onVis = function () { if (gone) return; try { document.hidden ? h.pause() : h.resume(); } catch (e) {} };
289
+ try { document.addEventListener("visibilitychange", onVis); } catch (e) {}
290
+ const os = h.stop && h.stop.bind(h);
291
+ h.stop = function () {
292
+ gone = true;
293
+ try { document.removeEventListener("visibilitychange", onVis); } catch (e) {}
294
+ if (os) os();
295
+ };
296
+ if (document.hidden) onVis(); // mounted while backgrounded β†’ start idle
297
+ return h;
298
+ } catch (e) { return h; }
299
+ }
300
+
301
+ export function mountOrb(canvas, opts) {
302
+ const h = mountGpuOrb(canvas, opts) // native-WebGPU worker orb (off the main thread) β€” the hero
303
+ || mountWebglOrb(canvas); // no WebGPU/Worker/OffscreenCanvas β†’ the WebGL2 wireframe floor
304
+ return budgetByVisibility(canvas, h);
305
+ }
306
+
307
+ // ─────────────────────────────────────────────────────────────────────────────────────────────────────────
308
+ // FALLBACK β€” the self-contained WebGL2 wireframe icosphere, restyled QUIET: where WebGPU isn't available
309
+ // (Brave shields, older GPUs) the orb must still look like the OS β€” a dim violet-ink lattice breathing on
310
+ // dark glass, never the loud rainbow wireframe. Geometry and motion are the proven originals; only the ink
311
+ // changed (single hue family, low alpha) so the fallback reads as a resting state of the hero orb.
312
+ // ─────────────────────────────────────────────────────────────────────────────────────────────────────────
313
+ function hueAt(t){ const k=0.5+0.5*Math.sin(t*2*Math.PI); return [0.42+0.14*k, 0.44+0.06*k, 0.66+0.24*k]; } // ink indigo β†’ soft violet, one quiet family
314
+ function norm(v){ const l=Math.hypot(v[0],v[1],v[2])||1; return [v[0]/l,v[1]/l,v[2]/l]; }
315
+ function icosphere(sub){
316
+ const t=(1+Math.sqrt(5))/2;
317
+ let V=[[-1,t,0],[1,t,0],[-1,-t,0],[1,-t,0],[0,-1,t],[0,1,t],[0,-1,-t],[0,1,-t],[t,0,-1],[t,0,1],[-t,0,-1],[-t,0,1]].map(norm);
318
+ let F=[[0,11,5],[0,5,1],[0,1,7],[0,7,10],[0,10,11],[1,5,9],[5,11,4],[11,10,2],[10,7,6],[7,1,8],[3,9,4],[3,4,2],[3,2,6],[3,6,8],[3,8,9],[4,9,5],[2,4,11],[6,2,10],[8,6,7],[9,8,1]];
319
+ const cache=new Map();
320
+ const mid=(a,b)=>{ const key=a<b?a+"_"+b:b+"_"+a; if(cache.has(key))return cache.get(key); const m=norm([(V[a][0]+V[b][0])/2,(V[a][1]+V[b][1])/2,(V[a][2]+V[b][2])/2]); V.push(m); const i=V.length-1; cache.set(key,i); return i; };
321
+ for(let s=0;s<sub;s++){ const nf=[]; for(const [a,b,c] of F){ const ab=mid(a,b),bc=mid(b,c),ca=mid(c,a); nf.push([a,ab,ca],[b,bc,ab],[c,ca,bc],[ab,bc,ca]); } F=nf; }
322
+ const seen=new Set(), E=[];
323
+ for(const [a,b,c] of F) for(const [x,y] of [[a,b],[b,c],[c,a]]){ const k=x<y?x+"_"+y:y+"_"+x; if(!seen.has(k)){ seen.add(k); E.push(x,y); } }
324
+ return { V, E };
325
+ }
326
+ function mat4Perspective(fovy, aspect, near, far){ const f=1/Math.tan(fovy/2), nf=1/(near-far); return new Float32Array([f/aspect,0,0,0, 0,f,0,0, 0,0,(far+near)*nf,-1, 0,0,2*far*near*nf,0]); }
327
+
328
+ function mountWebglOrb(canvas){
329
+ let gl; try { gl = canvas.getContext("webgl2", { alpha:true, antialias:true, premultipliedAlpha:false }); } catch(e){}
330
+ if(!gl) return { fallback:true, mode:"none", stop(){} };
331
+ const { V, E } = icosphere(3);
332
+ const pos=new Float32Array(E.length*3), col=new Float32Array(E.length*3);
333
+ for(let i=0;i<E.length;i++){ const p=V[E[i]]; pos[i*3]=p[0]; pos[i*3+1]=p[1]; pos[i*3+2]=p[2]; const h=hueAt(Math.atan2(p[2],p[0])/(2*Math.PI)+0.5); col[i*3]=h[0]; col[i*3+1]=h[1]; col[i*3+2]=h[2]; }
334
+ const vs=`#version 300 es
335
+ in vec3 aPos; in vec3 aCol; uniform mat4 uProj; uniform float uT; out vec3 vCol; out float vD;
336
+ void main(){
337
+ float a=uT*0.9, ca=cos(a), sa=sin(a);
338
+ vec3 p=vec3(ca*aPos.x+sa*aPos.z, aPos.y, -sa*aPos.x+ca*aPos.z);
339
+ float ax=uT*0.556, cx=cos(ax), sx=sin(ax);
340
+ p=vec3(p.x, cx*p.y - sx*p.z, sx*p.y + cx*p.z);
341
+ float br=1.0 + 0.05*sin(uT*1.3+p.y*3.0) + 0.035*sin(uT*0.7+p.x*4.0);
342
+ p*=br; vD=p.z; p.z-=3.15;
343
+ gl_Position=uProj*vec4(p,1.0); vCol=aCol;
344
+ }`;
345
+ const fs=`#version 300 es
346
+ precision highp float; in vec3 vCol; in float vD; out vec4 o;
347
+ void main(){ float d=0.40+0.30*smoothstep(-1.0,1.0,vD); o=vec4(vCol*d, 0.45); }`;
348
+ const sh=(t,s)=>{ const o=gl.createShader(t); gl.shaderSource(o,s); gl.compileShader(o); if(!gl.getShaderParameter(o,gl.COMPILE_STATUS)){ console.error("[orb] shader:", gl.getShaderInfoLog(o)); } return o; };
349
+ const prog=gl.createProgram(); gl.attachShader(prog,sh(gl.VERTEX_SHADER,vs)); gl.attachShader(prog,sh(gl.FRAGMENT_SHADER,fs)); gl.linkProgram(prog);
350
+ if(!gl.getProgramParameter(prog,gl.LINK_STATUS)){ console.error("[orb] link:", gl.getProgramInfoLog(prog)); return { fallback:true, mode:"none", stop(){} }; }
351
+ gl.useProgram(prog);
352
+ const mkBuf=(data,loc)=>{ const b=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,b); gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW); gl.enableVertexAttribArray(loc); gl.vertexAttribPointer(loc,3,gl.FLOAT,false,0,0); };
353
+ mkBuf(pos, gl.getAttribLocation(prog,"aPos")); mkBuf(col, gl.getAttribLocation(prog,"aCol"));
354
+ const uProj=gl.getUniformLocation(prog,"uProj"), uT=gl.getUniformLocation(prog,"uT");
355
+ gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); gl.lineWidth(1);
356
+ let raf=0, t0=performance.now(), stopped=false, paused=false;
357
+ function resize(){ const dpr=Math.min(window.devicePixelRatio||1, 2.5); const w=Math.max(2, canvas.clientWidth), h=Math.max(2, canvas.clientHeight); const W=Math.round(w*dpr), H=Math.round(h*dpr); if(canvas.width!==W||canvas.height!==H){ canvas.width=W; canvas.height=H; } gl.viewport(0,0,canvas.width,canvas.height); gl.uniformMatrix4fv(uProj,false, mat4Perspective(45*Math.PI/180, canvas.width/canvas.height, 0.1, 10)); }
358
+ function frame(){ if(stopped||paused) return; resize(); const t=(performance.now()-t0)/1000; gl.clearColor(0,0,0,0); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform1f(uT,t); gl.drawArrays(gl.LINES,0,E.length); raf=requestAnimationFrame(frame); }
359
+ frame();
360
+ return {
361
+ stop(){ stopped=true; cancelAnimationFrame(raf); raf=0; },
362
+ pause(){ if(paused||stopped) return; paused=true; if(raf){ cancelAnimationFrame(raf); raf=0; } }, // halt while unseen; the last frame stays painted
363
+ resume(){ if(!paused||stopped) return; paused=false; if(!raf) frame(); },
364
+ fallback:false, mode:"webgl" };
365
+ }
366
+
367
+ export default mountOrb;
sha256/bf790f49c2c3366fae494488b1832dac05908e18a37f5b5dd4292c76a6d130f7 ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // messenger-shadcn-ui.mjs β€” DROP-IN mount(el, model) rendering the Holo Messenger UX from STREAMING
2
+ // shadcn ΞΊ-components, faithful to the real app (network app-rail Β· Q sidebar Β· triage Β· rich rows Β·
3
+ // Q chat pane Β· earth wallpaper Β· real SVG line icons), same contract as the chatscope bundle.
4
+ //
5
+ // ADDITIVE + SAFE: only takes over window.HoloMessengerUI.mount on opt-in (?ui=shadcn or
6
+ // localStorage["holo.ui.shadcn"]="1"). Default boot stays the untouched chatscope UI.
7
+ //
8
+ // PERF: memoized rows Β· composer owns its draft Β· windowed thread (≀WINDOW rows in DOM; 1M chat stays tiny).
9
+ // PASS 1 = faithful shell. Rich message content + action surface are Pass 2/3.
10
+
11
+ const WANT = (() => {
12
+ try { const u = new URL(location.href);
13
+ if (u.searchParams.get("ui") === "shadcn") return true;
14
+ if (u.searchParams.get("ui") === "chatscope") return false;
15
+ return localStorage.getItem("holo.ui.shadcn") === "1";
16
+ } catch { return false; }
17
+ })();
18
+
19
+ const WINDOW = 80;
20
+ const BRANDS = "/usr/share/brands/";
21
+ const WP = "/apps/holo-messenger/_vendor/wallpaper-default.jpg"; // the earth photo (default)
22
+ const NET_SLUG = { whatsapp: "whatsapp", telegram: "telegram", signal: "signal", imessage: "imessage", instagram: "instagram", messenger: "messenger", discord: "discord", slack: "slack", gmessages: "googlemessages", googlemessages: "googlemessages", x: "x", twitter: "x", linkedin: "linkedin", gmail: "gmail", email: "gmail", internal: null };
23
+
24
+ const CSS = `
25
+ .wa{height:100dvh;display:grid;grid-template-columns:64px minmax(300px,.46fr) minmax(0,1fr);background:#0b141a;color:#e9edef;
26
+ font:14.5px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
27
+ .wa *{box-sizing:border-box}
28
+ .wa svg{display:block}
29
+ .rail{background:#111b21;border-right:1px solid #0a1015;display:flex;flex-direction:column;align-items:center;gap:7px;padding:12px 0}
30
+ .rb{position:relative;width:46px;height:46px;border-radius:15px;display:grid;place-items:center;cursor:pointer;color:#aebac1;transition:background .12s,color .12s;background:transparent;border:0}
31
+ .rb:hover{background:#202c33;color:#e9edef}.rb.on{background:#2a3942;color:#00a884}
32
+ .rb img{width:28px;height:28px;border-radius:8px;object-fit:cover}
33
+ .rb .dot{position:absolute;right:5px;bottom:5px;width:10px;height:10px;border-radius:50%;background:#00d95f;border:2px solid #111b21}
34
+ .rb .bdg{position:absolute;top:-3px;right:-3px;min-width:19px;height:19px;border-radius:10px;background:#00a884;color:#0b141a;font-size:11px;font-weight:700;display:grid;place-items:center;padding:0 4px;border:2px solid #111b21}
35
+ .rsep{width:28px;height:1px;background:#22303a;margin:3px 0}
36
+ .rgrow{flex:1 1 auto}
37
+ .rav{width:40px;height:40px;border-radius:50%;overflow:hidden;cursor:pointer;background:radial-gradient(circle at 35% 30%,#7cf0c8,#2b9e7a 60%,#0b3b2e);margin-top:2px}
38
+ .side{background:#111b21;border-right:1px solid #222d34;display:flex;flex-direction:column;min-width:0}
39
+ .stitle{display:flex;align-items:center;gap:6px;padding:15px 14px 10px}
40
+ .stitle .t{font-size:23px;font-weight:600;letter-spacing:-.4px;flex:1 1 auto}
41
+ .search{padding:4px 12px 8px;position:relative}
42
+ .search .si{position:absolute;left:26px;top:50%;transform:translateY(-50%);color:#8696a0;pointer-events:none;z-index:1;display:grid}
43
+ .filt{display:flex;align-items:center;gap:8px;padding:2px 14px 8px}
44
+ .chip{display:inline-flex;align-items:center;gap:6px;background:#202c33;color:#8696a0;border:0;border-radius:999px;padding:5px 14px;font-size:13px;cursor:pointer}
45
+ .chip.on{background:#0b3b2e;color:#00d95f}
46
+ .caret{background:#202c33;color:#8696a0;border:0;border-radius:999px;width:30px;height:28px;display:grid;place-items:center;cursor:pointer;font-size:11px}
47
+ .triage{margin:2px 12px 8px;display:flex;align-items:center;gap:9px;background:linear-gradient(90deg,#0e2a24,#122a1e);color:#7cf0c8;border:1px solid #123c30;border-radius:14px;padding:9px 14px;font-size:13.5px;cursor:pointer}
48
+ .triage .sk{color:#00d95f;display:grid;flex:0 0 auto}
49
+ .chats{flex:1 1 auto;overflow-y:auto;overflow-x:hidden}
50
+ .chats::-webkit-scrollbar{width:6px}.chats::-webkit-scrollbar-thumb{background:#374248;border-radius:6px}
51
+ .row{display:flex;gap:13px;align-items:center;padding:9px 14px;cursor:pointer;position:relative}
52
+ .row:after{content:"";position:absolute;left:78px;right:0;bottom:0;height:1px;background:#1c262d}
53
+ .row:hover{background:#202c33}.row.on{background:#2a3942}.row.on:after{background:transparent}
54
+ .av{position:relative;flex:0 0 auto;border-radius:50%;overflow:hidden}
55
+ .av img{width:100%;height:100%;object-fit:cover;display:block}
56
+ .row .b{min-width:0;flex:1 1 auto}
57
+ .row .n{color:#e9edef;font-size:16px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}
58
+ .row .p{color:#8696a0;font-size:13.5px;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:3px}
59
+ .row .rc{color:#53bdeb}
60
+ .row .m{margin-left:auto;text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:0 0 auto}
61
+ .row .t{color:#8696a0;font-size:12px}.row.unread .t{color:#00d95f;font-weight:500}
62
+ .row .pin{color:#f15c6d;font-size:13px;transform:rotate(45deg)}
63
+ .netdot{width:16px;height:16px;border-radius:4px;object-fit:cover;flex:0 0 auto}
64
+ .main{position:relative;display:flex;flex-direction:column;min-width:0;background:#0b141a}
65
+ .wp{position:absolute;inset:0;background:#0b141a center/cover no-repeat;z-index:0}
66
+ .wp:after{content:"";position:absolute;inset:0;background:linear-gradient(rgba(11,20,26,.35),rgba(11,20,26,.5))}
67
+ .mh,.thread,.composer,.e2ewrap{position:relative;z-index:1}
68
+ .mh{height:60px;flex:0 0 auto;background:#202c33;display:flex;align-items:center;gap:14px;padding:0 16px}
69
+ .mh .who .n{font-size:16px;color:#e9edef;font-weight:500}
70
+ .mh .who .s{font-size:13px;color:#00a884;margin-top:1px}
71
+ .mh .sp{margin-left:auto}.mh .icons{display:flex;gap:2px}
72
+ .ico{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;color:#aebac1;cursor:pointer;transition:background .12s;background:transparent;border:0}
73
+ .ico:hover{background:#ffffff14;color:#e9edef}
74
+ .ico.sk{color:#00d95f}
75
+ .e2ewrap{display:flex;justify-content:center;padding:14px 0 2px}
76
+ .e2e{background:#182229;color:#ffd279;font-size:12.5px;padding:6px 14px;border-radius:8px;box-shadow:0 1px .5px #0003}
77
+ .thread{flex:1 1 auto;overflow-y:auto;overflow-x:hidden;padding:10px 8% 14px;display:flex;flex-direction:column;gap:3px}
78
+ .thread::-webkit-scrollbar{width:6px}.thread::-webkit-scrollbar-thumb{background:#374248cc;border-radius:6px}
79
+ .more{align-self:center;color:#8696a0;font-size:12px;padding:8px;opacity:.85}
80
+ .day{align-self:center;background:#182229;color:#8696a0;font-size:12.5px;padding:5px 12px;border-radius:8px;margin:8px 0 6px;box-shadow:0 1px .5px #0003}
81
+ .bub{max-width:65%;padding:6px 9px 8px 10px;border-radius:8px;font-size:14.2px;line-height:1.42;box-shadow:0 1px .5px #0003;word-wrap:break-word;white-space:pre-wrap}
82
+ .in{align-self:flex-start;background:#202c33;border-top-left-radius:0}
83
+ .out{align-self:flex-end;background:#005c4b;border-top-right-radius:0}
84
+ .grp{margin-top:8px}
85
+ .bub .tt{font-size:11px;color:#ffffff8a;float:right;margin:6px 0 -3px 12px;position:relative;top:4px}
86
+ .bub .tt .rc{color:#53bdeb}
87
+ .empty{margin:auto;color:#8696a0;text-align:center;background:#182229;padding:8px 16px;border-radius:8px}
88
+ .composer{flex:0 0 auto;background:#202c33;display:flex;align-items:center;gap:6px;padding:8px 14px}
89
+ .composer .grow{flex:1 1 auto}
90
+ .send{width:44px;height:44px;border-radius:50%;background:#00a884;color:#0b141a;border:0;display:grid;place-items:center;cursor:pointer;flex:0 0 auto}
91
+ /* media */
92
+ .m-img{display:block;max-width:320px;max-height:340px;border-radius:6px;cursor:pointer;object-fit:cover}
93
+ .m-vid{position:relative;max-width:320px;border-radius:6px;overflow:hidden;cursor:pointer}
94
+ .m-vid img{display:block;width:100%;border-radius:6px}
95
+ .m-play{position:absolute;inset:0;display:grid;place-items:center}
96
+ .m-play span{width:48px;height:48px;border-radius:50%;background:#0009;color:#fff;display:grid;place-items:center;font-size:20px}
97
+ .m-file{display:flex;align-items:center;gap:10px;background:#ffffff0f;border-radius:8px;padding:9px 11px;min-width:200px;cursor:pointer}
98
+ .m-file .fi{width:38px;height:38px;border-radius:8px;background:#00a88433;color:#7cf0c8;display:grid;place-items:center;font-size:16px;flex:0 0 auto}
99
+ .m-file .fn{font-size:13.5px;color:#e9edef;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
100
+ .m-file .fs{font-size:12px;color:#8696a0;margin-top:2px}
101
+ .m-aud{display:flex;align-items:center;gap:10px;min-width:220px;padding:2px 0}
102
+ .m-aud audio{height:34px}
103
+ .lb{position:fixed;inset:0;background:#000c;z-index:60;display:grid;place-items:center;cursor:zoom-out}
104
+ .lb img,.lb video{max-width:90vw;max-height:90vh;border-radius:8px}
105
+ .lb .x{position:absolute;top:18px;right:22px;color:#fff;font-size:28px;cursor:pointer;background:0;border:0}
106
+ /* attach tray + pay sheet */
107
+ .tray{position:absolute;bottom:66px;left:14px;background:#233138;border-radius:12px;box-shadow:0 10px 34px #0009;padding:6px;z-index:6;min-width:236px}
108
+ .tray button{display:flex;align-items:center;gap:11px;width:100%;background:0;border:0;color:#e9edef;font-size:14.5px;padding:10px 12px;border-radius:8px;cursor:pointer;text-align:left}
109
+ .tray button:hover{background:#2a3942}.tray button:disabled{opacity:.5}
110
+ .tray .sep{height:1px;background:#2a3942;margin:4px 6px}
111
+ .paywrap{position:fixed;inset:0;background:#000a;z-index:60;display:grid;place-items:center}
112
+ .pay{background:#111b21;border-radius:14px;padding:20px;width:346px;max-width:90vw;box-shadow:0 20px 60px #000a}
113
+ .pay h3{margin:0 0 4px;font-size:17px}.pay .psub{color:#8696a0;font-size:13px;margin-bottom:14px}
114
+ .pay .seg{display:flex;background:#202c33;border-radius:10px;padding:3px;margin-bottom:14px}
115
+ .pay .seg button{flex:1;background:0;border:0;color:#8696a0;padding:8px;border-radius:8px;cursor:pointer;font-size:14px}
116
+ .pay .seg button.on{background:#00a884;color:#0b141a;font-weight:600}
117
+ .pay .amt{width:100%;background:#202c33;border:0;border-radius:10px;color:#e9edef;font-size:26px;text-align:center;padding:12px;margin-bottom:10px;outline:0}
118
+ .pay .chips{display:flex;gap:8px;margin-bottom:12px}
119
+ .pay .chips button{flex:1;background:#202c33;border:0;color:#e9edef;border-radius:8px;padding:9px;cursor:pointer}
120
+ .pay .chips button.on{background:#0b3b2e;color:#00d95f}
121
+ .pay .memo{width:100%;background:#202c33;border:0;border-radius:10px;color:#e9edef;padding:10px 12px;margin-bottom:12px;font-size:14px;outline:0}
122
+ .pay .err{color:#f15c6d;font-size:13px;margin-bottom:8px;text-align:center}
123
+ .pay .go{width:100%;background:#00a884;color:#0b141a;border:0;border-radius:10px;padding:12px;font-weight:600;cursor:pointer;font-size:15px}
124
+ .pay .go:disabled{opacity:.5;cursor:default}
125
+ .pay .cancel{width:100%;background:0;color:#8696a0;border:0;padding:10px;margin-top:6px;cursor:pointer}
126
+ `;
127
+
128
+ async function ensureImportmap() {
129
+ if (document.querySelector('script[type="importmap"][data-holo-ui]')) return;
130
+ const map = await (await fetch("/apps/ui/vendor/importmap.json")).json();
131
+ const imports = {}; for (const [k, v] of Object.entries(map.imports || map)) imports[k] = typeof v === "string" ? v.replace(/^\.\//, "/apps/ui/") : v;
132
+ const s = document.createElement("script"); s.type = "importmap"; s.setAttribute("data-holo-ui", "1"); s.textContent = JSON.stringify({ imports }); document.head.appendChild(s);
133
+ }
134
+ let _deps = null;
135
+ async function deps() {
136
+ if (_deps) return _deps;
137
+ await ensureImportmap();
138
+ const React = await import("react");
139
+ const { createRoot } = await import("react-dom/client");
140
+ const reg = await (await fetch("/apps/ui/registry/index.json")).json();
141
+ const K = Object.fromEntries(reg.components.map((c) => [c.name, c.holo]));
142
+ const [button, badge, avatar, input] = await Promise.all(["button", "badge", "avatar", "input"].map((n) => import(K[n])));
143
+ return (_deps = { React, createRoot, C: { button, badge, avatar, input } });
144
+ }
145
+ if (!document.getElementById("wa-shadcn-css")) { const st = document.createElement("style"); st.id = "wa-shadcn-css"; st.textContent = CSS; document.head.appendChild(st); }
146
+
147
+ const initials = (s) => (String(s || "?").trim().split(/\s+/).map((w) => w[0]).join("").slice(0, 2) || "?").toUpperCase();
148
+ const hue = (s) => { let h = 0; s = String(s || ""); for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0; return `hsl(${h % 360} 40% 46%)`; };
149
+ const isOut = (m) => !!(m && (m.mine || m.out || m.fromMe || m.dir === "out" || m.from === "me" || m.self));
150
+ const threadOf = (model, id) => { try { if (id && model.thread) return model.thread(id) || []; } catch {} return (model.threads && model.threads[id]) || []; };
151
+ const rcMark = (m) => m.status === "read" || m.status === "delivered" ? "βœ“βœ“" : m.status === "sent" ? "βœ“" : "";
152
+ const slugOf = (net) => { const k = String(net || "").toLowerCase(); return NET_SLUG[k] === undefined ? k : NET_SLUG[k]; };
153
+ const mimeKind = (mime, kind) => { const k = String(kind || "").toLowerCase(); if (["image", "video", "audio", "voice"].includes(k)) return k === "voice" ? "audio" : k; const t = String(mime || "").split("/")[0]; if (t === "image" || t === "video" || t === "audio") return t; return "file"; };
154
+ const humanSize = (n) => { n = +n || 0; if (!n) return ""; const u = ["B", "KB", "MB", "GB"]; let i = 0; while (n >= 1024 && i < u.length - 1) { n /= 1024; i++; } return (n < 10 && i ? n.toFixed(1) : Math.round(n)) + " " + u[i]; };
155
+ const fileGlyph = (mime, name) => { const m = String(mime || ""), e = String(name || "").split(".").pop().toLowerCase(); if (m.includes("pdf") || e === "pdf") return "πŸ“•"; if (["zip", "rar", "7z"].includes(e)) return "πŸ—œ"; if (["doc", "docx"].includes(e)) return "πŸ“˜"; if (["xls", "xlsx", "csv"].includes(e)) return "πŸ“—"; return "πŸ“„"; };
156
+
157
+ function buildApp({ React, C }) {
158
+ const { createElement: h, memo, useState, useRef, useEffect, useCallback, useLayoutEffect } = React;
159
+ const Avatar = C.avatar.Avatar, AvatarImage = C.avatar.AvatarImage, AvatarFallback = C.avatar.AvatarFallback;
160
+ const Button = C.button.Button, Input = C.input.Input, Badge = C.badge.Badge;
161
+
162
+ // exact SVG line icons (from the real app's IC set)
163
+ const svg = (kids, s = 22, w = 1.8) => h("svg", { viewBox: "0 0 24 24", width: s, height: s, fill: "none", stroke: "currentColor", strokeWidth: w, strokeLinecap: "round", strokeLinejoin: "round" }, ...kids);
164
+ const P = (d, e) => h("path", { d, ...e });
165
+ const CIR = (cx, cy, r, e) => h("circle", { cx, cy, r, ...e });
166
+ const RC = (x, y, width, height, rx, e) => h("rect", { x, y, width, height, rx, ...e });
167
+ const fillC = { fill: "currentColor", stroke: "none" };
168
+ const IC = {
169
+ chats: () => svg([P("M20 11.4A7.6 7.6 0 0 1 8.9 18.2L4.5 19.4l1.2-4.2A7.6 7.6 0 1 1 20 11.4Z")]),
170
+ search: (s) => svg([CIR(11, 11, 7), P("m20 20-3.6-3.6")], s || 19),
171
+ phone: () => svg([P("M6.6 4H4.5A1.5 1.5 0 0 0 3 5.6 16 16 0 0 0 18.4 21a1.5 1.5 0 0 0 1.6-1.5v-2.1a1.5 1.5 0 0 0-1.2-1.45l-2.2-.45a1.5 1.5 0 0 0-1.5.6l-.5.7a12 12 0 0 1-5.1-5.1l.7-.5a1.5 1.5 0 0 0 .6-1.5l-.45-2.2A1.5 1.5 0 0 0 6.6 4Z")]),
172
+ video: () => svg([RC(3, 6.5, 12, 11, 2.5), P("m15 10.5 5.5-3v9l-5.5-3Z")]),
173
+ menu: () => svg([CIR(12, 5, 1.35, fillC), CIR(12, 12, 1.35, fillC), CIR(12, 19, 1.35, fillC)]),
174
+ newchat: () => svg([P("M13.5 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.5"), P("M18.4 3.6a2 2 0 0 1 2.8 2.8L13 14.6l-3.4.9.9-3.4 7.9-8.5Z")]),
175
+ emoji: () => svg([CIR(12, 12, 8.5), P("M8.8 14.2a4.2 4.2 0 0 0 6.4 0"), CIR(9, 10, 1, fillC), CIR(15, 10, 1, fillC)]),
176
+ plus: () => svg([P("M12 5.5v13M5.5 12h13")]),
177
+ mic: () => svg([RC(9, 3, 6, 11, 3), P("M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M8.5 21h7")]),
178
+ send: () => svg([P("M4.5 12 20.5 4.5 13 20.5l-2.8-6.4L4.5 12Z")]),
179
+ spark: (s) => svg([P("M12 3.2l1.7 4.6 4.6 1.7-4.6 1.7L12 15.8l-1.7-4.6L5.7 9.5l4.6-1.7L12 3.2Z"), P("M5.5 15.5l.8 2 2 .8-2 .8-.8 2-.8-2-2-.8 2-.8.8-2Z")], s || 20),
180
+ sun: () => svg([CIR(12, 12, 4), P("M12 2v2M12 20v2M4 12H2M22 12h-2M5.6 5.6 4.2 4.2M19.8 19.8l-1.4-1.4M18.4 5.6l1.4-1.4M4.2 19.8l1.4-1.4")]),
181
+ plusThin: () => svg([P("M12 5.5v13M5.5 12h13")], 26, 1.6),
182
+ };
183
+
184
+ const Av = (name, size, bg, src) => h("div", { className: "av", style: { height: size + "px", width: size + "px" } },
185
+ h(Avatar, { style: { height: "100%", width: "100%", background: bg || hue(name), display: "grid", placeItems: "center" } },
186
+ src ? h(AvatarImage, { src, alt: "", style: { height: "100%", width: "100%", objectFit: "cover" } }) : null,
187
+ h(AvatarFallback, { style: { background: bg || hue(name), color: "#fff", fontSize: (size * 0.36) + "px", fontWeight: 500, height: "100%", width: "100%", display: "grid", placeItems: "center" } }, initials(name))));
188
+ const Ico = (icon, onClick, title, cls) => h("button", { className: "ico" + (cls ? " " + cls : ""), onClick, title }, icon);
189
+ const netLogo = (net) => { const s = slugOf(net); return s ? h("img", { className: "netdot", src: BRANDS + s + ".svg", alt: "", onError: (e) => { e.currentTarget.style.display = "none"; } }) : null; };
190
+
191
+ // rich media in a bubble β€” image/video/audio/file, with lazy bridge-media resolution
192
+ function MediaView({ media, model, onMedia }) {
193
+ const [url, setUrl] = useState(media.url || media.thumb || "");
194
+ const bucket = mimeKind(media.mime, media.kind);
195
+ useEffect(() => { let alive = true;
196
+ if (!media.url && (media.lazy || media.pending || media.ref) && model.resolveBridgeMedia) {
197
+ Promise.resolve(model.resolveBridgeMedia(media)).then((u) => { if (alive && u) setUrl(typeof u === "string" ? u : (u.url || u.src || "")); }).catch(() => {});
198
+ } return () => { alive = false; }; }, []);
199
+ if (bucket === "image") return url ? h("img", { className: "m-img", src: url, alt: "", loading: "lazy", onClick: () => onMedia({ kind: "image", url }) }) : h("div", { className: "m-file" }, "πŸ–Ό Photo");
200
+ if (bucket === "video") return h("div", { className: "m-vid", onClick: () => onMedia({ kind: "video", url }) }, h("img", { src: media.thumb || url, alt: "" }), h("div", { className: "m-play" }, h("span", {}, "β–Ά")));
201
+ if (bucket === "audio") return h("div", { className: "m-aud" }, url ? h("audio", { controls: true, src: url }) : h("span", {}, "🎀 Voice message"));
202
+ return h("div", { className: "m-file", onClick: () => url && window.open(url, "_blank") }, h("div", { className: "fi" }, fileGlyph(media.mime, media.filename)), h("div", { style: { minWidth: 0 } }, h("div", { className: "fn" }, media.filename || "File"), media.size ? h("div", { className: "fs" }, humanSize(media.size)) : null));
203
+ }
204
+
205
+ const Rail = memo(function Rail({ nets, active, totalUnread, onPick }) {
206
+ return h("nav", { className: "rail" },
207
+ h("button", { className: "rb" + (active === "All" ? " on" : ""), title: "All chats", onClick: () => onPick("All") }, IC.chats(), totalUnread ? h("span", { className: "bdg" }, totalUnread > 99 ? "99+" : totalUnread) : null),
208
+ nets.length ? h("div", { className: "rsep" }) : null,
209
+ nets.map((n) => h("button", { key: n.id, className: "rb" + (active === n.id ? " on" : ""), title: n.label, onClick: () => onPick(n.id) },
210
+ (() => { const s = slugOf(n.id); return s ? h("img", { src: BRANDS + s + ".svg", alt: n.label, onError: (e) => { const t = document.createTextNode((n.label || "?")[0].toUpperCase()); try { e.currentTarget.replaceWith(t); } catch {} } }) : (n.label || "?")[0].toUpperCase(); })(),
211
+ h("span", { className: "dot" }), n.unread ? h("span", { className: "bdg" }, n.unread > 99 ? "99+" : n.unread) : null)),
212
+ h("button", { className: "rb", title: "Add network", onClick: () => onPick("+") }, IC.plusThin()),
213
+ h("div", { className: "rgrow" }),
214
+ h("div", { className: "rav" }));
215
+ });
216
+
217
+ const Row = memo(function Row({ c, on, preview, receipt, onSelect }) {
218
+ return h("div", { className: "row" + (on ? " on" : "") + (c.unread ? " unread" : ""), onClick: () => onSelect(c.id) },
219
+ Av(c.name, 49, c.isQ ? "#12b886" : hue(c.name), c.avatar),
220
+ h("div", { className: "b" },
221
+ h("div", { className: "n" }, c.name || c.id || "Chat", c.network ? netLogo(c.network) : null),
222
+ h("div", { className: "p" }, receipt ? h("span", { className: "rc" }, receipt + " ") : null, preview)),
223
+ h("div", { className: "m" },
224
+ h("div", { className: "t" }, c.time || c.ts || ""),
225
+ c.pinned ? h("span", { className: "pin" }, "πŸ“Œ") : null,
226
+ c.unread ? h(Badge, { style: { background: "#00a884", color: "#0b141a", borderRadius: "999px", height: "20px", minWidth: "20px", justifyContent: "center", padding: "0 6px", fontSize: "12px", fontWeight: 600 } }, String(c.unread)) : null));
227
+ });
228
+
229
+ function Thread({ model, activeId, onMedia }) {
230
+ const all = threadOf(model, activeId);
231
+ const [limit, setLimit] = useState(WINDOW);
232
+ const ref = useRef(null), prevId = useRef(activeId), anchorH = useRef(0), pin = useRef(true);
233
+ const toBottom = (el) => { el.scrollTop = el.scrollHeight; };
234
+ useEffect(() => { setLimit(WINDOW); }, [activeId]);
235
+ // Runs after every render (no deps): a fresh chat, or new messages arriving, both flow through here.
236
+ // While "pinned" we stay glued to the newest message β€” exactly like WhatsApp.
237
+ useLayoutEffect(() => { const el = ref.current; if (!el) return;
238
+ if (prevId.current !== activeId) { prevId.current = activeId; pin.current = true; anchorH.current = 0; toBottom(el); return; }
239
+ if (anchorH.current) { el.scrollTop = el.scrollHeight - anchorH.current; anchorH.current = 0; return; }
240
+ if (pin.current) toBottom(el); });
241
+ // Media resolves async (placeholder first, <img> swapped in later) and reflows the thread AFTER layout.
242
+ // A ResizeObserver on the scroll container won't catch it (its own box size never changes), and per-image
243
+ // listeners miss images added later β€” so listen for `load` in the CAPTURE phase on the container, which
244
+ // fires for ANY descendant image whenever it appears/loads. Keeps us glued to the newest message.
245
+ useEffect(() => { const el = ref.current; if (!el) return; pin.current = true; toBottom(el);
246
+ requestAnimationFrame(() => { if (pin.current && ref.current) toBottom(ref.current); });
247
+ const stick = () => { if (pin.current && ref.current) toBottom(ref.current); };
248
+ el.addEventListener("load", stick, true); el.addEventListener("error", stick, true);
249
+ return () => { el.removeEventListener("load", stick, true); el.removeEventListener("error", stick, true); };
250
+ }, [activeId]);
251
+ // Detach when the user scrolls up; re-attach ("jump to latest") once they're back near the bottom.
252
+ const onScroll = useCallback((e) => { const el = e.currentTarget;
253
+ pin.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
254
+ if (el.scrollTop < 120 && limit < all.length) { anchorH.current = el.scrollHeight; setLimit((l) => Math.min(all.length, l + WINDOW)); } }, [limit, all.length]);
255
+ const start = Math.max(0, all.length - limit), shown = all.slice(start);
256
+ if (!all.length) return h("div", { className: "thread", ref }, h("div", { className: "empty" }, "No messages yet. Say hello πŸ‘‹"));
257
+ const rows = [h("div", { className: "e2ewrap", key: "e2e" }, h("div", { className: "e2e" }, "πŸ”’ Messages are end-to-end encrypted")), h("div", { className: "day", key: "day" }, "Today")];
258
+ if (start > 0) rows.push(h("div", { className: "more", key: "more" }, `↑ ${start.toLocaleString()} earlier β€” scroll up`));
259
+ let lastOut = null;
260
+ shown.forEach((m, i) => { const out = isOut(m); const hasMedia = m.media && (m.media.url || m.media.thumb || m.media.ref || m.media.lazy || m.media.kind);
261
+ rows.push(h("div", { key: start + i, className: "bub " + (out ? "out" : "in") + (out !== lastOut ? " grp" : ""), style: hasMedia ? { maxWidth: "min(360px,72%)" } : null },
262
+ hasMedia ? h(MediaView, { media: m.media, model, onMedia }) : null,
263
+ m.text ? h("div", { style: hasMedia ? { marginTop: "5px" } : null }, m.text) : null,
264
+ h("span", { className: "tt" }, (m.time || m.ts || ""), out ? h("span", { className: "rc" }, " " + rcMark(m)) : null)));
265
+ lastOut = out; });
266
+ return h("div", { className: "thread", ref, onScroll }, rows);
267
+ }
268
+
269
+ const Composer = memo(function Composer({ activeId, onSend, onPlus }) {
270
+ const [draft, setDraft] = useState("");
271
+ const send = () => { const t = draft.trim(); if (!t) return; onSend(activeId, t); setDraft(""); };
272
+ return h("div", { className: "composer" },
273
+ Ico(IC.plus(), onPlus, "Attach"),
274
+ h("div", { className: "grow" }, h(Input, { placeholder: "Type a message", value: draft, autoFocus: true,
275
+ onChange: (e) => setDraft(e.target.value), onKeyDown: (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } },
276
+ style: { background: "#2a3942", border: "0", borderRadius: "10px", height: "44px", color: "#e9edef", paddingLeft: "16px" } })),
277
+ h("button", { className: "send", onClick: send, "aria-label": "Send" }, draft.trim() ? IC.send() : IC.mic()));
278
+ });
279
+
280
+ const TrayBtn = (glyph, label, onClick, disabled) => h("button", { onClick, disabled }, h("span", { style: { fontSize: "17px" } }, glyph), label);
281
+
282
+ function PaySheet({ model, activeId, conv, sheet, setSheet }) {
283
+ const set = (patch) => setSheet((s) => ({ ...s, ...patch, err: null }));
284
+ const amt = parseFloat(sheet.amount);
285
+ const go = async () => { set({ busy: true }); let r;
286
+ try { r = await model.holoPay(sheet.genesis || activeId, { kind: sheet.kind, amount: amt, memo: (sheet.memo || "").trim() }); } catch (e) { r = { ok: false, error: String(e && e.message || e) }; }
287
+ if (r && r.ok) setSheet(null); else setSheet((s) => ({ ...s, busy: false, err: (r && r.error) || "Couldn't create the payment" })); };
288
+ return h("div", { className: "paywrap", onClick: () => setSheet(null) },
289
+ h("div", { className: "pay", onClick: (e) => e.stopPropagation() },
290
+ h("h3", {}, sheet.kind === "send" ? "Send money" : "Request money"), h("div", { className: "psub" }, (sheet.kind === "send" ? "To " : "From ") + (conv.name || "this chat")),
291
+ h("div", { className: "seg" }, h("button", { className: sheet.kind === "send" ? "on" : "", onClick: () => set({ kind: "send" }) }, "Send"), h("button", { className: sheet.kind === "request" ? "on" : "", onClick: () => set({ kind: "request" }) }, "Request")),
292
+ h("input", { className: "amt", inputMode: "decimal", placeholder: "$0", value: sheet.amount, onChange: (e) => set({ amount: e.target.value.replace(/[^0-9.]/g, "") }), autoFocus: true }),
293
+ h("div", { className: "chips" }, [10, 20, 50, 100].map((a) => h("button", { key: a, className: amt === a ? "on" : "", onClick: () => set({ amount: String(a) }) }, "$" + a))),
294
+ h("input", { className: "memo", placeholder: "What's it for? (optional)", maxLength: 120, value: sheet.memo || "", onChange: (e) => set({ memo: e.target.value }) }),
295
+ sheet.err ? h("div", { className: "err" }, sheet.err) : null,
296
+ h("button", { className: "go", disabled: sheet.busy || !(amt > 0), onClick: go }, sheet.busy ? (sheet.kind === "send" ? "Confirm in your wallet…" : "Creating…") : ((sheet.kind === "send" ? "Send" : "Request") + (amt > 0 ? " $" + sheet.amount : " money"))),
297
+ h("button", { className: "cancel", onClick: () => setSheet(null) }, "Cancel")));
298
+ }
299
+
300
+ const previewOf = (model, c) => { if (c.preview) return c.preview; const t = threadOf(model, c.id); const last = t.length ? t[t.length - 1] : null; return (last && (last.text || (last.media ? "πŸ“Ž media" : ""))) || ""; };
301
+
302
+ return function App({ model }) {
303
+ const convs = Array.isArray(model.conversations) ? model.conversations : [];
304
+ const [activeId, setActiveId] = useState(null);
305
+ const [filter, setFilter] = useState("All");
306
+ const [q, setQ] = useState("");
307
+ const [lb, setLb] = useState(null);
308
+ const [attachOpen, setAttachOpen] = useState(false);
309
+ const [paySheet, setPaySheet] = useState(null);
310
+ const fileRef = useRef(null);
311
+ const onSelect = useCallback((id) => { setActiveId(id); setAttachOpen(false); }, []);
312
+ const active = (activeId && convs.some((c) => c.id === activeId)) ? activeId : ((convs.find((c) => c.active) || convs[0] || {}).id || null);
313
+ const conv = convs.find((c) => c.id === active) || {};
314
+ const onSend = useCallback((id, text) => { try { model.onSend && model.onSend(id, text); } catch (e) { console.error("[shadcn-ui] onSend", e); } }, [model]);
315
+ const call = useCallback((video) => { try { model.startCall && model.startCall(active, { video }); } catch (e) { console.error("[shadcn-ui] startCall", e); } }, [model, active]);
316
+ const pickFile = (accept) => { if (fileRef.current) { fileRef.current.accept = accept; fileRef.current.click(); } setAttachOpen(false); };
317
+ const onFile = (e) => { const f = e.target.files && e.target.files[0]; if (f) { try { model.onAttach && model.onAttach(active, f); } catch (er) { console.error("[shadcn-ui] onAttach", er); } } e.target.value = ""; };
318
+ const tryM = (fn, ...a) => { setAttachOpen(false); try { const r = model[fn] && model[fn](...a); if (r && r.catch) r.catch(() => {}); } catch (e) { console.error("[shadcn-ui] " + fn, e); } };
319
+ const nets = Array.isArray(model.networks) && model.networks.length ? model.networks
320
+ : Object.values(convs.reduce((a, c) => { const id = (c.network || c.platform); if (id && !a[id]) a[id] = { id, label: id[0].toUpperCase() + id.slice(1), unread: 0 }; if (id) a[id].unread += (c.unread || 0); return a; }, {}));
321
+ const totalUnread = convs.reduce((n, c) => n + (c.unread || 0), 0);
322
+ const signalUnread = model.signalUnread != null ? model.signalUnread : convs.filter((c) => c.unread).length;
323
+ const qs = q.trim().toLowerCase();
324
+ const shown = convs.filter((c) => (filter === "All" || (c.network || c.platform) === filter) && (!qs || (c.name || "").toLowerCase().includes(qs) || (previewOf(model, c) || "").toLowerCase().includes(qs)));
325
+ const sub = conv.presence || (conv.isQ ? "online, on your device" : (conv.status || conv.network || conv.platform || ""));
326
+ const runSearch = () => { const t = q.trim(); if (!t) return; try { if (model.qCommand) model.qCommand(t); else if (model.onNewChat) model.onNewChat(t); } catch {} };
327
+
328
+ return h("div", { className: "wa" },
329
+ h(Rail, { nets, active: filter, totalUnread, onPick: (id) => { if (id === "+") { try { model.openNetworks && model.openNetworks(); } catch {} } else setFilter(id); } }),
330
+ h("div", { className: "side" },
331
+ h("div", { className: "stitle" }, h("span", { className: "t" }, "Messenger"),
332
+ model.askQ ? Ico(IC.spark(), () => { try { model.askQ(); } catch {} }, "Ask Q", "sk") : null, Ico(IC.newchat(), () => { try { model.onNewChat && model.onNewChat(""); } catch {} }, "New chat")),
333
+ h("div", { className: "search" }, h("span", { className: "si" }, IC.search()),
334
+ h(Input, { placeholder: "Search, ask Q, or start a chat…", value: q, onChange: (e) => setQ(e.target.value), onKeyDown: (e) => { if (e.key === "Enter") runSearch(); },
335
+ style: { background: "#202c33", border: "0", borderRadius: "10px", height: "42px", color: "#e9edef", paddingLeft: "40px", fontSize: "14.5px" } })),
336
+ signalUnread ? h("div", { className: "triage" }, h("span", { className: "sk" }, IC.spark(18)), `${signalUnread} need you Β· ~${Math.max(1, Math.round(signalUnread * 0.4))} min`) : null,
337
+ h("div", { className: "chats" }, shown.map((c) => h(Row, { key: c.id, c, on: c.id === active, preview: previewOf(model, c), receipt: c.receipt || "", onSelect })))),
338
+ h("div", { className: "main" },
339
+ h("div", { className: "wp", style: { backgroundImage: `url(${WP})` } }),
340
+ h("div", { className: "mh" }, Av(conv.name, 40, conv.isQ ? "#12b886" : hue(conv.name), conv.avatar),
341
+ h("div", { className: "who" }, h("div", { className: "n" }, conv.name || ""), sub ? h("div", { className: "s" }, sub) : null),
342
+ h("div", { className: "sp" }), h("div", { className: "icons" }, Ico(IC.video(), () => call(true), "Video call"), Ico(IC.phone(), () => call(false), "Voice call"), Ico(IC.menu(), () => { try { model.onFavourite && model.onFavourite(active); } catch {} }, "Menu"))),
343
+ h(Thread, { model, activeId: active, onMedia: setLb }),
344
+ h("input", { ref: fileRef, type: "file", style: { display: "none" }, onChange: onFile }),
345
+ attachOpen ? h("div", { className: "tray" },
346
+ TrayBtn("πŸ–Ό", "Photos & videos", () => pickFile("image/*,video/*")),
347
+ TrayBtn("πŸ“„", "Document", () => pickFile("*/*")),
348
+ (conv.network && !conv.isQ && model.holoPay) ? TrayBtn("πŸ’Έ", "Send money", () => { setAttachOpen(false); setPaySheet({ kind: "send", amount: "", memo: "", busy: false, err: null }); }) : null,
349
+ h("div", { className: "sep" }),
350
+ model.startMeet ? TrayBtn("πŸ‘₯", "Start a meeting", () => tryM("startMeet", active, { video: true })) : null,
351
+ model.startTogether ? TrayBtn("πŸ–₯", "Share my screen", () => tryM("startTogether", active, { kind: "tab", title: "" })) : null,
352
+ model.startTogether ? TrayBtn("πŸ“", "Co-edit a doc", () => tryM("startTogether", active, { kind: "doc", title: "" })) : null,
353
+ (conv.network && !conv.isQ && model.qDraft) ? [h("div", { className: "sep", key: "s" }), TrayBtn("✨", "Draft a reply with Q", () => tryM("qDraft", active))] : null) : null,
354
+ h(Composer, { key: active, activeId: active, onSend, onPlus: () => setAttachOpen((v) => !v) })),
355
+ lb ? h("div", { className: "lb", onClick: () => setLb(null) }, h("button", { className: "x", "aria-label": "Close" }, "βœ•"),
356
+ lb.kind === "video" ? h("video", { src: lb.url, controls: true, autoPlay: true, onClick: (e) => e.stopPropagation() }) : h("img", { src: lb.url, alt: "", onClick: (e) => e.stopPropagation() })) : null,
357
+ paySheet ? h(PaySheet, { model, activeId: active, conv, sheet: paySheet, setSheet: setPaySheet }) : null);
358
+ };
359
+ }
360
+
361
+ async function mount(el, model) {
362
+ const d = await deps();
363
+ const App = buildApp(d);
364
+ let cur = model;
365
+ const root = d.createRoot(el);
366
+ const render = (mdl) => { cur = mdl || cur; root.render(d.React.createElement(App, { model: cur })); };
367
+ render(model);
368
+ console.log("[shadcn-ui] Holo Messenger (Pass 1) mounted from ΞΊ-components Β·", (model.conversations || []).length, "chats");
369
+ return { update: render, unmount: () => { try { root.unmount(); } catch {} } };
370
+ }
371
+
372
+ if (WANT && typeof window !== "undefined") {
373
+ const prev = window.HoloMessengerUI;
374
+ window.HoloMessengerUI = { mount, version: ((prev && prev.version) || "m1") + "+shadcn", _chatscope: prev };
375
+ console.log("[shadcn-ui] streaming-ΞΊ shadcn UI ACTIVE (opt out: ?ui=chatscope)");
376
+ }
377
+
378
+ export { mount };
sha256/d76d596376d1203a8c170ddbe9dab02442158671646c630ee1902d5953e63fc5 ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* messenger-skins.css β€” OPTIONAL colour re-tones, applied ONLY when <html> carries data-skin="…".
2
+ * Default (no attribute) is untouched, so this can never disturb the shipping look. Colours only β€” no
3
+ * layout β€” safe and fully reversible.
4
+ *
5
+ * The theme drives ~half its colour from --wa-* vars on .holo-wa-root and hardcodes the other half to the
6
+ * same values. This shared block re-points the major hardcoded surfaces back onto the vars; each skin then
7
+ * only remaps the vars and the whole surface re-tones consistently. */
8
+
9
+ html[data-skin] .holo-wa-root { background: var(--wa-bg) !important; color: var(--wa-ink); }
10
+ html[data-skin] .holo-wa-root .cs-main-container,
11
+ html[data-skin] .holo-wa-root .cs-chat-container,
12
+ html[data-skin] .holo-wa-root .cs-message-list { background: transparent; }
13
+ html[data-skin] .holo-wa-root .cs-sidebar,
14
+ html[data-skin] .holo-wa-root .holo-rail,
15
+ html[data-skin] .holo-wa-root .cs-conversation-list { background: var(--wa-side) !important; }
16
+ html[data-skin] .holo-wa-root .cs-conversation-header,
17
+ html[data-skin] .holo-wa-root .holo-list-title,
18
+ html[data-skin] .holo-wa-root .cs-message-input,
19
+ html[data-skin] .holo-wa-root .holo-composer { background: var(--wa-head) !important; }
20
+ html[data-skin] .holo-wa-root .cs-search,
21
+ html[data-skin] .holo-wa-root .holo-wp-search,
22
+ html[data-skin] .holo-wa-root .cs-message-input__content-editor-wrapper,
23
+ html[data-skin] .holo-wa-root .cs-message-input__content-editor { background: color-mix(in srgb, var(--wa-head) 78%, var(--wa-bg)) !important; color: var(--wa-ink) !important; }
24
+ html[data-skin] .holo-wa-root .cs-conversation:hover,
25
+ html[data-skin] .holo-wa-root .cs-conversation.cs-conversation--active { background: var(--wa-head) !important; }
26
+ html[data-skin] .holo-wa-root .cs-conversation__name,
27
+ html[data-skin] .holo-wa-root .cs-conversation-header__user-name { color: var(--wa-ink) !important; }
28
+ html[data-skin] .holo-wa-root .cs-conversation__info,
29
+ html[data-skin] .holo-wa-root .cs-conversation__last-sender,
30
+ html[data-skin] .holo-wa-root .cs-conversation-header__info { color: var(--wa-dim) !important; }
31
+ html[data-skin] .holo-wa-root .cs-message--incoming .cs-message__content { background: var(--wa-in) !important; color: var(--wa-ink) !important; }
32
+ html[data-skin] .holo-wa-root .cs-message--outgoing .cs-message__content { background: var(--wa-out) !important; }
33
+ html[data-skin] .holo-wa-root .cs-message__content { color: var(--wa-ink); }
34
+ html[data-skin] .holo-wa-root .holo-rail-btn.on,
35
+ html[data-skin] .holo-wa-root .holo-rail-net.on,
36
+ html[data-skin] .holo-wa-root .holo-catchup-pill { color: var(--wa-accent) !important; }
37
+ html[data-skin] .holo-wa-root .holo-c-send,
38
+ html[data-skin] .holo-wa-root .cs-button--send { background: var(--wa-accent) !important; }
39
+
40
+ /* ── cooler / graphite ── */
41
+ html[data-skin="graphite"] .holo-wa-root { --wa-bg:#0d1117; --wa-side:#12171e; --wa-head:#1c232c; --wa-in:#1c232c; --wa-out:#1f4a55; --wa-ink:#e6eaf0; --wa-dim:#8b96a3; --wa-accent:#4ab3d4; --wa-line:#222a34; }
42
+ /* ── warmer ── */
43
+ html[data-skin="warm"] .holo-wa-root { --wa-bg:#14100c; --wa-side:#1b1611; --wa-head:#271f18; --wa-in:#271f18; --wa-out:#4d3f1f; --wa-ink:#efe8df; --wa-dim:#a89a88; --wa-accent:#e0a53c; --wa-line:#2c241b; }
44
+ /* ── higher contrast ── */
45
+ html[data-skin="contrast"] .holo-wa-root { --wa-bg:#000000; --wa-side:#0a0a0a; --wa-head:#181818; --wa-in:#1d1d1d; --wa-out:#00805e; --wa-ink:#ffffff; --wa-dim:#a6adb4; --wa-accent:#00e08a; --wa-line:#2a2a2a; }
46
+ /* ── light mode (experimental: some deep-hardcoded text may stay dark) ── */
47
+ html[data-skin="light"] .holo-wa-root { --wa-bg:#d7dce1; --wa-side:#ffffff; --wa-head:#f0f2f5; --wa-in:#ffffff; --wa-out:#d9fdd3; --wa-ink:#111b21; --wa-dim:#54656f; --wa-accent:#008069; --wa-line:#e4e8ec; }
48
+ html[data-skin="light"] .holo-wa-root .cs-message__content { color: #111b21 !important; }
49
+ html[data-skin="light"] .holo-wa-root .cs-message-list { background: var(--wa-bg) !important; background-image: none !important; }
50
+ html[data-skin="light"] .holo-wa-root .holo-wp-tile { background-image: none !important; }
51
+
52
+ /* ────────────────────────────────────────────────────────────────────────────────────────────────
53
+ * HI-DPI + HIGH-FPS layer (always on, colour-independent). The honest "8K/retina" story: a DOM/CSS UI
54
+ * is ALREADY resolution-independent β€” text and the SVG icons are vectors, so on a retina/4K/8K panel it
55
+ * renders at the display's native device pixels with zero extra work (no bitmaps to upscale). What we
56
+ * actually tune here is smoothness + latency:
57
+ * β€’ content-visibility skips rendering/layout of off-screen chat rows β†’ a huge list scrolls at the
58
+ * display's full refresh (60/120Hz) and first paint is near-instant (browser does O(visible) work).
59
+ * β€’ the scrollers are promoted to their own GPU layer so scrolling never touches the main thread.
60
+ * β€’ crisp text rasterisation + high-quality image scaling for hi-DPI. */
61
+ .holo-wa-root { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
62
+ .holo-wa-root .cs-conversation { content-visibility: auto; contain-intrinsic-size: auto 72px; }
63
+ .holo-wa-root .cs-message { content-visibility: auto; contain-intrinsic-size: auto 44px; }
64
+ .holo-wa-root .cs-conversation-list,
65
+ .holo-wa-root .cs-message-list .scrollbar-container,
66
+ .holo-wa-root .cs-message-list__scroll-wrapper { will-change: scroll-position; transform: translateZ(0); backface-visibility: hidden; overflow-anchor: auto; }
67
+ .holo-wa-root .cs-avatar img, .holo-wa-root .holo-av-real, .holo-wa-root .holo-media-el img { image-rendering: auto; }
68
+ .holo-wa-root .holo-media-el img, .holo-wa-root .cs-message img { image-rendering: -webkit-optimize-contrast; }
69
+ @media (min-resolution: 1.5dppx) { .holo-wa-root { text-rendering: geometricPrecision; } }
70
+
71
+ /* floating skin picker */
72
+ .holo-skin-pick { position: fixed; right: 16px; bottom: 86px; z-index: 90; display: flex; gap: 4px; align-items: center; background: #0b141aee; border: 1px solid #2a3942; border-radius: 999px; padding: 5px; backdrop-filter: blur(10px); font: 12.5px ui-sans-serif, system-ui, sans-serif; box-shadow: 0 8px 30px #0007; }
73
+ .holo-skin-pick button { background: transparent; border: 0; color: #aebac1; border-radius: 999px; padding: 5px 11px; cursor: pointer; }
74
+ .holo-skin-pick button:hover { background: #ffffff14; color: #e9edef; }
75
+ .holo-skin-pick button.on { background: #00a884; color: #0b141a; font-weight: 600; }
76
+
77
+ /* instant wallpaper */
78
+ /* An inline low-res earth paints INSTANTLY (zero network β€” it ships in this CSS) as the chat-pane
79
+ * backdrop; the full 2560px wallpaper is preloaded (see app.html) and covers it the moment it decodes.
80
+ * So the pane is never empty and there is no visible load. */
81
+ html[data-skin] .holo-wa-root .cs-chat-container { background: var(--wa-bg) url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDABQODxIPDRQSERIXFhQYHzMhHxwcHz8tLyUzSkFOTUlBSEZSXHZkUldvWEZIZoxob3p9hIWET2ORm4+AmnaBhH//2wBDARYXFx8bHzwhITx/VEhUf39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3//wAARCAAgADADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwCAR+1SLHVaPUYm2Zyp/jyOB9KE1AbzgjPXaRgAf41pdisjQSL2/SphDx0/Sq8epW64zknuBV6O+s3XKzJ9CcGk5tFciZGIT6fpT1h+YZx+VTC5tuomT880yTUdNgI8ycF89EXJqPavoP2aW5ya28f8bMT9cVIsVqDyCfq1VPtPIOwgfWpDcKFyvzH8q1ujKzL8bWynAiT8RmpGmTsiAfSs0XR/5aKOem3mnrdkcBGz+FF0Go6aW6ZiEwF/6ZjH61XNvdH/AJZnn3qc3rFdrQMwqP7bcKP3cSj2C0tB3Z//2Q==") center center / cover no-repeat !important; }
82
+ html[data-skin] .holo-wa-root .cs-message-list { transition: background-image .25s ease; }
83
+
84
+ /* ────────────────────────────────────────────────────────────────────────────────────────────────
85
+ * SLACK skin β€” data-skin="slack". Unlike the colour-only re-tones above, this one also does LAYOUT: the
86
+ * Slack "window envelope". An aubergine chrome (far-left rail + channel sidebar) wraps a content pane that
87
+ * floats as a rounded island inset by an EVEN margin on ALL FOUR sides β€” the darker chrome shows through
88
+ * every gap (top, right, bottom, AND a left gutter between sidebar and pane), with rounded corners + a soft
89
+ * shadow for depth. Placed at end-of-file so source order beats the base skin block AND the wallpaper rule
90
+ * above (equal specificity β†’ later wins); every rule carries `.holo-wa-root` to match the base depth.
91
+ *
92
+ * Two coupling facts make the float robust: (1) the composer is a position:absolute overlay on .holo-main
93
+ * whose `left` is CSS `34%` β€” the SAME 34% as the sidebar's flex-basis β€” so re-anchoring it to
94
+ * `calc(34% + gap)` keeps it glued to the gapped pane at every window width, no JS. (2) the bundle gives the
95
+ * pane height:100%, which ignores margin and overflows; `height:auto` + flex:1 1 auto lets the even margin
96
+ * actually shrink it. ALL geometry lives in the β‰₯900px media query so the narrow/mobile single-column layout
97
+ * (sidebar collapses, composer full-bleed) is left exactly as the bundle intends. Colours + margins only,
98
+ * fully reversible, every feature intact. */
99
+ html[data-skin="slack"] .holo-wa-root {
100
+ --wa-bg:var(--holo-chrome, #150E1A); --wa-side:#2A1530; --wa-head:#1B1B1F; --wa-in:#26262B; --wa-out:#3A2140;
101
+ --wa-ink:#E9E5ED; --wa-dim:#A99DB4; --wa-accent:#C6A6E6; --wa-line:#ffffff12;
102
+ --slk-pane:#1B1B1F; --slk-hi:#5C2D66; --slk-hover:#3A2140; --slk-gap:var(--holo-env-gap, 10px);
103
+ background: var(--wa-bg) !important;
104
+ }
105
+ /* chrome behind the floating pane (the colour seen in the inset margin/gutter) */
106
+ html[data-skin="slack"] .holo-wa-root.holo-wa-root,
107
+ html[data-skin="slack"] .holo-wa-root .cs-main-container { background: var(--wa-bg) !important; }
108
+ /* the WebGPU wallpaper backdrop is off in Slack β€” the pane is a flat surface */
109
+ html[data-skin="slack"] .holo-wa-root .holo-backdrop { display: none !important; }
110
+ /* far-left workspace rail: flush with the chrome β€” transparent over the same --wa-bg ground as the menu, no seam,
111
+ so rail + list + gutter are ONE continuous background and only the conversation floats (the Slack move). */
112
+ html[data-skin="slack"] .holo-wa-root .holo-rail { background:var(--holo-chrome, #150E1A) !important; border-right:0 !important; }
113
+ html[data-skin="slack"] .holo-wa-root .holo-rail-btn.on,
114
+ html[data-skin="slack"] .holo-wa-root .holo-rail-net.on { color: var(--wa-accent) !important; }
115
+ /* THE LEFT MENU IS THE BACKGROUND β€” like Slack, the rail, the channel list and the gutter around the floating
116
+ pane are ONE continuous chrome (the --wa-bg ground), not a separate lighter panel. So every sidebar surface is
117
+ transparent: the menu items sit directly on the background, and the ONLY thing that floats is the conversation
118
+ island. This is what makes the whole shell read as one window with content lifted out of it. */
119
+ html[data-skin="slack"] .holo-wa-root .cs-sidebar.cs-sidebar--left,
120
+ html[data-skin="slack"] .holo-wa-root .cs-conversation-list,
121
+ html[data-skin="slack"] .holo-wa-root .holo-list-head,
122
+ html[data-skin="slack"] .holo-wa-root .holo-list-title,
123
+ html[data-skin="slack"] .holo-wa-root .holo-chips,
124
+ html[data-skin="slack"] .holo-wa-root .holo-catchup { background: transparent !important; }
125
+ html[data-skin="slack"] .holo-wa-root .cs-search { background:#1F0F24 !important; border:1px solid #ffffff12 !important; color:var(--wa-ink) !important; }
126
+ /* conversation rows = inset rounded pills (Slack). Inset applied to EVERY row so hover/active only swap the
127
+ * background β€” no layout jump. Active carries the highlight + white text. */
128
+ html[data-skin="slack"] .holo-wa-root .cs-conversation { margin:1px 8px !important; border-radius:8px !important; }
129
+ html[data-skin="slack"] .holo-wa-root .cs-conversation:hover { background: var(--slk-hover) !important; }
130
+ html[data-skin="slack"] .holo-wa-root .cs-conversation.cs-conversation--active { background: var(--slk-hi) !important; color:#fff !important; }
131
+ html[data-skin="slack"] .holo-wa-root .cs-conversation.cs-conversation--active * { color:#fff !important; }
132
+ /* pane + its inner surfaces (colours are width-independent; the float geometry is gated below) */
133
+ html[data-skin="slack"] .holo-wa-root .cs-chat-container { background: var(--slk-pane) !important; }
134
+ html[data-skin="slack"] .holo-wa-root .cs-message-list { background: var(--slk-pane) !important; background-image: none !important; }
135
+ html[data-skin="slack"] .holo-wa-root .cs-conversation-header { background: var(--slk-pane) !important; border-bottom: 1px solid #ffffff12; }
136
+ html[data-skin="slack"] .holo-wa-root .holo-composer { background: var(--slk-pane) !important; border-top: 1px solid #ffffff12; }
137
+ html[data-skin="slack"] .holo-wa-root .holo-c-input { background:#26262B !important; border:1px solid #ffffff14 !important; border-radius:8px !important; color:var(--wa-ink) !important; }
138
+
139
+ /* ── the floating envelope (desktop only; narrow layout keeps the bundle's single-column defaults) ── */
140
+ @media (min-width: 900px) {
141
+ html[data-skin="slack"] .holo-wa-root .cs-chat-container {
142
+ flex: 1 1 auto !important; min-width: 0; height: auto !important; align-self: stretch;
143
+ margin: var(--slk-gap) !important; /* even inset on all four sides */
144
+ border-radius: 12px; overflow: hidden;
145
+ box-shadow: 0 0 0 1px #00000055, 0 14px 38px #00000085;
146
+ }
147
+ /* glue the composer to the gapped pane: left tracks the sidebar's 34%, plus the gutter */
148
+ html[data-skin="slack"] .holo-wa-root .holo-composer {
149
+ left: calc(34% + var(--slk-gap)) !important; right: var(--slk-gap) !important;
150
+ bottom: var(--slk-gap) !important; width: auto !important; border-radius: 0 0 12px 12px;
151
+ }
152
+ }
153
+
154
+ /* ── THEATRE MODE β€” full-screen wallpaper + glass, under the Slack skin ────────────────────────────
155
+ * Theatre (`.theater`, toggle ⌘/Ctrl+\) collapses the rail + sidebar and floats ONE conversation over a
156
+ * FULL-BLEED wallpaper as centred glass capsules (see whatsapp-theme.css "Stage 6"). Three things make it
157
+ * immersive + fast here:
158
+ * 1. WALLPAPER edge-to-edge β€” a static image on the root (the whole viewport), NOT the WebGPU `.holo-backdrop`
159
+ * canvas (which we turn OFF: it was rendering at opacity:0, all cost no pixels). The image is the one
160
+ * app.html already preloads, so it paints with zero extra latency; every layer above it is transparent.
161
+ * 2. LIGHT + CLEAR β€” the heavy radial vignette + hue-tint is replaced by a soft top/bottom legibility scrim
162
+ * only, so the middle of the wallpaper stays bright and open.
163
+ * 3. STUNNING GLASS, CHEAP β€” real backdrop-blur is limited to the TWO capsules (header + composer); message
164
+ * bubbles are plain translucent fills (no per-bubble blur) so a long thread never janks input.
165
+ * Selector depth `…"slack"] .holo-wa-root.theater .X` = (0,4,1) beats the base slack rules (0,3,1) and
166
+ * theatre's own (0,3,0); transforms are left untouched so theatre's centring + auto-quiet fade keep animating. */
167
+ html[data-skin="slack"] .holo-wa-root.theater {
168
+ /* FOLLOW the operator's chosen wallpaper (--wp-img, set from localStorage holo-messenger/wallpaper-src),
169
+ falling back to the preloaded default when unset. `none` (the "plain" mode) is honoured β†’ dark. */
170
+ background: #0b0f14 var(--wp-img, url("/apps/holo-messenger/_vendor/wallpaper-default.jpg")) center center / cover no-repeat !important;
171
+ }
172
+ html[data-skin="slack"] .holo-wa-root.theater .holo-backdrop { display: none !important; } /* WebGPU canvas off β†’ lower latency */
173
+ html[data-skin="slack"] .holo-wa-root.theater .cs-chat-container {
174
+ background: transparent !important; margin: 0 !important; border-radius: 0 !important;
175
+ overflow: visible !important; box-shadow: none !important; /* full-bleed, no slack box */
176
+ }
177
+ /* transparent reading column, aligned to the SAME 812px as the chrome so bubbles line up with the composer */
178
+ html[data-skin="slack"] .holo-wa-root.theater .cs-message-list {
179
+ background: transparent !important;
180
+ padding-left: max(20px, calc((100% - 812px) / 2)) !important;
181
+ padding-right: max(20px, calc((100% - 812px) / 2)) !important;
182
+ }
183
+ /* clear + light: only a soft top/bottom scrim for legibility; the wallpaper stays bright in the middle */
184
+ html[data-skin="slack"] .holo-wa-root.theater .holo-main::before {
185
+ background: linear-gradient(to bottom, rgba(0,0,0,.30) 0%, transparent 16%, transparent 80%, rgba(0,0,0,.42) 100%) !important;
186
+ }
187
+ /* stunning glass capsules β€” vivid backdrop-blur, crisp edge, top highlight (only these two get real blur) */
188
+ html[data-skin="slack"] .holo-wa-root.theater .cs-conversation-header,
189
+ html[data-skin="slack"] .holo-wa-root.theater .holo-composer {
190
+ background: rgba(22,24,32,.44) !important;
191
+ -webkit-backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
192
+ backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
193
+ border: 1px solid rgba(255,255,255,.16) !important;
194
+ box-shadow: 0 14px 40px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.16) !important;
195
+ }
196
+ html[data-skin="slack"] .holo-wa-root.theater .holo-composer {
197
+ left: 50% !important; right: auto !important; width: min(calc(100% - 40px), 812px) !important;
198
+ bottom: 18px !important; border-radius: 18px !important;
199
+ }
200
+ /* bubbles: light translucent fills (no blur = no jank on long threads) */
201
+ html[data-skin="slack"] .holo-wa-root.theater .cs-message--incoming .cs-message__content { background: rgba(28,28,36,.62) !important; }
202
+ html[data-skin="slack"] .holo-wa-root.theater .cs-message--outgoing .cs-message__content { background: rgba(58,33,64,.60) !important; }
203
+
204
+ /* ── FRAME-COLLAPSED β€” the immersive focus view (chats folded into the rail) ───────────────────────
205
+ * "Collapse chats into the rail" (`.holo-main.frame-collapsed`) folds the conversation list away and lets
206
+ * ONE conversation take the whole frame. The slack skin otherwise left it broken: the composer stayed pinned
207
+ * to `left:34%` (the vanished sidebar edge) so it floated stranded in the middle. Here we make it the SAME
208
+ * immersive treatment as theatre β€” full-screen wallpaper + glass capsules β€” but KEEP the rail as a clean
209
+ * glass nav (that's the whole point of this mode), and centre the header/composer/reading-column in the frame
210
+ * to the RIGHT of the rail so everything lines up.
211
+ * Β· `:has(.holo-main.frame-collapsed)` puts the wallpaper on the ROOT (so it sits behind the rail too).
212
+ * Β· `:not(.theater)` so theatre (which hides the rail) keeps full ownership when both happen to be on.
213
+ * Β· Only 3 blur layers total (rail + header + composer); bubbles are plain translucent β€” stays responsive. */
214
+ html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) {
215
+ /* same as theatre: follow the operator's --wp-img, fall back to the preloaded default */
216
+ background: #0b0f14 var(--wp-img, url("/apps/holo-messenger/_vendor/wallpaper-default.jpg")) center center / cover no-repeat !important;
217
+ }
218
+ html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) .holo-backdrop { display: none !important; }
219
+ /* the left nav bar stays β€” a clean SOLID strip; the wallpaper covers the entire screen EXCEPT this rail */
220
+ html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) .holo-rail {
221
+ background: #17111D !important;
222
+ border-right: 1px solid rgba(255,255,255,.08) !important;
223
+ }
224
+ /* transparent full-bleed frame + reading column centred in the space right of the rail */
225
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-chat-container {
226
+ background: transparent !important; margin: 0 !important; border-radius: 0 !important; overflow: visible !important; box-shadow: none !important;
227
+ }
228
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message-list {
229
+ background: transparent !important;
230
+ padding-left: max(20px, calc((100% - 812px) / 2)) !important;
231
+ padding-right: max(20px, calc((100% - 812px) / 2)) !important;
232
+ }
233
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed::before {
234
+ content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
235
+ background: linear-gradient(to bottom, rgba(0,0,0,.30) 0%, transparent 16%, transparent 80%, rgba(0,0,0,.42) 100%);
236
+ }
237
+ /* glass header + composer, centred in the frame (the rail is the nav, the frame is everything right of it) */
238
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-conversation-header,
239
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer {
240
+ background: rgba(22,24,32,.44) !important;
241
+ -webkit-backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
242
+ backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
243
+ border: 1px solid rgba(255,255,255,.16) !important;
244
+ box-shadow: 0 14px 40px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.16) !important;
245
+ }
246
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-conversation-header {
247
+ margin: 14px auto 0 !important; max-width: 812px !important; width: calc(100% - 40px) !important; border-radius: 16px !important;
248
+ }
249
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer {
250
+ left: 50% !important; right: auto !important; transform: translateX(-50%) !important;
251
+ width: min(calc(100% - 40px), 812px) !important; bottom: 18px !important; border-radius: 18px !important;
252
+ }
253
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message--incoming .cs-message__content { background: rgba(28,28,36,.62) !important; }
254
+ html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message--outgoing .cs-message__content { background: rgba(58,33,64,.60) !important; }
255
+
256
+ /* ── BASE-LAYER fix: composer alignment in frame-collapsed, for ANY skin ───────────────────────────
257
+ * Skin-agnostic (this file is loaded regardless of the active skin). The bundle pins the composer to
258
+ * `left:34%` β€” the sidebar's flex-basis β€” but frame-collapsed folds the sidebar to 0, so on every NON-slack
259
+ * skin (graphite/warm/contrast/light/none) the composer floated stranded in the middle. Align it to the
260
+ * full-bleed chat (left:0 = the rail's right edge; right:0 is already the base). `:not(.theater)` yields to
261
+ * theatre's own centred composer; slack's higher-specificity immersive rule above wins for the slack skin. */
262
+ .holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer { left: 0 !important; }
263
+
264
+ /* ══ WHATSAPP SKIN β€” the messenger as WhatsApp Desktop ══════════════════════════════════════════════════════════
265
+ * Green/dark bubbles + the doodle chat texture; the whole conversation floats as ONE rounded window over the
266
+ * (dimmed) home wallpaper desktop. Default skin (messenger-skin.mjs). All pane rules carry BOTH .holo-wa-root and
267
+ * .holo-wa-root.wall-on selectors so they beat the wall-on living-wallpaper rules (0,5,1 > 0,4,1) in either state. */
268
+ html[data-skin="whatsapp"] .holo-wa-root {
269
+ --wa-bg:#0b141a; --wa-side:#111b21; --wa-head:#202c33; --wa-in:#202c33; --wa-out:#005c4b;
270
+ --wa-ink:#e9edef; --wa-dim:#8696a0; --wa-accent:#00a884; --wa-line:#ffffff14;
271
+ --wa-doodle:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27300%27%20height%3D%27300%27%20viewBox%3D%270%200%20300%20300%27%20fill%3D%27none%27%20stroke%3D%27url%28%23hd%29%27%20stroke-opacity%3D%27.12%27%20stroke-width%3D%272.3%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cdefs%3E%3ClinearGradient%20id%3D%27hd%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%271%27%20y2%3D%271%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%232ee6c6%27%2F%3E%3Cstop%20offset%3D%27.55%27%20stop-color%3D%27%234d8cff%27%2F%3E%3Cstop%20offset%3D%271%27%20stop-color%3D%27%23d46bff%27%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20transform%3D%27translate%2840%2044%29%20rotate%28-8%29%27%3E%3Cpath%20d%3D%27M-13-9h26a3%203%200%200%201%203%203v11a3%203%200%200%201-3%203H-2l-7%206v-6h-4a3%203%200%200%201-3-3v-11a3%203%200%200%201%203-3z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28150%2030%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0%2012C-16%202-14-11-5-11c4%200%205%203%205%203s1-3%205-3c9%200%2011%2013-5%2023z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28255%2048%29%20rotate%286%29%27%3E%3Cpath%20d%3D%27M-15-6h7l3-4h10l3%204h7a2%202%200%200%201%202%202v16a2%202%200%200%201-2%202h-30a2%202%200%200%201-2-2v-16a2%202%200%200%201%202-2z%20M0-1a7%207%200%201%200%20.1%200z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2892%20120%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0-14a14%2014%200%201%200%20.1%200z%20M-6-4a1%201%200%201%200%20.1%200z%20M6-4a1%201%200%201%200%20.1%200z%20M-7%204a10%2010%200%200%200%2014%200%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28205%20108%29%20rotate%28-12%29%27%3E%3Cpath%20d%3D%27M0-15l4%2010%2011%200-9%207%204%2011-10-7-10%207%204-11-9-7%2011%200z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2830%20128%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-6%2012a5%205%200%201%200%200-.1%20M-6%2012v-22l16-4v18a5%205%200%201%200%200-.1%20M-6-10l16-4%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28150%2096%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0-6a6%206%200%201%200%20.1%200z%20M0-15v5%20M0%2010v5%20M-15%200h5%20M10%200h5%20M-11-11l3%203%20M8%208l3%203%20M11-11l-3%203%20M-8%208l-3%203%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28268%20150%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-15%204L15-12-3%2015-6%203-15%204z%20M-6%203L15-12%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2860%20210%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-11-8h20v10a10%2010%200%200%201-20%200z%20M9-6h4a4%204%200%200%201%200%208h-4%20M-11%2016h20%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28145%20205%29%20rotate%288%29%27%3E%3Cpath%20d%3D%27M-12-12c0%2016%208%2024%2024%2024l3-7-7-4-4%203c-4-2-8-6-10-10l3-4-4-7z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28235%20205%29%20rotate%28-6%29%27%3E%3Cpath%20d%3D%27M-13-4h26v6h-26z%20M-10%202h20v14h-20z%20M0-4v20%20M0-4c-6-10-14-2%200%200%20M0-4c6-10%2014-2%200%200%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28100%20258%29%20rotate%2810%29%27%3E%3Cpath%20d%3D%27M0-3a3%203%200%201%200%20.1%200z%20M0-3c0-9%2010-9%206-2%20M2%200c8-4%2010%206%202%204%20M-1%202c3%208-7%209-5%201%20M-3-1c-8-3-6-11%201-5%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28195%20258%29%20rotate%28-6%29%27%3E%3Cpath%20d%3D%27M0-14a9%2011%200%201%201-.1%200z%20M0-3v6%20M0%203l-3%204h6z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28275%20258%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M3-14l-11%2015h7l-3%2013%2012-16h-7z%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
272
+ --wgap:var(--holo-env-gap, 10px);
273
+ background:var(--holo-chrome, #1f1f1e) !important;
274
+ }
275
+ /* THE DESKTOP behind the window = the home wallpaper (the backdrop canvas), full-bleed + dimmed. No wallpaper set
276
+ β‡’ a plain dark desktop. */
277
+ /* SUPERSEDED (user: clean nav-matched frame): the desktop behind the window is now ONE flat surface = the left-nav
278
+ chrome (see the root `background:var(--holo-chrome)` set above). The living-wallpaper canvas AND its scrim are
279
+ hidden outright, so the frame around the floating conversation reads as a single continuous nav ground and the
280
+ window is the only thing that floats (also drops the WebGPU per-frame cost β†’ snappier). The `.wall-on` variants
281
+ (0,4,1) + later source-order beat the bundle's `wall-on .holo-backdrop{display:block}`. */
282
+ html[data-skin="whatsapp"] .holo-wa-root .holo-backdrop { display:none !important; }
283
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-backdrop { display:none !important; }
284
+ html[data-skin="whatsapp"] .holo-wa-root .holo-wall-scrim { display:none !important; }
285
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-wall-scrim { display:none !important; }
286
+ /* rail = OS chrome */
287
+ html[data-skin="whatsapp"] .holo-wa-root .holo-rail { background:var(--holo-chrome) !important; border-right:0 !important; }
288
+ /* sidebar + list = solid WhatsApp panel (opaque β€” the desktop shows only in the frame around the window) */
289
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-main-container,
290
+ html[data-skin="whatsapp"] .holo-wa-root .cs-main-container,
291
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-sidebar.cs-sidebar--left,
292
+ html[data-skin="whatsapp"] .holo-wa-root .cs-sidebar.cs-sidebar--left,
293
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-conversation-list,
294
+ html[data-skin="whatsapp"] .holo-wa-root .cs-conversation-list,
295
+ html[data-skin="whatsapp"] .holo-wa-root .holo-list-head,
296
+ html[data-skin="whatsapp"] .holo-wa-root .holo-chips,
297
+ html[data-skin="whatsapp"] .holo-wa-root .holo-catchup { background:var(--wa-side) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }
298
+ /* CHAT = the WhatsApp doodle (opaque dark base + the line-art texture), NOT the home photo */
299
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-chat-container,
300
+ html[data-skin="whatsapp"] .holo-wa-root .cs-chat-container { background:#0b141a !important; }
301
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list,
302
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message-list {
303
+ background-color:#0b141a !important;
304
+ background-image:var(--wa-doodle) !important;
305
+ background-repeat:repeat !important; background-size:300px 300px !important; background-position:center center !important; }
306
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list::before,
307
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message-list::before,
308
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message-list::after { display:none !important; }
309
+ /* header + composer = solid WhatsApp bar (kills the wall-on glass) */
310
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-conversation-header,
311
+ html[data-skin="whatsapp"] .holo-wa-root .cs-conversation-header { background:var(--wa-head) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; border-bottom:0 !important; }
312
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-composer,
313
+ html[data-skin="whatsapp"] .holo-wa-root .holo-composer { background:var(--wa-head) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; border-top:0 !important; }
314
+ /* bubbles = WhatsApp green out / dark in; composer + search pills */
315
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message--outgoing .cs-message__content { background:var(--wa-out) !important; color:var(--wa-ink) !important; }
316
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message--incoming .cs-message__content { background:var(--wa-in) !important; color:var(--wa-ink) !important; }
317
+ /* ── WHATSAPP TEXT INPUTS β€” one rounded, immersive pill everywhere (composer, search, chat editor, onboarding).
318
+ WhatsApp's soft ~21px capsule on every field; a subtle lift on focus (deeper fill + a thin accent ring) so the
319
+ field feels alive without a hard border. Single radius token keeps them visually identical. */
320
+ html[data-skin="whatsapp"] .holo-wa-root .holo-c-input {
321
+ background:#2a3942 !important; color:var(--wa-ink) !important; border:0 !important;
322
+ border-radius:21px !important; padding:11px 18px !important; min-height:42px !important; font-size:15px !important;
323
+ transition:background-color .16s ease, box-shadow .16s ease !important; }
324
+ html[data-skin="whatsapp"] .holo-wa-root .holo-c-input:focus {
325
+ background:#33434d !important; box-shadow:0 0 0 1px rgba(0,168,132,.55) !important; }
326
+ html[data-skin="whatsapp"] .holo-wa-root .cs-search {
327
+ background:#202c33 !important; color:var(--wa-ink) !important; border:0 !important; border-radius:21px !important; }
328
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message-input__content-editor-wrapper,
329
+ html[data-skin="whatsapp"] .holo-wa-root .cs-message-input__content-editor { border-radius:21px !important; }
330
+ html[data-skin="whatsapp"] .holo-wa-root .holo-onboard-input { border-radius:21px !important; }
331
+ html[data-skin="whatsapp"] .holo-wa-root .cs-conversation.cs-conversation--active,
332
+ html[data-skin="whatsapp"] .holo-wa-root .cs-conversation:hover { background:#202c33 !important; }
333
+
334
+ /* ── THE FLOATING WINDOW (desktop β‰₯900px) β€” inset the whole content pane (.holo-main) so the wallpaper desktop
335
+ frames it. Everything inside (sidebar, chat, composer) rides the inset automatically β€” the composer stays
336
+ pixel-aligned with zero re-math. The window shrinks from the right when a drawer opens (--holo-aside-w). ── */
337
+ /* REFINED (user: smooth, no glitches): .holo-main is only the composer's ANCHOR box β€” the VISIBLE rounded island is
338
+ the base theme's `.cs-main-container` (position:fixed, inset --holo-env-gap, radius --holo-env-radius, shadow
339
+ --holo-env-shadow). The old 18px/14px inset here did NOT match that island, so the composer (a child of .holo-main)
340
+ landed ~8px inside the island's rounded bottom-right corner. Track the env-island EXACTLY (same gap + radius) and
341
+ drop .holo-main's own bg/shadow (the island already draws the frame) β†’ the composer sits flush, one clean window,
342
+ zero double-frame. Still shrinks from the right on drawer open, matching the island's own right:calc(...). */
343
+ @media (min-width:900px) {
344
+ html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) {
345
+ margin:var(--holo-env-gap, 10px) !important;
346
+ margin-right:calc(var(--holo-env-gap, 10px) + var(--holo-aside-w, 0px)) !important;
347
+ height:auto !important; align-self:stretch;
348
+ border-radius:var(--holo-env-radius, 10px) !important; overflow:hidden;
349
+ background:transparent !important; box-shadow:none !important; }
350
+ }
351
+
352
+ /* ── CANVAS WINDOW (canvas-window-crisp-v1) β€” the messenger renders as ONE clean floating canvas, just like Home.
353
+ Home's island reads clearly only because a bright wallpaper sits behind its 11% env-ring; the messenger is
354
+ dark-on-dark chrome, so that same ring nearly vanishes and the window looked edge-to-edge. Define it with a
355
+ CRISP brighter edge + a soft cast shadow so the whole surface floats as a distinct rounded window on the
356
+ chrome β€” same 10px env inset + radius as Home (composer stays pixel-aligned), just a readable edge. The
357
+ visible island is the base theme's `.cs-main-container` (fixed, inset env-gap); it escapes .holo-main's
358
+ overflow so its cast shadow shows. Desktop β‰₯900px only; Home's own island is untouched. Behind it the
359
+ chrome gutter is left flat and empty (no wallpaper backdrop, no second frame) β€” one window, clean. ── */
360
+ @media (min-width:900px) {
361
+ html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .cs-main-container {
362
+ box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 18px 46px -14px rgba(0,0,0,.66) !important; }
363
+ /* the rail sits in the chrome gutter; keep that gutter pure chrome so nothing peeks behind the window */
364
+ html[data-skin="whatsapp"] .holo-wa-root { background: var(--holo-chrome, #1f1f1e) !important; }
365
+ }
366
+
367
+ /* ── WHATSAPP-CLEAN SIDEBAR (whatsapp-clean-netstrip-v1) β€” the network strip (Telegram/WhatsApp/Gmail/LinkedIn
368
+ platform icons above the filter chips) is NOT connected on the web deploy β€” tapping only opens an
369
+ explainer sheet β€” so it reads as unwired chrome, and WhatsApp has no such row. Hide it for the WhatsApp
370
+ skin so the list is clean and familiar: search β†’ chips β†’ conversations, nothing decorative between. The
371
+ "All" filter it also held lives in the chips row, so nothing functional is lost. (Reappears the moment a
372
+ real network is bridged is a later, JS-gated refinement; this is the clean default look the operator asked
373
+ for β€” "only show wired elements".) ── */
374
+ html[data-skin="whatsapp"] .holo-netstrip { display: none !important; }
375
+
376
+ /* ── LIVING WALLPAPER IN THE MESSENGER (whatsapp-living-wallpaper-v1) β€” the chat wears the operator's OWN home
377
+ wallpaper. It is the SAME dynamic wallpaper plane as Home (--wp-img on .holo-backdrop), so it changes the
378
+ instant they change their home wallpaper, and it MORPHS continuously Home⇄chat via the pre-wired shared
379
+ view-transition-name:holo-wall (island ↔ window on the GPU compositor). The WhatsApp skin otherwise
380
+ suppresses this for the doodle; here we un-hide it for the chat pane ONLY when a wallpaper is present
381
+ (.wall-on), and lay a STRONG, near-uniform dark scrim over it so the photo stays SUBTLE and the bubbles
382
+ never fight it β€” sharp, immersive, familiar. The sidebar/header/composer stay solid WhatsApp (untouched
383
+ above). Appended last = wins the source-order tie over the skin's hide rules. No wallpaper β‡’ .wall-on is
384
+ absent β‡’ the flat look above still holds. ── */
385
+ /* The page-level .holo-backdrop canvas + .holo-wall-scrim stay HIDDEN (base skin rules 282-285) β€” un-hiding them
386
+ painted the photo in the chrome gutter BEHIND the opaque card ("loads in the background"), never in the chat.
387
+ Instead paint the wallpaper DIRECTLY on the chat pane (.cs-chat-container) β€” the photo lives INSIDE the chat box,
388
+ with the dark scrim layered in the SAME background over it (image is the lower layer). The message list scrolls
389
+ transparent over it, so the photo holds still while messages move β€” exactly WhatsApp. --wp-img cascades from
390
+ .holo-wa-root (main.jsx sets it from the operator's home wallpaper) β†’ changes live when they change Home. */
391
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-chat-container {
392
+ background-color:#0b141a !important;
393
+ background-image:
394
+ linear-gradient(180deg, rgba(11,20,26,.80) 0%, rgba(11,20,26,.74) 32%, rgba(11,20,26,.78) 68%, rgba(11,20,26,.86) 100%),
395
+ var(--wp-img) !important;
396
+ background-repeat:no-repeat, no-repeat !important;
397
+ background-size:cover, cover !important;
398
+ background-position:center center, center center !important; }
399
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list {
400
+ background:transparent !important; background-color:transparent !important; background-image:none !important; }
401
+
402
+ /* ── COHERENT RUNTIME-SWITCH TRANSITION (whatsapp-runtime-switch-v1) β€” every switch between holospaces (and Home⇄chat)
403
+ is now ONE clean, low-latency crossfade, not several animations fighting. The old build layered THREE systems on
404
+ each switch: (1) the View-Transition root crossfade; (2) a ONE-SIDED `holo-wall` wallpaper morph β€” the Home wall
405
+ carried view-transition-name:holo-wall but the destination holospace has no matching element (its backdrop is
406
+ hidden), so the wallpaper visibly slid/scaled to nothing ("the background wallpaper feels strange"); (3) a matching
407
+ one-sided `holo-q-orb` morph AND the space layer's OWN opacity fade doubling the root crossfade. Collapse to ONE
408
+ animation: the wall + orb stop morphing (they ride the single root crossfade) and the space layer stops
409
+ self-animating (keep only its drawer-resize `right` glide). Result: identical crisp ~.2s crossfade for ALL apps
410
+ β€” smooth, robust, coherent. Reduced-motion users still get the instant, no-animation path (unchanged). */
411
+ html[data-skin="whatsapp"] .holo-home-wall,
412
+ html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-backdrop,
413
+ html[data-skin="whatsapp"] .holo-home-orb,
414
+ html[data-skin="whatsapp"] .holo-global-orb { view-transition-name:none !important; }
415
+ html[data-skin="whatsapp"]::view-transition-old(root),
416
+ html[data-skin="whatsapp"]::view-transition-new(root) {
417
+ animation-duration:.2s !important; animation-timing-function:var(--holo-env-ease, cubic-bezier(.4,0,.2,1)) !important; }
418
+ html[data-skin="whatsapp"] .holo-space-layer {
419
+ transition:right .26s var(--holo-ease, cubic-bezier(.4,0,.2,1)) !important; }
420
+
421
+ /* ── RESIZABLE SIDEBAR (whatsapp-resize-v1) β€” the divider between the chat list and the conversation is now a
422
+ draggable handle, WhatsApp-desktop style. Width lives in one var (--holo-side-w) so the sidebar AND the handle
423
+ track it together; the enhancer in messenger-skin.mjs sets it on drag and persists to localStorage (returning
424
+ users reopen at their width). Default 34% when unset. Desktop only; hidden on mobile / home / a live holospace /
425
+ collapsed / expanded so it never floats over the wrong surface. */
426
+ @media (min-width:900px) {
427
+ html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .cs-sidebar.cs-sidebar--left {
428
+ flex:0 0 var(--holo-side-w, 34%) !important;
429
+ min-width:var(--holo-side-w, 34%) !important;
430
+ max-width:var(--holo-side-w, 34%) !important; }
431
+ html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .cs-main-container > .holo-side-resize {
432
+ position:absolute; top:0; bottom:0; left:var(--holo-side-w, 34%); width:9px; margin-left:-5px;
433
+ z-index:46; cursor:col-resize; touch-action:none; }
434
+ html[data-skin="whatsapp"] .holo-side-resize::after {
435
+ content:""; position:absolute; top:0; bottom:0; left:50%; width:1px; transform:translateX(-.5px);
436
+ background:transparent; transition:background .15s ease, box-shadow .15s ease; }
437
+ html[data-skin="whatsapp"] .holo-side-resize:hover::after,
438
+ html[data-skin="whatsapp"] .holo-side-resize.holo-drag::after {
439
+ background:var(--holo-accent, #00a884); box-shadow:0 0 0 1px var(--holo-accent, #00a884); }
440
+ }
441
+ html[data-skin="whatsapp"] .holo-wa-root.home-open .holo-side-resize,
442
+ html[data-skin="whatsapp"] .holo-wa-root.space-active .holo-side-resize,
443
+ html[data-skin="whatsapp"] .holo-main.frame-collapsed .holo-side-resize,
444
+ html[data-holo-expanded] .holo-side-resize { display:none !important; }
445
+ @media (max-width:899px) { html[data-skin="whatsapp"] .holo-side-resize { display:none !important; } }
446
+ /* while dragging: kill the sidebar's width easing (so the panel tracks the pointer 1:1, zero lag) and stop the chat
447
+ iframe from swallowing pointermove; the whole document shows the col-resize cursor. */
448
+ body.holo-side-dragging { cursor:col-resize !important; user-select:none !important; }
449
+ body.holo-side-dragging .cs-sidebar { transition:none !important; }
450
+ body.holo-side-dragging iframe { pointer-events:none !important; }
451
+
452
+ /* ── COMPOSER TRACKS THE DIVIDER (whatsapp-resize-v1) β€” the bottom entry bar and every chat-area overlay
453
+ (composer, its context + suggested-reply rows, the in-chat find bar, and the attach / emoji / sticker
454
+ popovers) are position:absolute children of the full-width .holo-main, pinned to the OLD fixed 34% list
455
+ edge. When the divider dragged the sidebar to --holo-side-w they stayed stranded at 34%, so the whole
456
+ bottom text field detached from the conversation column β€” the broken UX. Re-point their left to the SAME
457
+ var the sidebar uses, under the SAME guard as the sidebar-resize rule (desktop β‰₯900px, whatsapp skin, not
458
+ theater / collapsed / fullscreen-expanded) so the composer and popovers stay flush with the resized column.
459
+ Unset β†’ 34% (identical to before); set β†’ the dragged px width. No drag = zero change. */
460
+ @media (min-width:900px) {
461
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-composer,
462
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-compose-ctx,
463
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-suggest,
464
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-find {
465
+ left:var(--holo-side-w, 34%) !important; }
466
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-emoji-pop,
467
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-attach-menu,
468
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-sticker-pop {
469
+ left:calc(var(--holo-side-w, 34%) + 8px) !important; }
470
+ html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-emoji-btn {
471
+ left:calc(var(--holo-side-w, 34%) + 12px) !important; }
472
+ }
473
+
474
+ /* ══ AIM SKIN β€” data-skin="aim" (A0). The original 1999 instant-messenger feeling, reborn: warm platinum
475
+ * chrome, raised-bevel edges, sharp small type (Tahoma), the yellow accent, a classic blue title bar on the
476
+ * open conversation. Opt-in only (?skin=aim or localStorage holo.skin=aim); every other skin is untouched.
477
+ * NO AOL property β€” homage through shape, rhythm and sound character, all marks and sounds are ours.
478
+ * The experience layer (buddy list / sign-on / away / door sounds) is holo-aim.mjs; these are its clothes.
479
+ * Placed at end-of-file so source order beats the base skin block (equal specificity β†’ later wins). ══ */
480
+ html[data-skin="aim"] .holo-wa-root {
481
+ --wa-bg:#d6d2c8; --wa-side:#ffffff; --wa-head:#ece9d8; --wa-in:#ffffff; --wa-out:#fff3b8;
482
+ --wa-ink:#141414; --wa-dim:#5a5950; --wa-accent:#e8b800; --wa-line:#aca899;
483
+ font-family: Tahoma, Verdana, "Segoe UI", system-ui, sans-serif;
484
+ }
485
+ /* light-skin honesty: deep-hardcoded dark-theme text must flip dark-on-light (the "light" skin precedent) */
486
+ html[data-skin="aim"] .holo-wa-root .cs-message__content { color:#141414 !important; }
487
+ html[data-skin="aim"] .holo-wa-root .cs-message-list { background:var(--wa-bg) !important; background-image:none !important; }
488
+ html[data-skin="aim"] .holo-wa-root .holo-wp-tile { background-image:none !important; }
489
+ html[data-skin="aim"] .holo-wa-root .holo-backdrop, html[data-skin="aim"] .holo-wa-root .holo-wall-scrim { display:none !important; }
490
+ /* the classic window: bevel edges, sharp corners, small crisp type */
491
+ html[data-skin="aim"] .holo-wa-root .cs-sidebar.cs-sidebar--left { border-right:1px solid var(--wa-line) !important; }
492
+ html[data-skin="aim"] .holo-wa-root .cs-conversation__name { font-size:12.5px !important; }
493
+ html[data-skin="aim"] .holo-wa-root .cs-message__content { border-radius:4px !important; border:1px solid #c9c5b8; font-size:13px; }
494
+ html[data-skin="aim"] .holo-wa-root .holo-c-input,
495
+ html[data-skin="aim"] .holo-wa-root .cs-search,
496
+ html[data-skin="aim"] .holo-wa-root .cs-message-input__content-editor-wrapper,
497
+ html[data-skin="aim"] .holo-wa-root .cs-message-input__content-editor { border-radius:3px !important; background:#ffffff !important; color:#141414 !important; border:1px solid #7f9db9 !important; }
498
+ /* the conversation header = the classic blue title bar, white text */
499
+ html[data-skin="aim"] .holo-wa-root .cs-conversation-header { background:linear-gradient(180deg,#0a246a,#3a6ea5) !important; border-bottom:1px solid #002050 !important; }
500
+ html[data-skin="aim"] .holo-wa-root .cs-conversation-header__user-name,
501
+ html[data-skin="aim"] .holo-wa-root .cs-conversation-header__info { color:#ffffff !important; }
502
+ html[data-skin="aim"] .holo-wa-root .holo-c-send,
503
+ html[data-skin="aim"] .holo-wa-root .cs-button--send { background:var(--wa-accent) !important; color:#141414 !important; border-radius:3px !important; }
504
+ /* the Buddy List replaces the Direct section β€” ONE surface (holo-aim.mjs renders it) */
505
+ html[data-skin="aim"] .holo-wa-root .holo-direct-section { display:none !important; }
506
+ /* ── the Buddy List ── */
507
+ html[data-skin="aim"] .holo-aim-buddylist { display:flex; flex-direction:column; background:#ffffff; border:1px solid var(--wa-line); border-radius:3px; margin:6px 8px; font:12px Tahoma, Verdana, sans-serif; color:#141414; overflow:hidden; }
508
+ html[data-skin="aim"] .holo-aim-head { display:flex; align-items:center; gap:6px; padding:6px 8px; background:linear-gradient(180deg,#fff3b8,#f7c923); border-bottom:1px solid #cfa900; font-weight:700; }
509
+ html[data-skin="aim"] .holo-aim-mark { font-size:13px; }
510
+ html[data-skin="aim"] .holo-aim-me { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
511
+ html[data-skin="aim"] .holo-aim-mystate { font-weight:400; color:#5a5950; font-size:11px; }
512
+ html[data-skin="aim"] .holo-aim-mystate.online { color:#0a7d20; }
513
+ html[data-skin="aim"] .holo-aim-mystate.away { color:#a05a00; }
514
+ html[data-skin="aim"] .holo-aim-away-btn, html[data-skin="aim"] .holo-aim-return { font:11px Tahoma, sans-serif; background:#ece9d8; border:1px solid #aca899; border-radius:3px; padding:2px 8px; cursor:pointer; }
515
+ html[data-skin="aim"] .holo-aim-awaybar { padding:4px 10px; background:#fffbe0; border-bottom:1px solid #e8dfa0; color:#7a6a00; font-style:italic; font-size:11.5px; }
516
+ html[data-skin="aim"] .holo-aim-group { padding:4px 8px; background:#ece9d8; border-top:1px solid #d9d5c8; font-weight:700; font-size:11.5px; cursor:pointer; user-select:none; }
517
+ html[data-skin="aim"] .holo-aim-tri { color:#5a5950; }
518
+ html[data-skin="aim"] .holo-aim-buddy { display:flex; align-items:center; gap:6px; width:100%; text-align:left; background:transparent; border:0; padding:3px 10px 3px 16px; cursor:pointer; font:12px Tahoma, sans-serif; color:#141414; }
519
+ html[data-skin="aim"] .holo-aim-buddy:hover { background:#316ac5; color:#ffffff; }
520
+ html[data-skin="aim"] .holo-aim-buddy:hover .holo-aim-info { color:#ffffff; }
521
+ html[data-skin="aim"] .holo-aim-buddy.online .holo-aim-bname { font-weight:700; }
522
+ html[data-skin="aim"] .holo-aim-buddy.idle .holo-aim-bname { color:#7a7a72; }
523
+ html[data-skin="aim"] .holo-aim-buddy.idle:hover .holo-aim-bname { color:#e6e6e6; }
524
+ html[data-skin="aim"] .holo-aim-bname { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
525
+ html[data-skin="aim"] .holo-aim-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; background:#b8b4a6; }
526
+ html[data-skin="aim"] .holo-aim-dot.online { background:#22a834; box-shadow:0 0 2px #22a834; }
527
+ html[data-skin="aim"] .holo-aim-dot.idle { background:#e8b800; }
528
+ html[data-skin="aim"] .holo-aim-dot.away { background:#e07800; }
529
+ html[data-skin="aim"] .holo-aim-note { color:#a05a00; flex:0 0 auto; }
530
+ html[data-skin="aim"] .holo-aim-info { color:#8a887c; flex:0 0 auto; font-size:11px; cursor:pointer; }
531
+ /* ── sign-on + sheets + toast (spawned only under the aim skin) ── */
532
+ .holo-aim-signon, .holo-aim-awaysheet { position:fixed; inset:0; z-index:2147483400; background:rgba(30,28,20,.45); display:flex; align-items:center; justify-content:center; font:13px Tahoma, Verdana, sans-serif; }
533
+ .holo-aim-signon-card, .holo-aim-away-card { width:min(300px,92vw); background:#ece9d8; border:1px solid #716f64; border-radius:4px; box-shadow:0 10px 34px rgba(0,0,0,.4), inset 0 1px 0 #fff; padding:14px; display:flex; flex-direction:column; gap:8px; color:#141414; }
534
+ .holo-aim-signon-mark { font-weight:700; font-size:15px; padding-bottom:4px; border-bottom:1px solid #cfcbba; }
535
+ .holo-aim-signon-card label, .holo-aim-info-grouplab { font-size:11px; color:#5a5950; }
536
+ .holo-aim-sn, .holo-aim-away-msg, .holo-aim-info-group { font:13px Tahoma, sans-serif; background:#fff; border:1px solid #7f9db9; border-radius:2px; padding:5px 7px; color:#141414; }
537
+ .holo-aim-away-msg { height:56px; resize:none; }
538
+ .holo-aim-go, .holo-aim-away-go { background:linear-gradient(180deg,#fff3b8,#f7c923); border:1px solid #cfa900; border-radius:3px; padding:6px; font:700 13px Tahoma, sans-serif; cursor:pointer; }
539
+ .holo-aim-skip, .holo-aim-away-x { background:transparent; border:0; color:#5a5950; cursor:pointer; font:11px Tahoma, sans-serif; }
540
+ .holo-aim-away-title { font-weight:700; }
541
+ .holo-aim-away-presets { display:flex; flex-wrap:wrap; gap:4px; }
542
+ .holo-aim-away-presets button { font:11px Tahoma, sans-serif; background:#fff; border:1px solid #aca899; border-radius:3px; padding:2px 6px; cursor:pointer; }
543
+ .holo-aim-away-row { display:flex; gap:8px; align-items:center; justify-content:flex-end; }
544
+ .holo-aim-info-name { font-weight:700; display:flex; align-items:center; gap:6px; }
545
+ .holo-aim-info-name .holo-aim-dot { width:8px; height:8px; border-radius:50%; background:#b8b4a6; display:inline-block; }
546
+ .holo-aim-info-name .holo-aim-dot.online { background:#22a834; } .holo-aim-info-name .holo-aim-dot.idle { background:#e8b800; } .holo-aim-info-name .holo-aim-dot.away { background:#e07800; }
547
+ .holo-aim-info-state { font-weight:400; font-size:11px; color:#5a5950; }
548
+ .holo-aim-info-away { font-style:italic; color:#7a6a00; background:#fffbe0; border:1px solid #e8dfa0; border-radius:3px; padding:4px 7px; }
549
+ .holo-aim-info-verify { font-size:11.5px; color:#3a3a34; }
550
+ .holo-aim-info-profile { background:linear-gradient(180deg,#dce9f7,#a6caf0); border:1px solid #3a6ea5; border-radius:3px; padding:5px 9px; font:700 12px Tahoma, sans-serif; cursor:pointer; }
551
+ .holo-aim-toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%); z-index:2147483300; background:#ece9d8; border:1px solid #716f64; border-radius:4px; box-shadow:0 8px 24px rgba(0,0,0,.35); padding:7px 14px; font:12px Tahoma, Verdana, sans-serif; color:#141414; }
sha256/eb343aaebd5beec6186750769cdd48ddde4440b78f92d46c2cb851e893237944 ADDED
@@ -0,0 +1 @@
 
 
1
+ "use client";import{$,$a,A,Aa,Ab,B,Ba,Bb,C,Ca,Cb,D,Da,Db,E,Ea,Eb,F,Fa,Fb,G,Ga,Gb,H,Ha,Hb,I,Ia,Ib,J,Ja,Jb,K,Ka,Kb,L,La,Lb,M,Ma,Mb,N,Na,Nb,O,Oa,Ob,P,Pa,Pb,Q,Qa,Qb,R,Ra,Rb,S,Sa,Sb,T,Ta,Tb,U,Ua,Ub,V,Va,W,Wa,X,Xa,Y,Ya,Z,Za,_,_a,a,aa,ab,b,ba,bb,c,ca,cb,d,da,db,e,ea,eb,f,fa,fb,g,ga,gb,h,ha,hb,i,ia,ib,j,ja,jb,k,ka,kb,l,la,lb,m,ma,mb,n,na,nb,o,oa,ob,p,pa,pb,q,qa,qb,r,ra,rb,s,sa,sb,t,ta,tb,u,ua,ub,v,va,vb,w,wa,wb,x,xa,xb,y,ya,yb,z,za,zb}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import"./chunk-EJ2FITLI.js";import"./chunk-SQE76S5B.js";export{Fa as A11yContext,Ha as A11yContextProvider,K as ACTION_CLOSE,I as ACTION_NEXT,H as ACTION_PREV,J as ACTION_SWIPE,z as ACTIVE_SLIDE_COMPLETE,y as ACTIVE_SLIDE_ERROR,w as ACTIVE_SLIDE_LOADING,x as ACTIVE_SLIDE_PLAYING,B as CLASS_FLEX_CENTER,A as CLASS_FULLSIZE,C as CLASS_NO_SCROLL,D as CLASS_NO_SCROLL_PADDING,E as CLASS_SLIDE,F as CLASS_SLIDE_WRAPPER,G as CLASS_SLIDE_WRAPPER_INTERACTIVE,Fb as Carousel,Gb as CarouselModule,db as CloseIcon,Db as Controller,Bb as ControllerContext,Eb as ControllerModule,Ia as DocumentContext,Ka as DocumentContextProvider,W as ELEMENT_BUTTON,X as ELEMENT_ICON,Q as EVENT_ON_KEY_DOWN,R as EVENT_ON_KEY_UP,P as EVENT_ON_POINTER_CANCEL,L as EVENT_ON_POINTER_DOWN,O as EVENT_ON_POINTER_LEAVE,M as EVENT_ON_POINTER_MOVE,N as EVENT_ON_POINTER_UP,S as EVENT_ON_WHEEL,hb as ErrorIcon,La as EventsContext,Na as EventsProvider,Y as IMAGE_FIT_CONTAIN,Z as IMAGE_FIT_COVER,ab as IconButton,ub as ImageSlide,Ub as Lightbox,Ba as LightboxDefaultProps,Ta as LightboxDispatchContext,Oa as LightboxPropsContext,Qa as LightboxPropsProvider,vb as LightboxRoot,Ra as LightboxStateContext,Va as LightboxStateProvider,gb as LoadingIcon,a as MODULE_CAROUSEL,b as MODULE_CONTROLLER,c as MODULE_NAVIGATION,d as MODULE_NO_SCROLL,e as MODULE_PORTAL,f as MODULE_ROOT,g as MODULE_TOOLBAR,Kb as Navigation,Jb as NavigationButton,Lb as NavigationModule,fb as NextIcon,Mb as NoScroll,Nb as NoScrollModule,h as PLUGIN_CAPTIONS,i as PLUGIN_COUNTER,j as PLUGIN_DOWNLOAD,k as PLUGIN_FULLSCREEN,l as PLUGIN_INLINE,m as PLUGIN_SHARE,n as PLUGIN_SLIDESHOW,o as PLUGIN_THUMBNAILS,p as PLUGIN_ZOOM,Ob as Portal,Pb as PortalModule,eb as PreviousIcon,Wa as RTLContext,Ya as RTLContextProvider,Qb as Root,Rb as RootModule,t as SLIDE_STATUS_COMPLETE,s as SLIDE_STATUS_ERROR,q as SLIDE_STATUS_LOADING,u as SLIDE_STATUS_PLACEHOLDER,r as SLIDE_STATUS_PLAYING,wb as SwipeState,Za as TimeoutsContext,$a as TimeoutsProvider,Sb as Toolbar,Tb as ToolbarModule,_ as UNKNOWN_ACTION_TYPE,U as VK_ARROW_LEFT,V as VK_ARROW_RIGHT,T as VK_ESCAPE,v as activeSlideStatus,wa as addToolbarButton,ya as calculatePreload,ha as cleanup,$ as clsx,ca as composePrefix,pa as computeSlideRect,bb as createIcon,cb as createIconDisabled,Ca as createModule,Da as createNode,aa as cssClass,ba as cssVar,Ub as default,qa as devicePixelRatio,ta as getSlide,ua as getSlideIfPresent,ra as getSlideIndex,va as getSlideKey,sa as hasSlides,ja as hasWindow,ma as isImageFitCover,la as isImageSlide,fa as label,da as makeComposePrefix,za as makeInertWhen,ia as makeUseContext,na as parseInt,oa as parseLengthPercentage,Aa as reflow,ka as round,ob as setRef,xa as stopNavigationEventsPropagation,ea as translateLabel,ga as translateSlideCounter,Ga as useA11yContext,kb as useAnimation,lb as useContainerRect,Cb as useController,mb as useDelay,Ja as useDocumentContext,nb as useEventCallback,Ma as useEvents,pb as useForkRef,Ib as useKeyboardNavigation,ib as useLayoutEffect,Ua as useLightboxDispatch,Pa as useLightboxProps,Sa as useLightboxState,qb as useLoseFocus,jb as useMotionPreference,Hb as useNavigationState,xb as usePointerEvents,yb as usePointerSwipe,zb as usePreventWheelDefaults,rb as useRTL,Xa as useRTLContext,sb as useSensors,tb as useThrottle,_a as useTimeouts,Ab as useWheelSwipe,Ea as withPlugins};