@rr0/ufoathome 0.152.0 → 0.152.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -331,8 +331,8 @@ ${e} :is(select:not([multiple]):not([size]), .rr0-select) {
331
331
  <button id="copy" class="share-copy" type="button">Copy</button>
332
332
  </div>
333
333
  </dialog>
334
- `;class Zc extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(Zc.TAG)||customElements.define(Zc.TAG,Zc)}subject;messages=gg;languageToken=0;shadow;dialog;linkField;copyButton;linkBox;embedBox;linkOption;embedOption;freeze;embedMarkup;noteElement;codeEditor;codeLoading;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.shadow.innerHTML=BE;const e=t=>this.shadow.getElementById(t);this.dialog=e("dialog"),this.linkField=e("link"),this.copyButton=e("copy"),this.linkBox=e("link-box"),this.embedBox=e("embed-box"),this.linkOption=e("link-option"),this.embedOption=e("embed-option"),this.freeze=e("freeze"),this.embedMarkup=e("embed-markup"),this.noteElement=e("note"),e("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",t=>{t.target===this.dialog&&this.close()}),this.linkOption.addEventListener("click",()=>this.show("link")),this.embedOption.addEventListener("click",()=>this.show("embed")),this.freeze.addEventListener("change",()=>this.refresh()),this.copyButton.addEventListener("click",()=>void(this.embedBox.hidden?this.copy(this.linkField.value,this.linkField):this.copy(this.codeEditor?.text??this.embedMarkup.value,this.embedMarkup))),this.applyMessages()}async useLanguage(e){const t=++this.languageToken,i=e==="en"?gg:await DE(e);if(t===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(e){this.noteElement.textContent=e??"",this.noteElement.hidden=e===void 0}get isOpen(){return this.dialog.open||this.dialog.hasAttribute("open")}open(){this.refresh(),this.show("link"),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open",""),this.fitLink(),this.linkField.select()}close(){typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}refresh(){const e=this.subject;if(!e)return;const t=this.freeze.checked;this.linkField.value=t?na.frozenLink(e.link(),"0.152.0"):e.link(),this.fitLink();const s=`<script type="module" src="${t?na.frozen(e.module,"0.152.0"):na.current(e.module,import.meta.url,uh.home())}"><\/script>
335
- ${e.element()}`;this.embedMarkup.value=s,this.codeEditor&&(this.codeEditor.text=s)}applyMessages(){const e=this.messages,t=(i,s)=>{this.shadow.getElementById(i).textContent=s};t("title",e.share),t("link-label",e.link),t("embed-label",e.embed),t("copy",e.copy),t("freeze-label",e.freeze.replace("{version}","0.152.0")),this.freeze.parentElement.title=e.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",e.close),this.linkField.setAttribute("aria-label",e.link)}show(e){this.linkBox.hidden=e!=="link",this.embedBox.hidden=e!=="embed",this.linkOption.setAttribute("aria-pressed",String(e==="link")),this.embedOption.setAttribute("aria-pressed",String(e==="embed")),e==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=ae(async()=>{const{ShareCodeEditor:e}=await import("./ShareCodeEditor-CF7IVeXv.js");return{ShareCodeEditor:e}},__vite__mapDeps([0,1]),import.meta.url).then(({ShareCodeEditor:e})=>{this.codeEditor=new e(this.shadow.getElementById("embed-code"),this.embedMarkup.value,t=>{this.embedMarkup.value=t},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(e,t){try{await navigator.clipboard.writeText(e),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{t.select()}}}class Tn{constructor(e){this.preferences=e}read(e){if(e===void 0||typeof e=="string")return e===""?void 0:e;for(const i of this.preferences){const s=e[i]??e[Tn.base(i)];if(s)return s}const t=new Set(this.preferences.map(i=>Tn.base(i)));for(const[i,s]of Object.entries(e))if(s&&t.has(Tn.base(i)))return s;return Object.values(e).find(i=>i)??void 0}write(e,t,i){const s=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return s;const n={...e},r=Object.keys(n).find(a=>a===i)??Object.keys(n).find(a=>Tn.base(a)===Tn.base(i))??i;return s===void 0?delete n[r]:n[r]=s,Object.keys(n).length===0?void 0:n}static base(e){return e.toLowerCase().split("-")[0]}}function Pd(l,e){for(const t of l){const i=t.toLowerCase().split("-")[0];if(e.includes(i))return i}return"en"}class sr{static preferencesFor(e){const t=navigator.languages??[],i=this.declaredFor(e);return i?[i,...t]:t}static declaredFor(e){for(let t=e;t;){const i=t.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const s=t.getRootNode();t=s instanceof ShadowRoot?s.host:void 0}}}class bn{static ISO=/^P(?:(\d+(?:[.,]\d+)?)W)?(?:(\d+(?:[.,]\d+)?)D)?(?:T(?:(\d+(?:[.,]\d+)?)H)?(?:(\d+(?:[.,]\d+)?)M)?(?:(\d+(?:[.,]\d+)?)S)?)?$/;static seconds(e){const t=e.trim().toUpperCase(),i=bn.ISO.exec(t);if(!i||t==="P"||t.endsWith("T"))return;const[,s,n,r,a,o]=i,c=d=>d===void 0?0:Number(d.replace(",",".")),h=c(s)*604800+c(n)*86400+c(r)*3600+c(a)*60+c(o);return Number.isFinite(h)?h:void 0}static parse(e){let t=e.trim();if(t==="")return;const i=t.slice(-1),s="?~%".includes(i)?i:"";s!==""&&(t=t.slice(0,-1).trim());const n=t.split("/");if(n.length>2)return;const r=n.map(d=>bn.seconds(d));if(r.some(d=>d===void 0))return;const[a,o]=r,c=Math.min(a,o??a),h=Math.max(a,o??a);return{doubt:s,minSeconds:c,maxSeconds:h,chosenSeconds:(c+h)/2}}static isExact(e){const t=bn.parse(e);return t!==void 0&&t.doubt===""&&t.minSeconds===t.maxSeconds}static format(e){const t=Math.max(0,Math.round(e*10)/10),i=Math.floor(t/3600),s=Math.floor(t%3600/60),n=Math.round(t%60*10)/10;return`PT${`${i>0?`${i}H`:""}${s>0?`${s}M`:""}${n>0||i===0&&s===0?`${n}S`:""}`}`}static say(e){const t=Math.round(e*10)/10;if(t<60)return`${t} s`;const i=Math.floor(t/3600),s=Math.floor(t%3600/60),n=Math.round(t%60*10)/10,r=[];return i>0&&r.push(`${i} h`),s>0&&r.push(`${s} min`),n>0&&r.push(`${n} s`),r.join(" ")}}class Rt{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(e){return 2*Math.atan(e.sizeM/(2*e.distanceM))*180/Math.PI}static inMoons(e){return e/Rt.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(e,t,i){if(!(!e||!t))return{widthDeg:e.widthDeg+(t.widthDeg-e.widthDeg)*i,heightDeg:e.heightDeg+(t.heightDeg-e.heightDeg)*i}}static sizeMAt(e,t){return 2*e*Math.tan(t*Math.PI/360)}static distanceMAt(e,t){return e/(2*Math.tan(t*Math.PI/360))}}function HE(l,e,t){if(!l||!e)return t<1?l:e;const i=((e.azimuthDeg-l.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((l.azimuthDeg+i*t)%360+360)%360,altitudeDeg:l.altitudeDeg+(e.altitudeDeg-l.altitudeDeg)*t}}function wx(l,e="#39ff14"){return{kind:"oval",bounds:l,color:e,angle:0,transparency:0,haloScale:0,selected:!1}}function Mx(l,e,t="#39ff14"){return{kind:"polygon",bounds:l,points:e,color:t,angle:0,transparency:0,haloScale:0,selected:!1}}function GE(l,e="#39ff14"){const{width:t,height:i}=l;return Mx(l,[{x:0,y:0},{x:t,y:0},{x:t,y:i},{x:0,y:i}],e)}const VE={oval:wx,polygon:GE};function u1(l,e){return{...VE[e.presetId](l,e.color),transparency:e.transparency,haloScale:e.haloScale,blur:e.blur,brightness:e.brightness}}function WE(l,e,t){const{bounds:i}=l;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height}function xx(l,e,t){const i=l.bounds.width,s=l.bounds.height;return{...l,bounds:{x:e-i/2,y:t-s/2,width:i,height:s}}}function Nn(l,e,t){return l+(e-l)*t}function p1(l){const e=/^#([0-9a-f]{6})$/i.exec(l);if(!e)return;const t=parseInt(e[1],16);return[t>>16&255,t>>8&255,t&255]}function $E(l){return`#${l.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function KE(l,e,t){const i=p1(l),s=p1(e);return!i||!s?t<1?l:e:$E([Nn(i[0],s[0],t),Nn(i[1],s[1],t),Nn(i[2],s[2],t)])}function XE(l,e,t){const i={x:Nn(l.bounds.x,e.bounds.x,t),y:Nn(l.bounds.y,e.bounds.y,t),width:Nn(l.bounds.width,e.bounds.width,t),height:Nn(l.bounds.height,e.bounds.height,t)},s=Nn(l.angle,e.angle,t),n=Nn(l.transparency,e.transparency,t),r=Nn(l.haloScale,e.haloScale,t),a=Nn(l.blur??0,e.blur??0,t),o=Nn(l.brightness??0,e.brightness??0,t),c=KE(l.color,e.color,t),h=Rt.lerpAngular(l.angular,e.angular,t),d=HE(l.aim,e.aim,t);return l.kind==="polygon"&&e.kind==="polygon"&&l.points.length===e.points.length?{...l,bounds:i,angle:s,transparency:n,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d,points:l.points.map((u,p)=>({x:Nn(u.x,e.points[p].x,t),y:Nn(u.y,e.points[p].y,t)}))}:{...t<1?l:e,bounds:i,angle:s,transparency:n,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d}}class Na{static DEFAULT_COLOR="#e8e6df";static complete(e,t=[]){const i=new Map;return e.map((s,n)=>({keyframe:s,index:n})).sort((s,n)=>s.keyframe.t-n.keyframe.t).map(({keyframe:s,index:n})=>({t:s.t,shapes:(s.shapes??[]).map((r,a)=>{const o=`timeline.keyframes.${n}.shapes.${a}.shape`,c=Na.completed(r,i.get(r.sourceId),o,t);return i.set(r.sourceId,c),{sourceId:r.sourceId,shape:c}})}))}static thin(e,t){const i=new Map,s=new Set;return e.map((n,r)=>({t:n.t,shapes:n.shapes.map(a=>{const o=i.get(a.sourceId);if(i.set(a.sourceId,a.shape),!o)return{sourceId:a.sourceId,shape:a.shape};const c=Na.thinned(a.shape,o);if(t){const h=c;t(r,a.sourceId)?(delete h.bounds,delete h.points,s.add(a.sourceId)):s.delete(a.sourceId)&&(h.bounds=a.shape.bounds,a.shape.kind==="polygon"&&(h.points=a.shape.points),a.shape.aim&&(h.aim=a.shape.aim),a.shape.angular&&(h.angular=a.shape.angular))}return{sourceId:a.sourceId,shape:c}})}))}static thinned(e,t){const i=t,s={};for(const[n,r]of Object.entries(e))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[n]&&JSON.stringify(r)!==JSON.stringify(i[n]))&&(s[n]=r);return"bounds"in s&&(e.aim&&(s.aim=e.aim),e.angular&&(s.angular=e.angular)),s}static completed(e,t,i,s){const n=e.shape??{},r=t??Na.firstAppearance(n,i,s),a={...r};n.bounds&&t&&(t.aim||t.angular)&&!n.aim&&!n.angular&&s.push({kind:"pixels-over-angles",path:i}),n.bounds&&(n.aim||delete a.aim,n.angular||delete a.angular);const o=n.kind??r.kind??"oval",c={...a,...n,kind:o};if(o==="polygon"&&!c.points){s.push({kind:"defaulted",path:`${i}.points`,expected:"rectangle"});const{width:h,height:d}=c.bounds;return{...c,points:[{x:0,y:0},{x:h,y:0},{x:h,y:d},{x:0,y:d}]}}return c}static firstAppearance(e,t,i){return e.kind||i.push({kind:"defaulted",path:`${t}.kind`,expected:'"oval"'}),e.color||i.push({kind:"defaulted",path:`${t}.color`,expected:`"${Na.DEFAULT_COLOR}"`}),!e.bounds&&!e.aim&&i.push({kind:"unplaced",path:t}),!e.bounds&&!e.angular&&i.push({kind:"unsized",path:t}),{kind:e.kind??"oval",bounds:{...Na.NEUTRAL_BOUNDS},color:Na.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:Rt.CANVAS_WIDTH_PX/2,y:Rt.CANVAS_HEIGHT_PX/2,width:1,height:1}}class am{keyframes=[];order=[];groups=[];span=0;addKeyframe(e,t){const i=this.findInsertIndex(e);if(this.keyframes[i]?.t===e){const s=new Set(t.map(n=>n.sourceId));this.keyframes[i]={t:e,shapes:[...this.keyframes[i].shapes.filter(n=>!s.has(n.sourceId)),...t]}}else this.keyframes.splice(i,0,{t:e,shapes:[...t]});for(const s of t)this.order.includes(s.sourceId)||this.order.push(s.sourceId)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getKeyframeAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t];return i?.t===e?i:void 0}getShapeAt(e,t){return this.getKeyframeAt(e)?.shapes.find(i=>i.sourceId===t)?.shape}getLatestShapeAt(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return s.shape}}getInterpolatedShapeAt(e,t){const i=this.findShapeAtOrBefore(e,t);if(i?.t===e)return i.shape;const s=this.findShapeAtOrAfter(e,t);return i?s?XE(i.shape,s.shape,(e-i.t)/(s.t-i.t)):i.shape:s?.shape}findShapeAtOrBefore(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return{t:this.keyframes[i].t,shape:s.shape}}}findShapeAtOrAfter(e,t){for(let i=this.findInsertIndex(e);i<this.keyframes.length;i++){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return{t:this.keyframes[i].t,shape:s.shape}}}hitTest(e,t,i,s){const n=this.sourceIds;for(let r=n.length-1;r>=0;r--){if(s?.has(n[r]))continue;const a=this.getInterpolatedShapeAt(e,n[r]);if(a&&WE(a,t,i))return{sourceId:n[r],shape:a}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const i=this.keyframes[t].shapes.filter(s=>s.sourceId!==e);i.length===0?this.keyframes.splice(t,1):i.length!==this.keyframes[t].shapes.length&&(this.keyframes[t]={t:this.keyframes[t].t,shapes:i})}this.order=this.order.filter(t=>t!==e),this.removeFromGroup(e)}removeShapeAt(e,t){const i=this.findInsertIndex(e),s=this.keyframes[i];if(s?.t!==e)return;const n=s.shapes.filter(r=>r.sourceId!==t);n.length===0?this.keyframes.splice(i,1):n.length!==s.shapes.length&&(this.keyframes[i]={t:e,shapes:n})}group(e){if(!(e.length<2)){for(const t of e)this.removeFromGroup(t);this.groups.push([...e])}}ungroup(e){const t=this.groups.findIndex(i=>i.includes(e));t!==-1&&this.groups.splice(t,1)}groupMembers(e){return this.groups.find(t=>t.includes(e))}removeFromGroup(e){const t=this.groups.findIndex(s=>s.includes(e));if(t===-1)return;const i=this.groups[t].filter(s=>s!==e);i.length<2?this.groups.splice(t,1):this.groups[t]=i}bringToFront(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.push(e))}sendToBack(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.unshift(e))}get duration(){const e=this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t;return Math.max(e,this.span)}get hasSpan(){return this.span>0}setSpan(e){this.span=Math.max(0,e)}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return this.span>0?{keyframes:this.keyframes,order:this.order,groups:this.groups,span:this.span}:{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(e,t){const i=new am;for(const s of Na.complete(e.keyframes??[],t))i.addKeyframe(s.t,s.shapes);if(e.span!==void 0&&e.span>0&&(i.span=e.span),e.order){const s=i.order.filter(n=>!e.order.includes(n));i.order=[...e.order,...s]}return e.groups&&(i.groups=e.groups.map(s=>s.filter(n=>i.order.includes(n))).filter(s=>s.length>=2)),i}}function YE(l,e,t){return Math.max(e,Math.min(t,l))}function qE(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function ec(l,e,t){return l+(e-l)*t}function jE(l,e,t){return{lat:l.lat===void 0||e.lat===void 0?void 0:ec(l.lat,e.lat,t),lng:l.lng===void 0||e.lng===void 0?void 0:ec(l.lng,e.lng,t),elevationM:ec(l.elevationM,e.elevationM,t),headingDeg:l.headingDeg===void 0||e.headingDeg===void 0?void 0:qE(l.headingDeg,e.headingDeg,t),pitchDeg:ec(l.pitchDeg,e.pitchDeg,t),rollDeg:ec(l.rollDeg??0,e.rollDeg??0,t),fovDeg:ec(l.fovDeg,e.fovDeg,t),fNumber:l.fNumber,focusDistanceM:l.focusDistanceM,filter:l.filter}}class tn{static at(e,t,i,s,n){const r=e[i],o=e[i+1]-r;if(o<=0)return t[i];const c=tn.tangent(e,t,i,n),h=tn.tangent(e,t,i+1,n),d=(s-r)/o,u=d*d,p=u*d;return(2*p-3*u+1)*t[i]+(p-2*u+d)*o*c+(-2*p+3*u)*t[i+1]+(p-u)*o*h}static SETTLE_MS=120;static ARRIVAL=.5;static gaze(e,t,i,s){const n=e[i],a=e[i+1]-n;if(a<=0)return t[i];const o=h=>h+1<t.length?t[h+1]===t[h]:!0,c=t[i+1]!==t[i];if(c&&o(i+1)){const h=tn.tangent(e,t,i,!0),d=tn.ARRIVAL*(t[i+1]-t[i])/a;return tn.hermite(t[i],h,t[i+1],d,a,(s-n)/a)}return!c&&i>0&&t[i-1]!==t[i]?t[i]+tn.settle(e,t,i,s-n,a):tn.at(e,t,i,s,!0)}static settle(e,t,i,s,n){const r=e[i]-e[i-1];if(r<=0||s<=0)return 0;const a=tn.ARRIVAL*(t[i]-t[i-1])/r,o=Math.min(tn.SETTLE_MS,.4*r),c=Number.isFinite(n)?(1-Math.min(1,s/n))**2:1;return a*s*Math.exp(-s/o)*c}static hermite(e,t,i,s,n,r){const a=r*r,o=a*r;return(2*o-3*a+1)*e+(o-2*a+r)*n*t+(-2*o+3*a)*i+(o-a)*n*s}static BRAKE_S=.8;static paced(e,t,i,s){if(!i&&!s)return e;const n=t>0?Math.min(.5,tn.BRAKE_S/t):.5;if(i&&s){const a=1/(1-n);return e<=n?a*e*e/(2*n):e>=1-n?1-a*(1-e)*(1-e)/(2*n):a*(e-n/2)}const r=a=>{const o=1/(1-n/2);if(a<=1-n)return o*a;const c=a-(1-n);return o*(1-n)+o*(c-c*c/(2*n))};return s?r(e):1-r(1-e)}static tangent(e,t,i,s){const n=e.length-1,r=p=>(t[p+1]-t[p])/(e[p+1]-e[p]||1);if(i===0)return s?0:r(0);if(i===n)return s?0:r(n-1);const a=r(i-1),o=r(i);if(a*o<=0)return 0;const c=e[i]-e[i-1],h=e[i+1]-e[i],d=2*h+c,u=h+2*c;return(d+u)/(d/a+u/o)}}class Nd{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,pose:t}:this.keyframes.splice(i,0,{t:e,pose:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getLatestPoseAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].pose:void 0}getInterpolatedPoseAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.pose;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return s?.pose;if(!s)return this.settledAfterEnd(t-1,e);const n=jE(i.pose,s.pose,YE((e-i.t)/(s.t-i.t),0,1));return this.humanly(t-1,e,n)}settledAfterEnd(e,t){const i=this.keyframes[e];if(e<1)return i.pose;const s=this.keyframes[e-1],n=[s.t,i.t],r=(h,d)=>h===void 0||d===void 0?0:tn.settle(n,[h,d],1,t-i.t,1/0),a=s.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-s.pose.headingDeg)%360+540)%360-180,o=i.pose.headingDeg===void 0||a===void 0?i.pose.headingDeg:((i.pose.headingDeg+r(0,a))%360+360)%360,c=i.pose.pitchDeg+r(s.pose.pitchDeg,i.pose.pitchDeg);return o===i.pose.headingDeg&&c===i.pose.pitchDeg?i.pose:{...i.pose,headingDeg:o,pitchDeg:c}}humanly(e,t,i){const s=Math.max(0,e-1),n=Math.min(this.keyframes.length-1,e+2),r=this.keyframes.slice(s,n+1),a=e-s,o=r.map(y=>y.t),c=(y,M)=>{const S=r.map(E=>y(E.pose));if(!S.some(E=>E===void 0))return tn.at(o,S,a,t,M)},h=y=>{const M=r.map(S=>y(S.pose));if(!M.some(S=>S===void 0))return tn.gaze(o,M,a,t)},d=r.map(y=>y.pose.headingDeg);let u;if(d.every(y=>y!==void 0)){const y=[d[0]];for(let M=1;M<d.length;M++)y.push(y[M-1]+((d[M]-d[M-1])%360+540)%360-180);u=(tn.gaze(o,y,a,t)%360+360)%360}const p=this.keyframes[e],f=this.keyframes[e+1],m=(y,M)=>y.lat===M.lat&&y.lng===M.lng&&y.elevationM===M.elevationM,g=!m(p.pose,f.pose),v=g&&e>0&&m(this.keyframes[e-1].pose,p.pose),b=g&&e+2<this.keyframes.length&&m(f.pose,this.keyframes[e+2].pose);let w;if(v||b){const y=tn.paced((t-p.t)/(f.t-p.t),(f.t-p.t)/1e3,v,b),M=(S,E)=>S===void 0||E===void 0?void 0:S+(E-S)*y;w={lat:M(p.pose.lat,f.pose.lat),lng:M(p.pose.lng,f.pose.lng),elevationM:M(p.pose.elevationM,f.pose.elevationM)}}return{...i,lat:w?w.lat:c(y=>y.lat,!1)??i.lat,lng:w?w.lng:c(y=>y.lng,!1)??i.lng,elevationM:w?w.elevationM:c(y=>y.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:h(y=>y.pitchDeg)??i.pitchDeg,rollDeg:c(y=>y.rollDeg??0,!0)??i.rollDeg,fovDeg:c(y=>y.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Nd;for(const i of e.keyframes)t.addKeyframe(i.t,i.pose);return t}}class co{static MAX_CHANGE_PER_S=.05;points;followed;constructor(e){let t="none",i=0;this.points=e.map(({t:s,weather:n})=>(n.precipitationType!=="none"&&(t=n.precipitationType,i=n.precipitationIntensity),{t:s,lastFalling:t,lastFallingIntensity:i,intensity:n.precipitationType==="none"?0:n.precipitationIntensity,type:n.precipitationType})),this.followed=[];for(let s=0;s<this.points.length;s++){if(s===0){this.followed.push(this.points[0].intensity);continue}const n=this.points[s-1],r=this.points[s];this.followed.push(co.follow(this.followed[s-1],n.intensity,r.intensity,(r.t-n.t)/1e3,(r.t-n.t)/1e3))}}at(e){if(this.points.length===0||e<this.points[0].t)return;let t=this.points.length-1;for(;t>0&&this.points[t].t>e;)t--;const i=this.points[t],s=this.points[t+1],n=s?co.follow(this.followed[t],i.intensity,s.intensity,(s.t-i.t)/1e3,(e-i.t)/1e3):co.follow(this.followed[t],i.intensity,i.intensity,1,(e-i.t)/1e3);return{type:co.typeBetween(i,s,e,n),intensity:n,character:co.characterBetween(i,s,e)}}static characterBetween(e,t,i){return e.type==="none"?t&&t.type!=="none"?t.intensity:e.lastFallingIntensity:!t||t.type==="none"?e.intensity:e.intensity+(t.intensity-e.intensity)*(i-e.t)/(t.t-e.t||1)}static typeBetween(e,t,i,s){return e.type==="none"?t&&t.type!=="none"&&i>e.t?t.type:s>0?e.lastFalling:"none":t&&t.type==="none"&&s<=0?"none":e.type}static follow(e,t,i,s,n){const r=co.MAX_CHANGE_PER_S,a=s>0?(i-t)/s:0,o=d=>t+a*Math.min(Math.max(d,0),s);let c=e,h=0;for(let d=0;d<8&&h<n;d++){const u=o(h)-c;if(Math.abs(u)<1e-9){const w=h<s?a:0;if(Math.abs(w)<=r){const M=h<s?Math.min(n,s):n;c=o(M),h=M;continue}const y=Math.min(n,s);c+=Math.sign(w)*r*(y-h),h=y;continue}const p=Math.sign(u),f=h<s?a:0,m=r-p*f,g=m>0?h+Math.abs(u)/m:1/0,v=h<s?s:1/0,b=Math.min(n,g,v);c+=p*r*(b-h),h=b,b===g&&(c=o(h))}return Math.min(1,Math.max(0,c))}}const Jv=1e3,Hp=.65,Sx=.05,om={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function Io(l){if(l.cloudLayers!==void 0)return l.cloudLayers;const e=[],t=l.lowerCloudCover??l.cloudCover;return t>0&&e.push({id:"lower",type:"cumulus",baseM:l.cloudBaseM??Jv,thicknessM:650,coverage:t,sizeM:1400,density:1,darkness:l.cloudDarkness}),(l.highCloudCover??0)>0&&e.push({id:"cirrus",type:"cirrus",baseM:8e3,thicknessM:400,coverage:l.highCloudCover,sizeM:2200,density:.35,darkness:l.cloudDarkness,iceCrystalAlignment:l.iceCrystalAlignment}),e}function Ri(l,e,t){return l+(e-l)*t}function Qv(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function ZE(l,e,t){return Math.max(e,Math.min(t,l))}function JE(l=[],e=[],t){if(!(!l.length&&!e.length))return[...new Set([...l.map(i=>i.id),...e.map(i=>i.id)])].map(i=>{const s=l.find(o=>o.id===i),n=e.find(o=>o.id===i),r=s??{...n,density:0},a=n??{...s,density:0};return{...r,eastM:Ri(r.eastM,a.eastM,t),northM:Ri(r.northM,a.northM,t),baseM:Ri(r.baseM,a.baseM,t),thicknessM:Ri(r.thicknessM,a.thicknessM,t),widthM:Ri(r.widthM,a.widthM,t),depthM:Ri(r.depthM,a.depthM,t),rotationDeg:Qv(r.rotationDeg,a.rotationDeg,t),density:Ri(r.density,a.density,t),darkness:Ri(r.darkness??0,a.darkness??0,t)}})}function QE(l,e,t){if(l.cloudLayers===void 0&&e.cloudLayers===void 0)return;const i=Io(l),s=Io(e);return t>=1?s.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...s.map(r=>r.id)])].map(r=>{const a=i.find(d=>d.id===r),o=s.find(d=>d.id===r),c=a??{...o,coverage:0},h=o??{...a,coverage:0};return{...c,instances:JE(a?.instances,o?.instances,t),baseM:Ri(c.baseM,h.baseM,t),thicknessM:Ri(c.thicknessM,h.thicknessM,t),coverage:Ri(c.coverage,h.coverage,t),sizeM:Ri(c.sizeM,h.sizeM,t),density:Ri(c.density,h.density,t),darkness:Ri(c.darkness??l.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:c.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Ri(c.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:c.windSpeed===void 0&&h.windSpeed===void 0?void 0:Ri(c.windSpeed??l.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:c.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Qv(c.windDirectionDeg??l.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function eA(l,e,t){return{cloudLayers:QE(l,e,t),cloudCover:Ri(l.cloudCover,e.cloudCover,t),cloudDarkness:Ri(l.cloudDarkness,e.cloudDarkness,t),highCloudCover:l.highCloudCover===void 0||e.highCloudCover===void 0?void 0:Ri(l.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:Ri(l.iceCrystalAlignment,e.iceCrystalAlignment,t),rareIceCrystals:l.rareIceCrystals===void 0||e.rareIceCrystals===void 0?void 0:Ri(l.rareIceCrystals,e.rareIceCrystals,t),lowerCloudCover:l.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:Ri(l.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:l.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:Ri(l.cloudBaseM,e.cloudBaseM,t),relativeHumidity:l.relativeHumidity===void 0||e.relativeHumidity===void 0?void 0:Ri(l.relativeHumidity,e.relativeHumidity,t),precipitationType:t<1?l.precipitationType:e.precipitationType,precipitationIntensity:Ri(l.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Qv(l.windDirectionDeg,e.windDirectionDeg,t),windSpeed:Ri(l.windSpeed,e.windSpeed,t),storm:t<1?l.storm:e.storm}}class Fd{keyframes=[];ramp;addKeyframe(e,t){this.ramp=void 0;const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,weather:t}:this.keyframes.splice(i,0,{t:e,weather:t})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(e){this.ramp=void 0;const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getLatestWeatherAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].weather:void 0}getInterpolatedWeatherAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.weather;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return i?s?eA(i.weather,s.weather,ZE((e-i.t)/(s.t-i.t),0,1)):i.weather:s?.weather}getActualWeatherAt(e){const t=this.getInterpolatedWeatherAt(e);if(!t)return;const i=(this.ramp??=new co(this.keyframes)).at(e);if(!i)return t;const{type:s,intensity:n,character:r}=i,a=r>0?Math.min(1,n/r):s==="none"?0:1;return{...t,precipitationType:s,precipitationIntensity:r,precipitationAmount:a}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Fd;for(const i of e.keyframes)t.addKeyframe(i.t,{...om,...i.weather});return t}}class Ud{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,sound:t}:this.keyframes.splice(i,0,{t:e,sound:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}getLatestSoundAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].sound:void 0}getInterpolatedSoundAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.sound;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return s?.sound;if(!s)return i.sound;const n=(e-i.t)/(s.t-i.t);return this.lerp(i.sound,s.sound,Math.max(0,Math.min(1,n)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Ud;for(const i of e.keyframes)t.addKeyframe(i.t,i.sound);return t}lerp(e,t,i){return{kind:i<1?e.kind:t.kind,volume:e.volume+(t.volume-e.volume)*i,pitchHz:e.pitchHz+(t.pitchHz-e.pitchHz)*i,src:i<1?e.src:t.src}}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}}const tA=["none","hum","whistle","rumble","crackle"],iA=100,sA={kind:"none",volume:0,pitchHz:iA};class Oc{static DEFAULT_FOCAL_MM=50;static FOCAL_RANGE_MM={minMm:14,maxMm:135};static BODIES=[{id:"eos-450d",name:"Canon EOS 450D (APS-C)",widthMm:22.2,heightMm:14.8,pixelUm:5.2,year:2008},{id:"eos-60da",name:"Canon EOS 60Da (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.3,year:2012},{id:"eos-70d",name:"Canon EOS 70D (APS-C)",widthMm:22.5,heightMm:15,pixelUm:4.1,year:2013},{id:"eos-80d",name:"Canon EOS 80D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:3.7,year:2016},{id:"eos-7d",name:"Canon EOS 7D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.1,year:2009},{id:"eos-7d-ii",name:"Canon EOS 7D Mark II (APS-C)",widthMm:22.4,heightMm:15,pixelUm:4.1,year:2014},{id:"eos-5d",name:"Canon EOS 5D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:8.2,year:2005},{id:"eos-5d-ii",name:"Canon EOS 5D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:6.4,year:2008},{id:"eos-5d-iii",name:"Canon EOS 5D Mark III (full frame)",widthMm:36,heightMm:24,pixelUm:6.25,year:2012},{id:"eos-5d-iv",name:"Canon EOS 5D Mark IV (full frame)",widthMm:36,heightMm:24,pixelUm:5.36,year:2016},{id:"eos-6d",name:"Canon EOS 6D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:6.55,year:2012},{id:"eos-6d-ii",name:"Canon EOS 6D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:5.77,year:2017},{id:"nikon-d3",name:"Nikon D3 / D700 (full frame)",widthMm:36,heightMm:23.9,pixelUm:8.44,year:2007},{id:"nikon-d7000",name:"Nikon D7000 (DX)",widthMm:23.6,heightMm:15.6,pixelUm:4.78,year:2010},{id:"nikon-d7100",name:"Nikon D7100 / D7200 (DX)",widthMm:23.5,heightMm:15.6,pixelUm:3.9,year:2013},{id:"nikon-d500",name:"Nikon D500 / D7500 (DX)",widthMm:23.5,heightMm:15.7,pixelUm:4.2,year:2016}];static instruments(){return Oc.BODIES.map(e=>({id:e.id,category:"dslr",name:e.name,projection:"rectilinear",frame:{widthMm:e.widthMm,heightMm:e.heightMm,focalLengthMm:Oc.DEFAULT_FOCAL_MM,focalRangeMm:Oc.FOCAL_RANGE_MM},fNumber:8,fNumberRange:{min:1.4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/8e3,max:3600},years:{from:e.year},apertureBlades:7,detailUm:e.pixelUm,medium:{kind:"sensor",iso:100}}))}static names(){return Object.fromEntries(Oc.BODIES.map(e=>[e.id,e.name]))}}class Er{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*Er.DEFAULT_EYEPIECE_MM*Math.tan(Er.DEFAULT_APPARENT_FIELD_DEG*Math.PI/360);static RANGE={min:26/40*.63,max:26/6*3};static BINOCULARS=[{id:"binoculars-zeiss-6x30",name:"Carl Zeiss 6x30",magnification:6,apertureMm:30,trueFieldDeg:5,fromYear:1960},{id:"binoculars-zeiss-dialyt-10x40",name:"Carl Zeiss Dialyt 10x40 B T*",magnification:10,apertureMm:40,trueFieldDeg:6.3,fromYear:1975},{id:"binoculars-jenoptem-10x50",name:"Jenoptem 10x50 W",magnification:10,apertureMm:50,trueFieldDeg:7.3,fromYear:1960},{id:"binoculars-swarovski-7x50-habicht",name:"Swarovski 7x50 SL Habicht",magnification:7,apertureMm:50,trueFieldDeg:6.6,fromYear:1960},{id:"binoculars-swarovski-7x50-slc",name:"Swarovski 7x50 SLC",magnification:7,apertureMm:50,trueFieldDeg:7.1,fromYear:1990},{id:"binoculars-nikon-10x42-edg",name:"Nikon 10x42 EDG",magnification:10,apertureMm:42,trueFieldDeg:6.5,fromYear:2011},{id:"binoculars-canon-15x50-is",name:"Canon 15x50 IS All Weather",magnification:15,apertureMm:50,trueFieldDeg:4.5,fromYear:2008},{id:"binoculars-celestron-15x70",name:"Celestron 15x70 SkyMaster",magnification:15,apertureMm:70,trueFieldDeg:4.4,fromYear:1990},{id:"binoculars-miyauchi-25x141",name:"Miyauchi BR-141 Galaxy 45 25x141",magnification:25,apertureMm:141,trueFieldDeg:2.6,fromYear:2e3}];static TELESCOPES=[{id:"telescope-generic-60-700",name:"Telescope 60/700",apertureMm:60,focalLengthMm:700},{id:"telescope-generic-60-1000",name:"Telescope 60/1000",apertureMm:60,focalLengthMm:1e3},{id:"telescope-celestron-onyx-80edf",name:"Celestron Onyx 80EDF",apertureMm:80,focalLengthMm:500,fromYear:2010},{id:"telescope-celestron-c5",name:"Celestron C5 f/10",apertureMm:125,focalLengthMm:1250,fromYear:1970},{id:"telescope-celestron-c8",name:"Celestron C8 f/10",apertureMm:203,focalLengthMm:2032,fromYear:1970},{id:"telescope-celestron-c11",name:"Celestron C11 f/10",apertureMm:280,focalLengthMm:2800,fromYear:1970},{id:"telescope-celestron-c14",name:"Celestron C14 f/11",apertureMm:355.6,focalLengthMm:3910,fromYear:1970},{id:"telescope-meade-etx-80",name:"Meade ETX 80 f/5",apertureMm:80,focalLengthMm:400,fromYear:1996},{id:"telescope-meade-etx-90",name:"Meade ETX 90 f/13.8",apertureMm:90,focalLengthMm:1242,fromYear:1996},{id:"telescope-meade-etx-125",name:"Meade ETX 125 f/15",apertureMm:127,focalLengthMm:1900,fromYear:1996},{id:"telescope-meade-lx200-8",name:"Meade LX200 8 in f/10",apertureMm:200,focalLengthMm:2e3,fromYear:1992},{id:"telescope-meade-lx200-10",name:"Meade LX200 10 in f/10",apertureMm:250,focalLengthMm:2500,fromYear:1992},{id:"telescope-meade-lx200-12",name:"Meade LX200 12 in f/10",apertureMm:305,focalLengthMm:3048,fromYear:1992},{id:"telescope-meade-lx200-14",name:"Meade LX200 14 in f/10",apertureMm:355,focalLengthMm:3556,fromYear:1992},{id:"telescope-meade-lx200-16",name:"Meade LX200 16 in f/10",apertureMm:406,focalLengthMm:4064,fromYear:1992}];static instruments(){const e=Er.BINOCULARS.map(s=>({id:s.id,category:"binoculars",name:s.name,projection:"rectilinear",visualAid:{apertureMm:s.apertureMm,magnification:s.magnification,trueFieldDeg:s.trueFieldDeg},...s.fromYear!==void 0?{years:{from:s.fromYear}}:{}})),t=Er.FIELD_STOP_MM,i=Er.TELESCOPES.map(s=>({id:s.id,category:"telescope",name:s.name,projection:"rectilinear",frame:{widthMm:t*16/9,heightMm:t,focalLengthMm:s.focalLengthMm,focalRangeMm:{minMm:s.focalLengthMm*Er.RANGE.min,maxMm:s.focalLengthMm*Er.RANGE.max}},visualAid:{apertureMm:s.apertureMm,eyepieceFocalMm:Er.DEFAULT_EYEPIECE_MM},...s.fromYear!==void 0?{years:{from:s.fromYear}}:{}}));return[...e,...i]}static names(){return Object.fromEntries(Er.instruments().map(e=>[e.id,e.name]))}}const rd=[{id:"eye",category:"eye",name:"Naked eye",projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",category:"camera",name:"Camera, unknown device",projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"roamer-1-120",category:"camera",name:"Roamer 1, 120 film",projection:"rectilinear",frame:{widthMm:74,heightMm:60,focalLengthMm:100},fNumber:11,exposureSeconds:1/50,years:{from:1930,to:1965},detailUm:40,medium:{kind:"negative",iso:125}},{id:"instamatic-126",category:"camera",name:"Instamatic, 126 film",projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20,medium:{kind:"negative",iso:64}},{id:"slr-35mm-50",category:"camera",name:"35 mm SLR, 50 mm lens",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20,medium:{kind:"negative",iso:100}},{id:"slr-35mm-zoom",category:"camera",name:"35 mm SLR, 70-210 mm zoom",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20,medium:{kind:"negative",iso:100}},{id:"phone-landscape",category:"phone",name:"Phone, held sideways",projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"phone-portrait",category:"phone",name:"Phone, held upright",projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"dashcam",category:"video",name:"Dashcam",projection:"equidistant",frame:{widthMm:5.76,heightMm:3.24,focalLengthMm:3.2},fNumber:2,exposureSeconds:1/30,exposureRangeSeconds:{min:1/1e4,max:1/30},years:{from:2008},apertureBlades:void 0,detailUm:3,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},{id:"cctv",category:"video",name:"Security camera",projection:"rectilinear",frame:{widthMm:4.8,heightMm:3.6,focalLengthMm:3.6},fNumber:2,exposureSeconds:1/50,exposureRangeSeconds:{min:1/1e5,max:1/50},years:{from:1990},apertureBlades:void 0,detailUm:6,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},...Oc.instruments(),...Er.instruments()];class Yt{static get default(){return rd[0]}static byId(e){return rd.find(t=>t.id===e)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(e){const t=e.frame;return t?Yt.fieldOf(e.projection,t.heightMm,t.focalLengthMm):e.visualAid?.trueFieldDeg??Yt.UNAIDED_FIELD_DEG}static fieldOf(e,t,i){return(e==="equidistant"?t/i:2*Math.atan(t/(2*i)))*180/Math.PI}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Yt.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Yt.aspectOf(e))}static CATEGORIES=["eye","camera","dslr","phone","video","binoculars","telescope"];static unavailability(e,t){const i=e.years;if(!(t===void 0||!i)){if(t<i.from)return{kind:"before",from:i.from};if(i.to!==void 0&&t>i.to)return{kind:"after",to:i.to}}}static availableAt(e){return e===void 0?rd:rd.filter(t=>!t.years||e>=t.years.from&&(t.years.to===void 0||e<=t.years.to))}static fieldOfViewDegAt(e,t){const i=e.frame;if(!(!i||t<=0))return Yt.fieldOf(e.projection,i.heightMm,t)}static focalLengthMmFor(e,t){const i=e.frame;if(!(!i||t<=0||t>=180))return e.projection==="equidistant"?i.heightMm/(t*Math.PI/180):i.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){if(e.apertureBlades===void 0)return 0;const i=t??e.fNumber,s=e.fNumberRange?.min;if(i===void 0||s===void 0)return 1;const n=Math.max(0,Math.min(1,(i/s-1)/.3));return n*n*(3-2*n)}static starPointsOf(e,t){const i=e.apertureBlades;return i===void 0||i<3||Yt.bladesShowing(e,t)<.5?0:i%2===0?i:i*2}}class Gl extends Error{}class lm{constructor(e){this.name=e}validate(e){return!0}}class Ex extends lm{min;max;constructor(e,t,i){super(e),this.min=t,this.max=i}validate(e){if(typeof e!="number")throw new Gl(`${this.name} value must be a number, but was ${e}`);if(e<this.min||e>this.max)throw new Gl(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${e}`);return super.validate(e)}}class ys{name;min;max;duration;subUnit;validator;constructor(e,t,i,s,n=new Ex(e,t,i)){this.name=e,this.min=t,this.max=i,this.subUnit=s,this.duration=s?(s.max-s.min+1)*s.duration:1,this.validator=n}validate(e){return this.validator.validate(e)}[Symbol.iterator](){let e=this.min;return{next:()=>{const t={done:e>this.max,value:e};return e++,t}}}}class Ax{millisecond;second;minute;hour;day;month;year}class nA extends Ax{}class Tx extends nA{millisecond=new ys("millisecond",0,999,void 0);second=new ys("second",0,59,this.millisecond);minute=new ys("minute",0,59,this.second);hour=new ys("hour",0,23,this.minute);day=new ys("day",1,31,this.hour);month=new ys("month",1,12,this.day);year=new ys("year",0,9999,this.month)}const pt=new Tx;class rA extends Ex{constructor(e=1,t=12){super("month",e,t)}}class pa{static instance=new pa;render(e){return e.value.toString()}}class rn{unit;#e;constructor(e,t){this.unit=t,this.value=typeof e=="number"?e:e.value}get value(){return this.#e}set value(e){this.unit.validate(e),this.#e=e}get duration(){return this.value*this.unit.duration}#t(e){if(this.constructor.name!==e.constructor.name)throw new lm(`${this.unit.name} "${this.toString()}" cannot be compared with ${e.unit?.name} "${e.toString()}"`)}compare(e){return this.#t(e),this.value-e.value}isEqual(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}previous(e=this.unit){const t=this.value-1;return new this.constructor(t,e)}next(e=this.unit){const t=this.value+1;return new this.constructor(t,e)}toString(e=pa.instance){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class xi{static#e=new Map;static register(e,t){xi.#e.set(e,t)}static get(e){const t=xi.#e.get(e);if(!t)throw new Gl(`No default parser registered for ${e.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return t()}}class Gp extends rn{constructor(e=new Date().getFullYear(),t=pt.year){super(e,t)}static fromString(e,t=xi.get(Gp)){return new Gp(t.parse(e))}}class xa extends pa{static default=new xa("0",2);constructor(e,t){super(),this.char=e,this.size=t}render(e){return super.render(e).padStart(this.size,this.char)}}class Vp extends rn{constructor(e=new Date().getMonth()+1,t=pt.month){super(e,t)}static fromString(e,t=xi.get(Vp)){return new Vp(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Wp extends rn{constructor(e=new Date().getDate(),t=pt.day){super(e,t)}static fromString(e,t=xi.get(Wp)){const i=t.parse(e);return new Wp(i)}toString(e=xa.default){return super.toString(e)}}class $p extends rn{constructor(e=new Date().getHours(),t=pt.hour){super(e,t)}static fromString(e,t=xi.get($p)){return new $p(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Kp extends rn{constructor(e=new Date().getMinutes(),t=pt.minute){super(e,t)}static fromString(e,t=xi.get(Kp)){return new Kp(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Xp extends rn{constructor(e=new Date().getSeconds(),t=pt.second){super(e,t)}static fromString(e,t=xi.get(Xp)){return new Xp(t.parse(e),pt.second)}toString(e=xa.default){return super.toString(e)}}class jl extends rn{static renderer=new xa("0",3);constructor(e,t=pt.millisecond){super(e,t)}static parseFraction(e){return parseInt(e.padEnd(3,"0").substring(0,3),10)}toString(e=jl.renderer){return super.toString(e)}}class aA{render(e){return e.toString()}}class oA extends aA{render(e){const t=e.value,i=Math.abs(t),s=Math.floor(i/60),n=i%60;if(s===0&&n===0)return"Z";{const r=t<0?"-":"+",a=s.toString().padStart(2,"0"),o=n>0?":"+n.toString().padEnd(2,"0"):"";return r+a+o}}}class ph{value;name="timeshift";renderer;constructor(e=0){this.value=e}static fromString(e,t=xi.get(ph),i=void 0){const s=t.parse(e,i);return new ph(s)}toString(e=new oA){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class Qs{static timeshift(e,t){return e+(Qs.isDaylight(t)?60:0)}static isDaylight(e){const{year:t,month:i,day:s}=e,n=e.hour??12;if(![t,i,s].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=Qs.rule(t);if(!r)return!1;const a=Qs.rank(i,s,n);return a>=Qs.rank(r.start.month,r.start.day,2)&&a<Qs.rank(r.end.month,r.end.day,2)}static rule(e){if(e<1967)return;const t={month:10,day:Qs.sunday(e,10,-1)};return e>=2007?{start:{month:3,day:Qs.sunday(e,3,2)},end:{month:11,day:Qs.sunday(e,11,1)}}:e>=1987?{start:{month:4,day:Qs.sunday(e,4,1)},end:t}:e===1975?{start:{month:2,day:23},end:t}:e===1974?{start:{month:1,day:6},end:t}:{start:{month:4,day:Qs.sunday(e,4,-1)},end:t}}static sunday(e,t,i){const s=new Date(Date.UTC(2e3,t-1,1));s.setUTCFullYear(e);const n=1+(7-s.getUTCDay())%7;if(i>0)return n+7*(i-1);const r=[31,Qs.isLeap(e)?29:28,31,30,31,30,31,31,30,31,30,31][t-1];let a=n;for(;a+7<=r;)a+=7;return a}static isLeap(e){return e%4===0&&(e%100!==0||e%400===0)}static rank(e,t,i){return(e*100+t)*100+i}}const lA={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},cA={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},hA={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},dA={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},uA={name:"PT",timeshift:l=>Qs.timeshift(-480,l),title:"Pacific Time (US)"},pA={name:"MT",timeshift:l=>Qs.timeshift(-420,l),title:"Mountain Time (US)"},fA={name:"CT",timeshift:l=>Qs.timeshift(-360,l),title:"Central Time (US)"},mA={name:"ET",timeshift:l=>Qs.timeshift(-300,l),title:"Eastern Time (US)"},gA={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},vA={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},bA={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},yA={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},wA={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},MA={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},xA={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},SA={name:"Z",timeshift:"Z",title:"UTC"},EA={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},AA={name:"BST",timeshift:"+01",title:"British Summer Time"},TA={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},IA={name:"CET",timeshift:"+01",title:"Central European Time"},_A={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},RA={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},DA={name:"BJT",timeshift:"+08",title:"Beijing Time"},kA={name:"CST",timeshift:"-06",title:"Central Standard Time"},CA={name:"JST",timeshift:"+09",title:"Japan Standard Time"},LA={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},OA={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},PA={name:"LST",timeshift:"?",title:"Local Sideral Time"},f1=[MA,LA,wA,DA,AA,kA,vA,IA,TA,fA,gA,yA,bA,mA,EA,RA,CA,PA,hA,_A,dA,pA,OA,cA,lA,uA,xA,SA];class cm{static instance=new cm;renderComponent(e,t){return e[t].toString()}renderSecond(e){return this.renderComponent(e,"second")+(e.millisecond?"."+e.millisecond.toString():"")}render(e){const t=[];e.year&&t.push(this.renderComponent(e,"year")),e.month&&t.push(this.renderComponent(e,"month")),e.day&&t.push(this.renderComponent(e,"day"));const i=[];e.hour&&i.push(this.renderComponent(e,"hour")),e.minute&&i.push(this.renderComponent(e,"minute")),e.second&&i.push(this.renderSecond(e));const s=t.join("-"),n=e.timeshift?e.timeshift.toString():"",r=i.join(":")+n;return s+(r.length>0?"T"+r:"")}}class jo extends Gl{constructor(e="method is abstract"){super(e)}}class eb{units;constructor(e){this.units=e}newYear(e){throw new jo}newMonth(e){throw new jo}newDay(e){throw new jo}newHour(e){throw new jo}newMinute(e){throw new jo}newSecond(e){throw new jo}}class NA extends Ax{millisecond=new ys("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new ys("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new ys("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new ys("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new ys("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new ys("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new ys("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const tb=new NA;class ib{static instance=new ib;render(e){const t=ol.toSpec(e);let i="P";const s=t.years;s&&(i+=s.toString()+"Y");const n=t.months;n&&(i+=n.toString(pa.instance)+"MM");const r=t.days;r&&(i+=r.toString(pa.instance)+"D");const a=t.hours;a&&(i+=a.toString(pa.instance)+"H");const o=t.minutes;o&&(i+=o.toString(pa.instance)+"M");const c=t.seconds;return c&&(i+=c.toString(pa.instance)+"S"),i}}class ol extends rn{constructor(e={years:new Date().getFullYear(),months:new Date().getMonth(),days:new Date().getDate(),hours:new Date().getHours(),minutes:new Date().getMinutes(),seconds:new Date().getSeconds(),milliseconds:new Date().getMilliseconds()}){super({value:typeof e=="number"?e:+(e.years?e.years*pt.year.duration:0)+(e.months?e.months*pt.month.duration:0)+(e.days?e.days*pt.day.duration:0)+(e.hours?e.hours*pt.hour.duration:0)+(e.minutes?e.minutes*pt.minute.duration:0)+(e.seconds?e.seconds*pt.second.duration:0)},new ys("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(e,t=UA){let i=typeof e=="number"?e:e.value;const s=i>0?1:-1;i=Math.abs(i);const n={},r=i/pt.year.duration,a=Math.floor(r);a>0&&(n.years=t.newYear(s*a),i-=a*pt.year.duration);const o=i/pt.month.duration,c=Math.floor(o);c>0&&(n.months=t.newMonth(s*c),i-=c*pt.month.duration);const h=i/pt.day.duration,d=Math.floor(h);d>0&&(n.days=t.newDay(s*d),i-=d*pt.day.duration);const u=i/pt.hour.duration,p=Math.floor(u);p>0&&(n.hours=t.newHour(s*p),i-=p*pt.hour.duration);const f=i/pt.minute.duration,m=Math.floor(f);m>0&&(n.minutes=t.newMinute(s*m),i-=m*pt.minute.duration);const g=i/pt.second.duration,v=Math.floor(s*g);return v>0&&(n.seconds=t.newSecond(v)),n}static fromString(e,t=xi.get(ol)){return new ol(t.parse(e))}static between(e,t){const i=t.getTime(),s=e.getTime();return new ol(i-s)}toSpec(){return ol.toSpec(this)}toString(e=ib.instance){return e.render(this)}}class Ix extends eb{constructor(e){super(e)}newYear(e){return new Gp(e,this.units.year)}newMonth(e){return new Vp(e,this.units.month)}newDay(e){return new Wp(e,this.units.day)}newHour(e){return new $p(e,this.units.hour)}newMinute(e){return new Kp(e,this.units.minute)}newSecond(e){return new Xp(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new ph(typeof e=="number"?e:e.value)}}const FA=new Ix(pt),UA=new Ix(tb);class kr{#e;#t;#i;#s;#n;#r;#a;#o;constructor(e={year:new Date().getFullYear(),month:new Date().getMonth()+1,day:new Date().getDate(),hour:new Date().getHours(),minute:new Date().getMinutes(),second:new Date().getSeconds(),timeshift:kr.timeshiftOf(new Date)}){this.year=e.year,this.month=e.month,this.day=e.day,this.hour=e.hour,this.minute=e.minute,this.second=e.second,this.millisecond=e.millisecond,this.timeshift=e.timeshift}get year(){return this.#e}set year(e){const t=typeof e=="number";this.#e&&t?this.#e.value=e:this.#e=t?this.factory.newYear(e):!e||e.start||e instanceof rn?e:this.factory.newYear(e)}get month(){return this.#t}set month(e){const t=typeof e=="number";this.#t&&t?this.#t.value=e:this.#t=t?this.factory.newMonth(e):!e||e.start||e instanceof rn?e:this.factory.newMonth(e)}get day(){return this.#i}set day(e){const t=typeof e=="number";this.#i&&t?this.#i.value=e:this.#i=t?this.factory.newDay(e):!e||e.start||e instanceof rn?e:this.factory.newDay(e)}get hour(){return this.#s}set hour(e){const t=typeof e=="number";this.#s&&t?this.#s.value=e:this.#s=t?this.factory.newHour(e):!e||e.start||e instanceof rn?e:this.factory.newHour(e)}get minute(){return this.#n}set minute(e){const t=typeof e=="number";this.#n&&t?this.#n.value=e:this.#n=t?this.factory.newMinute(e):!e||e.start||e instanceof rn?e:this.factory.newMinute(e)}get second(){return this.#r}set second(e){const t=typeof e=="number";this.#r&&t?this.#r.value=e:this.#r=t?this.factory.newSecond(e):!e||e.start||e instanceof rn?e:this.factory.newSecond(e)}get millisecond(){return this.#a}set millisecond(e){const t=typeof e=="number";this.#a&&t?this.#a.value=e:this.#a=t||e&&!(e instanceof rn)?this.factory.newMillisecond(e):e}get timeshift(){return this.#o}set timeshift(e){const t=typeof e=="number";this.#o&&t?this.#o.value=e:this.#o=t||e&&!(e instanceof ph)?this.factory.newTimeshift(e):e}get factory(){return FA}static fromString(e,t=xi.get(kr)){const{year:i,month:s,day:n,hour:r,minute:a,second:o,millisecond:c,timeshift:h}=t.parse(e);return new kr({year:i,month:s,day:n,hour:r,minute:a,second:o,millisecond:c,timeshift:h})}static timeshiftOf(e){return-e.getTimezoneOffset()||0}static fromDate(e){return new kr({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return kr.fromString(i)}#l(e){if(this.constructor.name!==e.constructor.name)throw new lm(`Date "${this.toString()}" cannot be compared with "${e.toString()}"`)}compare(e){return this.#l(e),this.getTime()-e.getTime()}delta(e){const t=this.compare(e);return new ol(t)}getTime(){return(this.year?.duration||0)+(this.month?.duration||0)+(this.day?.duration||0)+(this.hour?.duration||0)+(this.minute?.duration||0)+(this.second?.duration||0)+(this.millisecond?.duration||0)}isEqual(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}clone(){return new kr(this.toSpec())}previous(){let e=this.clone();try{e.second=this.second.previous()}catch{try{e.minute=this.minute.previous()}catch{try{e.hour=this.hour.previous()}catch{try{e.day=this.day.previous()}catch{try{e.month=this.month.previous()}catch{e.year=this.year.previous()}}}}}return e}next(){let e=this.clone();try{e.second=this.second.next()}catch{try{e.minute=this.minute.next()}catch{try{e.hour=this.hour.next()}catch{try{e.day=this.day.next()}catch{try{e.month=this.month.next()}catch{e.year=this.year.next()}}}}}return e}toString(e=cm.instance){return e.render(this)}toSpec(){const e={},t=this.year?.toSpec();t&&(e.year=t);const i=this.month?.toSpec();i&&(e.month=i);const s=this.day?.toSpec();s&&(e.day=s);const n=this.hour?.toSpec();n&&(e.hour=n);const r=this.minute?.toSpec();r&&(e.minute=r);const a=this.second?.toSpec();a&&(e.second=a);const o=this.millisecond?.toSpec();o&&(e.millisecond=o);const c=this.timeshift?.toSpec();return c&&(e.timeshift=c),e}toJSON(){return this.toSpec()}}class nu extends pa{static instance=new nu(xa.default);constructor(e){super(),this.valueRenderer=e}render(e){return(this.valueRenderer?this.valueRenderer.render(e):super.render(e))+this.qualifier(e)}qualifier(e){return e.uncertain?e.approximate?"%":"?":e.approximate?"~":""}}class Zl extends rn{#e;#t;constructor(e,t){super(e,t),this.#e=e.uncertain||!1,this.#t=e.approximate||!1}get uncertain(){return this.#e}set uncertain(e){return this.#e=e}get approximate(){return this.#t}set approximate(e){return this.#t=e}isCertainAndPrecise(){return!this.approximate&&!this.uncertain}isEqual(e){return this.isCertainAndPrecise()&&super.isEqual(e)}isBefore(e){return this.isCertainAndPrecise()&&super.isBefore(e)}isAfter(e){return this.isCertainAndPrecise()&&super.isAfter(e)}toString(e=nu.instance){return super.toString(e)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class _x extends Tx{year=new ys("year",-9999,9999,this.month);yearExtended=new ys("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const xp=new _x;class ll extends Zl{constructor(e,t=xp.year){super(e,t)}static fromString(e,t=xp.year,i=xi.get(ll)){const s=i.parse(e),n=s.value.start;if(e.startsWith("Y")&&(t=xp.yearExtended),n!==void 0){const r=new ll(Object.assign({...s},{value:Math.max(n,t.min)})),a=new ll(Object.assign({...s},{value:Math.min(s.value.end,t.max)}));return{start:r,end:a}}else return new ll(s,t)}}class Rx extends lm{monthValidator=new rA;validate(e){switch(e){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(e)}}}class cl extends Zl{constructor(e,t=new ys(pt.month.name,1,24,pt.day,new Rx)){super(e,t)}static fromString(e,t=xi.get(cl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.month;const r=new cl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new cl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new cl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class hl extends Zl{constructor(e,t=pt.day){super(e,t)}static fromString(e,t=xi.get(hl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.day;const r=new hl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new hl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new hl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class dl extends Zl{constructor(e,t=pt.hour){super(e,t)}static fromString(e,t=xi.get(dl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.hour;const r=new dl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new dl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new dl(i)}}class ul extends Zl{constructor(e,t=pt.minute){super(e,t)}static fromString(e,t=xi.get(ul)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.minute,r=new ul(Object.assign({...i},{value:Math.max(s,n.min)})),a=new ul(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new ul(i)}toString(e=nu.instance){return super.toString(e)}}class pl extends Zl{constructor(e,t=pt.second){super(e,t)}static fromString(e,t=xi.get(pl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.second,r=new pl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new pl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new pl(i)}}class fh extends ph{static fromString(e,t=xi.get(fh),i=void 0){return new fh(t.parse(e,i))}}class Dx extends eb{constructor(e){super(e)}newYear(e){return new ll(e,this.units.year)}newMonth(e){return new cl(e,this.units.month)}newDay(e){return new hl(e,this.units.day)}newHour(e){return new dl(e,this.units.hour)}newMinute(e){return new ul(e,this.units.minute)}newSecond(e){return new pl(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new fh(typeof e=="number"?e:e.value)}}const zA=new Dx(xp);new Dx(tb);class Zo extends kr{constructor(e){super(e)}get factory(){return zA}get uncertain(){return this.year?.uncertain===!0||this.month?.uncertain===!0||this.day?.uncertain===!0||this.hour?.uncertain===!0||this.minute?.uncertain===!0||this.second?.uncertain===!0}get approximate(){return this.year?.approximate===!0||this.month?.approximate===!0||this.day?.approximate===!0||this.hour?.approximate===!0||this.minute?.approximate===!0||this.second?.approximate===!0}static fromDate(e){return new Zo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static fromString(e,t=xi.get(Zo)){const i=t.parse(e);return new Zo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Zo.fromString(i)}clone(){return new Zo(this.toSpec())}}class _h extends Zl{uncertainComponent;approximateComponent;constructor(e,t){super(e,t),this.uncertainComponent=e.uncertainComponent||!1,this.approximateComponent=e.approximateComponent||!1}get uncertain(){return super.uncertain||this.uncertainComponent}set uncertain(e){return super.uncertain=e}get approximate(){return super.approximate||this.approximateComponent}set approximate(e){return super.approximate=e}get uncertainGroup(){return super.uncertain}get approximateGroup(){return super.approximate}toSpec(){return{...super.toSpec(),uncertain:this.uncertainGroup,approximate:this.approximateGroup,uncertainComponent:this.uncertainComponent,approximateComponent:this.approximateComponent}}toJSON(){return this.toSpec()}}class BA extends _x{year=new ys("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const vg=new BA;class fl extends _h{constructor(e,t=vg.year){super(e,t)}static fromString(e,t=vg.year,i=xi.get(fl)){const s=i.parse(e),n=s.value.start;if(n!==void 0){const r=new fl(Object.assign({...s},{value:Math.max(n,t.min)})),a=new fl(Object.assign({...s},{value:Math.min(s.value.end,t.max)})),o={start:r,end:a},c=s.value.estimate;return c&&(o.estimate=c),o}else return new fl(s)}}class HA extends Rx{validate(e){switch(e){case 25:case 26:case 27:case 28:case 29:case 30:case 31:case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:return!0;default:return super.validate(e)}}}class ml extends _h{constructor(e,t=new ys(pt.month.name,1,41,pt.day,new HA)){super(e,t)}static fromString(e,t=xi.get(ml)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.month,r=new ml(Object.assign({...i},{value:Math.max(s,n.min)})),a=new ml(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new ml(i)}toString(e){return super.toString(e).padStart(2,"0")}}class gl extends _h{constructor(e,t=pt.day){super(e,t)}static fromString(e,t=xi.get(gl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.day,r=new gl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new gl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new gl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class vl extends _h{constructor(e,t=pt.hour){super(e,t)}static fromString(e,t=xi.get(vl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.hour,r=new vl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new vl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new vl(i)}}class bl extends _h{constructor(e,t=pt.minute){super(e,t)}static fromString(e,t=xi.get(bl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.minute,r=new bl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new bl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new bl(i)}}class yl extends _h{constructor(e,t=pt.second){super(e,t)}static fromString(e,t=pt.second,i=xi.get(yl)){const s=i.parse(e),n=s.value.start;if(n!==void 0){const r=new yl(Object.assign({...s},{value:Math.max(n,t.min)})),a=new yl(Object.assign({...s},{value:Math.min(s.value.end,t.max)}));return{start:r,end:a}}else return new yl(s,t)}}class kx extends fh{}class GA extends nu{qualifier(){return""}}class ho extends cm{static instance=new ho;static valueRenderer=new GA(xa.default);static names=["year","month","day","hour","minute","second"];static qualifier(e,t){return e?t?"%":"?":t?"~":""}renderComponent(e,t){const i=e[t],s=ho.names.slice(ho.names.indexOf(t)+1).map(a=>e[a]).filter(Boolean),n=ho.qualifier(i.uncertainComponent,i.approximateComponent),r=ho.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!s.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!s.some(a=>a.approximate));return n+i.toString(ho.valueRenderer)+r}}class Cx extends eb{constructor(e){super(e)}newYear(e){return new fl(e,this.units.year)}newMonth(e){return new ml(e,this.units.month)}newDay(e){return new gl(e,this.units.day)}newHour(e){return new vl(e,this.units.hour)}newMinute(e){return new bl(e,this.units.minute)}newSecond(e){return new yl(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new kx(typeof e=="number"?e:e.value)}}const VA=new Cx(vg);new Cx(tb);class Jo extends Zo{constructor(e){super(e)}toString(e=ho.instance){return super.toString(e)}get year(){return super.year}set year(e){super.year=e}get month(){return super.month}set month(e){super.month=e}get factory(){return VA}static fromDate(e){return new Jo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static fromString(e,t=xi.get(Jo)){const i=t.parse(e);return new Jo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Jo.fromString(i)}clone(){return new Jo(this.toSpec())}}class hm{regExp;constructor(e,t){this.name=e,this.regExp=new RegExp(`^(?:${t})$`)}regexGroups(e){const t=this.regExp.exec(e);if(!t)throw new Gl(`Invalid ${this.name} "${e}"`);return t.groups}parseGroups(e){throw new jo(`${this.constructor.name} is abstract`)}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}class sb extends hm{constructor(e,t){super(e,t)}static read(e){return{value:e?parseInt(e,10):void 0}}parseGroups(e){return sb.read(e[this.name])}parse(e){if(e.startsWith("-"))throw new Gl(`${this.name} cannot be negative`);return super.parse(e)}}class ce{static groupName(...e){return e.reduce((t,i)=>t?t+i.charAt(0).toUpperCase()+i.substring(1):i,"")}static group(e,...t){return`(?<${e}>${t.join("")})`}static optional(e){return e+"?"}static nonCapturingGroup(...e){return`(?:${e.join("")})`}static optionalGroup(e,...t){return ce.optional(ce.group(e,...t))}static optionalNonCapturingGroup(...e){return ce.optional(ce.nonCapturingGroup(...e))}static numberGroup(e,t,i,s="\\d"){return ce.group(e,`${i||""}[${s}]${t}`)}}const m1="timeshiftValue",g1="shiftHour",v1="shiftMinute";class nb extends hm{static format(e=""){return f1.map(t=>t.name).join("|")+"|"+ce.nonCapturingGroup(ce.group(e+g1,ce.numberGroup(ce.groupName(e,m1),"{2}","[+-]")),ce.optionalNonCapturingGroup(":?",ce.numberGroup(ce.groupName(e,v1),"{2}",void 0)))}constructor(){super(m1,nb.format())}parse(e,t){let i=0;const s=f1.find(n=>n.name===e);if(s){if(typeof s.timeshift=="function")try{return s.timeshift(t??{})}catch(n){throw new Gl(`The time zone ${e} depends on the date: ${n.message}`)}e=s.timeshift}if(e!=="Z"){const n=this.regexGroups(e),r=n[g1];r&&(i+=parseInt(r,10)*60);const a=n[v1];a&&(i+=parseInt(a,10))}return i}}class Ki extends sb{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=Ki.uncertainGroup+Ki.approximateGroup;constructor(e,t){super(e,t)}static qualifierFormat(e,t){return ce.optionalGroup(e,`\\${t}`)}static formatSuffix(e){return this.qualifierFormat(ce.groupName(Ki.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(Ki.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(Ki.uncertainAndApproximateGroup,e),"%")}static numberFormat(e,t,i){return ce.numberGroup(e,t,i,"\\dX")+this.formatSuffix(e)}getValueAndSign(e){let t=e[this.name],i;return t.charAt(0)==="-"?(i=-1,t=t.substring(1)):i=1,{valueStr:t,sign:i}}parseGroups(e){const{valueStr:t,sign:i}=this.getValueAndSign(e);let s=0,n;for(n=0;n<t.length;n++){const c=t[n];if(c==="X")break;s=s*10+parseInt(c,10)}if(n<t.length){let c=1;for(let u=0;u<t.length-n;u++)c*=10;const h=i*s*c,d=h+c-1;s={start:h,end:d}}else s*=i;const r=e[ce.groupName(Ki.uncertainAndApproximateGroup,this.name)],a=e[ce.groupName(Ki.approximateGroup,this.name)]||r,o=e[ce.groupName(Ki.uncertainGroup,this.name)]||r;return{value:s,approximate:a?!!a:!1,uncertain:o?!!o:!1}}}const b1="yearValue";class Yp extends Ki{constructor(){super(b1,Yp.format())}static format(e=""){return"Y?"+Ki.numberFormat(ce.groupName(e,b1),"+","[-]?")}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const y1="monthValue";class qp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,y1),"{1,2}",void 0)}constructor(){super(y1,qp.format())}}const w1="dayValue";class jp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,w1),"{1,2}",void 0)}constructor(){super(w1,jp.format())}}const M1="hourValue";class Zp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,M1),"{1,2}",void 0)}constructor(){super(M1,Zp.format())}}const x1="minuteValue";class Jp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,x1),"{1,2}",void 0)}constructor(){super(x1,Jp.format())}}const S1="secondValue";class Qp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,S1),"{1,2}",void 0)}constructor(){super(S1,Qp.format())}}class ef extends nb{}class Ms extends hm{static yearGroup="year";static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(e=Ms.format()){super("date",e)}static format(e=""){return ce.group(ce.groupName(e,Ms.yearGroup),Yp.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,Ms.monthGroup),qp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,Ms.dayGroup),jp.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,Ms.hourGroup),Zp.format(e)),":",ce.group(ce.groupName(e,Ms.minuteGroup),Jp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,Ms.secondGroup),Qp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,Ms.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,Ms.timeshiftGroup),ef.format(e)))))}parseGroups(e){const t=e[Ms.millisecondGroup],i=t?jl.parseFraction(t):void 0,s=e[Ms.secondGroup],n=s?pl.fromString(s,new Qp):void 0,r=e[Ms.minuteGroup];let a;r&&(a=ul.fromString(r,new Jp),a.uncertain=a.uncertain||n?.uncertain||!1,a.approximate=a.approximate||n?.approximate||!1);const o=e[Ms.hourGroup];let c;o&&(c=dl.fromString(o,new Zp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[Ms.dayGroup];let d;h&&(d=hl.fromString(h,new jp),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[Ms.monthGroup];let p;u&&(p=cl.fromString(u,new qp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[Ms.yearGroup];let m;f&&(m=ll.fromString(f,void 0,new Yp),m.uncertain=m.uncertain||p?.uncertain||!1,m.approximate=m.approximate||p?.approximate||!1);const g=e[Ms.timeshiftGroup],v=g?fh.fromString(g,new ef,{year:m?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:m,month:p,day:d,hour:c,minute:a,second:n,millisecond:i,timeshift:v}}}class ds extends Ki{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=ds.uncertainGroup+ds.approximateGroup;constructor(e,t){super(e,t)}static numberFormat(e,t,i){return this.qualifierFormat(ce.groupName(ds.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(ds.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(ds.uncertainAndApproximateGroup,e),"%")+Ki.numberFormat(e,t,i)}parseGroups(e){const t=super.parseGroups(e),i=e[ce.groupName(ds.uncertainAndApproximateGroup,this.name)];return(e[ce.groupName(ds.uncertainGroup,this.name)]||i)&&(t.uncertainComponent=!0),(e[ce.groupName(ds.approximateGroup,this.name)]||i)&&(t.approximateComponent=!0),t}}const Oh="yearValue",E1="exp",A1="signif";class tf extends ds{constructor(){super(Oh,tf.format())}static format(e=""){return"Y?"+ce.nonCapturingGroup(ce.group(ce.groupName(e,E1),"[-]?\\d+E\\d+")+"|"+ds.numberFormat(ce.groupName(e,Oh),"+","[-]?")+ce.optionalGroup(ce.groupName(e,A1),"S\\d+"))}parseGroups(e){const t=e[E1];if(t){const r=t.indexOf("E"),a=parseInt(t.substring(r+1),10),c=parseInt(t.substring(0,r),10)*Math.pow(10,a);e[Oh]=c.toString()}const i=e[A1],s=e[Oh];if(i){const r=parseInt(i.substring(1),10),{valueStr:a,sign:o}=this.getValueAndSign(e);let c="";for(let h=0;h<a.length;h++)c+=h<r?a.charAt(h):"X";e[Oh]=(o<0?"-":"")+c}const n=super.parseGroups(e);return i&&(n.value.estimate=parseInt(s,10)),n}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const T1="monthValue";class sf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,T1),"{1,2}",void 0)}constructor(){super(T1,sf.format())}}const I1="dayValue";class nf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,I1),"{1,2}",void 0)}constructor(){super(I1,nf.format())}}const _1="hourValue";class rf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,_1),"{1,2}",void 0)}constructor(){super(_1,rf.format())}}const R1="secondValue";class af extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,R1),"{1,2}",void 0)}constructor(){super(R1,af.format())}}const D1="minuteValue";class of extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,D1),"{1,2}",void 0)}constructor(){super(D1,of.format())}}class WA extends ef{}class xs extends hm{static yearGroup=Ms.yearGroup;static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(){super("date",xs.format())}static format(e=""){return ce.group(ce.groupName(e,xs.yearGroup),tf.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,xs.monthGroup),sf.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,xs.dayGroup),nf.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,xs.hourGroup),rf.format(e)),":",ce.group(ce.groupName(e,xs.minuteGroup),of.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,xs.secondGroup),af.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,xs.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,xs.timeshiftGroup),WA.format(e)))))}parseGroups(e){const t=e[xs.millisecondGroup],i=t?jl.parseFraction(t):void 0,s=e[xs.secondGroup];let n;s&&(n=yl.fromString(s,void 0,new af),n.uncertain=n?.uncertain||!1,n.approximate=n?.approximate||!1);const r=e[xs.minuteGroup];let a;r&&(a=bl.fromString(r,new of),a.uncertain=a.uncertain||n?.uncertain||!1,a.approximate=a.approximate||n?.approximate||!1);const o=e[xs.hourGroup];let c;o&&(c=vl.fromString(o,new rf),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[xs.dayGroup];let d;h&&(d=gl.fromString(h,new nf),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[xs.monthGroup];let p;u&&(p=ml.fromString(u,new sf),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[xs.yearGroup];let m;f&&(m=fl.fromString(f,void 0,new tf),m.uncertain=m.uncertain||p?.uncertain||!1,m.approximate=m.approximate||p?.approximate||!1);const g=e[xs.timeshiftGroup],v=g?kx.fromString(g,new ef,{year:m?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:m,month:p,day:d,hour:c,minute:a,second:n,millisecond:i,timeshift:v}}}const Lx=["spring","summer","autumn","winter"],bg=21,$A=32,KA=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let XA;function YA(){return XA??=new xs}function tc(l){return typeof l?.value=="number"?l.value:void 0}function Sp(l){const e=l.trim();if(/^\d{1,2}:/.test(e)){const r=KA.exec(e)?.groups;return r?{year:void 0,month:void 0,day:void 0,hour:Number(r.hour),minute:Number(r.minute),second:r.second?Number(r.second):void 0,raw:e}:void 0}let t;try{t=Jo.fromString(e,YA())}catch{return}const i=tc(t.year),s=tc(t.month),n=s!==void 0&&s>=bg&&s<=$A;if(!(t.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(s!==void 0&&s>12&&!n)&&!(n&&(t.day||t.hour)))return{year:i,month:n?void 0:s,...n?{season:Lx[(s-bg)%4]}:{},day:tc(t.day),hour:tc(t.hour),minute:tc(t.minute),second:tc(t.second),raw:e}}function wl(l){if(l.raw!==void 0)return l.raw;if(l.year===void 0){if(l.hour===void 0)return"";let t=`${String(l.hour).padStart(2,"0")}:${String(l.minute??0).padStart(2,"0")}`;return l.second!==void 0&&(t+=`:${String(l.second).padStart(2,"0")}`),t}let e=String(l.year).padStart(4,"0");return l.season!==void 0?`${e}-${bg+Lx.indexOf(l.season)}`:(l.month===void 0||(e+=`-${String(l.month).padStart(2,"0")}`,l.day===void 0)||(e+=`-${String(l.day).padStart(2,"0")}`,l.hour===void 0)||(e+=`T${String(l.hour).padStart(2,"0")}:${String(l.minute??0).padStart(2,"0")}`,l.second!==void 0&&(e+=`:${String(l.second).padStart(2,"0")}`)),e)}function yg(l){if(l.year!==void 0)return Date.UTC(l.year,(l.month??1)-1,l.day??1,l.hour??0,l.minute??0,l.second??0)}function k1(l){return(((l.day??0)*24+(l.hour??0))*60+(l.minute??0))*6e4+(l.second??0)*1e3}const qA=["year","month","day","hour","minute"],jA=["day","hour","minute"];function C1(l,e){return e.filter(t=>l[t]!==void 0).join(",")}function mh(l){if(l.durationSeconds!==void 0)return l.durationSeconds*1e3;const e=l.durationText===void 0?void 0:bn.parse(l.durationText);if(e)return e.chosenSeconds*1e3;if(!l.time||!l.endTime)return;const t=l.time.year!==void 0&&l.endTime.year!==void 0,i=t?qA:jA,s=C1(l.time,i);if(!(s===""||s!==C1(l.endTime,i)))return t?yg(l.endTime)-yg(l.time):k1(l.endTime)-k1(l.time)}function ZA(l){if(l.durationSeconds===void 0&&!(!l.time||!l.endTime))return mh(l)===void 0?"imprecise":void 0}class dm{constructor(e,t,i,s,n,r,a,o,c=[],h,d,u,p=[],f=[],m=[],g=[]){this.event=e,this.timeline=t,this.observerTrack=i,this.weatherTrack=s,this.soundTrack=n,this.observer=r,this.id=a,this.weather=o,this.decor=c,this.weatherSource=h,this.instrumentId=d,this.exposureSeconds=u,this.milestones=p,this.references=f,this.roads=m,this.traces=g}provenance=wn.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;metering;lens;vehicle;get observerCount(){return 1+this.decor.filter(e=>e.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Yt.byId(this.instrumentId)}static create(e,t,i){return new dm({eventType:"sighting",time:e,place:t},new am,new Nd,new Fd,new Ud,i)}}const JA=0,QA=0;function at(l,e){const t=l.observerTrack.getInterpolatedPoseAt(e);if(t)return t;const i=l.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:JA,headingDeg:void 0,pitchDeg:QA,fovDeg:Yt.fieldOfViewDeg(l.instrument)}}function is(l,e){return l.weatherTrack.getInterpolatedWeatherAt(e)??l.weather??om}function Ph(l,e){return l.weatherTrack.getActualWeatherAt(e)??l.weather??om}function rb(l,e){return l.soundTrack.getInterpolatedSoundAt(e)??sA}class zd{constructor(e,t){this.json=e,this.url=t,this.tracks=(e.events??[]).filter(i=>i.eventType===Di.SIGHTING_EVENT&&typeof i.url=="string"&&i.url!=="").map(i=>({event:i,url:new URL(i.url,t).href,kind:i.interpretationOf===void 0?"observer":"reading"}))}tracks;caseChanged=!1;transcripts=new Map;static around(e,t,i,s,n){const r=(e.observer?.id??e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",a={id:e.id??"case",...t!==void 0?{time:t}:{},events:[{type:"event",eventType:Di.SIGHTING_EVENT,...t!==void 0?{time:t}:{},...i!==void 0?{title:i}:{},url:`observer-${r}.json`}]},o=new zd(a,new URL("case.json",n).href),c=o.tracks[0];return c.recording=e,c.base={url:s},c.event.id=o.proposedId(c),o.caseChanged=!0,o}accountOf(e){if(e.kind!=="reading")return;const t=[e.event.interpretationOf].flat(),i=this.tracks.filter(s=>s.kind==="observer");return i.find(s=>s.event.id!==void 0&&t.includes(s.event.id))??i.find(s=>s.recording?.id!==void 0&&t.includes(s.recording.id))}get interviews(){return(this.json.events??[]).filter(e=>e.eventType===Di.INTERVIEW_EVENT)}intervieweeOf(e){return this.intervieweesOf(e)[0]}intervieweesOf(e){const t=this.tracks.filter(i=>i.kind==="observer");return[e.interviewOf].flat().filter(i=>typeof i=="string").flatMap(i=>{const s=t.find(n=>n.event.id===i)??t.find(n=>n.recording?.id===i);return s?[s]:[]})}addInterview(e,t,i,s,n){const r=this.eventIds(),a=e?e.event.id??this.proposedId(e):"case";let o=1;for(;r.has(`interview-${a}-${o}`);)o++;const c={type:"event",eventType:Di.INTERVIEW_EVENT,id:`interview-${a}-${o}`,...e?{interviewOf:this.ensureId(e)}:{},time:t,...n!==void 0?{medium:n}:{},...s!==void 0&&s.length>0?{by:s}:{},...i!==void 0?{title:i}:{}};return this.json.events=[...this.json.events??[],c],this.caseChanged=!0,c}transcriptText(e){return this.transcripts.get(e)?.text}keepTranscript(e,t){this.transcripts.set(e,{text:t,loaded:this.transcripts.get(e)?.loaded})}transcriptChanged(e){return e.loaded!==e.text}deleteInterview(e){return this.interviews.includes(e)?(this.json.events=(this.json.events??[]).filter(t=>t!==e),this.transcripts.delete(e),this.caseChanged=!0,!0):!1}keep(e,t,i=!1){e.recording=t,i&&(e.loaded=JSON.stringify(t)),e.kind==="reading"&&t.interpretation?.title!==void 0&&(e.event.title=t.interpretation.title)}replaceJson(e){const i=(e.events??[]).filter(n=>n.eventType===Di.SIGHTING_EVENT&&typeof n.url=="string"&&n.url!=="").map(n=>{const r=new URL(n.url,this.url).href,a=n.interpretationOf===void 0?"observer":"reading",o=this.tracks.find(c=>c.url===r);return o?(o.event=n,o.kind=a,o):{event:n,url:r,kind:a}});this.tracks.splice(0,this.tracks.length,...i);const s=new Map;for(const[n,r]of this.transcripts){const a=(e.events??[]).find(o=>o.eventType===Di.INTERVIEW_EVENT&&(n.id!==void 0&&o.id===n.id||n.url!==void 0&&o.url===n.url));a&&s.set(a,r)}this.transcripts.clear();for(const[n,r]of s)this.transcripts.set(n,r);this.json=e,this.caseChanged=!0}touch(){this.caseChanged=!0}get dirty(){return this.caseChanged||this.tracks.some(e=>this.changed(e))||[...this.transcripts.values()].some(e=>this.transcriptChanged(e))}markExported(e){if(this.caseChanged=!1,!!e){for(const t of this.tracks)t.recording&&(t.loaded=JSON.stringify(t.recording));for(const t of this.transcripts.values())t.loaded=t.text}}changed(e){return e.recording!==void 0&&(e.loaded===void 0||JSON.stringify(e.recording)!==e.loaded)}static ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]*$/;eventIds(e){return new Set((this.json.events??[]).filter(t=>t!==e?.event).map(t=>t.id).filter(t=>t!==void 0))}proposedId(e){const t=a=>(a??"").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),i=typeof e.event.title=="string"?e.event.title:void 0,s=t(e.recording?.observer?.lastName)||t(e.recording?.observer?.id)||t(i),n=this.eventIds(e);if(s!==""){let a=s;for(let o=2;n.has(a);o++)a=`${s}-${o}`;return a}let r=1;for(;n.has(`sighting-${r}`);)r++;return`sighting-${r}`}ensureId(e){return e.event.id===void 0&&(e.event.id=this.proposedId(e),this.caseChanged=!0),e.event.id}setId(e,t){const i=e.event.id,s=a=>a===i||a===e.recording?.id,n=(this.json.events??[]).filter(a=>a.eventType===Di.SIGHTING_EVENT&&a.interpretationOf!==void 0&&[a.interpretationOf].flat().some(o=>o!==void 0&&s(o))),r=this.interviews.filter(a=>[a.interviewOf].flat().some(o=>o!==void 0&&s(o)));if(t==="")return i===void 0?"ok":n.length>0||r.length>0?"empty":(delete e.event.id,this.caseChanged=!0,"ok");if(!zd.ID_PATTERN.test(t))return"invalid";if(this.eventIds(e).has(t))return"taken";if(t===i)return"ok";for(const a of n){const o=[a.interpretationOf].flat().map(c=>s(c)?t:c);a.interpretationOf=Array.isArray(a.interpretationOf)?o:o[0]}for(const a of r){const o=[a.interviewOf].flat().map(c=>c!==void 0&&s(c)?t:c);a.interviewOf=Array.isArray(a.interviewOf)?o:o[0]}return e.event.id=t,this.caseChanged=!0,"ok"}problems(){return Di.problems(this.json,this.tracks.map(e=>e.recording?.id).filter(e=>e!==void 0))}addReading(e,t,i,s){const n=e.recording;if(!n)throw new Error("A reading is added to an account that has been loaded");const r=e.event.url.replace(/^.*\//,"").replace(/^observer-/,"").replace(/\.json$/,""),a=new Set(this.tracks.map(R=>R.event.url)),o=new Set(this.tracks.map(R=>R.recording?.id));let c=this.tracks.filter(R=>R.kind==="reading").length+1;for(;a.has(`interpretation-${r}-${c}.json`)||o.has(`${n.id??r}-interpretation-${c}`);)c++;const h=`interpretation-${r}-${c}.json`,d=e.event.url.includes("/")?e.event.url.replace(/[^/]*$/,""):"",{id:u,version:p,observer:f,account:m,description:g,sources:v,tags:b,timeline:w,milestones:y,interpretation:M,...S}=structuredClone(n),E={version:1,id:`${n.id??r}-interpretation-${c}`,...S,tags:["interpretation"],timeline:{keyframes:[],order:[],groups:[]},interpretation:{...i!==void 0?{title:i}:{},bodies:[]}},x={type:"event",eventType:"sighting",interpretationOf:this.ensureId(e),time:t,...s!==void 0&&s.length>0?{by:s}:{},...i!==void 0?{title:i}:{},url:d+h};this.json.events=[...this.json.events??[],x],this.caseChanged=!0;const A={event:x,url:new URL(x.url,this.url).href,kind:"reading",recording:E};return this.tracks.push(A),A}idsOf(e){return[e.event.id,e.recording?.id].filter(t=>t!==void 0)}readingsOf(e){const t=this.idsOf(e);return this.tracks.filter(i=>i.kind==="reading"&&[i.event.interpretationOf].flat().some(s=>s!==void 0&&t.includes(s)))}addObservation(e,t,i,s){const n=new Set(this.tracks.map(m=>m.event.url)),r=new Set(this.tracks.map(m=>m.recording?.id)),a=(e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",o=s?"interpretation":"observer";let c=`${o}-${a}.json`,h=e.id??a;for(let m=2;n.has(c)||r.has(h);m++)c=`${o}-${a}-${m}.json`,h=`${e.id??a}-${m}`;const d={...e,id:h},u=this.tracks[0]?.event.url?.includes("/")?this.tracks[0].event.url.replace(/[^/]*$/,""):"",p={type:"event",eventType:"sighting",...s?{interpretationOf:this.ensureId(s.account)}:{},...t!==void 0?{time:t}:{},...s?.by&&s.by.length>0?{by:s.by}:{},...i!==void 0?{title:i}:{},url:u+c};this.json.events=[...this.json.events??[],p],this.caseChanged=!0;const f={event:p,url:new URL(p.url,this.url).href,kind:s?"reading":"observer",recording:d};return this.tracks.push(f),s||(p.id=this.proposedId(f)),f}deleteObservation(e){if(e.kind!=="observer")return{deleted:!1,readings:0};const t=this.readingsOf(e).length;if(t>0)return{deleted:!1,readings:t};const i=this.tracks.indexOf(e);return i<0?{deleted:!1,readings:0}:(this.tracks.splice(i,1),this.json.events=(this.json.events??[]).filter(s=>s!==e.event),this.caseChanged=!0,{deleted:!0})}deleteReading(e){if(e.kind!=="reading")return!1;const t=this.tracks.indexOf(e);return t<0?!1:(this.tracks.splice(t,1),this.json.events=(this.json.events??[]).filter(i=>i!==e.event),this.caseChanged=!0,!0)}files(e=!0,t=!1){const i=this.url.replace(/[^/]*$/,""),s=o=>o.startsWith(i)?o.slice(i.length):o,n=this.tracks.filter(o=>e&&o.recording!==void 0&&(t||this.changed(o))).map(o=>({path:s(o.url),content:JSON.stringify(o.recording,null,2)+`
334
+ `;class Zc extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(Zc.TAG)||customElements.define(Zc.TAG,Zc)}subject;messages=gg;languageToken=0;shadow;dialog;linkField;copyButton;linkBox;embedBox;linkOption;embedOption;freeze;embedMarkup;noteElement;codeEditor;codeLoading;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.shadow.innerHTML=BE;const e=t=>this.shadow.getElementById(t);this.dialog=e("dialog"),this.linkField=e("link"),this.copyButton=e("copy"),this.linkBox=e("link-box"),this.embedBox=e("embed-box"),this.linkOption=e("link-option"),this.embedOption=e("embed-option"),this.freeze=e("freeze"),this.embedMarkup=e("embed-markup"),this.noteElement=e("note"),e("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",t=>{t.target===this.dialog&&this.close()}),this.linkOption.addEventListener("click",()=>this.show("link")),this.embedOption.addEventListener("click",()=>this.show("embed")),this.freeze.addEventListener("change",()=>this.refresh()),this.copyButton.addEventListener("click",()=>void(this.embedBox.hidden?this.copy(this.linkField.value,this.linkField):this.copy(this.codeEditor?.text??this.embedMarkup.value,this.embedMarkup))),this.applyMessages()}async useLanguage(e){const t=++this.languageToken,i=e==="en"?gg:await DE(e);if(t===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(e){this.noteElement.textContent=e??"",this.noteElement.hidden=e===void 0}get isOpen(){return this.dialog.open||this.dialog.hasAttribute("open")}open(){this.refresh(),this.show("link"),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open",""),this.fitLink(),this.linkField.select()}close(){typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}refresh(){const e=this.subject;if(!e)return;const t=this.freeze.checked;this.linkField.value=t?na.frozenLink(e.link(),"0.152.1"):e.link(),this.fitLink();const s=`<script type="module" src="${t?na.frozen(e.module,"0.152.1"):na.current(e.module,import.meta.url,uh.home())}"><\/script>
335
+ ${e.element()}`;this.embedMarkup.value=s,this.codeEditor&&(this.codeEditor.text=s)}applyMessages(){const e=this.messages,t=(i,s)=>{this.shadow.getElementById(i).textContent=s};t("title",e.share),t("link-label",e.link),t("embed-label",e.embed),t("copy",e.copy),t("freeze-label",e.freeze.replace("{version}","0.152.1")),this.freeze.parentElement.title=e.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",e.close),this.linkField.setAttribute("aria-label",e.link)}show(e){this.linkBox.hidden=e!=="link",this.embedBox.hidden=e!=="embed",this.linkOption.setAttribute("aria-pressed",String(e==="link")),this.embedOption.setAttribute("aria-pressed",String(e==="embed")),e==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=ae(async()=>{const{ShareCodeEditor:e}=await import("./ShareCodeEditor-CF7IVeXv.js");return{ShareCodeEditor:e}},__vite__mapDeps([0,1]),import.meta.url).then(({ShareCodeEditor:e})=>{this.codeEditor=new e(this.shadow.getElementById("embed-code"),this.embedMarkup.value,t=>{this.embedMarkup.value=t},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(e,t){try{await navigator.clipboard.writeText(e),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{t.select()}}}class Tn{constructor(e){this.preferences=e}read(e){if(e===void 0||typeof e=="string")return e===""?void 0:e;for(const i of this.preferences){const s=e[i]??e[Tn.base(i)];if(s)return s}const t=new Set(this.preferences.map(i=>Tn.base(i)));for(const[i,s]of Object.entries(e))if(s&&t.has(Tn.base(i)))return s;return Object.values(e).find(i=>i)??void 0}write(e,t,i){const s=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return s;const n={...e},r=Object.keys(n).find(a=>a===i)??Object.keys(n).find(a=>Tn.base(a)===Tn.base(i))??i;return s===void 0?delete n[r]:n[r]=s,Object.keys(n).length===0?void 0:n}static base(e){return e.toLowerCase().split("-")[0]}}function Pd(l,e){for(const t of l){const i=t.toLowerCase().split("-")[0];if(e.includes(i))return i}return"en"}class sr{static preferencesFor(e){const t=navigator.languages??[],i=this.declaredFor(e);return i?[i,...t]:t}static declaredFor(e){for(let t=e;t;){const i=t.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const s=t.getRootNode();t=s instanceof ShadowRoot?s.host:void 0}}}class bn{static ISO=/^P(?:(\d+(?:[.,]\d+)?)W)?(?:(\d+(?:[.,]\d+)?)D)?(?:T(?:(\d+(?:[.,]\d+)?)H)?(?:(\d+(?:[.,]\d+)?)M)?(?:(\d+(?:[.,]\d+)?)S)?)?$/;static seconds(e){const t=e.trim().toUpperCase(),i=bn.ISO.exec(t);if(!i||t==="P"||t.endsWith("T"))return;const[,s,n,r,a,o]=i,c=d=>d===void 0?0:Number(d.replace(",",".")),h=c(s)*604800+c(n)*86400+c(r)*3600+c(a)*60+c(o);return Number.isFinite(h)?h:void 0}static parse(e){let t=e.trim();if(t==="")return;const i=t.slice(-1),s="?~%".includes(i)?i:"";s!==""&&(t=t.slice(0,-1).trim());const n=t.split("/");if(n.length>2)return;const r=n.map(d=>bn.seconds(d));if(r.some(d=>d===void 0))return;const[a,o]=r,c=Math.min(a,o??a),h=Math.max(a,o??a);return{doubt:s,minSeconds:c,maxSeconds:h,chosenSeconds:(c+h)/2}}static isExact(e){const t=bn.parse(e);return t!==void 0&&t.doubt===""&&t.minSeconds===t.maxSeconds}static format(e){const t=Math.max(0,Math.round(e*10)/10),i=Math.floor(t/3600),s=Math.floor(t%3600/60),n=Math.round(t%60*10)/10;return`PT${`${i>0?`${i}H`:""}${s>0?`${s}M`:""}${n>0||i===0&&s===0?`${n}S`:""}`}`}static say(e){const t=Math.round(e*10)/10;if(t<60)return`${t} s`;const i=Math.floor(t/3600),s=Math.floor(t%3600/60),n=Math.round(t%60*10)/10,r=[];return i>0&&r.push(`${i} h`),s>0&&r.push(`${s} min`),n>0&&r.push(`${n} s`),r.join(" ")}}class Rt{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(e){return 2*Math.atan(e.sizeM/(2*e.distanceM))*180/Math.PI}static inMoons(e){return e/Rt.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(e,t,i){if(!(!e||!t))return{widthDeg:e.widthDeg+(t.widthDeg-e.widthDeg)*i,heightDeg:e.heightDeg+(t.heightDeg-e.heightDeg)*i}}static sizeMAt(e,t){return 2*e*Math.tan(t*Math.PI/360)}static distanceMAt(e,t){return e/(2*Math.tan(t*Math.PI/360))}}function HE(l,e,t){if(!l||!e)return t<1?l:e;const i=((e.azimuthDeg-l.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((l.azimuthDeg+i*t)%360+360)%360,altitudeDeg:l.altitudeDeg+(e.altitudeDeg-l.altitudeDeg)*t}}function wx(l,e="#39ff14"){return{kind:"oval",bounds:l,color:e,angle:0,transparency:0,haloScale:0,selected:!1}}function Mx(l,e,t="#39ff14"){return{kind:"polygon",bounds:l,points:e,color:t,angle:0,transparency:0,haloScale:0,selected:!1}}function GE(l,e="#39ff14"){const{width:t,height:i}=l;return Mx(l,[{x:0,y:0},{x:t,y:0},{x:t,y:i},{x:0,y:i}],e)}const VE={oval:wx,polygon:GE};function u1(l,e){return{...VE[e.presetId](l,e.color),transparency:e.transparency,haloScale:e.haloScale,blur:e.blur,brightness:e.brightness}}function WE(l,e,t){const{bounds:i}=l;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height}function xx(l,e,t){const i=l.bounds.width,s=l.bounds.height;return{...l,bounds:{x:e-i/2,y:t-s/2,width:i,height:s}}}function Nn(l,e,t){return l+(e-l)*t}function p1(l){const e=/^#([0-9a-f]{6})$/i.exec(l);if(!e)return;const t=parseInt(e[1],16);return[t>>16&255,t>>8&255,t&255]}function $E(l){return`#${l.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function KE(l,e,t){const i=p1(l),s=p1(e);return!i||!s?t<1?l:e:$E([Nn(i[0],s[0],t),Nn(i[1],s[1],t),Nn(i[2],s[2],t)])}function XE(l,e,t){const i={x:Nn(l.bounds.x,e.bounds.x,t),y:Nn(l.bounds.y,e.bounds.y,t),width:Nn(l.bounds.width,e.bounds.width,t),height:Nn(l.bounds.height,e.bounds.height,t)},s=Nn(l.angle,e.angle,t),n=Nn(l.transparency,e.transparency,t),r=Nn(l.haloScale,e.haloScale,t),a=Nn(l.blur??0,e.blur??0,t),o=Nn(l.brightness??0,e.brightness??0,t),c=KE(l.color,e.color,t),h=Rt.lerpAngular(l.angular,e.angular,t),d=HE(l.aim,e.aim,t);return l.kind==="polygon"&&e.kind==="polygon"&&l.points.length===e.points.length?{...l,bounds:i,angle:s,transparency:n,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d,points:l.points.map((u,p)=>({x:Nn(u.x,e.points[p].x,t),y:Nn(u.y,e.points[p].y,t)}))}:{...t<1?l:e,bounds:i,angle:s,transparency:n,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d}}class Na{static DEFAULT_COLOR="#e8e6df";static complete(e,t=[]){const i=new Map;return e.map((s,n)=>({keyframe:s,index:n})).sort((s,n)=>s.keyframe.t-n.keyframe.t).map(({keyframe:s,index:n})=>({t:s.t,shapes:(s.shapes??[]).map((r,a)=>{const o=`timeline.keyframes.${n}.shapes.${a}.shape`,c=Na.completed(r,i.get(r.sourceId),o,t);return i.set(r.sourceId,c),{sourceId:r.sourceId,shape:c}})}))}static thin(e,t){const i=new Map,s=new Set;return e.map((n,r)=>({t:n.t,shapes:n.shapes.map(a=>{const o=i.get(a.sourceId);if(i.set(a.sourceId,a.shape),!o)return{sourceId:a.sourceId,shape:a.shape};const c=Na.thinned(a.shape,o);if(t){const h=c;t(r,a.sourceId)?(delete h.bounds,delete h.points,s.add(a.sourceId)):s.delete(a.sourceId)&&(h.bounds=a.shape.bounds,a.shape.kind==="polygon"&&(h.points=a.shape.points),a.shape.aim&&(h.aim=a.shape.aim),a.shape.angular&&(h.angular=a.shape.angular))}return{sourceId:a.sourceId,shape:c}})}))}static thinned(e,t){const i=t,s={};for(const[n,r]of Object.entries(e))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[n]&&JSON.stringify(r)!==JSON.stringify(i[n]))&&(s[n]=r);return"bounds"in s&&(e.aim&&(s.aim=e.aim),e.angular&&(s.angular=e.angular)),s}static completed(e,t,i,s){const n=e.shape??{},r=t??Na.firstAppearance(n,i,s),a={...r};n.bounds&&t&&(t.aim||t.angular)&&!n.aim&&!n.angular&&s.push({kind:"pixels-over-angles",path:i}),n.bounds&&(n.aim||delete a.aim,n.angular||delete a.angular);const o=n.kind??r.kind??"oval",c={...a,...n,kind:o};if(o==="polygon"&&!c.points){s.push({kind:"defaulted",path:`${i}.points`,expected:"rectangle"});const{width:h,height:d}=c.bounds;return{...c,points:[{x:0,y:0},{x:h,y:0},{x:h,y:d},{x:0,y:d}]}}return c}static firstAppearance(e,t,i){return e.kind||i.push({kind:"defaulted",path:`${t}.kind`,expected:'"oval"'}),e.color||i.push({kind:"defaulted",path:`${t}.color`,expected:`"${Na.DEFAULT_COLOR}"`}),!e.bounds&&!e.aim&&i.push({kind:"unplaced",path:t}),!e.bounds&&!e.angular&&i.push({kind:"unsized",path:t}),{kind:e.kind??"oval",bounds:{...Na.NEUTRAL_BOUNDS},color:Na.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:Rt.CANVAS_WIDTH_PX/2,y:Rt.CANVAS_HEIGHT_PX/2,width:1,height:1}}class am{keyframes=[];order=[];groups=[];span=0;addKeyframe(e,t){const i=this.findInsertIndex(e);if(this.keyframes[i]?.t===e){const s=new Set(t.map(n=>n.sourceId));this.keyframes[i]={t:e,shapes:[...this.keyframes[i].shapes.filter(n=>!s.has(n.sourceId)),...t]}}else this.keyframes.splice(i,0,{t:e,shapes:[...t]});for(const s of t)this.order.includes(s.sourceId)||this.order.push(s.sourceId)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getKeyframeAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t];return i?.t===e?i:void 0}getShapeAt(e,t){return this.getKeyframeAt(e)?.shapes.find(i=>i.sourceId===t)?.shape}getLatestShapeAt(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return s.shape}}getInterpolatedShapeAt(e,t){const i=this.findShapeAtOrBefore(e,t);if(i?.t===e)return i.shape;const s=this.findShapeAtOrAfter(e,t);return i?s?XE(i.shape,s.shape,(e-i.t)/(s.t-i.t)):i.shape:s?.shape}findShapeAtOrBefore(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return{t:this.keyframes[i].t,shape:s.shape}}}findShapeAtOrAfter(e,t){for(let i=this.findInsertIndex(e);i<this.keyframes.length;i++){const s=this.keyframes[i].shapes.find(n=>n.sourceId===t);if(s)return{t:this.keyframes[i].t,shape:s.shape}}}hitTest(e,t,i,s){const n=this.sourceIds;for(let r=n.length-1;r>=0;r--){if(s?.has(n[r]))continue;const a=this.getInterpolatedShapeAt(e,n[r]);if(a&&WE(a,t,i))return{sourceId:n[r],shape:a}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const i=this.keyframes[t].shapes.filter(s=>s.sourceId!==e);i.length===0?this.keyframes.splice(t,1):i.length!==this.keyframes[t].shapes.length&&(this.keyframes[t]={t:this.keyframes[t].t,shapes:i})}this.order=this.order.filter(t=>t!==e),this.removeFromGroup(e)}removeShapeAt(e,t){const i=this.findInsertIndex(e),s=this.keyframes[i];if(s?.t!==e)return;const n=s.shapes.filter(r=>r.sourceId!==t);n.length===0?this.keyframes.splice(i,1):n.length!==s.shapes.length&&(this.keyframes[i]={t:e,shapes:n})}group(e){if(!(e.length<2)){for(const t of e)this.removeFromGroup(t);this.groups.push([...e])}}ungroup(e){const t=this.groups.findIndex(i=>i.includes(e));t!==-1&&this.groups.splice(t,1)}groupMembers(e){return this.groups.find(t=>t.includes(e))}removeFromGroup(e){const t=this.groups.findIndex(s=>s.includes(e));if(t===-1)return;const i=this.groups[t].filter(s=>s!==e);i.length<2?this.groups.splice(t,1):this.groups[t]=i}bringToFront(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.push(e))}sendToBack(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.unshift(e))}get duration(){const e=this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t;return Math.max(e,this.span)}get hasSpan(){return this.span>0}setSpan(e){this.span=Math.max(0,e)}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return this.span>0?{keyframes:this.keyframes,order:this.order,groups:this.groups,span:this.span}:{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(e,t){const i=new am;for(const s of Na.complete(e.keyframes??[],t))i.addKeyframe(s.t,s.shapes);if(e.span!==void 0&&e.span>0&&(i.span=e.span),e.order){const s=i.order.filter(n=>!e.order.includes(n));i.order=[...e.order,...s]}return e.groups&&(i.groups=e.groups.map(s=>s.filter(n=>i.order.includes(n))).filter(s=>s.length>=2)),i}}function YE(l,e,t){return Math.max(e,Math.min(t,l))}function qE(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function ec(l,e,t){return l+(e-l)*t}function jE(l,e,t){return{lat:l.lat===void 0||e.lat===void 0?void 0:ec(l.lat,e.lat,t),lng:l.lng===void 0||e.lng===void 0?void 0:ec(l.lng,e.lng,t),elevationM:ec(l.elevationM,e.elevationM,t),headingDeg:l.headingDeg===void 0||e.headingDeg===void 0?void 0:qE(l.headingDeg,e.headingDeg,t),pitchDeg:ec(l.pitchDeg,e.pitchDeg,t),rollDeg:ec(l.rollDeg??0,e.rollDeg??0,t),fovDeg:ec(l.fovDeg,e.fovDeg,t),fNumber:l.fNumber,focusDistanceM:l.focusDistanceM,filter:l.filter}}class tn{static at(e,t,i,s,n){const r=e[i],o=e[i+1]-r;if(o<=0)return t[i];const c=tn.tangent(e,t,i,n),h=tn.tangent(e,t,i+1,n),d=(s-r)/o,u=d*d,p=u*d;return(2*p-3*u+1)*t[i]+(p-2*u+d)*o*c+(-2*p+3*u)*t[i+1]+(p-u)*o*h}static SETTLE_MS=120;static ARRIVAL=.5;static gaze(e,t,i,s){const n=e[i],a=e[i+1]-n;if(a<=0)return t[i];const o=h=>h+1<t.length?t[h+1]===t[h]:!0,c=t[i+1]!==t[i];if(c&&o(i+1)){const h=tn.tangent(e,t,i,!0),d=tn.ARRIVAL*(t[i+1]-t[i])/a;return tn.hermite(t[i],h,t[i+1],d,a,(s-n)/a)}return!c&&i>0&&t[i-1]!==t[i]?t[i]+tn.settle(e,t,i,s-n,a):tn.at(e,t,i,s,!0)}static settle(e,t,i,s,n){const r=e[i]-e[i-1];if(r<=0||s<=0)return 0;const a=tn.ARRIVAL*(t[i]-t[i-1])/r,o=Math.min(tn.SETTLE_MS,.4*r),c=Number.isFinite(n)?(1-Math.min(1,s/n))**2:1;return a*s*Math.exp(-s/o)*c}static hermite(e,t,i,s,n,r){const a=r*r,o=a*r;return(2*o-3*a+1)*e+(o-2*a+r)*n*t+(-2*o+3*a)*i+(o-a)*n*s}static BRAKE_S=.8;static paced(e,t,i,s){if(!i&&!s)return e;const n=t>0?Math.min(.5,tn.BRAKE_S/t):.5;if(i&&s){const a=1/(1-n);return e<=n?a*e*e/(2*n):e>=1-n?1-a*(1-e)*(1-e)/(2*n):a*(e-n/2)}const r=a=>{const o=1/(1-n/2);if(a<=1-n)return o*a;const c=a-(1-n);return o*(1-n)+o*(c-c*c/(2*n))};return s?r(e):1-r(1-e)}static tangent(e,t,i,s){const n=e.length-1,r=p=>(t[p+1]-t[p])/(e[p+1]-e[p]||1);if(i===0)return s?0:r(0);if(i===n)return s?0:r(n-1);const a=r(i-1),o=r(i);if(a*o<=0)return 0;const c=e[i]-e[i-1],h=e[i+1]-e[i],d=2*h+c,u=h+2*c;return(d+u)/(d/a+u/o)}}class Nd{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,pose:t}:this.keyframes.splice(i,0,{t:e,pose:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getLatestPoseAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].pose:void 0}getInterpolatedPoseAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.pose;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return s?.pose;if(!s)return this.settledAfterEnd(t-1,e);const n=jE(i.pose,s.pose,YE((e-i.t)/(s.t-i.t),0,1));return this.humanly(t-1,e,n)}settledAfterEnd(e,t){const i=this.keyframes[e];if(e<1)return i.pose;const s=this.keyframes[e-1],n=[s.t,i.t],r=(h,d)=>h===void 0||d===void 0?0:tn.settle(n,[h,d],1,t-i.t,1/0),a=s.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-s.pose.headingDeg)%360+540)%360-180,o=i.pose.headingDeg===void 0||a===void 0?i.pose.headingDeg:((i.pose.headingDeg+r(0,a))%360+360)%360,c=i.pose.pitchDeg+r(s.pose.pitchDeg,i.pose.pitchDeg);return o===i.pose.headingDeg&&c===i.pose.pitchDeg?i.pose:{...i.pose,headingDeg:o,pitchDeg:c}}humanly(e,t,i){const s=Math.max(0,e-1),n=Math.min(this.keyframes.length-1,e+2),r=this.keyframes.slice(s,n+1),a=e-s,o=r.map(y=>y.t),c=(y,M)=>{const S=r.map(E=>y(E.pose));if(!S.some(E=>E===void 0))return tn.at(o,S,a,t,M)},h=y=>{const M=r.map(S=>y(S.pose));if(!M.some(S=>S===void 0))return tn.gaze(o,M,a,t)},d=r.map(y=>y.pose.headingDeg);let u;if(d.every(y=>y!==void 0)){const y=[d[0]];for(let M=1;M<d.length;M++)y.push(y[M-1]+((d[M]-d[M-1])%360+540)%360-180);u=(tn.gaze(o,y,a,t)%360+360)%360}const p=this.keyframes[e],f=this.keyframes[e+1],m=(y,M)=>y.lat===M.lat&&y.lng===M.lng&&y.elevationM===M.elevationM,g=!m(p.pose,f.pose),v=g&&e>0&&m(this.keyframes[e-1].pose,p.pose),b=g&&e+2<this.keyframes.length&&m(f.pose,this.keyframes[e+2].pose);let w;if(v||b){const y=tn.paced((t-p.t)/(f.t-p.t),(f.t-p.t)/1e3,v,b),M=(S,E)=>S===void 0||E===void 0?void 0:S+(E-S)*y;w={lat:M(p.pose.lat,f.pose.lat),lng:M(p.pose.lng,f.pose.lng),elevationM:M(p.pose.elevationM,f.pose.elevationM)}}return{...i,lat:w?w.lat:c(y=>y.lat,!1)??i.lat,lng:w?w.lng:c(y=>y.lng,!1)??i.lng,elevationM:w?w.elevationM:c(y=>y.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:h(y=>y.pitchDeg)??i.pitchDeg,rollDeg:c(y=>y.rollDeg??0,!0)??i.rollDeg,fovDeg:c(y=>y.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Nd;for(const i of e.keyframes)t.addKeyframe(i.t,i.pose);return t}}class co{static MAX_CHANGE_PER_S=.05;points;followed;constructor(e){let t="none",i=0;this.points=e.map(({t:s,weather:n})=>(n.precipitationType!=="none"&&(t=n.precipitationType,i=n.precipitationIntensity),{t:s,lastFalling:t,lastFallingIntensity:i,intensity:n.precipitationType==="none"?0:n.precipitationIntensity,type:n.precipitationType})),this.followed=[];for(let s=0;s<this.points.length;s++){if(s===0){this.followed.push(this.points[0].intensity);continue}const n=this.points[s-1],r=this.points[s];this.followed.push(co.follow(this.followed[s-1],n.intensity,r.intensity,(r.t-n.t)/1e3,(r.t-n.t)/1e3))}}at(e){if(this.points.length===0||e<this.points[0].t)return;let t=this.points.length-1;for(;t>0&&this.points[t].t>e;)t--;const i=this.points[t],s=this.points[t+1],n=s?co.follow(this.followed[t],i.intensity,s.intensity,(s.t-i.t)/1e3,(e-i.t)/1e3):co.follow(this.followed[t],i.intensity,i.intensity,1,(e-i.t)/1e3);return{type:co.typeBetween(i,s,e,n),intensity:n,character:co.characterBetween(i,s,e)}}static characterBetween(e,t,i){return e.type==="none"?t&&t.type!=="none"?t.intensity:e.lastFallingIntensity:!t||t.type==="none"?e.intensity:e.intensity+(t.intensity-e.intensity)*(i-e.t)/(t.t-e.t||1)}static typeBetween(e,t,i,s){return e.type==="none"?t&&t.type!=="none"&&i>e.t?t.type:s>0?e.lastFalling:"none":t&&t.type==="none"&&s<=0?"none":e.type}static follow(e,t,i,s,n){const r=co.MAX_CHANGE_PER_S,a=s>0?(i-t)/s:0,o=d=>t+a*Math.min(Math.max(d,0),s);let c=e,h=0;for(let d=0;d<8&&h<n;d++){const u=o(h)-c;if(Math.abs(u)<1e-9){const w=h<s?a:0;if(Math.abs(w)<=r){const M=h<s?Math.min(n,s):n;c=o(M),h=M;continue}const y=Math.min(n,s);c+=Math.sign(w)*r*(y-h),h=y;continue}const p=Math.sign(u),f=h<s?a:0,m=r-p*f,g=m>0?h+Math.abs(u)/m:1/0,v=h<s?s:1/0,b=Math.min(n,g,v);c+=p*r*(b-h),h=b,b===g&&(c=o(h))}return Math.min(1,Math.max(0,c))}}const Jv=1e3,Hp=.65,Sx=.05,om={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function Io(l){if(l.cloudLayers!==void 0)return l.cloudLayers;const e=[],t=l.lowerCloudCover??l.cloudCover;return t>0&&e.push({id:"lower",type:"cumulus",baseM:l.cloudBaseM??Jv,thicknessM:650,coverage:t,sizeM:1400,density:1,darkness:l.cloudDarkness}),(l.highCloudCover??0)>0&&e.push({id:"cirrus",type:"cirrus",baseM:8e3,thicknessM:400,coverage:l.highCloudCover,sizeM:2200,density:.35,darkness:l.cloudDarkness,iceCrystalAlignment:l.iceCrystalAlignment}),e}function Ri(l,e,t){return l+(e-l)*t}function Qv(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function ZE(l,e,t){return Math.max(e,Math.min(t,l))}function JE(l=[],e=[],t){if(!(!l.length&&!e.length))return[...new Set([...l.map(i=>i.id),...e.map(i=>i.id)])].map(i=>{const s=l.find(o=>o.id===i),n=e.find(o=>o.id===i),r=s??{...n,density:0},a=n??{...s,density:0};return{...r,eastM:Ri(r.eastM,a.eastM,t),northM:Ri(r.northM,a.northM,t),baseM:Ri(r.baseM,a.baseM,t),thicknessM:Ri(r.thicknessM,a.thicknessM,t),widthM:Ri(r.widthM,a.widthM,t),depthM:Ri(r.depthM,a.depthM,t),rotationDeg:Qv(r.rotationDeg,a.rotationDeg,t),density:Ri(r.density,a.density,t),darkness:Ri(r.darkness??0,a.darkness??0,t)}})}function QE(l,e,t){if(l.cloudLayers===void 0&&e.cloudLayers===void 0)return;const i=Io(l),s=Io(e);return t>=1?s.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...s.map(r=>r.id)])].map(r=>{const a=i.find(d=>d.id===r),o=s.find(d=>d.id===r),c=a??{...o,coverage:0},h=o??{...a,coverage:0};return{...c,instances:JE(a?.instances,o?.instances,t),baseM:Ri(c.baseM,h.baseM,t),thicknessM:Ri(c.thicknessM,h.thicknessM,t),coverage:Ri(c.coverage,h.coverage,t),sizeM:Ri(c.sizeM,h.sizeM,t),density:Ri(c.density,h.density,t),darkness:Ri(c.darkness??l.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:c.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Ri(c.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:c.windSpeed===void 0&&h.windSpeed===void 0?void 0:Ri(c.windSpeed??l.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:c.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Qv(c.windDirectionDeg??l.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function eA(l,e,t){return{cloudLayers:QE(l,e,t),cloudCover:Ri(l.cloudCover,e.cloudCover,t),cloudDarkness:Ri(l.cloudDarkness,e.cloudDarkness,t),highCloudCover:l.highCloudCover===void 0||e.highCloudCover===void 0?void 0:Ri(l.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:Ri(l.iceCrystalAlignment,e.iceCrystalAlignment,t),rareIceCrystals:l.rareIceCrystals===void 0||e.rareIceCrystals===void 0?void 0:Ri(l.rareIceCrystals,e.rareIceCrystals,t),lowerCloudCover:l.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:Ri(l.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:l.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:Ri(l.cloudBaseM,e.cloudBaseM,t),relativeHumidity:l.relativeHumidity===void 0||e.relativeHumidity===void 0?void 0:Ri(l.relativeHumidity,e.relativeHumidity,t),precipitationType:t<1?l.precipitationType:e.precipitationType,precipitationIntensity:Ri(l.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Qv(l.windDirectionDeg,e.windDirectionDeg,t),windSpeed:Ri(l.windSpeed,e.windSpeed,t),storm:t<1?l.storm:e.storm}}class Fd{keyframes=[];ramp;addKeyframe(e,t){this.ramp=void 0;const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,weather:t}:this.keyframes.splice(i,0,{t:e,weather:t})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(e){this.ramp=void 0;const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}getLatestWeatherAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].weather:void 0}getInterpolatedWeatherAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.weather;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return i?s?eA(i.weather,s.weather,ZE((e-i.t)/(s.t-i.t),0,1)):i.weather:s?.weather}getActualWeatherAt(e){const t=this.getInterpolatedWeatherAt(e);if(!t)return;const i=(this.ramp??=new co(this.keyframes)).at(e);if(!i)return t;const{type:s,intensity:n,character:r}=i,a=r>0?Math.min(1,n/r):s==="none"?0:1;return{...t,precipitationType:s,precipitationIntensity:r,precipitationAmount:a}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Fd;for(const i of e.keyframes)t.addKeyframe(i.t,{...om,...i.weather});return t}}class Ud{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,sound:t}:this.keyframes.splice(i,0,{t:e,sound:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}getLatestSoundAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].sound:void 0}getInterpolatedSoundAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.sound;const s=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return s?.sound;if(!s)return i.sound;const n=(e-i.t)/(s.t-i.t);return this.lerp(i.sound,s.sound,Math.max(0,Math.min(1,n)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Ud;for(const i of e.keyframes)t.addKeyframe(i.t,i.sound);return t}lerp(e,t,i){return{kind:i<1?e.kind:t.kind,volume:e.volume+(t.volume-e.volume)*i,pitchHz:e.pitchHz+(t.pitchHz-e.pitchHz)*i,src:i<1?e.src:t.src}}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const s=t+i>>>1;this.keyframes[s].t<e?t=s+1:i=s}return t}}const tA=["none","hum","whistle","rumble","crackle"],iA=100,sA={kind:"none",volume:0,pitchHz:iA};class Oc{static DEFAULT_FOCAL_MM=50;static FOCAL_RANGE_MM={minMm:14,maxMm:135};static BODIES=[{id:"eos-450d",name:"Canon EOS 450D (APS-C)",widthMm:22.2,heightMm:14.8,pixelUm:5.2,year:2008},{id:"eos-60da",name:"Canon EOS 60Da (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.3,year:2012},{id:"eos-70d",name:"Canon EOS 70D (APS-C)",widthMm:22.5,heightMm:15,pixelUm:4.1,year:2013},{id:"eos-80d",name:"Canon EOS 80D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:3.7,year:2016},{id:"eos-7d",name:"Canon EOS 7D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.1,year:2009},{id:"eos-7d-ii",name:"Canon EOS 7D Mark II (APS-C)",widthMm:22.4,heightMm:15,pixelUm:4.1,year:2014},{id:"eos-5d",name:"Canon EOS 5D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:8.2,year:2005},{id:"eos-5d-ii",name:"Canon EOS 5D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:6.4,year:2008},{id:"eos-5d-iii",name:"Canon EOS 5D Mark III (full frame)",widthMm:36,heightMm:24,pixelUm:6.25,year:2012},{id:"eos-5d-iv",name:"Canon EOS 5D Mark IV (full frame)",widthMm:36,heightMm:24,pixelUm:5.36,year:2016},{id:"eos-6d",name:"Canon EOS 6D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:6.55,year:2012},{id:"eos-6d-ii",name:"Canon EOS 6D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:5.77,year:2017},{id:"nikon-d3",name:"Nikon D3 / D700 (full frame)",widthMm:36,heightMm:23.9,pixelUm:8.44,year:2007},{id:"nikon-d7000",name:"Nikon D7000 (DX)",widthMm:23.6,heightMm:15.6,pixelUm:4.78,year:2010},{id:"nikon-d7100",name:"Nikon D7100 / D7200 (DX)",widthMm:23.5,heightMm:15.6,pixelUm:3.9,year:2013},{id:"nikon-d500",name:"Nikon D500 / D7500 (DX)",widthMm:23.5,heightMm:15.7,pixelUm:4.2,year:2016}];static instruments(){return Oc.BODIES.map(e=>({id:e.id,category:"dslr",name:e.name,projection:"rectilinear",frame:{widthMm:e.widthMm,heightMm:e.heightMm,focalLengthMm:Oc.DEFAULT_FOCAL_MM,focalRangeMm:Oc.FOCAL_RANGE_MM},fNumber:8,fNumberRange:{min:1.4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/8e3,max:3600},years:{from:e.year},apertureBlades:7,detailUm:e.pixelUm,medium:{kind:"sensor",iso:100}}))}static names(){return Object.fromEntries(Oc.BODIES.map(e=>[e.id,e.name]))}}class Er{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*Er.DEFAULT_EYEPIECE_MM*Math.tan(Er.DEFAULT_APPARENT_FIELD_DEG*Math.PI/360);static RANGE={min:26/40*.63,max:26/6*3};static BINOCULARS=[{id:"binoculars-zeiss-6x30",name:"Carl Zeiss 6x30",magnification:6,apertureMm:30,trueFieldDeg:5,fromYear:1960},{id:"binoculars-zeiss-dialyt-10x40",name:"Carl Zeiss Dialyt 10x40 B T*",magnification:10,apertureMm:40,trueFieldDeg:6.3,fromYear:1975},{id:"binoculars-jenoptem-10x50",name:"Jenoptem 10x50 W",magnification:10,apertureMm:50,trueFieldDeg:7.3,fromYear:1960},{id:"binoculars-swarovski-7x50-habicht",name:"Swarovski 7x50 SL Habicht",magnification:7,apertureMm:50,trueFieldDeg:6.6,fromYear:1960},{id:"binoculars-swarovski-7x50-slc",name:"Swarovski 7x50 SLC",magnification:7,apertureMm:50,trueFieldDeg:7.1,fromYear:1990},{id:"binoculars-nikon-10x42-edg",name:"Nikon 10x42 EDG",magnification:10,apertureMm:42,trueFieldDeg:6.5,fromYear:2011},{id:"binoculars-canon-15x50-is",name:"Canon 15x50 IS All Weather",magnification:15,apertureMm:50,trueFieldDeg:4.5,fromYear:2008},{id:"binoculars-celestron-15x70",name:"Celestron 15x70 SkyMaster",magnification:15,apertureMm:70,trueFieldDeg:4.4,fromYear:1990},{id:"binoculars-miyauchi-25x141",name:"Miyauchi BR-141 Galaxy 45 25x141",magnification:25,apertureMm:141,trueFieldDeg:2.6,fromYear:2e3}];static TELESCOPES=[{id:"telescope-generic-60-700",name:"Telescope 60/700",apertureMm:60,focalLengthMm:700},{id:"telescope-generic-60-1000",name:"Telescope 60/1000",apertureMm:60,focalLengthMm:1e3},{id:"telescope-celestron-onyx-80edf",name:"Celestron Onyx 80EDF",apertureMm:80,focalLengthMm:500,fromYear:2010},{id:"telescope-celestron-c5",name:"Celestron C5 f/10",apertureMm:125,focalLengthMm:1250,fromYear:1970},{id:"telescope-celestron-c8",name:"Celestron C8 f/10",apertureMm:203,focalLengthMm:2032,fromYear:1970},{id:"telescope-celestron-c11",name:"Celestron C11 f/10",apertureMm:280,focalLengthMm:2800,fromYear:1970},{id:"telescope-celestron-c14",name:"Celestron C14 f/11",apertureMm:355.6,focalLengthMm:3910,fromYear:1970},{id:"telescope-meade-etx-80",name:"Meade ETX 80 f/5",apertureMm:80,focalLengthMm:400,fromYear:1996},{id:"telescope-meade-etx-90",name:"Meade ETX 90 f/13.8",apertureMm:90,focalLengthMm:1242,fromYear:1996},{id:"telescope-meade-etx-125",name:"Meade ETX 125 f/15",apertureMm:127,focalLengthMm:1900,fromYear:1996},{id:"telescope-meade-lx200-8",name:"Meade LX200 8 in f/10",apertureMm:200,focalLengthMm:2e3,fromYear:1992},{id:"telescope-meade-lx200-10",name:"Meade LX200 10 in f/10",apertureMm:250,focalLengthMm:2500,fromYear:1992},{id:"telescope-meade-lx200-12",name:"Meade LX200 12 in f/10",apertureMm:305,focalLengthMm:3048,fromYear:1992},{id:"telescope-meade-lx200-14",name:"Meade LX200 14 in f/10",apertureMm:355,focalLengthMm:3556,fromYear:1992},{id:"telescope-meade-lx200-16",name:"Meade LX200 16 in f/10",apertureMm:406,focalLengthMm:4064,fromYear:1992}];static instruments(){const e=Er.BINOCULARS.map(s=>({id:s.id,category:"binoculars",name:s.name,projection:"rectilinear",visualAid:{apertureMm:s.apertureMm,magnification:s.magnification,trueFieldDeg:s.trueFieldDeg},...s.fromYear!==void 0?{years:{from:s.fromYear}}:{}})),t=Er.FIELD_STOP_MM,i=Er.TELESCOPES.map(s=>({id:s.id,category:"telescope",name:s.name,projection:"rectilinear",frame:{widthMm:t*16/9,heightMm:t,focalLengthMm:s.focalLengthMm,focalRangeMm:{minMm:s.focalLengthMm*Er.RANGE.min,maxMm:s.focalLengthMm*Er.RANGE.max}},visualAid:{apertureMm:s.apertureMm,eyepieceFocalMm:Er.DEFAULT_EYEPIECE_MM},...s.fromYear!==void 0?{years:{from:s.fromYear}}:{}}));return[...e,...i]}static names(){return Object.fromEntries(Er.instruments().map(e=>[e.id,e.name]))}}const rd=[{id:"eye",category:"eye",name:"Naked eye",projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",category:"camera",name:"Camera, unknown device",projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"roamer-1-120",category:"camera",name:"Roamer 1, 120 film",projection:"rectilinear",frame:{widthMm:74,heightMm:60,focalLengthMm:100},fNumber:11,exposureSeconds:1/50,years:{from:1930,to:1965},detailUm:40,medium:{kind:"negative",iso:125}},{id:"instamatic-126",category:"camera",name:"Instamatic, 126 film",projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20,medium:{kind:"negative",iso:64}},{id:"slr-35mm-50",category:"camera",name:"35 mm SLR, 50 mm lens",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20,medium:{kind:"negative",iso:100}},{id:"slr-35mm-zoom",category:"camera",name:"35 mm SLR, 70-210 mm zoom",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20,medium:{kind:"negative",iso:100}},{id:"phone-landscape",category:"phone",name:"Phone, held sideways",projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"phone-portrait",category:"phone",name:"Phone, held upright",projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"dashcam",mounted:!0,category:"video",name:"Dashcam",projection:"equidistant",frame:{widthMm:5.76,heightMm:3.24,focalLengthMm:3.2},fNumber:2,exposureSeconds:1/30,exposureRangeSeconds:{min:1/1e4,max:1/30},years:{from:2008},apertureBlades:void 0,detailUm:3,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},{id:"cctv",mounted:!0,category:"video",name:"Security camera",projection:"rectilinear",frame:{widthMm:4.8,heightMm:3.6,focalLengthMm:3.6},fNumber:2,exposureSeconds:1/50,exposureRangeSeconds:{min:1/1e5,max:1/50},years:{from:1990},apertureBlades:void 0,detailUm:6,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},...Oc.instruments(),...Er.instruments()];class Yt{static get default(){return rd[0]}static byId(e){return rd.find(t=>t.id===e)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(e){const t=e.frame;return t?Yt.fieldOf(e.projection,t.heightMm,t.focalLengthMm):e.visualAid?.trueFieldDeg??Yt.UNAIDED_FIELD_DEG}static fieldOf(e,t,i){return(e==="equidistant"?t/i:2*Math.atan(t/(2*i)))*180/Math.PI}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Yt.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Yt.aspectOf(e))}static CATEGORIES=["eye","camera","dslr","phone","video","binoculars","telescope"];static unavailability(e,t){const i=e.years;if(!(t===void 0||!i)){if(t<i.from)return{kind:"before",from:i.from};if(i.to!==void 0&&t>i.to)return{kind:"after",to:i.to}}}static availableAt(e){return e===void 0?rd:rd.filter(t=>!t.years||e>=t.years.from&&(t.years.to===void 0||e<=t.years.to))}static fieldOfViewDegAt(e,t){const i=e.frame;if(!(!i||t<=0))return Yt.fieldOf(e.projection,i.heightMm,t)}static focalLengthMmFor(e,t){const i=e.frame;if(!(!i||t<=0||t>=180))return e.projection==="equidistant"?i.heightMm/(t*Math.PI/180):i.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){if(e.apertureBlades===void 0)return 0;const i=t??e.fNumber,s=e.fNumberRange?.min;if(i===void 0||s===void 0)return 1;const n=Math.max(0,Math.min(1,(i/s-1)/.3));return n*n*(3-2*n)}static starPointsOf(e,t){const i=e.apertureBlades;return i===void 0||i<3||Yt.bladesShowing(e,t)<.5?0:i%2===0?i:i*2}}class Gl extends Error{}class lm{constructor(e){this.name=e}validate(e){return!0}}class Ex extends lm{min;max;constructor(e,t,i){super(e),this.min=t,this.max=i}validate(e){if(typeof e!="number")throw new Gl(`${this.name} value must be a number, but was ${e}`);if(e<this.min||e>this.max)throw new Gl(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${e}`);return super.validate(e)}}class ys{name;min;max;duration;subUnit;validator;constructor(e,t,i,s,n=new Ex(e,t,i)){this.name=e,this.min=t,this.max=i,this.subUnit=s,this.duration=s?(s.max-s.min+1)*s.duration:1,this.validator=n}validate(e){return this.validator.validate(e)}[Symbol.iterator](){let e=this.min;return{next:()=>{const t={done:e>this.max,value:e};return e++,t}}}}class Ax{millisecond;second;minute;hour;day;month;year}class nA extends Ax{}class Tx extends nA{millisecond=new ys("millisecond",0,999,void 0);second=new ys("second",0,59,this.millisecond);minute=new ys("minute",0,59,this.second);hour=new ys("hour",0,23,this.minute);day=new ys("day",1,31,this.hour);month=new ys("month",1,12,this.day);year=new ys("year",0,9999,this.month)}const pt=new Tx;class rA extends Ex{constructor(e=1,t=12){super("month",e,t)}}class pa{static instance=new pa;render(e){return e.value.toString()}}class rn{unit;#e;constructor(e,t){this.unit=t,this.value=typeof e=="number"?e:e.value}get value(){return this.#e}set value(e){this.unit.validate(e),this.#e=e}get duration(){return this.value*this.unit.duration}#t(e){if(this.constructor.name!==e.constructor.name)throw new lm(`${this.unit.name} "${this.toString()}" cannot be compared with ${e.unit?.name} "${e.toString()}"`)}compare(e){return this.#t(e),this.value-e.value}isEqual(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}previous(e=this.unit){const t=this.value-1;return new this.constructor(t,e)}next(e=this.unit){const t=this.value+1;return new this.constructor(t,e)}toString(e=pa.instance){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class xi{static#e=new Map;static register(e,t){xi.#e.set(e,t)}static get(e){const t=xi.#e.get(e);if(!t)throw new Gl(`No default parser registered for ${e.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return t()}}class Gp extends rn{constructor(e=new Date().getFullYear(),t=pt.year){super(e,t)}static fromString(e,t=xi.get(Gp)){return new Gp(t.parse(e))}}class xa extends pa{static default=new xa("0",2);constructor(e,t){super(),this.char=e,this.size=t}render(e){return super.render(e).padStart(this.size,this.char)}}class Vp extends rn{constructor(e=new Date().getMonth()+1,t=pt.month){super(e,t)}static fromString(e,t=xi.get(Vp)){return new Vp(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Wp extends rn{constructor(e=new Date().getDate(),t=pt.day){super(e,t)}static fromString(e,t=xi.get(Wp)){const i=t.parse(e);return new Wp(i)}toString(e=xa.default){return super.toString(e)}}class $p extends rn{constructor(e=new Date().getHours(),t=pt.hour){super(e,t)}static fromString(e,t=xi.get($p)){return new $p(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Kp extends rn{constructor(e=new Date().getMinutes(),t=pt.minute){super(e,t)}static fromString(e,t=xi.get(Kp)){return new Kp(t.parse(e))}toString(e=xa.default){return super.toString(e)}}class Xp extends rn{constructor(e=new Date().getSeconds(),t=pt.second){super(e,t)}static fromString(e,t=xi.get(Xp)){return new Xp(t.parse(e),pt.second)}toString(e=xa.default){return super.toString(e)}}class jl extends rn{static renderer=new xa("0",3);constructor(e,t=pt.millisecond){super(e,t)}static parseFraction(e){return parseInt(e.padEnd(3,"0").substring(0,3),10)}toString(e=jl.renderer){return super.toString(e)}}class aA{render(e){return e.toString()}}class oA extends aA{render(e){const t=e.value,i=Math.abs(t),s=Math.floor(i/60),n=i%60;if(s===0&&n===0)return"Z";{const r=t<0?"-":"+",a=s.toString().padStart(2,"0"),o=n>0?":"+n.toString().padEnd(2,"0"):"";return r+a+o}}}class ph{value;name="timeshift";renderer;constructor(e=0){this.value=e}static fromString(e,t=xi.get(ph),i=void 0){const s=t.parse(e,i);return new ph(s)}toString(e=new oA){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class Qs{static timeshift(e,t){return e+(Qs.isDaylight(t)?60:0)}static isDaylight(e){const{year:t,month:i,day:s}=e,n=e.hour??12;if(![t,i,s].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=Qs.rule(t);if(!r)return!1;const a=Qs.rank(i,s,n);return a>=Qs.rank(r.start.month,r.start.day,2)&&a<Qs.rank(r.end.month,r.end.day,2)}static rule(e){if(e<1967)return;const t={month:10,day:Qs.sunday(e,10,-1)};return e>=2007?{start:{month:3,day:Qs.sunday(e,3,2)},end:{month:11,day:Qs.sunday(e,11,1)}}:e>=1987?{start:{month:4,day:Qs.sunday(e,4,1)},end:t}:e===1975?{start:{month:2,day:23},end:t}:e===1974?{start:{month:1,day:6},end:t}:{start:{month:4,day:Qs.sunday(e,4,-1)},end:t}}static sunday(e,t,i){const s=new Date(Date.UTC(2e3,t-1,1));s.setUTCFullYear(e);const n=1+(7-s.getUTCDay())%7;if(i>0)return n+7*(i-1);const r=[31,Qs.isLeap(e)?29:28,31,30,31,30,31,31,30,31,30,31][t-1];let a=n;for(;a+7<=r;)a+=7;return a}static isLeap(e){return e%4===0&&(e%100!==0||e%400===0)}static rank(e,t,i){return(e*100+t)*100+i}}const lA={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},cA={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},hA={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},dA={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},uA={name:"PT",timeshift:l=>Qs.timeshift(-480,l),title:"Pacific Time (US)"},pA={name:"MT",timeshift:l=>Qs.timeshift(-420,l),title:"Mountain Time (US)"},fA={name:"CT",timeshift:l=>Qs.timeshift(-360,l),title:"Central Time (US)"},mA={name:"ET",timeshift:l=>Qs.timeshift(-300,l),title:"Eastern Time (US)"},gA={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},vA={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},bA={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},yA={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},wA={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},MA={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},xA={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},SA={name:"Z",timeshift:"Z",title:"UTC"},EA={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},AA={name:"BST",timeshift:"+01",title:"British Summer Time"},TA={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},IA={name:"CET",timeshift:"+01",title:"Central European Time"},_A={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},RA={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},DA={name:"BJT",timeshift:"+08",title:"Beijing Time"},kA={name:"CST",timeshift:"-06",title:"Central Standard Time"},CA={name:"JST",timeshift:"+09",title:"Japan Standard Time"},LA={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},OA={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},PA={name:"LST",timeshift:"?",title:"Local Sideral Time"},f1=[MA,LA,wA,DA,AA,kA,vA,IA,TA,fA,gA,yA,bA,mA,EA,RA,CA,PA,hA,_A,dA,pA,OA,cA,lA,uA,xA,SA];class cm{static instance=new cm;renderComponent(e,t){return e[t].toString()}renderSecond(e){return this.renderComponent(e,"second")+(e.millisecond?"."+e.millisecond.toString():"")}render(e){const t=[];e.year&&t.push(this.renderComponent(e,"year")),e.month&&t.push(this.renderComponent(e,"month")),e.day&&t.push(this.renderComponent(e,"day"));const i=[];e.hour&&i.push(this.renderComponent(e,"hour")),e.minute&&i.push(this.renderComponent(e,"minute")),e.second&&i.push(this.renderSecond(e));const s=t.join("-"),n=e.timeshift?e.timeshift.toString():"",r=i.join(":")+n;return s+(r.length>0?"T"+r:"")}}class jo extends Gl{constructor(e="method is abstract"){super(e)}}class eb{units;constructor(e){this.units=e}newYear(e){throw new jo}newMonth(e){throw new jo}newDay(e){throw new jo}newHour(e){throw new jo}newMinute(e){throw new jo}newSecond(e){throw new jo}}class NA extends Ax{millisecond=new ys("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new ys("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new ys("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new ys("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new ys("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new ys("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new ys("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const tb=new NA;class ib{static instance=new ib;render(e){const t=ol.toSpec(e);let i="P";const s=t.years;s&&(i+=s.toString()+"Y");const n=t.months;n&&(i+=n.toString(pa.instance)+"MM");const r=t.days;r&&(i+=r.toString(pa.instance)+"D");const a=t.hours;a&&(i+=a.toString(pa.instance)+"H");const o=t.minutes;o&&(i+=o.toString(pa.instance)+"M");const c=t.seconds;return c&&(i+=c.toString(pa.instance)+"S"),i}}class ol extends rn{constructor(e={years:new Date().getFullYear(),months:new Date().getMonth(),days:new Date().getDate(),hours:new Date().getHours(),minutes:new Date().getMinutes(),seconds:new Date().getSeconds(),milliseconds:new Date().getMilliseconds()}){super({value:typeof e=="number"?e:+(e.years?e.years*pt.year.duration:0)+(e.months?e.months*pt.month.duration:0)+(e.days?e.days*pt.day.duration:0)+(e.hours?e.hours*pt.hour.duration:0)+(e.minutes?e.minutes*pt.minute.duration:0)+(e.seconds?e.seconds*pt.second.duration:0)},new ys("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(e,t=UA){let i=typeof e=="number"?e:e.value;const s=i>0?1:-1;i=Math.abs(i);const n={},r=i/pt.year.duration,a=Math.floor(r);a>0&&(n.years=t.newYear(s*a),i-=a*pt.year.duration);const o=i/pt.month.duration,c=Math.floor(o);c>0&&(n.months=t.newMonth(s*c),i-=c*pt.month.duration);const h=i/pt.day.duration,d=Math.floor(h);d>0&&(n.days=t.newDay(s*d),i-=d*pt.day.duration);const u=i/pt.hour.duration,p=Math.floor(u);p>0&&(n.hours=t.newHour(s*p),i-=p*pt.hour.duration);const f=i/pt.minute.duration,m=Math.floor(f);m>0&&(n.minutes=t.newMinute(s*m),i-=m*pt.minute.duration);const g=i/pt.second.duration,v=Math.floor(s*g);return v>0&&(n.seconds=t.newSecond(v)),n}static fromString(e,t=xi.get(ol)){return new ol(t.parse(e))}static between(e,t){const i=t.getTime(),s=e.getTime();return new ol(i-s)}toSpec(){return ol.toSpec(this)}toString(e=ib.instance){return e.render(this)}}class Ix extends eb{constructor(e){super(e)}newYear(e){return new Gp(e,this.units.year)}newMonth(e){return new Vp(e,this.units.month)}newDay(e){return new Wp(e,this.units.day)}newHour(e){return new $p(e,this.units.hour)}newMinute(e){return new Kp(e,this.units.minute)}newSecond(e){return new Xp(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new ph(typeof e=="number"?e:e.value)}}const FA=new Ix(pt),UA=new Ix(tb);class kr{#e;#t;#i;#s;#n;#r;#a;#o;constructor(e={year:new Date().getFullYear(),month:new Date().getMonth()+1,day:new Date().getDate(),hour:new Date().getHours(),minute:new Date().getMinutes(),second:new Date().getSeconds(),timeshift:kr.timeshiftOf(new Date)}){this.year=e.year,this.month=e.month,this.day=e.day,this.hour=e.hour,this.minute=e.minute,this.second=e.second,this.millisecond=e.millisecond,this.timeshift=e.timeshift}get year(){return this.#e}set year(e){const t=typeof e=="number";this.#e&&t?this.#e.value=e:this.#e=t?this.factory.newYear(e):!e||e.start||e instanceof rn?e:this.factory.newYear(e)}get month(){return this.#t}set month(e){const t=typeof e=="number";this.#t&&t?this.#t.value=e:this.#t=t?this.factory.newMonth(e):!e||e.start||e instanceof rn?e:this.factory.newMonth(e)}get day(){return this.#i}set day(e){const t=typeof e=="number";this.#i&&t?this.#i.value=e:this.#i=t?this.factory.newDay(e):!e||e.start||e instanceof rn?e:this.factory.newDay(e)}get hour(){return this.#s}set hour(e){const t=typeof e=="number";this.#s&&t?this.#s.value=e:this.#s=t?this.factory.newHour(e):!e||e.start||e instanceof rn?e:this.factory.newHour(e)}get minute(){return this.#n}set minute(e){const t=typeof e=="number";this.#n&&t?this.#n.value=e:this.#n=t?this.factory.newMinute(e):!e||e.start||e instanceof rn?e:this.factory.newMinute(e)}get second(){return this.#r}set second(e){const t=typeof e=="number";this.#r&&t?this.#r.value=e:this.#r=t?this.factory.newSecond(e):!e||e.start||e instanceof rn?e:this.factory.newSecond(e)}get millisecond(){return this.#a}set millisecond(e){const t=typeof e=="number";this.#a&&t?this.#a.value=e:this.#a=t||e&&!(e instanceof rn)?this.factory.newMillisecond(e):e}get timeshift(){return this.#o}set timeshift(e){const t=typeof e=="number";this.#o&&t?this.#o.value=e:this.#o=t||e&&!(e instanceof ph)?this.factory.newTimeshift(e):e}get factory(){return FA}static fromString(e,t=xi.get(kr)){const{year:i,month:s,day:n,hour:r,minute:a,second:o,millisecond:c,timeshift:h}=t.parse(e);return new kr({year:i,month:s,day:n,hour:r,minute:a,second:o,millisecond:c,timeshift:h})}static timeshiftOf(e){return-e.getTimezoneOffset()||0}static fromDate(e){return new kr({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return kr.fromString(i)}#l(e){if(this.constructor.name!==e.constructor.name)throw new lm(`Date "${this.toString()}" cannot be compared with "${e.toString()}"`)}compare(e){return this.#l(e),this.getTime()-e.getTime()}delta(e){const t=this.compare(e);return new ol(t)}getTime(){return(this.year?.duration||0)+(this.month?.duration||0)+(this.day?.duration||0)+(this.hour?.duration||0)+(this.minute?.duration||0)+(this.second?.duration||0)+(this.millisecond?.duration||0)}isEqual(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}clone(){return new kr(this.toSpec())}previous(){let e=this.clone();try{e.second=this.second.previous()}catch{try{e.minute=this.minute.previous()}catch{try{e.hour=this.hour.previous()}catch{try{e.day=this.day.previous()}catch{try{e.month=this.month.previous()}catch{e.year=this.year.previous()}}}}}return e}next(){let e=this.clone();try{e.second=this.second.next()}catch{try{e.minute=this.minute.next()}catch{try{e.hour=this.hour.next()}catch{try{e.day=this.day.next()}catch{try{e.month=this.month.next()}catch{e.year=this.year.next()}}}}}return e}toString(e=cm.instance){return e.render(this)}toSpec(){const e={},t=this.year?.toSpec();t&&(e.year=t);const i=this.month?.toSpec();i&&(e.month=i);const s=this.day?.toSpec();s&&(e.day=s);const n=this.hour?.toSpec();n&&(e.hour=n);const r=this.minute?.toSpec();r&&(e.minute=r);const a=this.second?.toSpec();a&&(e.second=a);const o=this.millisecond?.toSpec();o&&(e.millisecond=o);const c=this.timeshift?.toSpec();return c&&(e.timeshift=c),e}toJSON(){return this.toSpec()}}class nu extends pa{static instance=new nu(xa.default);constructor(e){super(),this.valueRenderer=e}render(e){return(this.valueRenderer?this.valueRenderer.render(e):super.render(e))+this.qualifier(e)}qualifier(e){return e.uncertain?e.approximate?"%":"?":e.approximate?"~":""}}class Zl extends rn{#e;#t;constructor(e,t){super(e,t),this.#e=e.uncertain||!1,this.#t=e.approximate||!1}get uncertain(){return this.#e}set uncertain(e){return this.#e=e}get approximate(){return this.#t}set approximate(e){return this.#t=e}isCertainAndPrecise(){return!this.approximate&&!this.uncertain}isEqual(e){return this.isCertainAndPrecise()&&super.isEqual(e)}isBefore(e){return this.isCertainAndPrecise()&&super.isBefore(e)}isAfter(e){return this.isCertainAndPrecise()&&super.isAfter(e)}toString(e=nu.instance){return super.toString(e)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class _x extends Tx{year=new ys("year",-9999,9999,this.month);yearExtended=new ys("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const xp=new _x;class ll extends Zl{constructor(e,t=xp.year){super(e,t)}static fromString(e,t=xp.year,i=xi.get(ll)){const s=i.parse(e),n=s.value.start;if(e.startsWith("Y")&&(t=xp.yearExtended),n!==void 0){const r=new ll(Object.assign({...s},{value:Math.max(n,t.min)})),a=new ll(Object.assign({...s},{value:Math.min(s.value.end,t.max)}));return{start:r,end:a}}else return new ll(s,t)}}class Rx extends lm{monthValidator=new rA;validate(e){switch(e){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(e)}}}class cl extends Zl{constructor(e,t=new ys(pt.month.name,1,24,pt.day,new Rx)){super(e,t)}static fromString(e,t=xi.get(cl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.month;const r=new cl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new cl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new cl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class hl extends Zl{constructor(e,t=pt.day){super(e,t)}static fromString(e,t=xi.get(hl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.day;const r=new hl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new hl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new hl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class dl extends Zl{constructor(e,t=pt.hour){super(e,t)}static fromString(e,t=xi.get(dl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){let n=pt.hour;const r=new dl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new dl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new dl(i)}}class ul extends Zl{constructor(e,t=pt.minute){super(e,t)}static fromString(e,t=xi.get(ul)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.minute,r=new ul(Object.assign({...i},{value:Math.max(s,n.min)})),a=new ul(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new ul(i)}toString(e=nu.instance){return super.toString(e)}}class pl extends Zl{constructor(e,t=pt.second){super(e,t)}static fromString(e,t=xi.get(pl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.second,r=new pl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new pl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new pl(i)}}class fh extends ph{static fromString(e,t=xi.get(fh),i=void 0){return new fh(t.parse(e,i))}}class Dx extends eb{constructor(e){super(e)}newYear(e){return new ll(e,this.units.year)}newMonth(e){return new cl(e,this.units.month)}newDay(e){return new hl(e,this.units.day)}newHour(e){return new dl(e,this.units.hour)}newMinute(e){return new ul(e,this.units.minute)}newSecond(e){return new pl(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new fh(typeof e=="number"?e:e.value)}}const zA=new Dx(xp);new Dx(tb);class Zo extends kr{constructor(e){super(e)}get factory(){return zA}get uncertain(){return this.year?.uncertain===!0||this.month?.uncertain===!0||this.day?.uncertain===!0||this.hour?.uncertain===!0||this.minute?.uncertain===!0||this.second?.uncertain===!0}get approximate(){return this.year?.approximate===!0||this.month?.approximate===!0||this.day?.approximate===!0||this.hour?.approximate===!0||this.minute?.approximate===!0||this.second?.approximate===!0}static fromDate(e){return new Zo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static fromString(e,t=xi.get(Zo)){const i=t.parse(e);return new Zo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Zo.fromString(i)}clone(){return new Zo(this.toSpec())}}class _h extends Zl{uncertainComponent;approximateComponent;constructor(e,t){super(e,t),this.uncertainComponent=e.uncertainComponent||!1,this.approximateComponent=e.approximateComponent||!1}get uncertain(){return super.uncertain||this.uncertainComponent}set uncertain(e){return super.uncertain=e}get approximate(){return super.approximate||this.approximateComponent}set approximate(e){return super.approximate=e}get uncertainGroup(){return super.uncertain}get approximateGroup(){return super.approximate}toSpec(){return{...super.toSpec(),uncertain:this.uncertainGroup,approximate:this.approximateGroup,uncertainComponent:this.uncertainComponent,approximateComponent:this.approximateComponent}}toJSON(){return this.toSpec()}}class BA extends _x{year=new ys("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const vg=new BA;class fl extends _h{constructor(e,t=vg.year){super(e,t)}static fromString(e,t=vg.year,i=xi.get(fl)){const s=i.parse(e),n=s.value.start;if(n!==void 0){const r=new fl(Object.assign({...s},{value:Math.max(n,t.min)})),a=new fl(Object.assign({...s},{value:Math.min(s.value.end,t.max)})),o={start:r,end:a},c=s.value.estimate;return c&&(o.estimate=c),o}else return new fl(s)}}class HA extends Rx{validate(e){switch(e){case 25:case 26:case 27:case 28:case 29:case 30:case 31:case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:return!0;default:return super.validate(e)}}}class ml extends _h{constructor(e,t=new ys(pt.month.name,1,41,pt.day,new HA)){super(e,t)}static fromString(e,t=xi.get(ml)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.month,r=new ml(Object.assign({...i},{value:Math.max(s,n.min)})),a=new ml(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new ml(i)}toString(e){return super.toString(e).padStart(2,"0")}}class gl extends _h{constructor(e,t=pt.day){super(e,t)}static fromString(e,t=xi.get(gl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.day,r=new gl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new gl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new gl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class vl extends _h{constructor(e,t=pt.hour){super(e,t)}static fromString(e,t=xi.get(vl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.hour,r=new vl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new vl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new vl(i)}}class bl extends _h{constructor(e,t=pt.minute){super(e,t)}static fromString(e,t=xi.get(bl)){const i=t.parse(e),s=i.value.start;if(s!==void 0){const n=pt.minute,r=new bl(Object.assign({...i},{value:Math.max(s,n.min)})),a=new bl(Object.assign({...i},{value:Math.min(i.value.end,n.max)}));return{start:r,end:a}}else return new bl(i)}}class yl extends _h{constructor(e,t=pt.second){super(e,t)}static fromString(e,t=pt.second,i=xi.get(yl)){const s=i.parse(e),n=s.value.start;if(n!==void 0){const r=new yl(Object.assign({...s},{value:Math.max(n,t.min)})),a=new yl(Object.assign({...s},{value:Math.min(s.value.end,t.max)}));return{start:r,end:a}}else return new yl(s,t)}}class kx extends fh{}class GA extends nu{qualifier(){return""}}class ho extends cm{static instance=new ho;static valueRenderer=new GA(xa.default);static names=["year","month","day","hour","minute","second"];static qualifier(e,t){return e?t?"%":"?":t?"~":""}renderComponent(e,t){const i=e[t],s=ho.names.slice(ho.names.indexOf(t)+1).map(a=>e[a]).filter(Boolean),n=ho.qualifier(i.uncertainComponent,i.approximateComponent),r=ho.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!s.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!s.some(a=>a.approximate));return n+i.toString(ho.valueRenderer)+r}}class Cx extends eb{constructor(e){super(e)}newYear(e){return new fl(e,this.units.year)}newMonth(e){return new ml(e,this.units.month)}newDay(e){return new gl(e,this.units.day)}newHour(e){return new vl(e,this.units.hour)}newMinute(e){return new bl(e,this.units.minute)}newSecond(e){return new yl(e,this.units.second)}newMillisecond(e){return new jl(e,this.units.millisecond)}newTimeshift(e){return new kx(typeof e=="number"?e:e.value)}}const VA=new Cx(vg);new Cx(tb);class Jo extends Zo{constructor(e){super(e)}toString(e=ho.instance){return super.toString(e)}get year(){return super.year}set year(e){super.year=e}get month(){return super.month}set month(e){super.month=e}get factory(){return VA}static fromDate(e){return new Jo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:kr.timeshiftOf(e)})}static fromString(e,t=xi.get(Jo)){const i=t.parse(e);return new Jo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Jo.fromString(i)}clone(){return new Jo(this.toSpec())}}class hm{regExp;constructor(e,t){this.name=e,this.regExp=new RegExp(`^(?:${t})$`)}regexGroups(e){const t=this.regExp.exec(e);if(!t)throw new Gl(`Invalid ${this.name} "${e}"`);return t.groups}parseGroups(e){throw new jo(`${this.constructor.name} is abstract`)}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}class sb extends hm{constructor(e,t){super(e,t)}static read(e){return{value:e?parseInt(e,10):void 0}}parseGroups(e){return sb.read(e[this.name])}parse(e){if(e.startsWith("-"))throw new Gl(`${this.name} cannot be negative`);return super.parse(e)}}class ce{static groupName(...e){return e.reduce((t,i)=>t?t+i.charAt(0).toUpperCase()+i.substring(1):i,"")}static group(e,...t){return`(?<${e}>${t.join("")})`}static optional(e){return e+"?"}static nonCapturingGroup(...e){return`(?:${e.join("")})`}static optionalGroup(e,...t){return ce.optional(ce.group(e,...t))}static optionalNonCapturingGroup(...e){return ce.optional(ce.nonCapturingGroup(...e))}static numberGroup(e,t,i,s="\\d"){return ce.group(e,`${i||""}[${s}]${t}`)}}const m1="timeshiftValue",g1="shiftHour",v1="shiftMinute";class nb extends hm{static format(e=""){return f1.map(t=>t.name).join("|")+"|"+ce.nonCapturingGroup(ce.group(e+g1,ce.numberGroup(ce.groupName(e,m1),"{2}","[+-]")),ce.optionalNonCapturingGroup(":?",ce.numberGroup(ce.groupName(e,v1),"{2}",void 0)))}constructor(){super(m1,nb.format())}parse(e,t){let i=0;const s=f1.find(n=>n.name===e);if(s){if(typeof s.timeshift=="function")try{return s.timeshift(t??{})}catch(n){throw new Gl(`The time zone ${e} depends on the date: ${n.message}`)}e=s.timeshift}if(e!=="Z"){const n=this.regexGroups(e),r=n[g1];r&&(i+=parseInt(r,10)*60);const a=n[v1];a&&(i+=parseInt(a,10))}return i}}class Ki extends sb{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=Ki.uncertainGroup+Ki.approximateGroup;constructor(e,t){super(e,t)}static qualifierFormat(e,t){return ce.optionalGroup(e,`\\${t}`)}static formatSuffix(e){return this.qualifierFormat(ce.groupName(Ki.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(Ki.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(Ki.uncertainAndApproximateGroup,e),"%")}static numberFormat(e,t,i){return ce.numberGroup(e,t,i,"\\dX")+this.formatSuffix(e)}getValueAndSign(e){let t=e[this.name],i;return t.charAt(0)==="-"?(i=-1,t=t.substring(1)):i=1,{valueStr:t,sign:i}}parseGroups(e){const{valueStr:t,sign:i}=this.getValueAndSign(e);let s=0,n;for(n=0;n<t.length;n++){const c=t[n];if(c==="X")break;s=s*10+parseInt(c,10)}if(n<t.length){let c=1;for(let u=0;u<t.length-n;u++)c*=10;const h=i*s*c,d=h+c-1;s={start:h,end:d}}else s*=i;const r=e[ce.groupName(Ki.uncertainAndApproximateGroup,this.name)],a=e[ce.groupName(Ki.approximateGroup,this.name)]||r,o=e[ce.groupName(Ki.uncertainGroup,this.name)]||r;return{value:s,approximate:a?!!a:!1,uncertain:o?!!o:!1}}}const b1="yearValue";class Yp extends Ki{constructor(){super(b1,Yp.format())}static format(e=""){return"Y?"+Ki.numberFormat(ce.groupName(e,b1),"+","[-]?")}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const y1="monthValue";class qp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,y1),"{1,2}",void 0)}constructor(){super(y1,qp.format())}}const w1="dayValue";class jp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,w1),"{1,2}",void 0)}constructor(){super(w1,jp.format())}}const M1="hourValue";class Zp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,M1),"{1,2}",void 0)}constructor(){super(M1,Zp.format())}}const x1="minuteValue";class Jp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,x1),"{1,2}",void 0)}constructor(){super(x1,Jp.format())}}const S1="secondValue";class Qp extends Ki{static format(e=""){return Ki.numberFormat(ce.groupName(e,S1),"{1,2}",void 0)}constructor(){super(S1,Qp.format())}}class ef extends nb{}class Ms extends hm{static yearGroup="year";static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(e=Ms.format()){super("date",e)}static format(e=""){return ce.group(ce.groupName(e,Ms.yearGroup),Yp.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,Ms.monthGroup),qp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,Ms.dayGroup),jp.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,Ms.hourGroup),Zp.format(e)),":",ce.group(ce.groupName(e,Ms.minuteGroup),Jp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,Ms.secondGroup),Qp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,Ms.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,Ms.timeshiftGroup),ef.format(e)))))}parseGroups(e){const t=e[Ms.millisecondGroup],i=t?jl.parseFraction(t):void 0,s=e[Ms.secondGroup],n=s?pl.fromString(s,new Qp):void 0,r=e[Ms.minuteGroup];let a;r&&(a=ul.fromString(r,new Jp),a.uncertain=a.uncertain||n?.uncertain||!1,a.approximate=a.approximate||n?.approximate||!1);const o=e[Ms.hourGroup];let c;o&&(c=dl.fromString(o,new Zp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[Ms.dayGroup];let d;h&&(d=hl.fromString(h,new jp),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[Ms.monthGroup];let p;u&&(p=cl.fromString(u,new qp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[Ms.yearGroup];let m;f&&(m=ll.fromString(f,void 0,new Yp),m.uncertain=m.uncertain||p?.uncertain||!1,m.approximate=m.approximate||p?.approximate||!1);const g=e[Ms.timeshiftGroup],v=g?fh.fromString(g,new ef,{year:m?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:m,month:p,day:d,hour:c,minute:a,second:n,millisecond:i,timeshift:v}}}class ds extends Ki{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=ds.uncertainGroup+ds.approximateGroup;constructor(e,t){super(e,t)}static numberFormat(e,t,i){return this.qualifierFormat(ce.groupName(ds.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(ds.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(ds.uncertainAndApproximateGroup,e),"%")+Ki.numberFormat(e,t,i)}parseGroups(e){const t=super.parseGroups(e),i=e[ce.groupName(ds.uncertainAndApproximateGroup,this.name)];return(e[ce.groupName(ds.uncertainGroup,this.name)]||i)&&(t.uncertainComponent=!0),(e[ce.groupName(ds.approximateGroup,this.name)]||i)&&(t.approximateComponent=!0),t}}const Oh="yearValue",E1="exp",A1="signif";class tf extends ds{constructor(){super(Oh,tf.format())}static format(e=""){return"Y?"+ce.nonCapturingGroup(ce.group(ce.groupName(e,E1),"[-]?\\d+E\\d+")+"|"+ds.numberFormat(ce.groupName(e,Oh),"+","[-]?")+ce.optionalGroup(ce.groupName(e,A1),"S\\d+"))}parseGroups(e){const t=e[E1];if(t){const r=t.indexOf("E"),a=parseInt(t.substring(r+1),10),c=parseInt(t.substring(0,r),10)*Math.pow(10,a);e[Oh]=c.toString()}const i=e[A1],s=e[Oh];if(i){const r=parseInt(i.substring(1),10),{valueStr:a,sign:o}=this.getValueAndSign(e);let c="";for(let h=0;h<a.length;h++)c+=h<r?a.charAt(h):"X";e[Oh]=(o<0?"-":"")+c}const n=super.parseGroups(e);return i&&(n.value.estimate=parseInt(s,10)),n}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const T1="monthValue";class sf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,T1),"{1,2}",void 0)}constructor(){super(T1,sf.format())}}const I1="dayValue";class nf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,I1),"{1,2}",void 0)}constructor(){super(I1,nf.format())}}const _1="hourValue";class rf extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,_1),"{1,2}",void 0)}constructor(){super(_1,rf.format())}}const R1="secondValue";class af extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,R1),"{1,2}",void 0)}constructor(){super(R1,af.format())}}const D1="minuteValue";class of extends ds{static format(e=""){return ds.numberFormat(ce.groupName(e,D1),"{1,2}",void 0)}constructor(){super(D1,of.format())}}class WA extends ef{}class xs extends hm{static yearGroup=Ms.yearGroup;static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(){super("date",xs.format())}static format(e=""){return ce.group(ce.groupName(e,xs.yearGroup),tf.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,xs.monthGroup),sf.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,xs.dayGroup),nf.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,xs.hourGroup),rf.format(e)),":",ce.group(ce.groupName(e,xs.minuteGroup),of.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,xs.secondGroup),af.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,xs.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,xs.timeshiftGroup),WA.format(e)))))}parseGroups(e){const t=e[xs.millisecondGroup],i=t?jl.parseFraction(t):void 0,s=e[xs.secondGroup];let n;s&&(n=yl.fromString(s,void 0,new af),n.uncertain=n?.uncertain||!1,n.approximate=n?.approximate||!1);const r=e[xs.minuteGroup];let a;r&&(a=bl.fromString(r,new of),a.uncertain=a.uncertain||n?.uncertain||!1,a.approximate=a.approximate||n?.approximate||!1);const o=e[xs.hourGroup];let c;o&&(c=vl.fromString(o,new rf),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[xs.dayGroup];let d;h&&(d=gl.fromString(h,new nf),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[xs.monthGroup];let p;u&&(p=ml.fromString(u,new sf),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[xs.yearGroup];let m;f&&(m=fl.fromString(f,void 0,new tf),m.uncertain=m.uncertain||p?.uncertain||!1,m.approximate=m.approximate||p?.approximate||!1);const g=e[xs.timeshiftGroup],v=g?kx.fromString(g,new ef,{year:m?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:m,month:p,day:d,hour:c,minute:a,second:n,millisecond:i,timeshift:v}}}const Lx=["spring","summer","autumn","winter"],bg=21,$A=32,KA=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let XA;function YA(){return XA??=new xs}function tc(l){return typeof l?.value=="number"?l.value:void 0}function Sp(l){const e=l.trim();if(/^\d{1,2}:/.test(e)){const r=KA.exec(e)?.groups;return r?{year:void 0,month:void 0,day:void 0,hour:Number(r.hour),minute:Number(r.minute),second:r.second?Number(r.second):void 0,raw:e}:void 0}let t;try{t=Jo.fromString(e,YA())}catch{return}const i=tc(t.year),s=tc(t.month),n=s!==void 0&&s>=bg&&s<=$A;if(!(t.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(s!==void 0&&s>12&&!n)&&!(n&&(t.day||t.hour)))return{year:i,month:n?void 0:s,...n?{season:Lx[(s-bg)%4]}:{},day:tc(t.day),hour:tc(t.hour),minute:tc(t.minute),second:tc(t.second),raw:e}}function wl(l){if(l.raw!==void 0)return l.raw;if(l.year===void 0){if(l.hour===void 0)return"";let t=`${String(l.hour).padStart(2,"0")}:${String(l.minute??0).padStart(2,"0")}`;return l.second!==void 0&&(t+=`:${String(l.second).padStart(2,"0")}`),t}let e=String(l.year).padStart(4,"0");return l.season!==void 0?`${e}-${bg+Lx.indexOf(l.season)}`:(l.month===void 0||(e+=`-${String(l.month).padStart(2,"0")}`,l.day===void 0)||(e+=`-${String(l.day).padStart(2,"0")}`,l.hour===void 0)||(e+=`T${String(l.hour).padStart(2,"0")}:${String(l.minute??0).padStart(2,"0")}`,l.second!==void 0&&(e+=`:${String(l.second).padStart(2,"0")}`)),e)}function yg(l){if(l.year!==void 0)return Date.UTC(l.year,(l.month??1)-1,l.day??1,l.hour??0,l.minute??0,l.second??0)}function k1(l){return(((l.day??0)*24+(l.hour??0))*60+(l.minute??0))*6e4+(l.second??0)*1e3}const qA=["year","month","day","hour","minute"],jA=["day","hour","minute"];function C1(l,e){return e.filter(t=>l[t]!==void 0).join(",")}function mh(l){if(l.durationSeconds!==void 0)return l.durationSeconds*1e3;const e=l.durationText===void 0?void 0:bn.parse(l.durationText);if(e)return e.chosenSeconds*1e3;if(!l.time||!l.endTime)return;const t=l.time.year!==void 0&&l.endTime.year!==void 0,i=t?qA:jA,s=C1(l.time,i);if(!(s===""||s!==C1(l.endTime,i)))return t?yg(l.endTime)-yg(l.time):k1(l.endTime)-k1(l.time)}function ZA(l){if(l.durationSeconds===void 0&&!(!l.time||!l.endTime))return mh(l)===void 0?"imprecise":void 0}class dm{constructor(e,t,i,s,n,r,a,o,c=[],h,d,u,p=[],f=[],m=[],g=[]){this.event=e,this.timeline=t,this.observerTrack=i,this.weatherTrack=s,this.soundTrack=n,this.observer=r,this.id=a,this.weather=o,this.decor=c,this.weatherSource=h,this.instrumentId=d,this.exposureSeconds=u,this.milestones=p,this.references=f,this.roads=m,this.traces=g}provenance=wn.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;metering;lens;vehicle;get observerCount(){return 1+this.decor.filter(e=>e.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Yt.byId(this.instrumentId)}static create(e,t,i){return new dm({eventType:"sighting",time:e,place:t},new am,new Nd,new Fd,new Ud,i)}}const JA=0,QA=0;function at(l,e){const t=l.observerTrack.getInterpolatedPoseAt(e);if(t)return t;const i=l.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:JA,headingDeg:void 0,pitchDeg:QA,fovDeg:Yt.fieldOfViewDeg(l.instrument)}}function is(l,e){return l.weatherTrack.getInterpolatedWeatherAt(e)??l.weather??om}function Ph(l,e){return l.weatherTrack.getActualWeatherAt(e)??l.weather??om}function rb(l,e){return l.soundTrack.getInterpolatedSoundAt(e)??sA}class zd{constructor(e,t){this.json=e,this.url=t,this.tracks=(e.events??[]).filter(i=>i.eventType===Di.SIGHTING_EVENT&&typeof i.url=="string"&&i.url!=="").map(i=>({event:i,url:new URL(i.url,t).href,kind:i.interpretationOf===void 0?"observer":"reading"}))}tracks;caseChanged=!1;transcripts=new Map;static around(e,t,i,s,n){const r=(e.observer?.id??e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",a={id:e.id??"case",...t!==void 0?{time:t}:{},events:[{type:"event",eventType:Di.SIGHTING_EVENT,...t!==void 0?{time:t}:{},...i!==void 0?{title:i}:{},url:`observer-${r}.json`}]},o=new zd(a,new URL("case.json",n).href),c=o.tracks[0];return c.recording=e,c.base={url:s},c.event.id=o.proposedId(c),o.caseChanged=!0,o}accountOf(e){if(e.kind!=="reading")return;const t=[e.event.interpretationOf].flat(),i=this.tracks.filter(s=>s.kind==="observer");return i.find(s=>s.event.id!==void 0&&t.includes(s.event.id))??i.find(s=>s.recording?.id!==void 0&&t.includes(s.recording.id))}get interviews(){return(this.json.events??[]).filter(e=>e.eventType===Di.INTERVIEW_EVENT)}intervieweeOf(e){return this.intervieweesOf(e)[0]}intervieweesOf(e){const t=this.tracks.filter(i=>i.kind==="observer");return[e.interviewOf].flat().filter(i=>typeof i=="string").flatMap(i=>{const s=t.find(n=>n.event.id===i)??t.find(n=>n.recording?.id===i);return s?[s]:[]})}addInterview(e,t,i,s,n){const r=this.eventIds(),a=e?e.event.id??this.proposedId(e):"case";let o=1;for(;r.has(`interview-${a}-${o}`);)o++;const c={type:"event",eventType:Di.INTERVIEW_EVENT,id:`interview-${a}-${o}`,...e?{interviewOf:this.ensureId(e)}:{},time:t,...n!==void 0?{medium:n}:{},...s!==void 0&&s.length>0?{by:s}:{},...i!==void 0?{title:i}:{}};return this.json.events=[...this.json.events??[],c],this.caseChanged=!0,c}transcriptText(e){return this.transcripts.get(e)?.text}keepTranscript(e,t){this.transcripts.set(e,{text:t,loaded:this.transcripts.get(e)?.loaded})}transcriptChanged(e){return e.loaded!==e.text}deleteInterview(e){return this.interviews.includes(e)?(this.json.events=(this.json.events??[]).filter(t=>t!==e),this.transcripts.delete(e),this.caseChanged=!0,!0):!1}keep(e,t,i=!1){e.recording=t,i&&(e.loaded=JSON.stringify(t)),e.kind==="reading"&&t.interpretation?.title!==void 0&&(e.event.title=t.interpretation.title)}replaceJson(e){const i=(e.events??[]).filter(n=>n.eventType===Di.SIGHTING_EVENT&&typeof n.url=="string"&&n.url!=="").map(n=>{const r=new URL(n.url,this.url).href,a=n.interpretationOf===void 0?"observer":"reading",o=this.tracks.find(c=>c.url===r);return o?(o.event=n,o.kind=a,o):{event:n,url:r,kind:a}});this.tracks.splice(0,this.tracks.length,...i);const s=new Map;for(const[n,r]of this.transcripts){const a=(e.events??[]).find(o=>o.eventType===Di.INTERVIEW_EVENT&&(n.id!==void 0&&o.id===n.id||n.url!==void 0&&o.url===n.url));a&&s.set(a,r)}this.transcripts.clear();for(const[n,r]of s)this.transcripts.set(n,r);this.json=e,this.caseChanged=!0}touch(){this.caseChanged=!0}get dirty(){return this.caseChanged||this.tracks.some(e=>this.changed(e))||[...this.transcripts.values()].some(e=>this.transcriptChanged(e))}markExported(e){if(this.caseChanged=!1,!!e){for(const t of this.tracks)t.recording&&(t.loaded=JSON.stringify(t.recording));for(const t of this.transcripts.values())t.loaded=t.text}}changed(e){return e.recording!==void 0&&(e.loaded===void 0||JSON.stringify(e.recording)!==e.loaded)}static ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]*$/;eventIds(e){return new Set((this.json.events??[]).filter(t=>t!==e?.event).map(t=>t.id).filter(t=>t!==void 0))}proposedId(e){const t=a=>(a??"").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),i=typeof e.event.title=="string"?e.event.title:void 0,s=t(e.recording?.observer?.lastName)||t(e.recording?.observer?.id)||t(i),n=this.eventIds(e);if(s!==""){let a=s;for(let o=2;n.has(a);o++)a=`${s}-${o}`;return a}let r=1;for(;n.has(`sighting-${r}`);)r++;return`sighting-${r}`}ensureId(e){return e.event.id===void 0&&(e.event.id=this.proposedId(e),this.caseChanged=!0),e.event.id}setId(e,t){const i=e.event.id,s=a=>a===i||a===e.recording?.id,n=(this.json.events??[]).filter(a=>a.eventType===Di.SIGHTING_EVENT&&a.interpretationOf!==void 0&&[a.interpretationOf].flat().some(o=>o!==void 0&&s(o))),r=this.interviews.filter(a=>[a.interviewOf].flat().some(o=>o!==void 0&&s(o)));if(t==="")return i===void 0?"ok":n.length>0||r.length>0?"empty":(delete e.event.id,this.caseChanged=!0,"ok");if(!zd.ID_PATTERN.test(t))return"invalid";if(this.eventIds(e).has(t))return"taken";if(t===i)return"ok";for(const a of n){const o=[a.interpretationOf].flat().map(c=>s(c)?t:c);a.interpretationOf=Array.isArray(a.interpretationOf)?o:o[0]}for(const a of r){const o=[a.interviewOf].flat().map(c=>c!==void 0&&s(c)?t:c);a.interviewOf=Array.isArray(a.interviewOf)?o:o[0]}return e.event.id=t,this.caseChanged=!0,"ok"}problems(){return Di.problems(this.json,this.tracks.map(e=>e.recording?.id).filter(e=>e!==void 0))}addReading(e,t,i,s){const n=e.recording;if(!n)throw new Error("A reading is added to an account that has been loaded");const r=e.event.url.replace(/^.*\//,"").replace(/^observer-/,"").replace(/\.json$/,""),a=new Set(this.tracks.map(R=>R.event.url)),o=new Set(this.tracks.map(R=>R.recording?.id));let c=this.tracks.filter(R=>R.kind==="reading").length+1;for(;a.has(`interpretation-${r}-${c}.json`)||o.has(`${n.id??r}-interpretation-${c}`);)c++;const h=`interpretation-${r}-${c}.json`,d=e.event.url.includes("/")?e.event.url.replace(/[^/]*$/,""):"",{id:u,version:p,observer:f,account:m,description:g,sources:v,tags:b,timeline:w,milestones:y,interpretation:M,...S}=structuredClone(n),E={version:1,id:`${n.id??r}-interpretation-${c}`,...S,tags:["interpretation"],timeline:{keyframes:[],order:[],groups:[]},interpretation:{...i!==void 0?{title:i}:{},bodies:[]}},x={type:"event",eventType:"sighting",interpretationOf:this.ensureId(e),time:t,...s!==void 0&&s.length>0?{by:s}:{},...i!==void 0?{title:i}:{},url:d+h};this.json.events=[...this.json.events??[],x],this.caseChanged=!0;const A={event:x,url:new URL(x.url,this.url).href,kind:"reading",recording:E};return this.tracks.push(A),A}idsOf(e){return[e.event.id,e.recording?.id].filter(t=>t!==void 0)}readingsOf(e){const t=this.idsOf(e);return this.tracks.filter(i=>i.kind==="reading"&&[i.event.interpretationOf].flat().some(s=>s!==void 0&&t.includes(s)))}addObservation(e,t,i,s){const n=new Set(this.tracks.map(m=>m.event.url)),r=new Set(this.tracks.map(m=>m.recording?.id)),a=(e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",o=s?"interpretation":"observer";let c=`${o}-${a}.json`,h=e.id??a;for(let m=2;n.has(c)||r.has(h);m++)c=`${o}-${a}-${m}.json`,h=`${e.id??a}-${m}`;const d={...e,id:h},u=this.tracks[0]?.event.url?.includes("/")?this.tracks[0].event.url.replace(/[^/]*$/,""):"",p={type:"event",eventType:"sighting",...s?{interpretationOf:this.ensureId(s.account)}:{},...t!==void 0?{time:t}:{},...s?.by&&s.by.length>0?{by:s.by}:{},...i!==void 0?{title:i}:{},url:u+c};this.json.events=[...this.json.events??[],p],this.caseChanged=!0;const f={event:p,url:new URL(p.url,this.url).href,kind:s?"reading":"observer",recording:d};return this.tracks.push(f),s||(p.id=this.proposedId(f)),f}deleteObservation(e){if(e.kind!=="observer")return{deleted:!1,readings:0};const t=this.readingsOf(e).length;if(t>0)return{deleted:!1,readings:t};const i=this.tracks.indexOf(e);return i<0?{deleted:!1,readings:0}:(this.tracks.splice(i,1),this.json.events=(this.json.events??[]).filter(s=>s!==e.event),this.caseChanged=!0,{deleted:!0})}deleteReading(e){if(e.kind!=="reading")return!1;const t=this.tracks.indexOf(e);return t<0?!1:(this.tracks.splice(t,1),this.json.events=(this.json.events??[]).filter(i=>i!==e.event),this.caseChanged=!0,!0)}files(e=!0,t=!1){const i=this.url.replace(/[^/]*$/,""),s=o=>o.startsWith(i)?o.slice(i.length):o,n=this.tracks.filter(o=>e&&o.recording!==void 0&&(t||this.changed(o))).map(o=>({path:s(o.url),content:JSON.stringify(o.recording,null,2)+`
336
336
  `})),r=decodeURIComponent(this.url.replace(/[?#].*$/,"").replace(/^.*\//,""))||"case.json",a=[...this.transcripts].filter(([o,c])=>e&&o.url!==void 0&&(t||this.transcriptChanged(c))).map(([o,c])=>({path:s(new URL(o.url,this.url).href),content:c.text}));return[{path:r,content:JSON.stringify(this.json,null,2)+`
337
337
  `},...n,...a]}}class lf{constructor(e,t,i,s){this.button=e,this.onPick=i,this.idOf=s;const n=this.panel=e.ownerDocument.createElement("div");n.id=t,n.className="add-menu",n.setAttribute("popover",""),n.setAttribute("role","menu");const r=`--add-menu-${t}`;e.style.setProperty("anchor-name",r),n.style.setProperty("position-anchor",r),e.setAttribute("popovertarget",t),e.setAttribute("aria-haspopup","menu"),e.after(n)}static CSS=`
338
338
  .add-menu { padding: .3em 0; border: 1px solid color-mix(in srgb, CanvasText 30%, transparent); border-radius: 4px; background: Canvas; color: CanvasText;
@@ -4245,12 +4245,12 @@ canvas[data-cursor="rotate"] {
4245
4245
  pointer-events: none;
4246
4246
  white-space: nowrap;
4247
4247
  }
4248
- `;class Cl{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const i of e.observerTrack.allKeyframes){const{lat:s,lng:n,headingDeg:r}=i.pose;s===void 0||n===void 0||t.push({t:i.t,lat:s,lng:n,headingDeg:r})}if(t.length===0){const i=e.event.place?.[0];if(!i)return;t.push({t:0,lat:i.lat,lng:i.lng})}return new Cl(t)}static TRAVEL_M=50;get travels(){return this.spanM>Cl.TRAVEL_M}get moved(){return this.spanM>Cl.STATIONARY_M}get spanM(){const e=this.box,t=(e.south+e.north)/2,i=(e.west+e.east)/2;return Math.max(Math.abs(ot(t,e.east,t,e.west).x),Math.abs(ot(e.north,i,e.south,i).z))}get center(){const e=this.box;return{lat:(e.south+e.north)/2,lng:(e.west+e.east)/2}}boundsAround(e,t){const{lat:i,lng:s}=this.center,n=Math.max(this.spanM*(1+t),e)/2;return{north:_n(0,-n,i,s).lat,south:_n(0,n,i,s).lat,east:_n(n,0,i,s).lng,west:_n(-n,0,i,s).lng}}get box(){const e=this.points.map(i=>i.lat),t=this.points.map(i=>i.lng);return{south:Math.min(...e),north:Math.max(...e),west:Math.min(...t),east:Math.max(...t)}}}class lr{constructor(e,t){this.rotationPassed=e,this.scale=t}static SWAY_M=.012;static BREATH_M=.003;static DRIFT_YAW_DEG=.5;static DRIFT_PITCH_DEG=.4;static DRIFT_ROLL_DEG=.3;static GAZE_DRIFT_SHARE=.35;static HAND_HELD_S=.5;static HZ=[.11,.23,.17,.29,.37,.07];static of(e){const t=e.event.tags?.includes("paralysis")||(e.exposure??0)>lr.HAND_HELD_S,i=e.sway??(t?0:1);if(i>0)return new lr(Math.max(1-(e.instrument.stabilization??0),lr.GAZE_DRIFT_SHARE),i)}offsetAt(e){const t=e/1e3,i=this.scale,s=(d,u)=>Math.sin(2*Math.PI*d*t+u),[n,r,a,o,c,h]=lr.HZ;return{eastM:i*lr.SWAY_M*(.7*s(n,.3)+.3*s(o,1.9)),northM:i*lr.SWAY_M*(.6*s(a,2.2)+.4*s(c,.8)),upM:i*lr.BREATH_M*s(r,0),yawDeg:i*this.rotationPassed*lr.DRIFT_YAW_DEG*(.6*s(h,1.1)+.4*s(o,2.7)),pitchDeg:i*this.rotationPassed*lr.DRIFT_PITCH_DEG*(.5*s(r,1.6)+.5*s(a,.4)),rollDeg:i*this.rotationPassed*lr.DRIFT_ROLL_DEG*s(n,2.9)}}}class ci{constructor(e,t){this.stretches=e,this.rotationPassed=t}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STOP_LURCH_M=.035;static STOP_PITCH_DEG=3;static START_LURCH_M=.015;static START_PITCH_DEG=1.2;static JOLT_HZ=1.4;static JOLT_DECAY_S=.35;static JOLT_LASTS_MS=1500;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(e){const t=Cl.of(e);if(!t||t.points.length<2)return;const i=[];let s=0;for(let n=1;n<t.points.length;n++){const r=t.points[n-1],a=t.points[n],o=(a.t-r.t)/1e3;if(o<=0)continue;const c=ot(a.lat,a.lng,r.lat,r.lng),h=c.x,d=-c.z,u=Math.hypot(h,d),p=u/o,f=ci.stepHzFor(p);i.push({startMs:r.t,endMs:a.t,speedMPerS:p,eastUnit:u>0?h/u:0,northUnit:u>0?d/u:0,stepHz:f,stepsBefore:s,rampsIn:!0,rampsOut:!0}),s+=f*o}for(let n=0;n<i.length;n++){const r=i[n-1],a=i[n+1];i[n].rampsIn=r===void 0||r.stepHz===0,i[n].rampsOut=a===void 0||a.stepHz===0}if(i.some(n=>n.stepHz>0))return new ci(i,1-(e.instrument.stabilization??0))}static bodyAt(e,t,i=!1){const s=ci.of(e)?.offsetAt(t)??ci.STILL;return i?s:ci.add(s,lr.of(e)?.offsetAt(t))}static stepHzFor(e){return e<ci.SLOWEST_WALK_M_PER_S||e>ci.FASTEST_WALK_M_PER_S?0:ci.REFERENCE_STEP_HZ*Math.pow(e/ci.REFERENCE_SPEED_M_PER_S,ci.CADENCE_EXPONENT)}offsetAt(e){return ci.add(this.cycleAt(e),this.joltAt(e))}joltAt(e){for(const t of this.stretches){if(t.stepHz===0)continue;const i=t.speedMPerS/ci.REFERENCE_SPEED_M_PER_S,s=(a,o,c,h)=>{if(a<0||a>ci.JOLT_LASTS_MS)return;const d=a/1e3,u=Math.exp(-d/ci.JOLT_DECAY_S)*Math.sin(2*Math.PI*ci.JOLT_HZ*d),p=h*o*i*u;return{eastM:p*t.eastUnit,northM:p*t.northUnit,upM:-Math.abs(p)*.3,rollDeg:0,pitchDeg:-h*c*i*u*this.rotationPassed,yawDeg:0}},n=t.rampsOut?s(e-t.endMs,ci.STOP_LURCH_M,ci.STOP_PITCH_DEG,1):void 0;if(n)return n;const r=t.rampsIn?s(e-t.startMs,ci.START_LURCH_M,ci.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(e,t){return t?{eastM:e.eastM+t.eastM,northM:e.northM+t.northM,upM:e.upM+t.upM,rollDeg:e.rollDeg+t.rollDeg,pitchDeg:e.pitchDeg+t.pitchDeg,yawDeg:e.yawDeg+t.yawDeg}:e}cycleAt(e){const t=this.stretches.find(o=>e>=o.startMs&&e<=o.endMs);if(!t||t.stepHz===0)return ci.STILL;const i=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,s=2*Math.PI*i,n=this.amplitudeAt(t,e),r=ci.SWAY_M*n*Math.cos(s/2),a=n*this.rotationPassed*t.speedMPerS/ci.REFERENCE_SPEED_M_PER_S;return{eastM:r*t.northUnit,northM:-r*t.eastUnit,upM:ci.RISE_M_PER_M_PER_S*t.speedMPerS*n*Math.cos(s),rollDeg:ci.HEAD_ROLL_DEG*a*Math.cos(s/2),pitchDeg:-1.25*a*Math.cos(s),yawDeg:ci.HEAD_YAW_DEG*a*Math.cos(s/2)}}amplitudeAt(e,t){const i=1e3/e.stepHz,s=Math.min(i,(e.endMs-e.startMs)/2);if(s<=0)return 1;const n=t-e.startMs,r=e.endMs-t,a=Math.min(e.rampsIn?n/s:1,e.rampsOut?r/s:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class Z3{constructor(e,t){this.timeline=e,this.onFrame=t}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const e=()=>{if(this.state!=="playing")return;const t=performance.now();if(this.currentT+=(t-this.lastWallTime)*this.playbackRate,this.lastWallTime=t,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(e){this.currentT=Math.max(0,Math.min(e,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(e){const t=new Map;for(const i of this.timeline.sourceIds){const s=this.timeline.getInterpolatedShapeAt(e,i);s&&t.set(i,s)}this.onFrame(e,t)}}class Ll{static sessionDeclared=!1;static unlock(e){if(Ll.declarePlayback(),e.state!=="running")try{Promise.resolve(e.resume()).catch(()=>{});const t=e.createBufferSource();t.buffer=e.createBuffer(1,1,22050),t.connect(e.destination),t.start(0)}catch{}}static declarePlayback(){if(!(Ll.sessionDeclared||typeof navigator>"u")){Ll.sessionDeclared=!0;try{const e=navigator.audioSession;e&&(e.type="playback")}catch{}}}}const ly=.05,cy=.08,hy=2,dy=3,J3=14,Q3=.02;class eI{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",e);return}}Ll.unlock(this.context)}setSound(e){if(this.requested=e,!this.context)return;const t=this.keyFor(e);if(!t){this.silence();return}if(this.voice?.key!==t){this.stopVoice();const i=++this.voiceToken;t.startsWith("src:")?this.buildRecordedVoice(e.src,t,i):this.voice=this.buildSynthesizedVoice(e,t)}this.applyTo(this.voice,e)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(e){if(!(e.volume<=0))return e.src?`src:${e.src}`:e.kind==="none"?void 0:e.kind}applyTo(e,t){const i=this.context;if(!e||!i)return;const s=i.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,s,ly);for(const{param:n,ratio:r}of e.pitch)n.setTargetAtTime(Math.min(t.pitchHz*r,i.sampleRate/2-1),s,ly)}buildSynthesizedVoice(e,t){const i=this.context;if(i)switch(e.kind){case"hum":return this.buildHum(i,t);case"whistle":return this.buildWhistle(i,t);case"rumble":return this.buildRumble(i,t);case"crackle":return this.buildCrackle(i,t);default:return}}buildHum(e,t){const i=e.createOscillator();i.type="sawtooth";const s=e.createOscillator();s.type="sawtooth";const n=e.createBiquadFilter();n.type="lowpass",n.Q.value=1;const r=e.createGain();return r.gain.value=0,i.connect(n),s.connect(n),n.connect(r).connect(this.output(e)),i.start(),s.start(),{key:t,nodes:[n,r],sources:[i,s],volumeParam:r.gain,gainScale:.16,pitch:[{param:i.frequency,ratio:1},{param:s.frequency,ratio:1.006},{param:n.frequency,ratio:6}]}}buildWhistle(e,t){const i=e.createOscillator();i.type="sine";const s=e.createOscillator();s.type="sine",s.frequency.value=5;const n=e.createGain(),r=e.createGain();return r.gain.value=0,s.connect(n).connect(i.frequency),i.connect(r).connect(this.output(e)),i.start(),s.start(),{key:t,nodes:[n,r],sources:[i,s],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:n.gain,ratio:.012}]}}buildRumble(e,t){const i=e.createBufferSource();i.buffer=this.brownNoise(e),i.loop=!0;const s=e.createBiquadFilter();s.type="lowpass",s.Q.value=.8;const n=e.createGain();return n.gain.value=0,i.connect(s).connect(n).connect(this.output(e)),i.start(),{key:t,nodes:[s,n],sources:[i],volumeParam:n.gain,gainScale:1.4,pitch:[{param:s.frequency,ratio:1}]}}buildCrackle(e,t){const i=e.createBufferSource();i.buffer=this.whiteNoise(e),i.loop=!0;const s=e.createBiquadFilter();s.type="bandpass",s.Q.value=1.2;const n=e.createGain();n.gain.value=0;const r=e.createBufferSource();r.buffer=this.crackleEnvelope(e),r.loop=!0;const a=e.createGain();return a.gain.value=0,r.connect(a).connect(n.gain),i.connect(s).connect(n).connect(this.output(e)),i.start(),r.start(),{key:t,nodes:[s,n,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:s.frequency,ratio:4}]}}async buildRecordedVoice(e,t,i){const s=this.context;if(!s)return;let n;try{n=await this.getBuffer(e)}catch(o){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",o);return}if(i!==this.voiceToken||!this.context)return;const r=s.createBufferSource();r.buffer=n,r.loop=!0;const a=s.createGain();a.gain.value=0,r.connect(a).connect(this.output(s)),r.start(),this.voice={key:t,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(e){const t=this.context;if(!t)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(e);return i||(i=fetch(e).then(s=>{if(!s.ok)throw new Error(`Audio fetch failed (${s.status}): ${e}`);return s.arrayBuffer()}).then(s=>t.decodeAudioData(s)),this.buffers.set(e,i)),i}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*hy),e.sampleRate),i=t.getChannelData(0);for(let s=0;s<i.length;s++)i[s]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*hy),e.sampleRate),i=t.getChannelData(0);let s=0,n=0;for(let r=0;r<i.length;r++)s=(s+.02*(Math.random()*2-1))/1.02,i[r]=s,n=Math.max(n,Math.abs(s));if(n>0)for(let r=0;r<i.length;r++)i[r]/=n;return t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*dy),e.sampleRate),i=t.getChannelData(0),s=Math.max(1,Math.floor(Q3*e.sampleRate)),n=Math.round(dy*J3);for(let r=0;r<n;r++){const a=Math.floor(Math.random()*i.length),o=.4+Math.random()*.6;for(let c=0;c<s&&a+c<i.length;c++)i[a+c]=Math.max(i[a+c],o*(1-c/s))}this.crackleBuffer=t}return this.crackleBuffer}stopVoice(){const e=this.voice,t=this.context;if(this.voice=void 0,!e||!t)return;const i=t.currentTime;e.volumeParam.cancelScheduledValues(i),e.volumeParam.setTargetAtTime(0,i,cy/3);const s=i+cy;for(const n of e.sources){n.onended=()=>{n.disconnect();for(const r of e.nodes)r.disconnect()};try{n.stop(s)}catch{n.disconnect();for(const r of e.nodes)r.disconnect()}}}}class ia{static KINDS=["beams","launches","reentries"];static isEmpty(e){return!e||ia.KINDS.every(t=>!e[t]?.length)}static written(e){if(ia.isEmpty(e))return;const t={};for(const i of ia.KINDS)e[i]?.length&&(t[i]=e[i]);return t}static read(e,t){const i=t,s={};for(const r of ia.KINDS){const a=[...e?.[r]??[],...i?.[r]??[]];a.length>0&&(s[r]=a)}let n=t;if(i&&ia.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:o,...c}=i;n=ia.isReading(c)?c:void 0}return{skyEvents:ia.written(s),interpretation:n}}static isReading(e){return(e.bodies?.length??0)>0||e.title!==void 0||(e.smoke?.length??0)>0}}function Ol(l){return[...l].sort((e,t)=>e.t-t.t)}function Nm(l,e){let t;for(const i of Ol(l)){if(i.t>e)break;t=i}return t}const Fm=Math.PI/180,yu=180/Math.PI;class Bn{constructor(e,t,i){this.kind=e,this.canvasHeightPx=t,this.fovDeg=i;const s=i*Fm/2;this.focalPx=e==="equidistant"?t/2/s:t/2/Math.tan(s)}focalPx;static of(e,t,i){return new Bn(e.projection,t,i)}degToPx(e){const t=e*Fm;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*yu:2*Math.atan(e/(2*this.focalPx))*yu}angleDegToRadiusPx(e){const t=e*Fm;return this.kind==="equidistant"?this.focalPx*t:this.focalPx*Math.tan(t)}halfWidthAngleDeg(e){return this.radiusPxToAngleDeg(this.canvasHeightPx*e/2)}radiusPxToAngleDeg(e){return this.kind==="equidistant"?e/this.focalPx*yu:Math.atan(e/this.focalPx)*yu}ofBounds(e){return{widthDeg:this.pxToDeg(e.width),heightDeg:this.pxToDeg(e.height)}}toBoundsSize(e){return{width:this.degToPx(e.widthDeg),height:this.degToPx(e.heightDeg)}}widthPx(e){return this.degToPx(Rt.angularWidthDeg(e))}}class Fi{static fovOf(e,t){return at(e,t)?.fovDeg??Yt.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,i)=>{const s=i.ofBounds(t.bounds);return t.angular?.widthDeg===s.widthDeg&&t.angular.heightDeg===s.heightDeg?t:{...t,angular:s}})}static toBounds(e){this.eachKeyframe(e,(t,i)=>this.sizedFromAngle(t,i))}static sizedFromAngle(e,t){if(!e.angular)return e;const{width:i,height:s}=t.toBoundsSize(e.angular),n={x:e.bounds.x+(e.bounds.width-i)/2,y:e.bounds.y+(e.bounds.height-s)/2,width:i,height:s};if(e.kind!=="polygon")return{...e,bounds:n};const r=e.bounds.width===0?1:i/e.bounds.width,a=e.bounds.height===0?1:s/e.bounds.height;return{...e,bounds:n,points:e.points.map(o=>({x:o.x*r,y:o.y*a}))}}static toAim(e){this.eachKeyframe(e,(t,i,s)=>{const n=t.aim&&this.positionOf(e,t.aim,t.bounds,i,s);if(n&&Math.abs(n.x-t.bounds.x)<Fi.UNMOVED_PX&&Math.abs(n.y-t.bounds.y)<Fi.UNMOVED_PX)return t;const r=this.aimFrom(e,i,s,t.bounds);return r?{...t,aim:r}:t})}static UNMOVED_PX=.01;static aimOf(e,t,i){const s=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,s,at(e,t),i)}static aimFrom(e,t,i,s){if(i?.headingDeg===void 0)return;const n=this.frameCentre(e),r=t.radiusPxToAngleDeg(s.x+s.width/2-n.x),a=t.radiusPxToAngleDeg(n.y-(s.y+s.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(e){this.eachKeyframe(e,(t,i,s)=>this.placedByAim(e,t,i,s))}static placedByAim(e,t,i,s){const n=t.aim&&this.positionOf(e,t.aim,t.bounds,i,s);return n?{...t,bounds:{...t.bounds,...n}}:t}static derivable(e){const t=new Set,i=new Map,s=new Map;return e.timeline.allKeyframes.forEach((n,r)=>{const a=at(e,n.t),o=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,this.fovOf(e,n.t));for(const{sourceId:c,shape:h}of n.shapes){const d=s.get(c),u=i.get(c);if(s.set(c,h),!d||!u){i.set(c,h);continue}const p=Object.fromEntries(Object.entries(h).filter(([g,v])=>g!=="bounds"&&g!=="points"&&JSON.stringify(v)!==JSON.stringify(d[g]))),f={...u,...p},m=this.placedByAim(e,this.sizedFromAngle(f,o),o,a);Fi.near(m,h)?(t.add(`${r}:${c}`),i.set(c,f)):i.set(c,h)}}),(n,r)=>t.has(`${n}:${r}`)}static SAME_PX=1e-6;static near(e,t){const i=(r,a)=>Math.abs(r-a)<=Fi.SAME_PX*Math.max(1,Math.abs(a)),s=e.bounds,n=t.bounds;return!i(s.x,n.x)||!i(s.y,n.y)||!i(s.width,n.width)||!i(s.height,n.height)?!1:t.kind!=="polygon"||e.kind!=="polygon"?!0:e.points.length===t.points.length&&e.points.every((r,a)=>i(r.x,t.points[a].x)&&i(r.y,t.points[a].y))}static positionOf(e,t,i,s,n){if(n?.headingDeg===void 0)return;const r=this.frameCentre(e),a=this.shortestArc(t.azimuthDeg-n.headingDeg),o=t.altitudeDeg-n.pitchDeg;return{x:r.x+this.offAxisPx(s,a)-i.width/2,y:r.y-this.offAxisPx(s,o)-i.height/2}}static frameCentre(e){return{x:Yt.frameWidthPx(e.instrument,Rt.CANVAS_HEIGHT_PX)/2,y:Rt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=Fi.OFF_CANVAS_DEG?Math.sign(t)*Fi.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,i){const s=Yt.frameWidthPx(t,Rt.CANVAS_HEIGHT_PX)/2,n=Yt.frameWidthPx(e.instrument,Rt.CANVAS_HEIGHT_PX)/2,r=Rt.CANVAS_HEIGHT_PX/2;for(const a of[...e.timeline.allKeyframes]){const o=this.fovOf(e,a.t),c=i?.get(a.t)??o,h=Bn.of(t,Rt.CANVAS_HEIGHT_PX,c),d=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,o);e.timeline.addKeyframe(a.t,a.shapes.map(u=>{const{bounds:p}=u.shape,f=p.x+p.width/2-s,m=p.y+p.height/2-r,g=Math.hypot(f,m),v=g===0?1:d.angleDegToRadiusPx(h.radiusPxToAngleDeg(g))/g,b={...p,x:n+f*v-p.width/2,y:r+m*v-p.height/2};return{...u,shape:{...u.shape,bounds:b}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:i}=e;for(const s of[...i.allKeyframes]){const n=at(e,s.t),r=this.fovOf(e,s.t),a=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,r);let o=!1;const c=s.shapes.map(h=>{const d=t(h.shape,a,n);return d===h.shape?h:(o=!0,{...h,shape:d})});o&&i.addKeyframe(s.t,c)}}}class gn{static restatedDecor(e){const t=gn.originOf(e);return e.decor.map(i=>{let s=i;if(i.saidPosition){const n=gn.restated(i.saidPosition,i,gn.frameAt(e,0,t,i.id));JSON.stringify(n)!==JSON.stringify(i.saidPosition)&&(s={...i,saidPosition:n},n||delete s.saidPosition)}if(i.track?.some(n=>n.saidPosition)){const n=i.track.map(r=>{if(!r.saidPosition)return r;const a=gn.restated(r.saidPosition,r,gn.frameAt(e,r.t,t,i.id));if(JSON.stringify(a)===JSON.stringify(r.saidPosition))return r;const o={...r,saidPosition:a};return a||delete o.saidPosition,o});s={...s,track:n}}return s})}static restatedObserverTrack(e){const t=e.observerTrack.toJSON(),i=gn.originOf(e);return!i||!t.keyframes.some(s=>s.pose.saidPosition)?t:{...t,keyframes:t.keyframes.map(s=>{const{pose:n}=s;if(!n.saidPosition||n.lat===void 0||n.lng===void 0)return s;const r=jt.toLocal({lat:n.lat,lng:n.lng},i),a=gn.restated(n.saidPosition,r,gn.frameAt(e,s.t,i));if(JSON.stringify(a)===JSON.stringify(n.saidPosition))return s;const o={...n,saidPosition:a};return a||delete o.saidPosition,{...s,pose:o}})}}static restatedInterpretation(e){const t=e.interpretation;if(!t?.bodies.some(s=>s.track.some(n=>n.saidPosition)))return t;const i=gn.originOf(e);return{...t,bodies:t.bodies.map(s=>s.track.some(n=>n.saidPosition)?{...s,track:s.track.map(n=>{if(!n.saidPosition)return n;const r=n.eastM!==void 0&&n.northM!==void 0?gn.restated(n.saidPosition,{eastM:n.eastM,northM:n.northM},gn.frameAt(e,n.t,i)):void 0;if(JSON.stringify(r)===JSON.stringify(n.saidPosition))return n;const a={...n,saidPosition:r};return r||delete a.saidPosition,a})}:s)}}static originOf(e){const t=e.observerTrack.getInterpolatedPoseAt(0),i=e.event.place?.[0],s=t?.lat??i?.lat,n=t?.lng??i?.lng;return typeof s=="number"&&typeof n=="number"?{lat:s,lng:n}:void 0}static frameAt(e,t,i,s){const n=[{label:"",eastM:0,northM:0},...e.decor.filter(r=>r.id!==s).map(r=>{const{eastM:a,northM:o}=tr(r,t);return{id:r.id,label:r.id,eastM:a,northM:o}})];return{origin:i,references:n}}static restated(e,t,i){return jt.restated(e,{eastM:t.eastM,northM:t.northM},i)}}function xf(l){return wn.restore(Gg(l),l.provenance)}function Gg(l){return Fi.toAngular(l),Fi.toAim(l),{version:1,id:l.id,time:l.event.time,endTime:l.event.endTime,durationSeconds:l.event.durationSeconds,durationText:l.event.durationText,utcOffsetHours:l.event.utcOffsetHours,timeZone:l.event.timeZone,place:l.event.place,observer:l.observer,account:l.account,sources:l.sources?.length?l.sources:void 0,sway:l.sway,vehicle:l.vehicle,description:l.event.description,image:l.event.image,summary:l.event.summary,summaryTime:l.event.summaryTime,tags:l.event.tags,timeline:l.timeline.toJSON(),observerTrack:gn.restatedObserverTrack(l),weatherTrack:l.weatherTrack.toJSON(),soundTrack:l.soundTrack.toJSON(),weather:l.weather,decor:gn.restatedDecor(l),milestones:l.milestones.length>0?l.milestones:void 0,references:l.references.length>0?l.references:void 0,roads:l.roads.length>0?l.roads:void 0,traces:l.traces.length>0?l.traces:void 0,weatherSource:l.weatherSource,instrument:l.instrumentId,exposureSeconds:l.exposureSeconds,iso:l.iso,metering:l.metering,lens:l.lens,lightPollution:l.lightPollution,observerMap:l.observerMap,interpretation:gn.restatedInterpretation(l),variants:l.variants.length>0?l.variants:void 0,skyEvents:ia.written(l.skyEvents),frozen:l.frozen}}function bb(l){al.check(l,"sighting");const{recording:e,provenance:t}=wn.strip(l),i=tI(e);return i.provenance=t,i}function tI(l){const e=[],t=new dm({eventType:"sighting",time:l.time,endTime:l.endTime,durationSeconds:l.durationSeconds,durationText:l.durationText,utcOffsetHours:l.utcOffsetHours,timeZone:l.timeZone,place:l.place,description:l.description,image:l.image,summary:l.summary,summaryTime:l.summaryTime,tags:l.tags},am.fromJSON(l.timeline,e),l.observerTrack?Nd.fromJSON(l.observerTrack):new Nd,l.weatherTrack?Fd.fromJSON(l.weatherTrack):new Fd,l.soundTrack?Ud.fromJSON(l.soundTrack):new Ud,l.observer&&{id:l.observer.id,title:l.observer.title,lastName:l.observer.lastName,firstNames:l.observer.firstNames},l.id,l.weather,(l.decor??[]).map(s=>{if(!s.facade?.plain)return s;const{plain:n,...r}=s.facade;return{...s,facade:{...r,openings:"plain"}}}),l.weatherSource,l.instrument,l.exposureSeconds??l.observerTrack?.keyframes.map(s=>s.pose.exposureSeconds).find(s=>s!==void 0),Ol(l.milestones??[]),l.references??[],l.roads??[],l.traces??[]);t.account=l.account,t.sources=l.sources,t.sway=l.sway,t.iso=l.iso,t.metering=l.metering,t.lens=l.lens,t.lightPollution=l.lightPollution,t.observerMap=l.observerMap,t.vehicle=l.vehicle;const i=ia.read(l.skyEvents,l.interpretation);return t.interpretation=i.interpretation,t.variants=Array.isArray(l.variants)?l.variants:[],t.skyEvents=i.skyEvents,t.frozen=l.frozen,t.loadIssues=e,Fi.toBounds(t),Fi.toPosition(t),t}class wh{static EN={"unknown-key":"{path}: unknown key, ignored","wrong-type":"{path}: expected {expected}, found {found}","not-in-list":"{path}: {found} is not one of {expected}",defaulted:"{path}: missing, {expected} used",unplaced:"{path}: no aim (and no bounds), drawn at the middle of the view",unsized:"{path}: no angular size (and no bounds), drawn one pixel wide","pixels-over-angles":"{path}: bounds restated without aim or angular, so the shape follows the pixels"};static text(e,t=wh.EN){return t[e.kind].replace("{path}",e.path).replace("{expected}",e.expected??"").replace("{found}",e.found??"")}static warn(e,t){if(e.length===0)return;const i=e.map(s=>` ${wh.text(s)}`);console.warn(`UFO@home: ${e.length} problem(s) in ${t??"this recording"}:
4248
+ `;class Cl{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const i of e.observerTrack.allKeyframes){const{lat:s,lng:n,headingDeg:r}=i.pose;s===void 0||n===void 0||t.push({t:i.t,lat:s,lng:n,headingDeg:r})}if(t.length===0){const i=e.event.place?.[0];if(!i)return;t.push({t:0,lat:i.lat,lng:i.lng})}return new Cl(t)}static TRAVEL_M=50;get travels(){return this.spanM>Cl.TRAVEL_M}get moved(){return this.spanM>Cl.STATIONARY_M}get spanM(){const e=this.box,t=(e.south+e.north)/2,i=(e.west+e.east)/2;return Math.max(Math.abs(ot(t,e.east,t,e.west).x),Math.abs(ot(e.north,i,e.south,i).z))}get center(){const e=this.box;return{lat:(e.south+e.north)/2,lng:(e.west+e.east)/2}}boundsAround(e,t){const{lat:i,lng:s}=this.center,n=Math.max(this.spanM*(1+t),e)/2;return{north:_n(0,-n,i,s).lat,south:_n(0,n,i,s).lat,east:_n(n,0,i,s).lng,west:_n(-n,0,i,s).lng}}get box(){const e=this.points.map(i=>i.lat),t=this.points.map(i=>i.lng);return{south:Math.min(...e),north:Math.max(...e),west:Math.min(...t),east:Math.max(...t)}}}class lr{constructor(e,t){this.rotationPassed=e,this.scale=t}static SWAY_M=.012;static BREATH_M=.003;static DRIFT_YAW_DEG=.5;static DRIFT_PITCH_DEG=.4;static DRIFT_ROLL_DEG=.3;static GAZE_DRIFT_SHARE=.35;static HAND_HELD_S=.5;static HZ=[.11,.23,.17,.29,.37,.07];static of(e){if(e.instrument.mounted)return;const t=e.event.tags?.includes("paralysis")||(e.exposure??0)>lr.HAND_HELD_S,i=e.sway??(t?0:1);if(i>0)return new lr(Math.max(1-(e.instrument.stabilization??0),lr.GAZE_DRIFT_SHARE),i)}offsetAt(e){const t=e/1e3,i=this.scale,s=(d,u)=>Math.sin(2*Math.PI*d*t+u),[n,r,a,o,c,h]=lr.HZ;return{eastM:i*lr.SWAY_M*(.7*s(n,.3)+.3*s(o,1.9)),northM:i*lr.SWAY_M*(.6*s(a,2.2)+.4*s(c,.8)),upM:i*lr.BREATH_M*s(r,0),yawDeg:i*this.rotationPassed*lr.DRIFT_YAW_DEG*(.6*s(h,1.1)+.4*s(o,2.7)),pitchDeg:i*this.rotationPassed*lr.DRIFT_PITCH_DEG*(.5*s(r,1.6)+.5*s(a,.4)),rollDeg:i*this.rotationPassed*lr.DRIFT_ROLL_DEG*s(n,2.9)}}}class ci{constructor(e,t){this.stretches=e,this.rotationPassed=t}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STOP_LURCH_M=.035;static STOP_PITCH_DEG=3;static START_LURCH_M=.015;static START_PITCH_DEG=1.2;static JOLT_HZ=1.4;static JOLT_DECAY_S=.35;static JOLT_LASTS_MS=1500;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(e){const t=Cl.of(e);if(!t||t.points.length<2)return;const i=[];let s=0;for(let n=1;n<t.points.length;n++){const r=t.points[n-1],a=t.points[n],o=(a.t-r.t)/1e3;if(o<=0)continue;const c=ot(a.lat,a.lng,r.lat,r.lng),h=c.x,d=-c.z,u=Math.hypot(h,d),p=u/o,f=ci.stepHzFor(p);i.push({startMs:r.t,endMs:a.t,speedMPerS:p,eastUnit:u>0?h/u:0,northUnit:u>0?d/u:0,stepHz:f,stepsBefore:s,rampsIn:!0,rampsOut:!0}),s+=f*o}for(let n=0;n<i.length;n++){const r=i[n-1],a=i[n+1];i[n].rampsIn=r===void 0||r.stepHz===0,i[n].rampsOut=a===void 0||a.stepHz===0}if(i.some(n=>n.stepHz>0))return new ci(i,1-(e.instrument.stabilization??0))}static bodyAt(e,t,i=!1){const s=ci.of(e)?.offsetAt(t)??ci.STILL;return i?s:ci.add(s,lr.of(e)?.offsetAt(t))}static stepHzFor(e){return e<ci.SLOWEST_WALK_M_PER_S||e>ci.FASTEST_WALK_M_PER_S?0:ci.REFERENCE_STEP_HZ*Math.pow(e/ci.REFERENCE_SPEED_M_PER_S,ci.CADENCE_EXPONENT)}offsetAt(e){return ci.add(this.cycleAt(e),this.joltAt(e))}joltAt(e){for(const t of this.stretches){if(t.stepHz===0)continue;const i=t.speedMPerS/ci.REFERENCE_SPEED_M_PER_S,s=(a,o,c,h)=>{if(a<0||a>ci.JOLT_LASTS_MS)return;const d=a/1e3,u=Math.exp(-d/ci.JOLT_DECAY_S)*Math.sin(2*Math.PI*ci.JOLT_HZ*d),p=h*o*i*u;return{eastM:p*t.eastUnit,northM:p*t.northUnit,upM:-Math.abs(p)*.3,rollDeg:0,pitchDeg:-h*c*i*u*this.rotationPassed,yawDeg:0}},n=t.rampsOut?s(e-t.endMs,ci.STOP_LURCH_M,ci.STOP_PITCH_DEG,1):void 0;if(n)return n;const r=t.rampsIn?s(e-t.startMs,ci.START_LURCH_M,ci.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(e,t){return t?{eastM:e.eastM+t.eastM,northM:e.northM+t.northM,upM:e.upM+t.upM,rollDeg:e.rollDeg+t.rollDeg,pitchDeg:e.pitchDeg+t.pitchDeg,yawDeg:e.yawDeg+t.yawDeg}:e}cycleAt(e){const t=this.stretches.find(o=>e>=o.startMs&&e<=o.endMs);if(!t||t.stepHz===0)return ci.STILL;const i=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,s=2*Math.PI*i,n=this.amplitudeAt(t,e),r=ci.SWAY_M*n*Math.cos(s/2),a=n*this.rotationPassed*t.speedMPerS/ci.REFERENCE_SPEED_M_PER_S;return{eastM:r*t.northUnit,northM:-r*t.eastUnit,upM:ci.RISE_M_PER_M_PER_S*t.speedMPerS*n*Math.cos(s),rollDeg:ci.HEAD_ROLL_DEG*a*Math.cos(s/2),pitchDeg:-1.25*a*Math.cos(s),yawDeg:ci.HEAD_YAW_DEG*a*Math.cos(s/2)}}amplitudeAt(e,t){const i=1e3/e.stepHz,s=Math.min(i,(e.endMs-e.startMs)/2);if(s<=0)return 1;const n=t-e.startMs,r=e.endMs-t,a=Math.min(e.rampsIn?n/s:1,e.rampsOut?r/s:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class Z3{constructor(e,t){this.timeline=e,this.onFrame=t}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const e=()=>{if(this.state!=="playing")return;const t=performance.now();if(this.currentT+=(t-this.lastWallTime)*this.playbackRate,this.lastWallTime=t,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(e){this.currentT=Math.max(0,Math.min(e,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(e){const t=new Map;for(const i of this.timeline.sourceIds){const s=this.timeline.getInterpolatedShapeAt(e,i);s&&t.set(i,s)}this.onFrame(e,t)}}class Ll{static sessionDeclared=!1;static unlock(e){if(Ll.declarePlayback(),e.state!=="running")try{Promise.resolve(e.resume()).catch(()=>{});const t=e.createBufferSource();t.buffer=e.createBuffer(1,1,22050),t.connect(e.destination),t.start(0)}catch{}}static declarePlayback(){if(!(Ll.sessionDeclared||typeof navigator>"u")){Ll.sessionDeclared=!0;try{const e=navigator.audioSession;e&&(e.type="playback")}catch{}}}}const ly=.05,cy=.08,hy=2,dy=3,J3=14,Q3=.02;class eI{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",e);return}}Ll.unlock(this.context)}setSound(e){if(this.requested=e,!this.context)return;const t=this.keyFor(e);if(!t){this.silence();return}if(this.voice?.key!==t){this.stopVoice();const i=++this.voiceToken;t.startsWith("src:")?this.buildRecordedVoice(e.src,t,i):this.voice=this.buildSynthesizedVoice(e,t)}this.applyTo(this.voice,e)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(e){if(!(e.volume<=0))return e.src?`src:${e.src}`:e.kind==="none"?void 0:e.kind}applyTo(e,t){const i=this.context;if(!e||!i)return;const s=i.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,s,ly);for(const{param:n,ratio:r}of e.pitch)n.setTargetAtTime(Math.min(t.pitchHz*r,i.sampleRate/2-1),s,ly)}buildSynthesizedVoice(e,t){const i=this.context;if(i)switch(e.kind){case"hum":return this.buildHum(i,t);case"whistle":return this.buildWhistle(i,t);case"rumble":return this.buildRumble(i,t);case"crackle":return this.buildCrackle(i,t);default:return}}buildHum(e,t){const i=e.createOscillator();i.type="sawtooth";const s=e.createOscillator();s.type="sawtooth";const n=e.createBiquadFilter();n.type="lowpass",n.Q.value=1;const r=e.createGain();return r.gain.value=0,i.connect(n),s.connect(n),n.connect(r).connect(this.output(e)),i.start(),s.start(),{key:t,nodes:[n,r],sources:[i,s],volumeParam:r.gain,gainScale:.16,pitch:[{param:i.frequency,ratio:1},{param:s.frequency,ratio:1.006},{param:n.frequency,ratio:6}]}}buildWhistle(e,t){const i=e.createOscillator();i.type="sine";const s=e.createOscillator();s.type="sine",s.frequency.value=5;const n=e.createGain(),r=e.createGain();return r.gain.value=0,s.connect(n).connect(i.frequency),i.connect(r).connect(this.output(e)),i.start(),s.start(),{key:t,nodes:[n,r],sources:[i,s],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:n.gain,ratio:.012}]}}buildRumble(e,t){const i=e.createBufferSource();i.buffer=this.brownNoise(e),i.loop=!0;const s=e.createBiquadFilter();s.type="lowpass",s.Q.value=.8;const n=e.createGain();return n.gain.value=0,i.connect(s).connect(n).connect(this.output(e)),i.start(),{key:t,nodes:[s,n],sources:[i],volumeParam:n.gain,gainScale:1.4,pitch:[{param:s.frequency,ratio:1}]}}buildCrackle(e,t){const i=e.createBufferSource();i.buffer=this.whiteNoise(e),i.loop=!0;const s=e.createBiquadFilter();s.type="bandpass",s.Q.value=1.2;const n=e.createGain();n.gain.value=0;const r=e.createBufferSource();r.buffer=this.crackleEnvelope(e),r.loop=!0;const a=e.createGain();return a.gain.value=0,r.connect(a).connect(n.gain),i.connect(s).connect(n).connect(this.output(e)),i.start(),r.start(),{key:t,nodes:[s,n,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:s.frequency,ratio:4}]}}async buildRecordedVoice(e,t,i){const s=this.context;if(!s)return;let n;try{n=await this.getBuffer(e)}catch(o){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",o);return}if(i!==this.voiceToken||!this.context)return;const r=s.createBufferSource();r.buffer=n,r.loop=!0;const a=s.createGain();a.gain.value=0,r.connect(a).connect(this.output(s)),r.start(),this.voice={key:t,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(e){const t=this.context;if(!t)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(e);return i||(i=fetch(e).then(s=>{if(!s.ok)throw new Error(`Audio fetch failed (${s.status}): ${e}`);return s.arrayBuffer()}).then(s=>t.decodeAudioData(s)),this.buffers.set(e,i)),i}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*hy),e.sampleRate),i=t.getChannelData(0);for(let s=0;s<i.length;s++)i[s]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*hy),e.sampleRate),i=t.getChannelData(0);let s=0,n=0;for(let r=0;r<i.length;r++)s=(s+.02*(Math.random()*2-1))/1.02,i[r]=s,n=Math.max(n,Math.abs(s));if(n>0)for(let r=0;r<i.length;r++)i[r]/=n;return t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*dy),e.sampleRate),i=t.getChannelData(0),s=Math.max(1,Math.floor(Q3*e.sampleRate)),n=Math.round(dy*J3);for(let r=0;r<n;r++){const a=Math.floor(Math.random()*i.length),o=.4+Math.random()*.6;for(let c=0;c<s&&a+c<i.length;c++)i[a+c]=Math.max(i[a+c],o*(1-c/s))}this.crackleBuffer=t}return this.crackleBuffer}stopVoice(){const e=this.voice,t=this.context;if(this.voice=void 0,!e||!t)return;const i=t.currentTime;e.volumeParam.cancelScheduledValues(i),e.volumeParam.setTargetAtTime(0,i,cy/3);const s=i+cy;for(const n of e.sources){n.onended=()=>{n.disconnect();for(const r of e.nodes)r.disconnect()};try{n.stop(s)}catch{n.disconnect();for(const r of e.nodes)r.disconnect()}}}}class ia{static KINDS=["beams","launches","reentries"];static isEmpty(e){return!e||ia.KINDS.every(t=>!e[t]?.length)}static written(e){if(ia.isEmpty(e))return;const t={};for(const i of ia.KINDS)e[i]?.length&&(t[i]=e[i]);return t}static read(e,t){const i=t,s={};for(const r of ia.KINDS){const a=[...e?.[r]??[],...i?.[r]??[]];a.length>0&&(s[r]=a)}let n=t;if(i&&ia.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:o,...c}=i;n=ia.isReading(c)?c:void 0}return{skyEvents:ia.written(s),interpretation:n}}static isReading(e){return(e.bodies?.length??0)>0||e.title!==void 0||(e.smoke?.length??0)>0}}function Ol(l){return[...l].sort((e,t)=>e.t-t.t)}function Nm(l,e){let t;for(const i of Ol(l)){if(i.t>e)break;t=i}return t}const Fm=Math.PI/180,yu=180/Math.PI;class Bn{constructor(e,t,i){this.kind=e,this.canvasHeightPx=t,this.fovDeg=i;const s=i*Fm/2;this.focalPx=e==="equidistant"?t/2/s:t/2/Math.tan(s)}focalPx;static of(e,t,i){return new Bn(e.projection,t,i)}degToPx(e){const t=e*Fm;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*yu:2*Math.atan(e/(2*this.focalPx))*yu}angleDegToRadiusPx(e){const t=e*Fm;return this.kind==="equidistant"?this.focalPx*t:this.focalPx*Math.tan(t)}halfWidthAngleDeg(e){return this.radiusPxToAngleDeg(this.canvasHeightPx*e/2)}radiusPxToAngleDeg(e){return this.kind==="equidistant"?e/this.focalPx*yu:Math.atan(e/this.focalPx)*yu}ofBounds(e){return{widthDeg:this.pxToDeg(e.width),heightDeg:this.pxToDeg(e.height)}}toBoundsSize(e){return{width:this.degToPx(e.widthDeg),height:this.degToPx(e.heightDeg)}}widthPx(e){return this.degToPx(Rt.angularWidthDeg(e))}}class Fi{static fovOf(e,t){return at(e,t)?.fovDeg??Yt.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,i)=>{const s=i.ofBounds(t.bounds);return t.angular?.widthDeg===s.widthDeg&&t.angular.heightDeg===s.heightDeg?t:{...t,angular:s}})}static toBounds(e){this.eachKeyframe(e,(t,i)=>this.sizedFromAngle(t,i))}static sizedFromAngle(e,t){if(!e.angular)return e;const{width:i,height:s}=t.toBoundsSize(e.angular),n={x:e.bounds.x+(e.bounds.width-i)/2,y:e.bounds.y+(e.bounds.height-s)/2,width:i,height:s};if(e.kind!=="polygon")return{...e,bounds:n};const r=e.bounds.width===0?1:i/e.bounds.width,a=e.bounds.height===0?1:s/e.bounds.height;return{...e,bounds:n,points:e.points.map(o=>({x:o.x*r,y:o.y*a}))}}static toAim(e){this.eachKeyframe(e,(t,i,s)=>{const n=t.aim&&this.positionOf(e,t.aim,t.bounds,i,s);if(n&&Math.abs(n.x-t.bounds.x)<Fi.UNMOVED_PX&&Math.abs(n.y-t.bounds.y)<Fi.UNMOVED_PX)return t;const r=this.aimFrom(e,i,s,t.bounds);return r?{...t,aim:r}:t})}static UNMOVED_PX=.01;static aimOf(e,t,i){const s=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,s,at(e,t),i)}static aimFrom(e,t,i,s){if(i?.headingDeg===void 0)return;const n=this.frameCentre(e),r=t.radiusPxToAngleDeg(s.x+s.width/2-n.x),a=t.radiusPxToAngleDeg(n.y-(s.y+s.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(e){this.eachKeyframe(e,(t,i,s)=>this.placedByAim(e,t,i,s))}static placedByAim(e,t,i,s){const n=t.aim&&this.positionOf(e,t.aim,t.bounds,i,s);return n?{...t,bounds:{...t.bounds,...n}}:t}static derivable(e){const t=new Set,i=new Map,s=new Map;return e.timeline.allKeyframes.forEach((n,r)=>{const a=at(e,n.t),o=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,this.fovOf(e,n.t));for(const{sourceId:c,shape:h}of n.shapes){const d=s.get(c),u=i.get(c);if(s.set(c,h),!d||!u){i.set(c,h);continue}const p=Object.fromEntries(Object.entries(h).filter(([g,v])=>g!=="bounds"&&g!=="points"&&JSON.stringify(v)!==JSON.stringify(d[g]))),f={...u,...p},m=this.placedByAim(e,this.sizedFromAngle(f,o),o,a);Fi.near(m,h)?(t.add(`${r}:${c}`),i.set(c,f)):i.set(c,h)}}),(n,r)=>t.has(`${n}:${r}`)}static SAME_PX=1e-6;static near(e,t){const i=(r,a)=>Math.abs(r-a)<=Fi.SAME_PX*Math.max(1,Math.abs(a)),s=e.bounds,n=t.bounds;return!i(s.x,n.x)||!i(s.y,n.y)||!i(s.width,n.width)||!i(s.height,n.height)?!1:t.kind!=="polygon"||e.kind!=="polygon"?!0:e.points.length===t.points.length&&e.points.every((r,a)=>i(r.x,t.points[a].x)&&i(r.y,t.points[a].y))}static positionOf(e,t,i,s,n){if(n?.headingDeg===void 0)return;const r=this.frameCentre(e),a=this.shortestArc(t.azimuthDeg-n.headingDeg),o=t.altitudeDeg-n.pitchDeg;return{x:r.x+this.offAxisPx(s,a)-i.width/2,y:r.y-this.offAxisPx(s,o)-i.height/2}}static frameCentre(e){return{x:Yt.frameWidthPx(e.instrument,Rt.CANVAS_HEIGHT_PX)/2,y:Rt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=Fi.OFF_CANVAS_DEG?Math.sign(t)*Fi.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,i){const s=Yt.frameWidthPx(t,Rt.CANVAS_HEIGHT_PX)/2,n=Yt.frameWidthPx(e.instrument,Rt.CANVAS_HEIGHT_PX)/2,r=Rt.CANVAS_HEIGHT_PX/2;for(const a of[...e.timeline.allKeyframes]){const o=this.fovOf(e,a.t),c=i?.get(a.t)??o,h=Bn.of(t,Rt.CANVAS_HEIGHT_PX,c),d=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,o);e.timeline.addKeyframe(a.t,a.shapes.map(u=>{const{bounds:p}=u.shape,f=p.x+p.width/2-s,m=p.y+p.height/2-r,g=Math.hypot(f,m),v=g===0?1:d.angleDegToRadiusPx(h.radiusPxToAngleDeg(g))/g,b={...p,x:n+f*v-p.width/2,y:r+m*v-p.height/2};return{...u,shape:{...u.shape,bounds:b}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:i}=e;for(const s of[...i.allKeyframes]){const n=at(e,s.t),r=this.fovOf(e,s.t),a=Bn.of(e.instrument,Rt.CANVAS_HEIGHT_PX,r);let o=!1;const c=s.shapes.map(h=>{const d=t(h.shape,a,n);return d===h.shape?h:(o=!0,{...h,shape:d})});o&&i.addKeyframe(s.t,c)}}}class gn{static restatedDecor(e){const t=gn.originOf(e);return e.decor.map(i=>{let s=i;if(i.saidPosition){const n=gn.restated(i.saidPosition,i,gn.frameAt(e,0,t,i.id));JSON.stringify(n)!==JSON.stringify(i.saidPosition)&&(s={...i,saidPosition:n},n||delete s.saidPosition)}if(i.track?.some(n=>n.saidPosition)){const n=i.track.map(r=>{if(!r.saidPosition)return r;const a=gn.restated(r.saidPosition,r,gn.frameAt(e,r.t,t,i.id));if(JSON.stringify(a)===JSON.stringify(r.saidPosition))return r;const o={...r,saidPosition:a};return a||delete o.saidPosition,o});s={...s,track:n}}return s})}static restatedObserverTrack(e){const t=e.observerTrack.toJSON(),i=gn.originOf(e);return!i||!t.keyframes.some(s=>s.pose.saidPosition)?t:{...t,keyframes:t.keyframes.map(s=>{const{pose:n}=s;if(!n.saidPosition||n.lat===void 0||n.lng===void 0)return s;const r=jt.toLocal({lat:n.lat,lng:n.lng},i),a=gn.restated(n.saidPosition,r,gn.frameAt(e,s.t,i));if(JSON.stringify(a)===JSON.stringify(n.saidPosition))return s;const o={...n,saidPosition:a};return a||delete o.saidPosition,{...s,pose:o}})}}static restatedInterpretation(e){const t=e.interpretation;if(!t?.bodies.some(s=>s.track.some(n=>n.saidPosition)))return t;const i=gn.originOf(e);return{...t,bodies:t.bodies.map(s=>s.track.some(n=>n.saidPosition)?{...s,track:s.track.map(n=>{if(!n.saidPosition)return n;const r=n.eastM!==void 0&&n.northM!==void 0?gn.restated(n.saidPosition,{eastM:n.eastM,northM:n.northM},gn.frameAt(e,n.t,i)):void 0;if(JSON.stringify(r)===JSON.stringify(n.saidPosition))return n;const a={...n,saidPosition:r};return r||delete a.saidPosition,a})}:s)}}static originOf(e){const t=e.observerTrack.getInterpolatedPoseAt(0),i=e.event.place?.[0],s=t?.lat??i?.lat,n=t?.lng??i?.lng;return typeof s=="number"&&typeof n=="number"?{lat:s,lng:n}:void 0}static frameAt(e,t,i,s){const n=[{label:"",eastM:0,northM:0},...e.decor.filter(r=>r.id!==s).map(r=>{const{eastM:a,northM:o}=tr(r,t);return{id:r.id,label:r.id,eastM:a,northM:o}})];return{origin:i,references:n}}static restated(e,t,i){return jt.restated(e,{eastM:t.eastM,northM:t.northM},i)}}function xf(l){return wn.restore(Gg(l),l.provenance)}function Gg(l){return Fi.toAngular(l),Fi.toAim(l),{version:1,id:l.id,time:l.event.time,endTime:l.event.endTime,durationSeconds:l.event.durationSeconds,durationText:l.event.durationText,utcOffsetHours:l.event.utcOffsetHours,timeZone:l.event.timeZone,place:l.event.place,observer:l.observer,account:l.account,sources:l.sources?.length?l.sources:void 0,sway:l.sway,vehicle:l.vehicle,description:l.event.description,image:l.event.image,summary:l.event.summary,summaryTime:l.event.summaryTime,tags:l.event.tags,timeline:l.timeline.toJSON(),observerTrack:gn.restatedObserverTrack(l),weatherTrack:l.weatherTrack.toJSON(),soundTrack:l.soundTrack.toJSON(),weather:l.weather,decor:gn.restatedDecor(l),milestones:l.milestones.length>0?l.milestones:void 0,references:l.references.length>0?l.references:void 0,roads:l.roads.length>0?l.roads:void 0,traces:l.traces.length>0?l.traces:void 0,weatherSource:l.weatherSource,instrument:l.instrumentId,exposureSeconds:l.exposureSeconds,iso:l.iso,metering:l.metering,lens:l.lens,lightPollution:l.lightPollution,observerMap:l.observerMap,interpretation:gn.restatedInterpretation(l),variants:l.variants.length>0?l.variants:void 0,skyEvents:ia.written(l.skyEvents),frozen:l.frozen}}function bb(l){al.check(l,"sighting");const{recording:e,provenance:t}=wn.strip(l),i=tI(e);return i.provenance=t,i}function tI(l){const e=[],t=new dm({eventType:"sighting",time:l.time,endTime:l.endTime,durationSeconds:l.durationSeconds,durationText:l.durationText,utcOffsetHours:l.utcOffsetHours,timeZone:l.timeZone,place:l.place,description:l.description,image:l.image,summary:l.summary,summaryTime:l.summaryTime,tags:l.tags},am.fromJSON(l.timeline,e),l.observerTrack?Nd.fromJSON(l.observerTrack):new Nd,l.weatherTrack?Fd.fromJSON(l.weatherTrack):new Fd,l.soundTrack?Ud.fromJSON(l.soundTrack):new Ud,l.observer&&{id:l.observer.id,title:l.observer.title,lastName:l.observer.lastName,firstNames:l.observer.firstNames},l.id,l.weather,(l.decor??[]).map(s=>{if(!s.facade?.plain)return s;const{plain:n,...r}=s.facade;return{...s,facade:{...r,openings:"plain"}}}),l.weatherSource,l.instrument,l.exposureSeconds??l.observerTrack?.keyframes.map(s=>s.pose.exposureSeconds).find(s=>s!==void 0),Ol(l.milestones??[]),l.references??[],l.roads??[],l.traces??[]);t.account=l.account,t.sources=l.sources,t.sway=l.sway,t.iso=l.iso,t.metering=l.metering,t.lens=l.lens,t.lightPollution=l.lightPollution,t.observerMap=l.observerMap,t.vehicle=l.vehicle;const i=ia.read(l.skyEvents,l.interpretation);return t.interpretation=i.interpretation,t.variants=Array.isArray(l.variants)?l.variants:[],t.skyEvents=i.skyEvents,t.frozen=l.frozen,t.loadIssues=e,Fi.toBounds(t),Fi.toPosition(t),t}class wh{static EN={"unknown-key":"{path}: unknown key, ignored","wrong-type":"{path}: expected {expected}, found {found}","not-in-list":"{path}: {found} is not one of {expected}",defaulted:"{path}: missing, {expected} used",unplaced:"{path}: no aim (and no bounds), drawn at the middle of the view",unsized:"{path}: no angular size (and no bounds), drawn one pixel wide","pixels-over-angles":"{path}: bounds restated without aim or angular, so the shape follows the pixels"};static text(e,t=wh.EN){return t[e.kind].replace("{path}",e.path).replace("{expected}",e.expected??"").replace("{found}",e.found??"")}static warn(e,t){if(e.length===0)return;const i=e.map(s=>` ${wh.text(s)}`);console.warn(`UFO@home: ${e.length} problem(s) in ${t??"this recording"}:
4249
4249
  ${i.join(`
4250
4250
  `)}`)}}class Ar{constructor(e){this.format=e}issues(e){const t=[];return this.object(e,this.format,"",t),t}object(e,t,i,s){if(!Ar.isObject(e)){s.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:Ar.typeOf(e)});return}for(const[n,r]of Object.entries(e)){const a=i?`${i}.${n}`:n,o=t[n];o?this.field(r,o,a,s):s.push({kind:"unknown-key",path:a})}}field(e,t,i,s){if(Ar.isStated(e)){this.field(e.value,t,i,s);return}if(!(t.loose||e===void 0||e===null))switch(t.type){case"enum":(typeof e!="string"||!t.values?.includes(e))&&s.push({kind:"not-in-list",path:i,expected:(t.values??[]).map(n=>`"${n}"`).join(", "),found:JSON.stringify(e)});return;case"object":t.fields?this.object(e,t.fields,i,s):Ar.isObject(e)||s.push({kind:"wrong-type",path:i,expected:"object",found:Ar.typeOf(e)});return;case"array":Array.isArray(e)?t.fields&&e.forEach((n,r)=>{const a=Ar.isStated(n)?n.value:n;this.object(a,t.fields,`${i}.${r}`,s)}):s.push({kind:"wrong-type",path:i,expected:"array",found:Ar.typeOf(e)});return;default:typeof e!==t.type&&s.push({kind:"wrong-type",path:i,expected:t.type,found:Ar.typeOf(e)})}}static isObject(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}static isStated(e){return Ar.isObject(e)&&"value"in e&&Object.keys(e).every(t=>t==="value"||t==="basis"||t==="rationale")}static typeOf(e){return Array.isArray(e)?"array":e===null?"null":typeof e}}class Cr{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(e,t){const i=Number.isFinite(t)?Math.max(0,t):0,s=Math.max(0,e-i*1e3),n=Math.max(0,e-s);return{fromMs:s,toMs:e,ms:n,seconds:n/1e3}}static instants(e,t,i,s,n){if(!(s>0))return 1;const r=n>0?Cr.travelDegOver(e,t,i,i+s*1e3)/n/Cr.PIXELS_PER_INSTANT:0,a=Cr.flashesOver(e,s)*Cr.INSTANTS_PER_FLASH,o=Math.ceil(Math.max(r,a));return o<2?1:Math.min(Cr.MAX_INSTANTS,o)}static travelDegOver(e,t,i,s){let n=0;for(const r of e){if(!r.track||r.track.length<2)continue;const a=Cr.directionAt(r,t,i),o=Cr.directionAt(r,t,s),c=Math.min(1,Math.max(-1,a.x*o.x+a.y*o.y+a.z*o.z));n=Math.max(n,Math.acos(c)*180/Math.PI)}return n}static flashesOver(e,t){let i=0;for(const s of e)for(const n of s.lights??[])n.pattern.kind==="flash"&&(i=Math.max(i,n.pattern.perMinute));return i/60*t}static directionAt(e,t,i){const s=tr(e,i),n=s.eastM,r=s.altitudeM-t,a=s.northM,o=Math.hypot(n,r,a);return o===0?{x:0,y:1,z:0}:{x:n/o,y:r/o,z:a/o}}}const A2={play:"Play",clickToPlay:"Click to play",pause:"Pause",noDuration:"No observation duration",currentPosition:"Current position",duration:"Duration",switchToElapsed:"click to show elapsed time",switchToClockTime:"click to show the time of day",fullscreen:"Fullscreen",exitFullscreen:"Exit fullscreen",mute:"Mute",unmute:"Unmute",noSound:"No sound recorded",moments:"Moments",moreControls:"More controls",fewerControls:"Fewer controls",showObserverMap:"Show where the observer was",hideObserverMap:"Hide where the observer was",mapImageryUnavailable:"Aerial imagery unavailable",zoomMapIn:"Zoom in",zoomMapOut:"Zoom out",fitMap:"Back to the whole path",placeObserverHere:"Put the observer here",showReferences:"Show the pictures of the place",hideReferences:"Hide the pictures of the place",showTraces:"Show the investigator's lines",hideTraces:"Hide the investigator's lines",referenceOpacity:"Picture opacity",referencesMenu:"Pictures of the place",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",observerHere:"The observer, here",decorHere:"Scenery",recordingIssues:"{count} problem(s) in this recording: it may not play as its author meant",issueTemplates:wh.EN},iI=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:A2},Symbol.toStringTag,{value:"Module"})),T2=Math.PI/180,sI=180/Math.PI,nI=256,I2=19,rI=1.25;function _2(l,e){return 156543.03392*Math.cos(l*T2)/2**e}function R2(l,e){return _2(l,e)*nI}function aI(l,e){let t=0;for(;t<I2&&R2(l,t+1)>=e;)t++;return t}function D2(l,e){return R2(l,e)}function oI(l,e){const t=e*rI;let i=0;for(;i<I2&&_2(l,i)>t;)i++;return i}function Ip(l){const e=l*T2;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function k2(l,e,t){const i=2**t;return{x:(l+180)/360*i,y:Ip(e)*i}}function C2(l,e,t){const i=Ip(l.north),s=Ip(l.south);return{x:(e-l.west)/(l.east-l.west),y:(Ip(t)-i)/(s-i)}}function lI(l,e,t){const{x:i,y:s}=k2(l,e,t);return{x:Math.floor(i),y:Math.floor(s),z:t}}function cI(l){const e=2**l.z,t=l.x/e*360-180,i=(l.x+1)/e*360-180,s=uy(l.y,e);return{south:uy(l.y+1,e),north:s,west:t,east:i}}function uy(l,e){const t=l/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*sI}function L2(l,e,t,i){const s=lI(l,e,t),n=Math.floor(i/2),r=[];for(let c=-n;c<=n;c++)for(let h=-n;h<=n;h++)r.push({x:s.x+h,y:s.y+c,z:t});const a=r.map(cI),o={south:Math.min(...a.map(c=>c.south)),north:Math.max(...a.map(c=>c.north)),west:Math.min(...a.map(c=>c.west)),east:Math.max(...a.map(c=>c.east))};return{tiles:r,bounds:o}}const hI="#2ec4ff";class tl{constructor(e){this.ctx=e}static SCALE_STEPS_M=[5e3,2e3,1e3,500,200,100,50,20,10,5];static MARKER_RADIUS_PX=8.5;static ON_MARKER_M=3;targets=[];hitTest(e,t){let i,s=1/0;for(const n of this.targets){const r=Math.hypot(n.x-e,n.y-t);r>n.radius||r>s||(i=n,s=r)}return i}get width(){return this.ctx.canvas.width}get height(){return this.ctx.canvas.height}paint(e){const{ctx:t}=this;t.save(),this.targets=[],t.clearRect(0,0,this.width,this.height),this.paintGround(e),this.paintNight(e.nightFraction),this.paintPath(e),this.paintTraces(e),e.position?(this.paintCone(e,e.position),this.paintDecor(e),this.paintMarkers(e),this.paintObserver(e,e.position)):(this.paintDecor(e),this.paintMarkers(e)),this.paintNorth(),this.paintFooter(e.bounds,e.attribution),t.restore()}toCanvas(e,t,i){const s=C2(e,i,t);return{x:s.x*this.width,y:s.y*this.height}}paintGround(e){const{ctx:t}=this;t.fillStyle="#1d2321",t.fillRect(0,0,this.width,this.height);const i=e.imagery;if(!i)return;const s=this.toCanvas(e.bounds,i.bounds.north,i.bounds.west),n=this.toCanvas(e.bounds,i.bounds.south,i.bounds.east);t.drawImage(i.source,s.x,s.y,n.x-s.x,n.y-s.y)}paintNight(e=0){if(e<=0)return;const{ctx:t}=this;t.save(),t.fillStyle=`rgba(6, 12, 30, ${Math.min(e,1)*.78})`,t.fillRect(0,0,this.width,this.height),t.restore()}paintDecor(e){const{ctx:t}=this;for(const i of e.decor){const s=this.toCanvas(e.bounds,i.lat,i.lng);if(i.label&&this.targets.push({kind:"decor",label:i.label,lat:i.lat,lng:i.lng,x:s.x,y:s.y,radius:7}),t.beginPath(),t.rect(s.x-3.5,s.y-3.5,7,7),t.fillStyle="rgba(120, 220, 255, 0.85)",t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.7)",t.stroke(),i.headingDeg===void 0)continue;const n=(i.headingDeg-90)*Math.PI/180;t.beginPath(),t.moveTo(s.x,s.y),t.lineTo(s.x+Math.cos(n)*10,s.y+Math.sin(n)*10),t.lineWidth=3,t.strokeStyle="rgba(0, 0, 0, 0.6)",t.stroke(),t.lineWidth=1.5,t.strokeStyle="rgba(120, 220, 255, 0.9)",t.stroke()}}paintPath(e){if(!e.path.moved)return;const{ctx:t}=this,i=e.path.points.map(s=>this.toCanvas(e.bounds,s.lat,s.lng));t.beginPath(),t.moveTo(i[0].x,i[0].y);for(const s of i.slice(1))t.lineTo(s.x,s.y);t.lineJoin="round",t.lineCap="round",t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=5,t.stroke(),t.strokeStyle="rgba(255, 255, 255, 0.9)",t.lineWidth=2,t.stroke()}paintTraces(e){const{ctx:t}=this;for(const i of e.traces??[]){const s=i.points.map(r=>this.toCanvas(e.bounds,r.lat,r.lng));if(s.length===0)continue;const n=i.color??hI;if(i.kind==="point")t.beginPath(),t.moveTo(s[0].x,s[0].y-6),t.lineTo(s[0].x+6,s[0].y),t.lineTo(s[0].x,s[0].y+6),t.lineTo(s[0].x-6,s[0].y),t.closePath(),t.fillStyle=n,t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.8)",t.stroke();else{t.beginPath(),t.moveTo(s[0].x,s[0].y);for(const r of s.slice(1))t.lineTo(r.x,r.y);i.kind==="polygon"&&t.closePath(),t.lineJoin="round",t.setLineDash([]),t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=4.5,t.stroke(),t.setLineDash([9,5]),t.strokeStyle=n,t.lineWidth=2.5,t.stroke(),t.setLineDash([])}if(i.label){t.font="11px sans-serif",t.textAlign="left",t.textBaseline="middle";let r=s[0];if(i.kind==="line"&&e.position){const a=this.toCanvas(e.bounds,e.position.lat,e.position.lng);r=s.reduce((o,c)=>Math.hypot(c.x-a.x,c.y-a.y)>Math.hypot(o.x-a.x,o.y-a.y)?c:o)}this.paintOutlinedText(i.label,r.x+9,r.y-9)}}}paintCone(e,t){const{headingDeg:i,coneHalfAngleDeg:s}=e;if(i===void 0||s===void 0)return;const{ctx:n}=this,r=this.toCanvas(e.bounds,t.lat,t.lng),a=Math.hypot(this.width,this.height),o=(i-90)*Math.PI/180,c=s*Math.PI/180;n.save(),n.beginPath(),n.moveTo(r.x,r.y),n.arc(r.x,r.y,a,o-c,o+c),n.closePath();const h=n.createRadialGradient(r.x,r.y,0,r.x,r.y,a);h.addColorStop(0,"rgba(255, 224, 130, 0.55)"),h.addColorStop(.35,"rgba(255, 224, 130, 0.22)"),h.addColorStop(1,"rgba(255, 224, 130, 0)"),n.fillStyle=h,n.fill(),n.restore()}paintMarkers(e){const{ctx:t}=this;t.textAlign="center",t.textBaseline="middle",t.font="bold 10px sans-serif";for(const i of[...e.markers].sort((s,n)=>Number(s.current)-Number(n.current))){const s=this.toCanvas(e.bounds,i.lat,i.lng);this.targets.push({kind:"milestone",label:i.note?`${i.label} — ${i.note}`:i.label,lat:i.lat,lng:i.lng,t:i.t,x:s.x,y:s.y,radius:tl.MARKER_RADIUS_PX}),t.beginPath(),t.arc(s.x,s.y,tl.MARKER_RADIUS_PX,0,Math.PI*2),t.fillStyle=i.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",t.fill(),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.9)",t.stroke(),t.fillStyle=i.current?"#1d2321":"#fff",t.fillText(i.label,s.x,s.y)}}paintObserver(e,t){const{ctx:i}=this,s=this.toCanvas(e.bounds,t.lat,t.lng);e.observerLabel&&this.targets.push({kind:"observer",label:e.observerLabel,lat:t.lat,lng:t.lng,x:s.x,y:s.y,radius:8});const n=e.markers.some(r=>{if(!r.current)return!1;const a=ot(r.lat,r.lng,t.lat,t.lng);return Math.hypot(a.x,a.z)<=tl.ON_MARKER_M});i.beginPath(),i.arc(s.x,s.y,n?tl.MARKER_RADIUS_PX+2.5:5.5,0,Math.PI*2),n||(i.fillStyle="#ff5a3c",i.fill()),i.lineWidth=4,i.strokeStyle="rgba(0, 0, 0, 0.5)",i.stroke(),i.lineWidth=n?3:2.5,i.strokeStyle=n?"#ff5a3c":"#fff",i.stroke()}paintNorth(){const{ctx:e}=this,t=this.width-14,i=16;e.beginPath(),e.moveTo(t,i-9),e.lineTo(t-4.5,i+5),e.lineTo(t,i+2),e.lineTo(t+4.5,i+5),e.closePath(),e.fillStyle="rgba(255, 255, 255, 0.92)",e.strokeStyle="rgba(0, 0, 0, 0.6)",e.lineWidth=1,e.fill(),e.stroke(),e.font="bold 9px sans-serif",e.textAlign="center",e.textBaseline="top",e.strokeText("N",t,i+6),e.fillText("N",t,i+6)}paintFooter(e,t){const{ctx:i}=this;i.font="9px sans-serif",i.textBaseline="bottom";const s=t?this.wrap(t,this.width-20):[];let n=this.height-4;i.textAlign="right";for(const p of s.slice().reverse())this.paintOutlinedText(p,this.width-6,n),n-=11;const r=(e.south+e.north)/2,o=Math.abs(ot(r,e.east,r,e.west).x)/this.width,c=tl.SCALE_STEPS_M.find(p=>p/o<=this.width/3);if(c===void 0)return;const h=c/o,d=8,u=n-3;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.6)",i.beginPath(),i.moveTo(d,u),i.lineTo(d+h,u),i.stroke(),i.lineWidth=1.5,i.strokeStyle="rgba(255, 255, 255, 0.95)",i.stroke(),i.textAlign="left",this.paintOutlinedText(c>=1e3?`${c/1e3} km`:`${c} m`,d,u-3)}paintOutlinedText(e,t,i){const{ctx:s}=this;s.lineWidth=3,s.strokeStyle="rgba(0, 0, 0, 0.75)",s.strokeText(e,t,i),s.fillStyle="#fff",s.fillText(e,t,i)}wrap(e,t){const i=[];let s="";for(const n of e.split(" ")){const r=s?`${s} ${n}`:n;s&&this.ctx.measureText(r).width>t?(i.push(s),s=n):s=r}return s&&i.push(s),i}}class ti{static MIN_ZOOM=.25;static MAX_ZOOM=64;static MIN_SPAN_M=400;static MARGIN=.6;static IMAGERY_PX=768;static fitted(e,t){return ti.including(e.boundsAround(ti.MIN_SPAN_M,ti.MARGIN),t)}zoom=1;centerX=.5;centerY=.5;get changed(){return this.zoom!==1||this.centerX!==.5||this.centerY!==.5}get zoomFactor(){return this.zoom}reset(){this.zoom=1,this.centerX=.5,this.centerY=.5}zoomAt(e,t,i){const s=Math.min(ti.MAX_ZOOM,Math.max(ti.MIN_ZOOM,this.zoom*i)),n=this.centerX+(e-.5)/this.zoom,r=this.centerY+(t-.5)/this.zoom;this.centerX=n-(e-.5)/s,this.centerY=r-(t-.5)/s,this.zoom=s}panBy(e,t){this.centerX-=e/this.zoom,this.centerY-=t/this.zoom}refit(e,t){if(!this.changed)return;const i=this.boundsWithin(e),s=ti.mercatorY01(t.north),n=ti.mercatorY01(t.south),r=ti.mercatorY01(i.north),a=ti.mercatorY01(i.south);this.zoom=(t.east-t.west)/(i.east-i.west),this.centerX=((i.west+i.east)/2-t.west)/(t.east-t.west),this.centerY=((r+a)/2-s)/(n-s)}keepInView(e,t,i){if(!this.changed)return!1;const s=this.boundsWithin(e),n=ti.mercatorY01(s.north),r=ti.mercatorY01(s.south),a=(t.lng-s.west)/(s.east-s.west),o=(ti.mercatorY01(t.lat)-n)/(r-n);return a>=i&&a<=1-i&&o>=i&&o<=1-i?!1:(this.panBy(.5-a,.5-o),!0)}boundsWithin(e){if(!this.changed)return e;const t=.5/this.zoom,i=ti.mercatorY01(e.north),s=ti.mercatorY01(e.south),n=e.east-e.west;return{west:e.west+(this.centerX-t)*n,east:e.west+(this.centerX+t)*n,north:ti.latitudeAt(i+(this.centerY-t)*(s-i)),south:ti.latitudeAt(i+(this.centerY+t)*(s-i))}}static including(e,t,i=3){const s=(e.north+e.south)/2,n=(e.east+e.west)/2,r=ot(s,e.east,s,n).x;let a=r;for(const o of t){const{x:c,z:h}=ot(o.lat,o.lng,s,n),d=Math.max(Math.abs(c),Math.abs(h));d<=r*i&&(a=Math.max(a,d*1.15))}return a<=r?e:{north:_n(0,-a,s,n).lat,south:_n(0,a,s,n).lat,east:_n(a,0,s,n).lng,west:_n(-a,0,s,n).lng}}static expand(e,t){const i=e.east-e.west,s=e.north-e.south;return{west:e.west-i*t,east:e.east+i*t,south:e.south-s*t,north:e.north+s*t}}static pointAt(e,t,i){const s=ti.mercatorY01(e.north),n=ti.mercatorY01(e.south);return{lat:ti.latitudeAt(s+i*(n-s)),lng:e.west+t*(e.east-e.west)}}static mercatorY01(e){const t=e*Math.PI/180;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}static latitudeAt(e){return Math.atan(Math.sinh(Math.PI*(1-2*e)))*180/Math.PI}}const ar=256,py=3,dI=32768;class O2{fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(e,t){const i=(e.south+e.north)/2,s=(e.west+e.east)/2,n=Math.abs(ot(i,e.east,i,e.west).x),r=Math.abs(ot(e.north,s,e.south,s).z),a=aI(i,Math.max(n,r)),{tiles:o}=L2(s,i,a,py),c=py*ar,h=new Float32Array(c*c),d=o[0];await Promise.all(o.map(p=>this.decodeTileInto(p,d,h,c)));const u=new Float32Array(t.width*t.height);for(let p=0;p<t.height;p++){const f=e.north+(e.south-e.north)*(p/(t.height-1));for(let m=0;m<t.width;m++){const g=e.west+(e.east-e.west)*(m/(t.width-1));u[p*t.width+m]=this.sampleAt(f,g,a,d,h,c)}}return{heights:u,width:t.width,height:t.height,bounds:e}}async decodeTileInto(e,t,i,s){const n=this.tileUrlTemplate.replace("{z}",String(e.z)).replace("{x}",String(e.x)).replace("{y}",String(e.y)),r=await this.fetchImpl(n);if(!r.ok)throw new Error(`Elevation tile fetch failed (${r.status}): ${n}`);const a=await createImageBitmap(await r.blob()),o=document.createElement("canvas");o.width=ar,o.height=ar;const c=o.getContext("2d");if(!c)throw new Error("2D canvas context unavailable");c.drawImage(a,0,0);const{data:h}=c.getImageData(0,0,ar,ar),d=(e.x-t.x)*ar,u=(e.y-t.y)*ar;for(let p=0;p<ar;p++)for(let f=0;f<ar;f++){const m=(p*ar+f)*4,g=h[m]*256+h[m+1]+h[m+2]/256-dI,v=d+f,b=u+p;i[b*s+v]=g}}sampleAt(e,t,i,s,n,r){const{x:a,y:o}=k2(t,e,i),c=(a-s.x)*ar,h=(o-s.y)*ar,d=Math.max(0,Math.min(r-1,Math.floor(c))),u=Math.max(0,Math.min(r-1,Math.floor(h))),p=Math.min(r-1,d+1),f=Math.min(r-1,u+1),m=c-d,g=h-u,v=n[u*r+d],b=n[u*r+p],w=n[f*r+d],y=n[f*r+p],M=v+(b-v)*m,S=w+(y-w)*m;return M+(S-M)*g}}class wm{constructor(e,t,i,s){this.width=e,this.height=t,this.samples=i,this.values=s}at(e,t,i=0){return this.values[(t*this.width+e)*this.samples+i]}static parse(e){const t=new DataView(e);if(e.byteLength<8||t.getUint16(0)!==18761||t.getUint16(2,!0)!==42)throw new Error("Not a little-endian TIFF");const i=t.getUint32(4,!0),s=t.getUint16(i,!0),n=new Map;for(let v=0;v<s;v++){const b=i+2+v*12;n.set(t.getUint16(b,!0),{type:t.getUint16(b+2,!0),count:t.getUint32(b+4,!0),value:t.getUint32(b+8,!0)})}const r=(v,b)=>{const w=n.get(v);if(w===void 0){if(b===void 0)throw new Error(`TIFF without tag ${v}`);return b}return w.type===3?w.value&65535:w.value},a=v=>{const b=n.get(v);if(b===void 0)throw new Error(`TIFF without tag ${v}`);const w=b.type===3?2:4,y=[];if(b.count*w<=4){const M=new DataView(new ArrayBuffer(4));M.setUint32(0,b.value,!0);for(let S=0;S<b.count;S++)y.push(w===2?M.getUint16(S*2,!0):M.getUint32(0,!0))}else for(let M=0;M<b.count;M++)y.push(w===2?t.getUint16(b.value+M*2,!0):t.getUint32(b.value+M*4,!0));return y};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(n.has(322))throw new Error("Tiled TIFF");const o=r(256),c=r(257),h=r(277,1),d=a(258)[0],u=r(339,1)===3;if(!(u&&d===32||!u&&d===8))throw new Error(`Unsupported TIFF samples: ${d} bits`);const p=a(273),f=a(279),m=new Uint8Array(o*c*h*(d/8));let g=0;for(let v=0;v<p.length&&g<m.length;v++){const b=Math.min(f[v],m.length-g);m.set(new Uint8Array(e,p[v],b),g),g+=b}if(g<m.length)throw new Error("Truncated TIFF");return new wm(o,c,h,u?new Float32Array(m.buffer):m)}}class uI{constructor(e,t,i,s,n){this.heights=e,this.plants=t,this.buildings=i,this.size=s,this.metresPerPixel=n}structureAt(e,t){const i=Math.floor(e/this.metresPerPixel+this.size/2),s=Math.floor(this.size/2-t/this.metresPerPixel);if(i<0||s<0||i>=this.size||s>=this.size)return;const n=s*this.size+i;if(!(this.plants[n]||this.buildings[n]))return this.heights[n]}tallestStructureNear(e,t,i){let s;const n=Math.ceil(i/this.metresPerPixel);for(let r=-n;r<=n;r++)for(let a=-n;a<=n;a++){if(Math.hypot(a,r)*this.metresPerPixel>i)continue;const o=this.structureAt(e+a*this.metresPerPixel,t+r*this.metresPerPixel);o!==void 0&&(s===void 0||o>s)&&(s=o)}return s}}class De{static METRES_PER_DEGREE=111320;static MIN_BRIDGE_M=4;static DEFAULT_DECK_M=6;static FOOTBRIDGE_DECK_M=2.5;static DECK_MARGIN_M=2.4;static JOIN_M=1;static JOIN_DEG=25;static RAIL_MATCH_M=6;static ROAD_MATCH_M=12;static DECK_SEEN_M=1.5;static DECK_STEP_M=.5;static DECK_GAP_M=2;static DECK_REACH_M=20;static DECK_MEETS_M=.3;static DECK_BEARING_M=4;static DEFAULT_DECK_HEIGHT_M=4;static MIN_POLE_M=6;static MAX_POLE_M=70;static MAX_SPAN_M=800;static MAX_LINES=16;static BY_VOLTAGE=[{upToKv:25,poleM:11,dropM:1.2,spreadM:.8},{upToKv:70,poleM:20,dropM:3,spreadM:3},{upToKv:100,poleM:22,dropM:3.5,spreadM:3.5},{upToKv:170,poleM:27,dropM:4.5,spreadM:4.5},{upToKv:250,poleM:32,dropM:5.5,spreadM:5.5},{upToKv:1e3,poleM:42,dropM:7,spreadM:7.5}];static toMetres(e,t){const[i,s]=e;return{east:(i-t.lng)*De.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180),north:(s-t.lat)*De.METRES_PER_DEGREE}}static path(e,t){return e.geometry.type!=="LineString"?[]:e.geometry.coordinates.map(i=>De.toMetres(i,t))}static bearing(e,t){return(Math.atan2(t.east-e.east,t.north-e.north)*180/Math.PI+360)%360}static distanceToSegment(e,t,i){const s=i.east-t.east,n=i.north-t.north,r=s*s+n*n,a=r===0?0:Math.max(0,Math.min(1,((e.east-t.east)*s+(e.north-t.north)*n)/r));return Math.hypot(e.east-(t.east+a*s),e.north-(t.north+a*n))}static bridges(e,t,i,s){const n=e.elevatedRoads.map(o=>({path:De.path(o,t),properties:o.properties})),r=(e.elevatedRailways??[]).map(o=>De.path(o,t)),a=[];for(const o of De.joined(e.bridges.map(c=>De.path(c,t)))){const c=o[0],h=o[o.length-1],d=Math.hypot(h.east-c.east,h.north-c.north);if(d<De.MIN_BRIDGE_M)continue;const u={east:(c.east+h.east)/2,north:(c.north+h.north)/2};if(Math.hypot(u.east,u.north)>i+d/2||De.carriesRailway(c,h,r))continue;const[p,f]=De.deckReach(c,h,s);a.push({eastM:De.tenth((p.east+f.east)/2),northM:De.tenth((p.north+f.north)/2),lengthM:De.tenth(Math.hypot(f.east-p.east,f.north-p.north)),widthM:De.roadOf(u,n).width,heightM:De.tenth(De.deckHeight(c,h,s)),headingDeg:De.tenth(De.bearing(c,h)%180),...De.roadOf(u,n).name?{name:De.roadOf(u,n).name}:{}})}return a.sort((o,c)=>Math.hypot(o.eastM,o.northM)-Math.hypot(c.eastM,c.northM)),a}static carriesRailway(e,t,i){const s={east:(e.east+t.east)/2,north:(e.north+t.north)/2},n=De.bearing(e,t)%180;for(const r of i)for(let a=0;a+1<r.length;a++){if(De.distanceToSegment(s,r[a],r[a+1])>De.RAIL_MATCH_M)continue;const o=Math.abs(De.bearing(r[a],r[a+1])%180-n);if(Math.min(o,180-o)<=De.JOIN_DEG)return!0}return!1}static joined(e){const t=e.filter(i=>i.length>=2);for(let i=0;i<t.length;i++)for(let s=i+1;s<t.length;s++){const n=De.join(t[i],t[s]);n!==void 0&&(t[i]=n,t.splice(s,1),s=i)}return t}static join(e,t){for(const i of[e,[...e].reverse()])for(const s of[t,[...t].reverse()]){const n=i[i.length-1],r=s[0];if(Math.hypot(n.east-r.east,n.north-r.north)>De.JOIN_M)continue;const a=Math.abs(De.bearing(i[0],n)-De.bearing(r,s[s.length-1]));if(Math.min(a,360-a)<=De.JOIN_DEG)return[...i,...s.slice(1)]}}static roadOf(e,t){let i;for(const a of t)for(let o=0;o+1<a.path.length;o++){const c=De.distanceToSegment(e,a.path[o],a.path[o+1]);(i===void 0||c<i.distance)&&(i={distance:c,properties:a.properties})}if(i===void 0||i.distance>De.ROAD_MATCH_M)return{width:De.DEFAULT_DECK_M};const s=[i.properties.nom_voie_ban_gauche,i.properties.nom_voie_ban_droite,i.properties.cpx_toponyme_route_nommee].find(a=>typeof a=="string"&&a.length>0),n=Number(i.properties.largeur_de_chaussee),r=Number.isFinite(n)&&n>0?De.tenth(n+De.DECK_MARGIN_M):i.properties.nature==="Sentier"?De.FOOTBRIDGE_DECK_M:De.DEFAULT_DECK_M;return s?{width:r,name:s}:{width:r}}static deckReach(e,t,i){const s=Math.hypot(t.east-e.east,t.north-e.north);if(i===void 0||s===0)return[e,t];const n={east:(e.east+t.east)/2,north:(e.north+t.north)/2},r={east:(t.east-e.east)/s,north:(t.north-e.north)/s},a=u=>(i.structureAt(n.east+r.east*u,n.north+r.north*u)??0)>=De.DECK_SEEN_M,o=u=>i.structureAt(n.east+r.east*u,n.north+r.north*u)??0,c=u=>{let p;for(let m=0;m<=s/2+De.DECK_REACH_M;m+=De.DECK_STEP_M)if(a(u*m))p=m;else if(p!==void 0&&m-p>De.DECK_GAP_M)break;if(p===void 0)return s/2;let f=p;for(;f-p<De.DECK_REACH_M&&o(u*(f+De.DECK_STEP_M))>=De.DECK_MEETS_M;)f+=De.DECK_STEP_M;return Math.max(s/2,f+De.DECK_BEARING_M)},h=c(-1),d=c(1);return[{east:n.east-r.east*h,north:n.north-r.north*h},{east:n.east+r.east*d,north:n.north+r.north*d}]}static deckHeight(e,t,i){if(i===void 0)return De.DEFAULT_DECK_HEIGHT_M;const s=[],n=20;for(let r=4;r<=n-4;r++){const a=i.structureAt(e.east+(t.east-e.east)*r/n,e.north+(t.north-e.north)*r/n);a!==void 0&&a>=1.5&&s.push(a)}return s.length===0?De.DEFAULT_DECK_HEIGHT_M:(s.sort((r,a)=>r-a),s[Math.floor(s.length/2)])}static lines(e,t,i,s){const n=[];for(const r of e.lines){const a=String(r.properties.voltage??""),o=De.kilovolts(a);if(o===void 0)continue;const c=De.BY_VOLTAGE.find(d=>o<=d.upToKv)??De.BY_VOLTAGE[De.BY_VOLTAGE.length-1],h=De.path(r,t);for(let d=0;d+1<h.length;d++){const u=h[d],p=h[d+1],f=Math.hypot(p.east-u.east,p.north-u.north);if(f<5||f>De.MAX_SPAN_M||De.distanceToSegment({east:0,north:0},u,p)>i)continue;const m=De.poleHeight(u,p,s)??c.poleM;n.push({eastM:De.tenth((u.east+p.east)/2),northM:De.tenth((u.north+p.north)/2),lengthM:De.tenth(f),headingDeg:De.tenth(De.bearing(u,p)),heightM:De.tenth(Math.max(4,m-c.dropM)),poleHeightM:De.tenth(m),acrossM:[-c.spreadM,0,c.spreadM],voltage:a})}}return n.sort((r,a)=>Math.hypot(r.eastM,r.northM)-Math.hypot(a.eastM,a.northM)),n.slice(0,De.MAX_LINES)}static kilovolts(e){const t=/([\d.,]+)\s*kV/i.exec(e);if(t===null)return;const i=Number(t[1].replace(",","."));return Number.isFinite(i)&&i>0?i:void 0}static poleHeight(e,t,i){if(i===void 0)return;const s=[e,t].map(n=>i.tallestStructureNear(n.east,n.north,3)).filter(n=>n!==void 0&&n>=De.MIN_POLE_M&&n<=De.MAX_POLE_M);return s.length===0?void 0:s.reduce((n,r)=>n+r,0)/s.length}static tenth(e){return Math.round(e*10)/10}}class Ft{static covers(e,t){return e>=41.2&&e<=51.3&&t>=-5.4&&t<=9.8}static WMS="https://data.geopf.fr/wms-r/wms";static WFS="https://data.geopf.fr/wfs/ows";static HEIGHT_LAYER="IGNF_LIDAR-HD_MNH_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93";static CLASS_LAYER="IGNF_LIDAR-HD_CLASS";static PHOTO_LAYER="ORTHOIMAGERY.ORTHOPHOTOS";static MAX_PHOTO_PIXELS=1e3;static METRES_PER_PIXEL=.5;static MAX_RADIUS_M=3e3;static MAX_LIDAR_RADIUS_M=150;static NO_DATA=-9999;static METRES_PER_DEGREE=111320;fetchImpl;wms;wfs;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.wms=e.wmsEndpoint??Ft.WMS,this.wfs=e.wfsEndpoint??Ft.WFS}static radius(e){return Math.min(e,Ft.MAX_RADIUS_M)}static lidarRadius(e){return Math.min(e,Ft.MAX_LIDAR_RADIUS_M)}async lidar(e,t){const i=Ft.lidarRadius(t),s=Math.ceil(2*i/Ft.METRES_PER_PIXEL),[n,r]=await Promise.all([this.raster(e,i,s,Ft.HEIGHT_LAYER),this.raster(e,i,s,Ft.CLASS_LAYER)]);if(n.samples!==1||r.samples<3)throw new Ir("unreachable","The survey answered in a layout this does not read");const a=n.values;if(a.every(d=>d===Ft.NO_DATA))throw new Ir("no-coverage","No LiDAR HD survey here yet");const o=new Uint8Array(s*s),c=new Uint8Array(s*s);for(let d=0;d<s*s;d++){const u=r.values[d*r.samples],p=r.values[d*r.samples+1],f=r.values[d*r.samples+2];o[d]=p>u&&p>f?1:0,c[d]=u>120&&p<90&&f<90?1:0}const h=2*i/s;return{size:s,metresPerPixel:h,heights:a,vegetation:o,building:c,structures:new uI(a,o,c,s,h)}}async laserDate(e){return Ft.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",e))}async photoDate(e){return Ft.latest(await this.dated("ORTHOIMAGERY.ORTHOPHOTOS.GRAPHE-MOSAIQUAGE:graphe_bdortho","geom","date_vol",e))}static latest(e){return e.map(i=>/^\d{4}-\d{2}-\d{2}/.exec(String(i??""))?.[0]).filter(i=>i!==void 0).sort().at(-1)}async dated(e,t,i,s){const r=[s.lng-1e-4,s.lat-1e-4,s.lng+1e-4,s.lat+1e-4].map(a=>a.toFixed(6)).join(",");try{return(await this.features(e,`BBOX(${t},${r},'EPSG:4326')`,i,20)).map(a=>a.properties[i])}catch{return[]}}async photo(e,t){const i=Ft.radius(t),s=Math.min(Ft.MAX_PHOTO_PIXELS,Math.ceil(2*i/Ft.METRES_PER_PIXEL)),n=await this.raster(e,i,s,Ft.PHOTO_LAYER);if(n.samples<3)throw new Ir("unreachable","The photograph came in a layout this does not read");return{size:s,metresPerPixel:2*i/s,samples:n.samples,values:n.values}}async vectors(e,t,i){const s=Ft.radius(t),n=s/Ft.METRES_PER_DEGREE,r=s/(Ft.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),o=`BBOX(geometrie,${[e.lng-r,e.lat-n,e.lng+r,e.lat+n].map(v=>v.toFixed(6)).join(",")},'EPSG:4326')`,[c,h,d,u,p,f]=await Promise.all([this.features("construction_lineaire",`${o} AND nature='Pont'`,"nature,geometrie"),this.features("troncon_de_route",`${o} AND position_par_rapport_au_sol>'0'`,"nature,largeur_de_chaussee,position_par_rapport_au_sol,nom_voie_ban_gauche,nom_voie_ban_droite,cpx_toponyme_route_nommee,geometrie"),this.features("troncon_de_voie_ferree",`${o} AND position_par_rapport_au_sol>'0'`,"position_par_rapport_au_sol,geometrie").catch(()=>[]),this.features("ligne_electrique",o,"voltage,geometrie"),i?this.features("batiment",o,Ft.BUILDING_PROPERTIES,5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",o,"toponyme,categorie,geometrie",100).catch(()=>[]):Promise.resolve([])]),m=i?await this.wholeWorship(f,p,[e.lng-r,e.lat-n,e.lng+r,e.lat+n]):[],g=[...p,...m];return{bridges:c,elevatedRoads:h,elevatedRailways:d,lines:u,buildings:g,zones:f,mapDate:Ft.latest(g.map(v=>v.properties.date_modification))}}static BUILDING_PROPERTIES="cleabs,nature,usage_1,hauteur,nombre_d_etages,materiaux_des_murs,materiaux_de_la_toiture,date_d_apparition,date_modification,geometrie";static MAX_WHOLE_M=300;async wholeWorship(e,t,i){const[s,n,r,a]=i,o=Ft.MAX_WHOLE_M/Ft.METRES_PER_DEGREE;let c;for(const d of e){if(d.properties.categorie!=="Religieux")continue;const[u,p,f,m]=Ft.extent(d);if(u>=s&&p>=n&&f<=r&&m<=a)continue;const g=[Math.max(u,s-o),Math.max(p,n-o),Math.min(f,r+o),Math.min(m,a+o)];c=c?[Math.min(c[0],g[0]),Math.min(c[1],g[1]),Math.max(c[2],g[2]),Math.max(c[3],g[3])]:g}if(!c)return[];const h=new Set(t.map(d=>d.properties.cleabs));try{return(await this.features("batiment",`BBOX(geometrie,${c.map(u=>u.toFixed(6)).join(",")},'EPSG:4326')`,Ft.BUILDING_PROPERTIES,1e3)).filter(u=>!h.has(u.properties.cleabs))}catch{return[]}}static extent(e){let t=1/0,i=1/0,s=-1/0,n=-1/0;const r=a=>{Array.isArray(a)&&typeof a[0]=="number"?(t=Math.min(t,a[0]),s=Math.max(s,a[0]),i=Math.min(i,a[1]),n=Math.max(n,a[1])):Array.isArray(a)&&a.forEach(r)};return r(e.geometry.coordinates),[t,i,s,n]}async elevatedRoadLines(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(n=>n.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${t} AND position_par_rapport_au_sol>'0'`,"geometrie",300),s=[];for(const n of i){const{type:r,coordinates:a}=n.geometry,o=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const c of o)s.push(c.map(h=>({lat:h[1],lng:h[0]})))}return s}async waterSurfaces(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("surface_hydrographique",`${t} AND position_par_rapport_au_sol='0' AND persistance='Permanent'`,"cleabs,nature,geometrie",500)}async roads(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_route",`${t} AND nature<>'Sentier' AND nature<>'Escalier' AND position_par_rapport_au_sol>='0'`,"cleabs,nature,largeur_de_chaussee,nombre_de_voies,sens_de_circulation,vitesse_moyenne_vl,urbain,nom_voie_ban_gauche,nom_voie_ban_droite,cpx_toponyme_route_nommee,geometrie",3e3)}async railways(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_voie_ferree",`${t} AND etat_de_l_objet='En service'`,"cleabs,nature,electrifie,largeur,nombre_de_voies,position_par_rapport_au_sol,cpx_toponyme,geometrie",3e3)}async raster(e,t,i,s){const n=t/Ft.METRES_PER_DEGREE,r=t/(Ft.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:s,STYLES:"",CRS:"EPSG:4326",BBOX:[e.lat-n,e.lng-r,e.lat+n,e.lng+r].map(c=>c.toFixed(6)).join(","),WIDTH:String(i),HEIGHT:String(i),FORMAT:"image/geotiff"});let o;try{o=await this.fetchImpl(`${this.wms}?${a}`)}catch(c){throw new Ir("unreachable",c instanceof Error?c.message:String(c))}if(!o.ok)throw new Ir("unreachable",`The survey answered ${o.status}`);try{return wm.parse(await o.arrayBuffer())}catch(c){throw new Ir("unreachable",c instanceof Error?c.message:String(c))}}async features(e,t,i,s=200){const n=new URLSearchParams({SERVICE:"WFS",VERSION:"2.0.0",REQUEST:"GetFeature",TYPENAMES:e.includes(":")?e:`BDTOPO_V3:${e}`,SRSNAME:"EPSG:4326",OUTPUTFORMAT:"application/json",COUNT:String(s),CQL_FILTER:t,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${n}`)}catch(o){throw new Ir("unreachable",o instanceof Error?o.message:String(o))}if(!r.ok)throw new Ir("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class po{static NEAR_M=15;static ALIGNED_DEG=30;static LONG_ENOUGH_M=15;static SAMPLE_M=5;static follows(e,t){if(e.length<2||t.length<2)return!1;const i=t[0],s=t.map(a=>ot(a.lat,a.lng,i.lat,i.lng)),n=e.map(a=>ot(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<n.length-1;a++){const o=n[a],c=n[a+1],h=Math.hypot(c.x-o.x,c.z-o.z);if(h<1e-6)continue;const d=Math.max(1,Math.ceil(h/po.SAMPLE_M)),u=Math.atan2(c.x-o.x,-(c.z-o.z));for(let p=0;p<=d;p++){const f=p/d,m=po.nearest(s,o.x+(c.x-o.x)*f,o.z+(c.z-o.z)*f);m.distanceM>po.NEAR_M||po.angleBetween(u,m.heading)<=po.ALIGNED_DEG&&(r+=h/d)}}return r>=po.LONG_ENOUGH_M}static nearest(e,t,i){let s={distanceM:1/0,heading:0};for(let n=0;n<e.length-1;n++){const r=e[n],a=e[n+1],o=a.x-r.x,c=a.z-r.z,h=o*o+c*c,d=h<1e-9?0:Math.max(0,Math.min(1,((t-r.x)*o+(i-r.z)*c)/h)),u=Math.hypot(t-(r.x+o*d),i-(r.z+c*d));u<s.distanceM&&(s={distanceM:u,heading:Math.atan2(o,-c)})}return s}static angleBetween(e,t){const i=Math.abs((e-t)*180/Math.PI%180);return Math.min(i,180-i)}}class Ot{static WMS="https://data.geopf.fr/wms-r/wms";static LAYERS=["IGNF_LIDAR-HD_MNT_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93","ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES"];static METRES_PER_PIXEL=4;static METRES_PER_DEGREE=111320;static CLASS_LAYER="IGNF_LIDAR-HD_CLASS";static SURFACE_LAYER="IGNF_LIDAR-HD_MNS_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93";static DECK=[240,240,0];static NO_CLASS=[0,0,0];static DECK_END_PIXELS=3;static DECK_HALF_WIDTH_M=8;static DECK_APPROACH_M=10;static DECK_STRAIGHT_MAX_M=200;static MIN_PIXELS=8;static MAX_PIXELS=700;static NO_DATA_BELOW=-100;static COARSE_METRES_PER_PIXEL=20;static MESH_FROM_VERTICES=33;static FINE_SPACING_M=7;static MAX_SEGMENTS=256;static MAX_HOLE_SHARE=.05;static DEFAULT_TIMEOUT_MS=12e3;static MAX_WINDOW_M=50;fetchImpl;wms;timeoutMs;maxWindowM;geoplatform;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.wms=e.wmsEndpoint??Ot.WMS,this.timeoutMs=e.timeoutMs??Ot.DEFAULT_TIMEOUT_MS,this.maxWindowM=e.maxWindowM??Ot.MAX_WINDOW_M,this.geoplatform=new Ft({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:e.wfsEndpoint})}async getElevationGrid(e,t,i){const s={lat:(e.south+e.north)/2,lng:(e.west+e.east)/2};if(!Ft.covers(s.lat,s.lng))throw new Error("The IGN's relief covers France only");const n=Math.abs(ot(s.lat,e.east,s.lat,e.west).x),r=Math.abs(ot(e.north,s.lng,e.south,s.lng).z);t=this.finer(t,n,r);const a={x:n/Math.max(1,t.width-1),y:r/Math.max(1,t.height-1)},o={x:Math.min(a.x,this.maxWindowM),y:Math.min(a.y,this.maxWindowM)},c={south:e.south-o.y/Ot.METRES_PER_DEGREE,north:e.north+o.y/Ot.METRES_PER_DEGREE,west:e.west-o.x/(Ot.METRES_PER_DEGREE*Math.cos(s.lat*Math.PI/180)),east:e.east+o.x/(Ot.METRES_PER_DEGREE*Math.cos(s.lat*Math.PI/180))},h=m=>Math.min(Ot.MAX_PIXELS,Math.max(Ot.MIN_PIXELS,Math.ceil(m/Ot.METRES_PER_PIXEL))),d={width:h(n+2*o.x),height:h(r+2*o.y)},u={x:(n+2*o.x)/d.width,y:(r+2*o.y)/d.height};let p=new Error("No layer of the IGN's relief answered");const f=Math.max(u.x,u.y)>Ot.COARSE_METRES_PER_PIXEL;for(const m of f?[...Ot.LAYERS].reverse():Ot.LAYERS)try{const g=await this.heights(c,d,m);m===Ot.LAYERS[0]&&await this.layBridgeDecks(g,c,d,i?.route);const v=this.sample(g,t,e,c,u,a);if(v)return{heights:v,width:t.width,height:t.height,bounds:e};p=new Error(`${m} does not cover this place`)}catch(g){p=g}throw p}finer(e,t,i){if(e.width<Ot.MESH_FROM_VERTICES||e.height<Ot.MESH_FROM_VERTICES)return e;const s=(n,r)=>{const a=Math.ceil(n/Ot.FINE_SPACING_M),o=Math.max(r-1,Math.min(Ot.MAX_SEGMENTS,a));return o%2===0?o:o+1};return{width:s(t,e.width)+1,height:s(i,e.height)+1}}async raster(e,t,i){const s=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:i,STYLES:"",CRS:"EPSG:4326",BBOX:[e.south,e.west,e.north,e.east].map(r=>r.toFixed(6)).join(","),WIDTH:String(t.width),HEIGHT:String(t.height),FORMAT:"image/geotiff"}),n=await this.fetchImpl(`${this.wms}?${s}`,{signal:AbortSignal.timeout(this.timeoutMs)});if(!n.ok)throw new Error(`The IGN's relief answered ${n.status}`);return wm.parse(await n.arrayBuffer())}async heights(e,t,i){const s=await this.raster(e,t,i);if(s.samples!==1||!(s.values instanceof Float32Array))throw new Error("The IGN's relief came in a layout this does not read");return s}async layBridgeDecks(e,t,i,s){if(!(!s||s.length<2)&&!(!(e.values instanceof Float32Array)||!e.values.some(n=>n>Ot.NO_DATA_BELOW)))try{const n=(await this.geoplatform.elevatedRoadLines({west:t.west,south:t.south,east:t.east,north:t.north})).filter(a=>po.follows(s,a));if(n.length===0)return;const r=Float32Array.from(e.values);await this.layClassifiedDecks(e,t,i,n),this.layRouteDecks(e,r,t,n)}catch{}}async layClassifiedDecks(e,t,i,s){try{const n=await this.raster(t,i,Ot.CLASS_LAYER);if(n.samples<3||n.width!==e.width||n.height!==e.height)return;const r=(g,[v,b,w])=>n.values[g*n.samples]===v&&n.values[g*n.samples+1]===b&&n.values[g*n.samples+2]===w,a=e.width,o=e.height,c=new Uint8Array(a*o);let h=!1;for(let g=0;g<c.length;g++)r(g,Ot.DECK)&&(c[g]=1,h=!0);if(!h)return;const d=Ot.DECK_END_PIXELS,u=[];for(let g=0;g<c.length;g++){if(c[g]!==1)continue;const v=g%a,b=(g-v)/a;for(let w=-d;w<=d;w++)for(let y=-d;y<=d;y++){const M=v+y,S=b+w;if(M<0||S<0||M>=a||S>=o)continue;const E=S*a+M;c[E]===0&&r(E,Ot.NO_CLASS)&&u.push(E)}}for(const g of u)c[g]=1;const p=this.paint(s,t,a,o),f=this.touching(c,p,a,o);if(f.every(g=>g===0))return;const m=await this.heights(t,i,Ot.SURFACE_LAYER);if(m.width!==a||m.height!==o)return;for(let g=0;g<f.length;g++){if(f[g]===0)continue;const v=m.values[g];Number.isFinite(v)&&v>Ot.NO_DATA_BELOW&&v>e.values[g]&&(e.values[g]=v)}}catch{}}layRouteDecks(e,t,i,s){const{width:n,height:r}=e,a=(i.north+i.south)/2,o=(i.east-i.west)*Ot.METRES_PER_DEGREE*Math.cos(a*Math.PI/180),c=(i.north-i.south)*Ot.METRES_PER_DEGREE,h=o/n,d=c/r,u=v=>({x:(v.lng-i.west)/(i.east-i.west)*o,y:(i.north-v.lat)/(i.north-i.south)*c}),p=(v,b)=>{const w=Math.floor(v/h),y=Math.floor(b/d);if(w<0||y<0||w>=n||y>=r)return;const M=t[y*n+w];return Number.isFinite(M)&&M>Ot.NO_DATA_BELOW?M:void 0},f=Ot.DECK_HALF_WIDTH_M,m=Ot.DECK_APPROACH_M,g=(v,b)=>{const w=Math.hypot(v.x-b.x,v.y-b.y)||1,y={x:(v.x-b.x)/w,y:(v.y-b.y)/w},M=[0,m/2,m].map(S=>p(v.x+y.x*S,v.y+y.y*S)).filter(S=>S!==void 0);return M.length>0?Math.max(...M):void 0};for(const v of Ot.chains(s.map(b=>b.map(u)))){const b=[0];for(let D=1;D<v.length;D++)b.push(b[D-1]+Math.hypot(v[D].x-v[D-1].x,v[D].y-v[D-1].y));const w=b[b.length-1];if(w<1||w>Ot.DECK_STRAIGHT_MAX_M)continue;const y=g(v[0],v[1]),M=g(v[v.length-1],v[v.length-2]);if(y===void 0||M===void 0)continue;const S=f+m,E=Math.max(0,Math.floor((Math.min(...v.map(D=>D.x))-S)/h)),x=Math.min(n-1,Math.ceil((Math.max(...v.map(D=>D.x))+S)/h)),A=Math.max(0,Math.floor((Math.min(...v.map(D=>D.y))-S)/d)),R=Math.min(r-1,Math.ceil((Math.max(...v.map(D=>D.y))+S)/d));for(let D=A;D<=R;D++)for(let L=E;L<=x;L++){const N=Ot.nearestAlong(v,b,{x:(L+.5)*h,y:(D+.5)*d});if(N.distance>f||N.s<-m||N.s>w+m)continue;const k=y+(M-y)*Math.min(1,Math.max(0,N.s/w)),C=D*n+L;t[C]>=k||(e.values[C]=k)}}}static chains(e){const t=e.filter(n=>n.length>=2).map(n=>[...n]),i=[],s=(n,r)=>Math.hypot(n.x-r.x,n.y-r.y)<=1;for(;t.length>0;){let n=t.shift(),r=!0;for(;r;){r=!1;for(let a=0;a<t.length;a++){const o=t[a],c=n[0],h=n[n.length-1];if(s(h,o[0]))n=[...n,...o.slice(1)];else if(s(h,o[o.length-1]))n=[...n,...[...o].reverse().slice(1)];else if(s(c,o[o.length-1]))n=[...o.slice(0,-1),...n];else if(s(c,o[0]))n=[...[...o].reverse().slice(0,-1),...n];else continue;t.splice(a,1),r=!0;break}}i.push(n)}return i}static nearestAlong(e,t,i){let s={s:0,distance:1/0};for(let n=0;n<e.length-1;n++){const r=e[n],a=e[n+1],o=a.x-r.x,c=a.y-r.y,h=o*o+c*c;if(h<1e-9)continue;let d=((i.x-r.x)*o+(i.y-r.y)*c)/h;n>0&&(d=Math.max(0,d)),n<e.length-2&&(d=Math.min(1,d));const u=Math.hypot(i.x-(r.x+o*d),i.y-(r.y+c*d));u<s.distance&&(s={s:t[n]+d*Math.sqrt(h),distance:u})}return s}paint(e,t,i,s){const n=new Uint8Array(i*s),r=o=>(o-t.west)/(t.east-t.west)*i,a=o=>(t.north-o)/(t.north-t.south)*s;for(const o of e)for(let c=0;c<o.length-1;c++){const h=r(o[c].lng),d=a(o[c].lat),u=r(o[c+1].lng),p=a(o[c+1].lat),f=Math.max(1,Math.ceil(Math.hypot(u-h,p-d)*2));for(let m=0;m<=f;m++){const g=Math.floor(h+(u-h)*m/f),v=Math.floor(d+(p-d)*m/f);for(let b=-1;b<=1;b++)for(let w=-1;w<=1;w++){const y=g+w,M=v+b;y>=0&&M>=0&&y<i&&M<s&&(n[M*i+y]=1)}}}return n}touching(e,t,i,s){const n=new Uint8Array(e.length),r=new Uint8Array(e.length);for(let a=0;a<e.length;a++){if(e[a]===0||r[a]===1)continue;const o=[],c=[a];r[a]=1;let h=!1;for(;c.length>0;){const d=c.pop();o.push(d),t[d]===1&&(h=!0);const u=d%i,p=(d-u)/i;for(let f=-1;f<=1;f++)for(let m=-1;m<=1;m++){const g=u+m,v=p+f;if(g<0||v<0||g>=i||v>=s)continue;const b=v*i+g;e[b]===1&&r[b]===0&&(r[b]=1,c.push(b))}}if(h)for(const d of o)n[d]=1}return n}sample(e,t,i,s,n,r){const{width:a,height:o}=t,c=new Float32Array(a*o),h=new Uint8Array(a*o),d=Math.min(r.x,this.maxWindowM)/n.x,u=Math.min(r.y,this.maxWindowM)/n.y;let p=0;for(let f=0;f<o;f++){const m=i.north+(i.south-i.north)*(o===1?.5:f/(o-1)),g=(s.north-m)/(s.north-s.south)*e.height-.5;for(let v=0;v<a;v++){const w=(i.west+(i.east-i.west)*(a===1?.5:v/(a-1))-s.west)/(s.east-s.west)*e.width-.5,y=d>1||u>1?this.tent(e,w,g,Math.max(1,d),Math.max(1,u)):this.bilinear(e,w,g),M=f*a+v;y===void 0?p++:(c[M]=y,h[M]=1)}}if(!(p===a*o||p/(a*o)>Ot.MAX_HOLE_SHARE))return this.fill(c,h,a,o),c}tent(e,t,i,s,n){let r=0,a=0,o=0;const c=Math.max(0,Math.ceil(i-n)),h=Math.min(e.height-1,Math.floor(i+n)),d=Math.max(0,Math.ceil(t-s)),u=Math.min(e.width-1,Math.floor(t+s));for(let p=c;p<=h;p++){const f=1-Math.abs(p-i)/n;if(!(f<=0))for(let m=d;m<=u;m++){const g=f*(1-Math.abs(m-t)/s);if(g<=0)continue;o+=g;const v=e.at(m,p);!Number.isFinite(v)||v<Ot.NO_DATA_BELOW||(r+=g*v,a+=g)}}return o>0&&a>=o*.5?r/a:void 0}bilinear(e,t,i){const s=Math.max(0,Math.min(e.width-1,Math.floor(t))),n=Math.max(0,Math.min(e.height-1,Math.floor(i))),r=Math.min(e.width-1,s+1),a=Math.min(e.height-1,n+1),o=Math.max(0,Math.min(1,t-s)),c=Math.max(0,Math.min(1,i-n)),h=e.at(s,n),d=e.at(r,n),u=e.at(s,a),p=e.at(r,a);for(const g of[h,d,u,p])if(!Number.isFinite(g)||g<Ot.NO_DATA_BELOW)return;const f=h+(d-h)*o,m=u+(p-u)*o;return f+(m-f)*c}fill(e,t,i,s){let n=t.reduce((r,a)=>r+(a?0:1),0);for(;n>0;){const r=[];for(let a=0;a<s;a++)for(let o=0;o<i;o++){const c=a*i+o;if(t[c])continue;let h=0,d=0;for(let u=-1;u<=1;u++)for(let p=-1;p<=1;p++){const f=a+u,m=o+p;f<0||m<0||f>=s||m>=i||!t[f*i+m]||(h+=e[f*i+m],d++)}d>0&&r.push([c,h/d])}if(r.length===0)return;for(const[a,o]of r)e[a]=o,t[a]=1;n-=r.length}}}class pI{providers;constructor(...e){this.providers=e}async getElevationGrid(e,t,i){let s=new Error("No source of relief to ask");for(const n of this.providers)try{return await n.getElevationGrid(e,t,i)}catch(r){s=r}throw s}}const _p=256,fI=5;async function P2(l,e,t,i){const s=(l.south+l.north)/2,n=(l.west+l.east)/2,r=Math.abs(ot(s,l.east,s,l.west).x),a=Math.abs(ot(l.north,n,l.south,n).z),o=Math.max(r,a),{zoom:c,gridSize:h}=mI(s,o,Math.max(e.width,e.height)),{tiles:d,bounds:u}=L2(n,s,c,h),p=h*_p,f=document.createElement("canvas");f.width=p,f.height=p;const m=f.getContext("2d");if(!m)throw new Error("2D canvas context unavailable");const g=d[0];await Promise.all(d.map(async y=>{const M=t(y),S=await i(M);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${M}`);const E=await createImageBitmap(await S.blob());m.drawImage(E,(y.x-g.x)*_p,(y.y-g.y)*_p)}));const v=Math.min(Math.max(e.width,e.height),p);if(v===p)return{source:f,width:p,height:p,bounds:u};const b=document.createElement("canvas");b.width=v,b.height=v;const w=b.getContext("2d");if(!w)throw new Error("2D canvas context unavailable");return w.drawImage(f,0,0,p,p,0,0,v,v),{source:b,width:v,height:v,bounds:u}}function mI(l,e,t){let i=oI(l,e/Math.max(1,t)),s=fy(l,i,e);for(;s>fI&&i>0;)i--,s=fy(l,i,e);return{zoom:i,gridSize:s,mPerPixel:D2(l,i)/_p}}function fy(l,e,t){const i=Math.ceil(t/2/D2(l,e));return Math.max(3,2*i+1)}class N2{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(e,t){return P2(e,t,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class Fn{static ENDPOINTS=["https://overpass-api.de/api/interpreter","https://overpass.kumi.systems/api/interpreter","https://overpass.private.coffee/api/interpreter"];static FRANCE_ENDPOINT="https://overpass.openstreetmap.fr/api/interpreter";static FRANCE={south:41.3,west:-5.2,north:51.1,east:9.6};static endpointsFor(e,t=Fn.ENDPOINTS){const i=/\((-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\)/.exec(e);if(!i)return[...t];const[s,n,r,a]=i.slice(1).map(Number),o=(s+r)/2,c=(n+a)/2,h=Fn.FRANCE;return o>=h.south&&o<=h.north&&c>=h.west&&c<=h.east?[Fn.FRANCE_ENDPOINT,...t.filter(u=>u!==Fn.FRANCE_ENDPOINT)]:[...t]}fetchImpl;endpoints;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.endpoints=e.endpoints}static queue=Promise.resolve();static HANG_MS=4e4;static RETRY_MS=4e3;query(e){return this.queued(()=>this.ask(e))}queued(e){const t=Fn.queue.then(e,e);return Fn.queue=t.catch(()=>{}),t}async ask(e){let t;for(const i of this.endpoints??Fn.endpointsFor(e))for(let s=0;s<2;s++){try{const n=await this.fetchImpl(`${i}?data=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(Fn.HANG_MS)});if(n.ok)return await n.json();if(t=new Error(`${new URL(i).host} refused (${n.status})`),n.status!==429&&n.status!==504)break}catch(n){t=new Error(`${new URL(i).host} unreachable (${String(n)})`);break}await new Promise(n=>setTimeout(n,Fn.RETRY_MS))}throw t??new Error("No Overpass instance answered")}}class fo{attribution="Roads © OpenStreetMap contributors, as surveyed today";contemporary=!0;static DRIVABLE=["motorway","trunk","primary","secondary","tertiary","unclassified","residential","service","track","motorway_link","trunk_link","primary_link","secondary_link","tertiary_link"];static WIDTH_M={motorway:11,trunk:9,primary:8,secondary:7,tertiary:6.5,unclassified:5.5,residential:5.5,service:4,track:3.5};static DEFAULT_WIDTH_M=5;client;constructor(e={}){this.client=new Fn(e)}async getRoads(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:30];way["highway"~"^(${fo.DRIVABLE.join("|")})$"](${t});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(e){const t=[];for(const i of e.elements??[]){const s=i.geometry,n=i.tags;!n||!s||s.length<2||t.push({id:`osm-${i.id??t.length}`,name:n.name,surface:fo.surfaceOf(n),widthM:fo.widthOf(n),...fo.paintOf(n),points:s.map(r=>({lat:r.lat,lng:r.lon}))})}return t}static paintOf(e){const t=e.highway??"",i=e.junction==="roundabout"||e.junction==="circular",s=e.oneway,n=s==="yes"||s==="1"||s==="true"||s===void 0&&(t==="motorway"||i),r=s==="-1"||s==="reverse",a=Number.parseInt(e.lanes??"",10),o=Number.parseInt(e.maxspeed??"",10),c=i?"roundabout":t==="motorway"?"motorway":t.endsWith("_link")?"slip":(t==="trunk"||t==="primary")&&(n||r)?"dual":t?"road":void 0;return{...c?{kind:c}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...s!==void 0||t==="motorway"||i?{direction:r?"backward":n?"forward":"both"}:{},...Number.isFinite(o)&&o>0?{speedKmh:o}:{}}}static widthOf(e){const t=Number.parseFloat(e.width??e.est_width??"");if(Number.isFinite(t)&&t>0)return t;const i=Number.parseInt(e.lanes??"",10);return Number.isFinite(i)&&i>0?i*3.5:fo.WIDTH_M[e.highway]??fo.DEFAULT_WIDTH_M}static surfaceOf(e){const t=e.surface;return t==="dirt"||t==="earth"||t==="mud"?"dirt":t==="gravel"||t==="fine_gravel"||t==="compacted"||t==="ground"||t==="sand"||t==="unpaved"?"gravel":t?"paved":e.highway==="track"?"gravel":"paved"}}const Um="https://ufoathome.org/roads/index.json";class Fc{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Fc.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Roads © OpenStreetMap contributors"}get contemporary(){return this.contemporaryRead??this.fallback?.contemporary??!0}async getRoads(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getRoads(e);return this.attributionRead=this.fallback.attribution,this.contemporaryRead=this.fallback.contemporary,i}async held(e){let t;try{t=await this.load()}catch{return}const i=t.find(({entry:s})=>s.north>=e.north&&s.south<=e.south&&s.east>=e.east&&s.west<=e.west);if(i)try{const s=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!s.ok)return;const n=await s.json();return Array.isArray(n?.ways)?(this.attributionRead=n.attribution,this.contemporaryRead=n.contemporary,n.ways):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const e=this.indexUrls.join(`
4251
- `);let t=Fc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Fc.shared.set(e,t),t.then(i=>{i.length===0&&Fc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.0")}`,t=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(t&&t!==Um?[t,Um]:[Um]).map(i=>i+e)}}class bo{attribution="Roads © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Type autoroutier":{surface:"paved",widthM:11},"Route à 2 chaussées":{surface:"paved",widthM:7},"Route à 1 chaussée":{surface:"paved",widthM:5.5},"Rond-point":{surface:"paved",widthM:6},Bretelle:{surface:"paved",widthM:5},"Route empierrée":{surface:"gravel",widthM:3.5},Chemin:{surface:"dirt",widthM:3},"Piste cyclable":{surface:"paved",widthM:2.5}};static DEFAULT={surface:"paved",widthM:5};static KINDS={"Type autoroutier":"motorway","Route à 2 chaussées":"dual","Route à 1 chaussée":"road","Rond-point":"roundabout",Bretelle:"slip"};static DIRECTIONS={"Double sens":"both","Sens direct":"forward","Sens inverse":"backward"};platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRoads(e){return(await this.platform.roads(e)).flatMap((i,s)=>bo.wayOf(i,s))}static wayOf(e,t){if(e.geometry.type!=="LineString")return[];const i=e.geometry.coordinates.map(([u,p])=>({lat:p,lng:u}));if(i.length<2)return[];const s=String(e.properties.nature??""),n=bo.BY_NATURE[s]??bo.DEFAULT,r=Number(e.properties.largeur_de_chaussee),a=Number(e.properties.nombre_de_voies),o=Number(e.properties.vitesse_moyenne_vl),c=bo.DIRECTIONS[String(e.properties.sens_de_circulation??"")],h=bo.KINDS[s],d=[e.properties.cpx_toponyme_route_nommee,e.properties.nom_voie_ban_gauche,e.properties.nom_voie_ban_droite].find(u=>typeof u=="string"&&u.length>0);return[{id:String(e.properties.cleabs??`ign-${t}`),...d?{name:d}:{},surface:n.surface,widthM:Number.isFinite(r)&&r>0?r:n.widthM,...e.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...c?{direction:c}:{},...Number.isFinite(o)&&o>0?{speedKmh:o}:{},points:i}]}}class gI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(e){if(bo.covers(e))try{const t=await this.regional.getRoads(e);if(t.length>0)return t}catch{}return this.worldwide.getRoads(e)}}class Vd{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getWater(e){return(await this.platform.waterSurfaces(e)).flatMap((i,s)=>Vd.surfacesOf(i,s))}static surfacesOf(e,t){const{type:i,coordinates:s}=e.geometry,n=i==="Polygon"?[s]:i==="MultiPolygon"?s:[],r=String(e.properties.cleabs??`ign-water-${t}`);return n.flatMap((a,o)=>{const c=a.map(h=>Vd.open(h.map(d=>({lat:d[1],lng:d[0]})))).filter(h=>h.length>=3);return c.length>0?[{id:n.length>1?`${r}-${o}`:r,rings:c}]:[]})}static open(e){const t=e[0],i=e[e.length-1];return e.length>1&&t.lat===i.lat&&t.lng===i.lng?e.slice(0,-1):e}}class il{attribution="Water © OpenStreetMap contributors";client;constructor(e={}){this.client=new Fn(e)}async getWater(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:30];(way["natural"="water"](${t});way["waterway"="riverbank"](${t});)->.w;(relation["natural"="water"](${t});relation["waterway"="riverbank"](${t});)->.r;.w out geom;.r out body;way(r.r)(${t});out geom;`;return il.surfacesFrom(await this.client.query(i))}static surfacesFrom(e){const t=e.elements??[],i=new Map;for(const r of t)r.type==="way"&&r.id!==void 0&&r.geometry&&i.set(r.id,r.geometry.map(a=>({lat:a.lat,lng:a.lon})));const s=[],n=new Set;for(const r of t){if(r.type!=="relation")continue;const a=c=>(r.members??[]).filter(h=>h.type==="way"&&h.role===c&&h.ref!==void 0&&i.has(h.ref)).map(h=>(n.add(h.ref),i.get(h.ref))),o=il.rings(a("inner"));for(const[c,h]of il.rings(a("outer")).entries()){const d=o.filter(u=>il.contains(h,u[0]));s.push({id:`osm-r${r.id}-${c}`,rings:[h,...d]})}}for(const r of t)if(!(r.type!=="way"||!r.tags||r.id===void 0||n.has(r.id))&&!(r.tags.natural!=="water"&&r.tags.waterway!=="riverbank"))for(const a of il.rings([i.get(r.id)??[]]))s.push({id:`osm-w${r.id}`,rings:[a]});return s}static rings(e){const t=(n,r)=>n.lat===r.lat&&n.lng===r.lng,i=e.filter(n=>n.length>=2).map(n=>[...n]),s=[];for(;i.length>0;){let n=i.pop(),r=!0;for(;!t(n[0],n[n.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const o=i[a],c=n[n.length-1];if(t(c,o[0]))n=[...n,...o.slice(1)];else if(t(c,o[o.length-1]))n=[...n,...[...o].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}n.length>=4&&t(n[0],n[n.length-1])&&s.push(n.slice(0,-1))}return s}static contains(e,t){let i=!1;for(let s=0,n=e.length-1;s<e.length;n=s++){const r=e[s],a=e[n];r.lat>t.lat!=a.lat>t.lat&&t.lng<(a.lng-r.lng)*(t.lat-r.lat)/(a.lat-r.lat)+r.lng&&(i=!i)}return i}}class vI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(e){if(Vd.covers(e))try{const t=await this.regional.getWater(e);if(t.length>0)return t}catch{}return this.worldwide.getWater(e)}}const zm="https://ufoathome.org/water/index.json";class Uc{attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Uc.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Water © OpenStreetMap contributors"}async getWater(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getWater(e);return this.attributionRead=this.fallback.attribution,i}async held(e){const i=(await this.load().catch(()=>[])).find(({entry:s})=>s.north>=e.north&&s.south<=e.south&&s.east>=e.east&&s.west<=e.west);if(i)try{const s=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!s.ok)return;const n=await s.json();return Array.isArray(n?.surfaces)?(this.attributionRead=n.attribution,n.surfaces):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const e=this.indexUrls.join(`
4252
- `);let t=Uc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Uc.shared.set(e,t),t.then(i=>{i.length===0&&Uc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.0")}`,t=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(t&&t!==zm?[t,zm]:[zm]).map(i=>i+e)}}class Ln{constructor(e){this.water=e}static CACHE_NAME="rr0-water";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static asked=new Map;get attribution(){return this.water.attribution}async getWater(e){const t=Ln.key(e);let i=Ln.asked.get(t);return i===void 0&&(i=this.recalled(t,e),Ln.asked.set(t,i),i.catch(()=>Ln.asked.delete(t))),structuredClone(await i)}static forget(){Ln.asked.clear()}static key(e){return`v${Ln.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}async recalled(e,t){const i=await Ln.openCache(),s=Ln.request(e);if(i)try{const r=await i.match(s);if(r){const{savedAt:a,surfaces:o}=await r.json();if(Date.now()-a<Ln.MAX_AGE_MS&&Array.isArray(o))return o;await i.delete(s)}}catch{}const n=await this.water.getWater(t);return i&&Ln.store(i,s,n),n}static async store(e,t,i){try{const s={savedAt:Date.now(),surfaces:i};await e.put(t,new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}}));const n=await e.keys();for(const r of n.slice(0,Math.max(0,n.length-Ln.MAX_STORED)))await e.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Ln.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__water__/${encodeURIComponent(e)}`)}}class yo{attribution="Railways © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Voie ferrée principale":{kind:"rail"},LGV:{kind:"rail",highSpeed:!0},"Voie de service":{kind:"rail",service:!0},Métro:{kind:"subway"},Tramway:{kind:"tram"},"Transport urbain":{kind:"light_rail"},"Funiculaire ou crémaillère":{kind:"funicular"}};static GAUGE_MM={Normale:1435,Etroite:1e3,Étroite:1e3,Large:1668};static NO_ALTITUDE=-1e3;platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRailways(e){return(await this.platform.railways(e)).flatMap((i,s)=>yo.linesOf(i,s))}static linesOf(e,t){const{type:i,coordinates:s}=e.geometry,n=i==="LineString"?[s]:i==="MultiLineString"?s:[],r=yo.BY_NATURE[String(e.properties.nature??"")];if(!r)return[];const a=String(e.properties.cleabs??`ign-rail-${t}`),o=Number(e.properties.nombre_de_voies),c=Number(e.properties.position_par_rapport_au_sol),h=e.properties.cpx_toponyme,d=yo.GAUGE_MM[String(e.properties.largeur??"")]??1435,u=yo.electrificationOf(r.kind,d,e.properties.electrifie);return n.flatMap((p,f)=>{const m=p.map(g=>({lat:g[1],lng:g[0],...g.length>2&&Number.isFinite(g[2])&&g[2]>yo.NO_ALTITUDE?{altitudeM:g[2]}:{}}));return m.length<2?[]:[{id:n.length>1?`${a}-${f}`:a,...typeof h=="string"&&h.length>0?{name:h}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:d,tracks:Number.isInteger(o)&&o>0?o:1,...u?{electrification:u}:{},level:Number.isFinite(c)?c:0,points:m}]})}static electrificationOf(e,t,i){if(i===!1)return"none";if(i===!0){if(e==="subway")return"third_rail";if(!(e==="funicular"||t<1435))return"overhead"}}}class zs{static NEAR_M=15;static ALIGNED_DEG=30;static SAMPLE_M=10;static ROUTES="train|subway|light_rail|tram|monorail";static KINDS="rail|light_rail|subway|tram|narrow_gauge|funicular|preserved";client;constructor(e={}){this.client=new Fn(e)}async named(e,t){if(e.length===0)return[...e];const i=`${t.south},${t.west},${t.north},${t.east}`,s=`[out:json][timeout:120];way["railway"~"^(${zs.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${zs.ROUTES})$"];out body;`;return zs.apply(e,await this.client.query(s),t)}static apply(e,t,i){const s={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},n=zs.ways(t,s);return n.length===0?[...e]:e.map(r=>{const a=r.points.map(v=>ot(v.lat,v.lng,s.lat,s.lng)),o=new Map,c=new Map,h=new Map;let d=0;const u=n.filter(v=>v.service===!!r.service);for(const v of zs.samples(a)){d++;const b=zs.waysAt(u,v);if(b.length===0)continue;const[w]=b;w.name&&o.set(w.name,(o.get(w.name)??0)+1),w.voltageV&&c.set(w.voltageV,(c.get(w.voltageV)??0)+1);for(const y of new Set(b.flatMap(M=>M.services)))h.set(y,(h.get(y)??0)+1)}const p=v=>[...v.entries()].sort((b,w)=>w[1]-b[1])[0]?.[0],f=r.name??p(o),m=r.voltageV??(r.electrification==="none"?void 0:p(c)),g=[...h.entries()].filter(([,v])=>v*4>=d).sort((v,b)=>b[1]-v[1]||v[0].localeCompare(b[0])).map(([v])=>v);return{...r,...f?{name:f}:{},...m?{voltageV:m}:{},...g.length>0?{services:g}:{}}})}static serviceOf(e){const t=e.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return t||[e.network,e.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(e){const t=new Map;for(const i of e.elements??[]){if(i.type!=="relation"||!i.tags)continue;const s=zs.serviceOf(i.tags);if(s)for(const n of i.members??[]){if(n.type!=="way"||n.ref===void 0)continue;const r=t.get(n.ref)??new Set;r.add(s),t.set(n.ref,r)}}return t}static voltageOf(e){const t=Number.parseInt((e.voltage??"").split(";")[0],10);return Number.isFinite(t)&&t>0?t:void 0}static ways(e,t){const i=zs.servicesByWay(e),s=[];for(const n of e.elements??[]){if(n.type!=="way"||!n.geometry||n.geometry.length<2)continue;const r=n.tags??{},a=zs.voltageOf(r);s.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(n.id??-1)??[]],path:n.geometry.map(o=>ot(o.lat,o.lon,t.lat,t.lng))})}return s}static samples(e){const t=[];for(let i=0;i<e.length-1;i++){const s=Math.hypot(e[i+1].x-e[i].x,e[i+1].z-e[i].z);if(s<1e-6)continue;const n=(e[i+1].x-e[i].x)/s,r=(e[i+1].z-e[i].z)/s;for(let a=zs.SAMPLE_M/2;a<s;a+=zs.SAMPLE_M)t.push({x:e[i].x+n*a,z:e[i].z+r*a,dx:n,dz:r})}return t}static waysAt(e,t){const i=Math.cos(zs.ALIGNED_DEG*Math.PI/180),s=[];for(const n of e){let r;for(let a=0;a<n.path.length-1;a++){const o=n.path[a],c=n.path[a+1],h=c.x-o.x,d=c.z-o.z,u=Math.hypot(h,d);if(u<1e-6||Math.abs((h*t.dx+d*t.dz)/u)<i)continue;const p=Math.max(0,Math.min(1,((t.x-o.x)*h+(t.z-o.z)*d)/(u*u))),f=Math.hypot(t.x-(o.x+h*p),t.z-(o.z+d*p));f<=zs.NEAR_M&&(r===void 0||f<r)&&(r=f)}r!==void 0&&s.push({way:n,distance:r})}return s.sort((n,r)=>n.distance-r.distance).map(({way:n})=>n)}}class zc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(e={}){this.client=new Fn(e)}async getRailways(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:25];way["railway"~"^(${zc.KINDS.join("|")})$"](${t})->.w;.w out tags geom;rel(bw.w)["route"~"^(${zs.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(e){const t=[],i=zs.servicesByWay(e);for(const s of e.elements??[]){const n=s.geometry,r=s.tags;if(s.type==="relation"||!r||!n||n.length<2)continue;const a=[...i.get(s.id??-1)??[]].sort(),o=zs.voltageOf(r),c=zc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),d=Number.parseInt(r.tracks??"",10),u=zc.electrificationOf(r.electrified),p=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;t.push({id:`osm-rail-${s.id??t.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...o?{voltageV:o}:{},kind:c,...r.service||r.usage==="industrial"?{service:!0}:{},...p?{highSpeed:!0}:{},gaugeMm:Number.isFinite(h)&&h>300?h:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(d)&&d>0?d:1,...u?{electrification:u}:{},level:zc.levelOf(r),points:n.map(f=>({lat:f.lat,lng:f.lon}))})}return t}static kindOf(e){switch(e.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(e){if(e!==void 0){if(e==="no")return"none";if(e==="contact_line"||e==="yes")return"overhead";if(e==="rail"||e==="4th_rail"||e==="ground-level_power_supply")return"third_rail"}}static levelOf(e){const t=Number.parseInt(e.layer??"",10);return e.tunnel&&e.tunnel!=="no"?Number.isFinite(t)&&t<0?t:-1:e.covered==="yes"&&e.location==="underground"?-1:e.bridge&&e.bridge!=="no"?Number.isFinite(t)&&t>0?t:1:0}}class bI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(e){if(!yo.covers(e))return this.worldwide.getRailways(e);let t;try{if(t=await this.regional.getRailways(e),t.length>0)return t}catch{}try{return await this.worldwide.getRailways(e)}catch(i){if(t)return t;throw i}}}class vs{constructor(e,t=Date.now){this.railways=e,this.now=t}static CACHE_NAME="rr0-railways";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static RETRY_AFTER_MS=300*1e3;static asked=new Map;static failedAt=-1/0;get attribution(){return this.railways.attribution}get contemporary(){return this.railways.contemporary}async getRailways(e){const t=vs.key(e);let i=vs.asked.get(t)??vs.containing(e);if(i===void 0){const s=this.recalled(t,e);i={bounds:e,answer:s},vs.asked.set(t,i),s.catch(()=>vs.asked.delete(t))}return structuredClone(await i.answer)}static forget(){vs.asked.clear(),vs.failedAt=-1/0}static key(e){return`v${vs.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}static containing(e){for(const t of vs.asked.values()){const i=t.bounds;if(i.north>=e.north&&i.south<=e.south&&i.east>=e.east&&i.west<=e.west)return t}}async recalled(e,t){const i=await vs.openCache(),s=vs.request(e);let n;if(i)try{const a=await i.match(s);if(a){const{savedAt:o,lines:c}=await a.json();if(Array.isArray(c)){if(this.now()-o<vs.MAX_AGE_MS)return c;n=c}}}catch{}if(this.now()-vs.failedAt<vs.RETRY_AFTER_MS){if(n)return n;throw new Error("The railway survey failed a moment ago: not asked again yet")}let r;try{r=await this.railways.getRailways(t)}catch(a){if(vs.failedAt=this.now(),n)return n;throw a}return i&&vs.store(i,s,{savedAt:this.now(),lines:r}),r}static async store(e,t,i){try{await e.delete(t),await e.put(t,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const s=await e.keys();for(const n of s.slice(0,Math.max(0,s.length-vs.MAX_STORED)))await e.delete(n)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(vs.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__railways__/${encodeURIComponent(e)}`)}}const Bm="https://ufoathome.org/railways/index.json";class Bc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Bc.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getRailways(e);return this.attributionRead=this.fallback.attribution,i}async held(e){const i=(await this.load().catch(()=>[])).find(({entry:s})=>s.north>=e.north&&s.south<=e.south&&s.east>=e.east&&s.west<=e.west);if(i)try{const s=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!s.ok)return;const n=await s.json();return Array.isArray(n?.lines)?(this.attributionRead=n.attribution,n.lines):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const e=this.indexUrls.join(`
4253
- `);let t=Bc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Bc.shared.set(e,t),t.then(i=>{i.length===0&&Bc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.0")}`,t=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(t&&t!==Bm?[t,Bm]:[Bm]).map(i=>i+e)}}function F2(){return{elevation:U2(),imagery:z2(),roads:B2(),water:H2(),railways:G2()}}function U2(){return new pI(new Ot,new O2)}function z2(){return new N2}function B2(){return new Fc({fallback:new gI(new bo,new fo)})}function H2(){return new Uc({fallback:new Ln(new vI(new Vd,new il))})}function G2(){return new Bc({fallback:new vs(new bI(new yo,new zc))})}const yI=new Set,sh="show-observer-map",nh="hide-milestones",Sl="minified";class Vt extends HTMLElement{static get observedAttributes(){return["src",sh,nh,Sl]}shadow;stageElement;canvas;canvasRenderer;chromeCanvas;chromeRenderer;chromeResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>{this.chromeDirty&&this.refresh()});chromeDirty=!1;tooltip;toolbar;issuesBox;issuesButton;issuesPanel;playPauseButton;fullscreenButton;cornerButtons;observerMapButton;referencesButton;tracesButton;tracesShownState=!0;referenceOpacityInput;referencesShownState=!0;accountHidden=!1;referenceViews=new Map;referencesMenu;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;mapZoomInButton;mapZoomOutButton;mapFitButton;observerMapView=new ti;observerMapDrag;suppressObserverMapClick=!1;observerMapImageryTimer;observerPlacing=!1;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;timePill;muteButton;volumeInput;controlsRow;momentsBox;momentsButton;momentsCurrent;momentsMenu;moreButton;controlsRight;seekSegments;seekDot;playerTitleBox;seekPreview;seekPreviewCanvas;seekPreviewTitle;seekPreviewTime;observerPath;observerMapBounds;observerMapImagery;observerMapImageryBounds;observerMapImageryViewWidth=0;observerMapImageryLoading=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=dm.create();issues=[];issueCheck=0;sightingAudio=new eI;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;static LIVE_BODY_MAX_RATE=2;get steadyBody(){return this.steadyObserver||this.player.playbackState!=="playing"||this.player.playbackRate>Vt.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=A2;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const e=this.controlsRow,t=e.classList.contains("more-open"),i=()=>e.scrollWidth>e.clientWidth+1,s=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,e.classList.remove("narrow","more-open","nomoments","compact","tiny"),e.clientWidth>0&&i()){e.classList.add("narrow");for(const n of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(n)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!s,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");Vt.setIcon(this.moreButton,e?et.UNFOLDED:et.FOLDED);const t=e?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=t,this.moreButton.setAttribute("aria-label",t),this.moreButton.setAttribute("aria-expanded",String(e))}addControl(e){this.controlsRight.insertBefore(e,this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null),this.fitControls()}observerMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeObserverMap());resizeObserverMap(){this.observerMapPanel.hidden||(this.sizeObserverMapCanvas(),this.paintObserverMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),i=t&&this.shapeAt(t.x,t.y),s=this.said.read(i?.shape.title);if(!s){this.tooltip.hidden=!0;return}this.tooltip.textContent=s,this.tooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-n.left+12}px`,this.tooltip.style.top=`${e.clientY-n.top+12}px`};handleObserverMapPointerMove=e=>{if(this.dragObserverMap(e))return;const t=this.observerMapTargetFrom(e);if(!t){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(e,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(e,t.label)};showObserverMapTooltip(e,t){this.tooltip.textContent=t,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-i.left+12}px`,this.tooltip.style.top=`${e.clientY-i.top+12}px`}handleObserverMapClick=e=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const t=this.observerMapTargetFrom(e);if(!t){this.observerPlacing&&this.placeObserverFrom(e);return}if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(e){const t=this.observerMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.observerMapRenderer.hitTest((e.clientX-t.left)/t.width*this.observerMapCanvas.width,(e.clientY-t.top)/t.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=e=>{e.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,moved:!1})};handleObserverMapPointerUp=e=>{const t=this.observerMapDrag;!t||t.pointerId!==e.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),t.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(e.pointerId)&&this.observerMapCanvas.releasePointerCapture(e.pointerId)))};dragObserverMap(e){const t=this.observerMapDrag;if(!t||t.pointerId!==e.pointerId)return!1;if(!t.moved){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<Vt.OBSERVER_MAP_DRAG_PX)return!1;t.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(e.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((e.clientX-t.lastX)/i.width,(e.clientY-t.lastY)/i.height),this.observerMapViewChanged()),t.lastX=e.clientX,t.lastY=e.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=e=>{e.preventDefault();const t=this.observerMapCanvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=e.deltaMode===0?e.deltaY:e.deltaY*40;this.zoomObserverMap((e.clientX-t.left)/t.width,(e.clientY-t.top)/t.height,Math.exp(-i*.002))};zoomObserverMap(e,t,i){this.observerMapView.zoomAt(e,t,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=ti.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=ti.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Vt.OBSERVER_MAP_IMAGERY_DELAY_MS))}static OBSERVER_MAP_FOLLOW_MARGIN=.1;static OBSERVER_MAP_IMAGERY_DELAY_MS=300;get observerMapViewBounds(){return this.observerMapBounds&&this.observerMapView.boundsWithin(this.observerMapBounds)}placeObserverFrom(e){const t=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!t||i.width===0||i.height===0)return;const s=ti.pointAt(t,(e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:s,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${j3}</style>${q3}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new yh(this.canvas.getContext("2d")),this.chromeCanvas=this.shadow.getElementById("chrome"),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.issuesBox=this.shadow.getElementById("issues"),this.issuesButton=this.shadow.getElementById("issues-button"),this.issuesPanel=this.shadow.getElementById("issues-panel"),this.issuesButton.addEventListener("click",a=>{a.stopPropagation(),this.issuesPanel.hidden=!this.issuesPanel.hidden,this.issuesButton.setAttribute("aria-expanded",String(!this.issuesPanel.hidden))}),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.tracesButton=this.shadow.getElementById("traces"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.referencesMenu=this.shadow.getElementById("references-menu"),this.milestonesButton=this.shadow.getElementById("milestones"),this.observerMapPanel=this.shadow.getElementById("observer-map-panel"),this.observerMapCanvas=this.shadow.getElementById("observer-map-canvas"),this.observerMapRenderer=new tl(this.observerMapCanvas.getContext("2d")),this.mapZoomInButton=this.shadow.getElementById("map-zoom-in"),this.mapZoomOutButton=this.shadow.getElementById("map-zoom-out"),this.mapFitButton=this.shadow.getElementById("map-fit"),this.seekInput=this.shadow.getElementById("seek"),this.playbackFlash=this.shadow.getElementById("playback-flash"),this.milestoneMarks=this.shadow.getElementById("milestone-marks"),this.milestoneCaption=this.shadow.getElementById("milestone-caption"),this.timeStartLabel=this.shadow.getElementById("time-start"),this.timeEndLabel=this.shadow.getElementById("time-end"),this.timePill=this.shadow.getElementById("time"),this.muteButton=this.shadow.getElementById("mute"),this.controlsRight=this.shadow.getElementById("controls-right"),this.seekSegments=this.shadow.getElementById("seek-segments"),this.seekDot=this.shadow.getElementById("seek-dot"),this.playerTitleBox=this.shadow.getElementById("player-title"),this.seekPreview=this.shadow.getElementById("seek-preview"),this.seekPreviewCanvas=this.shadow.getElementById("seek-preview-canvas"),this.seekPreviewTitle=this.shadow.getElementById("seek-preview-title"),this.seekPreviewTime=this.shadow.getElementById("seek-preview-time"),this.timePill.addEventListener("click",()=>this.toggleTimeDisplay()),this.timePill.addEventListener("keydown",a=>{a.key!=="Enter"&&a.key!==" "||(a.preventDefault(),this.toggleTimeDisplay())}),this.volumeInput=this.shadow.getElementById("volume"),this.controlsRow=this.shadow.querySelector(".controls"),this.momentsBox=this.shadow.getElementById("moments"),this.momentsButton=this.shadow.getElementById("moments-button"),this.momentsCurrent=this.shadow.getElementById("moments-current"),this.momentsMenu=this.shadow.getElementById("moments-menu"),this.momentsButton.addEventListener("click",()=>this.toggleMomentsMenu()),this.moreButton=this.shadow.getElementById("controls-more"),this.moreButton.addEventListener("click",()=>this.setControlsFolded(this.controlsRow.classList.contains("more-open"))),this.muteButton.addEventListener("click",()=>this.toggleMuted()),this.miniPlayed=this.shadow.getElementById("mini-played"),this.miniRemaining=this.shadow.getElementById("mini-remaining"),this.miniMuteButton=this.shadow.getElementById("mini-mute"),this.miniDot=this.shadow.getElementById("mini-dot"),this.miniScrubTime=this.shadow.getElementById("mini-scrub-time");const t=this.shadow.getElementById("mini-bar"),i=t.querySelector(".mini-track"),s=a=>{const o=i.getBoundingClientRect(),c=this.player.seekableDuration;if(o.width<=0||c<=0)return;const h=Math.min(Math.max((a.clientX-o.left)/o.width,0),1)*c;this.player.seek(h),this.miniScrubTime.textContent=this.formatElapsedAt(h),this.miniScrubTime.style.left=this.miniDot.style.left};let n=!1;t.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),t.setPointerCapture(a.pointerId),t.classList.add("scrubbing"),n=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,s(a))}),t.addEventListener("pointermove",a=>{t.hasPointerCapture(a.pointerId)&&s(a)});const r=a=>{t.classList.contains("scrubbing")&&(t.classList.remove("scrubbing"),t.hasPointerCapture(a.pointerId)&&t.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,n&&this.play())};t.addEventListener("pointerup",r),t.addEventListener("pointercancel",r),t.addEventListener("click",a=>a.stopPropagation()),this.miniMuteButton.addEventListener("click",a=>{a.stopPropagation(),this.toggleMuted()}),this.stageElement.addEventListener("pointerenter",this.handleMinifiedEnter),this.stageElement.addEventListener("pointerleave",this.handleMinifiedLeave),this.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>{this.player.seek(this.snapSeekToMark(Number(this.seekInput.value))),this.announceReveal()}),this.seekInput.addEventListener("pointerdown",a=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(a),this.beginTouchScrub(a)}),this.seekInput.addEventListener("pointerup",a=>{this.seekSnapArmed=!1,this.endTouchScrub(a)}),this.seekInput.addEventListener("pointercancel",a=>this.endTouchScrub(a)),this.seekInput.addEventListener("pointermove",a=>{this.nameMarkUnder(a),this.hoverSeek(a),this.touchScrub(a)}),this.seekInput.addEventListener("pointerleave",()=>{this.seekInput.removeAttribute("title"),this.leaveSeek()}),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.stageElement.addEventListener("pointerdown",()=>{this.handlePointerDown(),this.touchedStage()},!0);for(const a of["touchend","click"])this.stageElement.addEventListener(a,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",a=>{if(!(!this.enableClickToPlay||this.minified)){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}a.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",a=>{!this.enableClickToPlay||this.minified||(a.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),document.addEventListener("pointerdown",this.handleMomentsDismiss,!0),document.addEventListener("keydown",this.handleMomentsDismiss,!0),document.addEventListener("visibilitychange",this.handleVisibility),window.addEventListener("pagehide",this.handleHidden),document.addEventListener("pointerup",this.handlePointerRelease,!0),document.addEventListener("pointercancel",this.handlePointerRelease,!0),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.chromeResizeObserver?.observe(this.chromeCanvas),this.controlsFitObserver?.observe(this.controlsRow),this.controlsFitObserver?.observe(this.controlsRow.querySelector(".controls-left")),typeof MutationObserver<"u"&&(this.controlsMutations=new MutationObserver(()=>this.fitControls()),this.controlsMutations.observe(this.controlsRight,{attributes:!0,attributeFilter:["hidden"],childList:!0,subtree:!0})),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.refresh()}connectedCallback(){this.saidTexts=void 0,this.loadLocaleMessages();const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),document.removeEventListener("pointerdown",this.handleMomentsDismiss,!0),document.removeEventListener("keydown",this.handleMomentsDismiss,!0),document.removeEventListener("visibilitychange",this.handleVisibility),window.removeEventListener("pagehide",this.handleHidden),document.removeEventListener("pointerup",this.handlePointerRelease,!0),document.removeEventListener("pointercancel",this.handlePointerRelease,!0),window.clearTimeout(this.controlsIdleTimer),this.observerMapResizeObserver?.disconnect(),this.chromeResizeObserver?.disconnect(),this.controlsFitObserver?.disconnect(),this.controlsMutations?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(e,t,i){if(e==="src"&&i&&i!==t&&this.isConnected&&this.loadFromSrc(i),e===sh&&this.applyObserverMapDefault(),e===nh&&this.setMilestonesShown(!this.hasAttribute(nh)),e===Sl){const s=this.minified;this.stageElement.classList.toggle("minified",s),s&&t===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(Sl)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=e=>{!this.minified||e.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=e=>{!this.minified||e.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(V2)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const e=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",e),e&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(e){this.sightingData=await Ur.recording(e)}get sightingData(){return xf(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=bb(e),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(e,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.started=!1,this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault(),this.minified&&this.minifiedHovered&&this.play()}set playerTitle(e){this.titleOverride=e,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const e=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=e,this.playerTitleBox.hidden=e===""}get recordingIssues(){return this.issues}async reportIssues(e,t){const i=++this.issueCheck;let s=[];try{const{default:n}=await ae(async()=>{const{default:r}=await import("./sightingSchema-Bc1JhWrZ.js");return{default:r}},[],import.meta.url);s=new Ar(n).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...s,...t.loadIssues],wh.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(wI,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const e=this.issues.length;this.issuesBox.hidden=e===0,this.shadow.getElementById("issues-count").textContent=String(e);const t=this.messages.recordingIssues.replace("{count}",String(e));this.issuesButton.title=t,this.issuesButton.setAttribute("aria-label",t),this.shadow.getElementById("issues-title").textContent=t,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const s=document.createElement("li");return s.textContent=wh.text(i,this.messages.issueTemplates),s}))}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){if(!(this.player.seekableDuration<=0||this.playbackState==="playing")){if(this.clockHeld){this.playAfterHold=!0,this.announcePlayRequest();return}this.togglePlayPause()}}get playRequested(){return this.playbackState==="playing"||this.playAfterHold}announcePlayRequest(){this.announceReveal(),this.dispatchEvent(new CustomEvent("playrequest"))}announceReveal(){this.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("revealrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(e){if(e!==this.clockHeld){if(this.clockHeld=e,e){if(this.playbackState!=="playing")return;this.playAfterHold=!0,this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton();return}this.playAfterHold&&(this.playAfterHold=!1,!(this.player.seekableDuration<=0||this.playbackState==="playing")&&(this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton()))}}pause(){this.playAfterHold=!1,this.playbackState==="playing"&&this.togglePlayPause()}get positionLabel(){return this.timeStartLabel.textContent??""}get durationLabel(){return this.timeEndLabel.textContent??""}get showingClockTime(){return this.canShowClockTime}get canSwitchTimeDisplay(){return this.realStartMs!==void 0}toggleTimeDisplay(){this.canSwitchTimeDisplay&&(this.showClockTime=!this.showClockTime,this.updateTimeLabels(),this.updateTimeLabelTitles(),this.dispatchEvent(new CustomEvent("timedisplaychange",{bubbles:!0,composed:!0})))}get canShowClockTime(){return this.realStartMs!==void 0&&this.showClockTime}set showToolbar(e){this.toolbar.classList.toggle("hidden",!e),e?this.controlsRight.appendChild(this.fullscreenButton):this.cornerButtons.appendChild(this.fullscreenButton)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(s=>this.highlightedSourceIds.has(s))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==void 0}refresh(){this.applyFrameFormat(),this.updateMuteButton(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.updateTracesButton(),this.player.seek(this.player.time)}repaintOverlay(){this.quietFrame=!0;try{this.player.seek(this.player.time)}finally{this.quietFrame=!1}}quietFrame=!1;hostControls(e){const t=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(e)for(const i of t)e.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const s of t)this.controlsRight.insertBefore(s,i)}}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}get severalReferences(){return this.currentSighting.references.length>1}toggleReferences(){if(this.severalReferences){this.toggleReferencesMenu();return}this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity));for(const t of[...this.referenceViews.keys()])e.some(i=>i.id===t)||this.referenceViews.delete(t);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(e){let t=this.referenceViews.get(e.id);return t||(t={shown:!0,opacity:e.opacity},this.referenceViews.set(e.id,t)),t}toggleReferencesMenu(){this.referencesMenu.hidden?this.openReferencesMenu():this.closeReferencesMenu()}openReferencesMenu(){this.renderReferencesMenu(),this.referencesMenu.hidden=!1,this.placeReferencesMenu(),this.referencesButton.setAttribute("aria-expanded","true"),document.addEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.addEventListener("keydown",this.handleReferencesMenuKey,!0)}closeReferencesMenu(){this.referencesMenu.hidden||(this.referencesMenu.hidden=!0,this.referencesButton.setAttribute("aria-expanded","false"),document.removeEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.removeEventListener("keydown",this.handleReferencesMenuKey,!0))}handleReferencesMenuOutside=e=>{const t=e.composedPath();t.includes(this.referencesMenu)||t.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=e=>{e.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const e=this.referencesButton.getBoundingClientRect(),t=this.referencesMenu,i=4;t.style.bottom=`${Math.max(i,window.innerHeight-e.top+i)}px`,t.style.top="auto";const s=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-s-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),s=this.said.read(t.title)??t.id,n=document.createElement("div");n.className="reference-row";const r=document.createElement("label"),a=document.createElement("input");a.type="checkbox",a.checked=i.shown;const o=document.createElement("span");o.textContent=s,o.title=s,r.append(a,o);const c=document.createElement("input");return c.type="range",c.min="0",c.max="1",c.step="0.05",c.value=String(i.opacity),c.title=this.messages.referenceOpacity,c.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${s}`),c.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,c.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),c.addEventListener("input",()=>{i.opacity=Number(c.value),this.dispatchReferenceView()}),n.append(r,c),n});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...e)}updateReferencesButton(){const e=this.currentSighting.references.length>0,t=this.severalReferences,i=t?this.currentSighting.references.some(n=>this.viewOfReference(n).shown):this.referencesShownState;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState||t,this.referencesButton.setAttribute("aria-pressed",String(i)),t?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Vt.setIcon(this.referencesButton,i?et.PICTURES_ON:et.PICTURES_OFF);const s=t?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=s,this.referencesButton.setAttribute("aria-label",s),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}get tracesShown(){return this.tracesShownState}toggleTraces(){this.tracesShownState=!this.tracesShownState,this.updateTracesButton(),this.updateObserverMap(),this.dispatchEvent(new CustomEvent("traceview",{detail:{shown:this.tracesShown}}))}updateTracesButton(){this.tracesButton.hidden=this.currentSighting.traces.length===0,this.tracesButton.setAttribute("aria-pressed",String(this.tracesShownState)),Vt.setIcon(this.tracesButton,this.tracesShownState?et.TRACES_ON:et.TRACES_OFF);const e=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=e,this.tracesButton.setAttribute("aria-label",e)}dispatchReferenceView(){const e=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(t=>[t.id,{...this.viewOfReference(t)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:e}}))}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Ol(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const s=document.createElement("button");s.type="button",s.className="milestone-mark",s.style.left=`${Math.min(Math.max(i.t/e,0),1)*100}%`;const n=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${n} — ${r}`:n;return s.title=a,s.setAttribute("aria-label",a),s.dataset.t=String(i.t),s.addEventListener("click",()=>this.player.seek(i.t)),s})),this.refreshSeekSegments(e,t.map(i=>i.t)),this.refreshMomentsPicker(t)}refreshMomentsPicker(e){const t=this.milestonesShown&&e.length>0;this.momentsBox.hidden=!t,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...e.map(i=>{const s=document.createElement("li"),n=document.createElement("button");n.type="button",n.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return n.textContent=a?`${r} — ${a}`:r,n.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),s.appendChild(n),s})),this.momentsButton.title=this.messages.moments,this.showCurrentMoment(void 0)}showCurrentMoment(e){const i=(e?this.said.read(e.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const s of this.momentsMenu.querySelectorAll("button")){const n=e!==void 0&&Number(s.dataset.t)===e.t;s.getAttribute("aria-current")==="true"!==n&&s.setAttribute("aria-current",String(n))}}toggleMomentsMenu(){this.momentsMenu.hidden?(this.momentsMenu.hidden=!1,this.momentsButton.setAttribute("aria-expanded","true")):this.closeMomentsMenu()}closeMomentsMenu(){this.momentsMenu.hidden=!0,this.momentsButton.setAttribute("aria-expanded","false")}handleMomentsDismiss=e=>{if(!this.momentsMenu.hidden){if(e instanceof KeyboardEvent){e.key==="Escape"&&this.closeMomentsMenu();return}e.composedPath().some(t=>t===this.momentsMenu||t===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(e,t){const s=[0,...this.milestonesShown&&e>0?[...new Set(t.filter(r=>r>0&&r<e))].sort((r,a)=>r-a):[],Math.max(e,0)];this.seekSegmentList=[];const n=[];for(let r=0;r<s.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(s[r+1]-s[r],1));const o=document.createElement("i");o.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(o,c),n.push(a),this.seekSegmentList.push({start:s[r],end:s[r+1],element:a,played:c,hover:o})}this.seekSegments.replaceChildren(...n),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,s=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(s,0),1)*100}%`}paintMiniProgress(e){const t=this.player.seekableDuration,i=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(e)}miniDot;miniScrubTime;paintSeekProgress(e){for(const i of this.seekSegmentList)i.played.style.width=Vt.fillOf(i,e);const t=this.player.seekableDuration;this.seekDot.style.left=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`}hoverSeek(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),n=s*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=Vt.fillOf(p,n),p.element.classList.toggle("hovered",n>=p.start&&(n<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],o=a.length>0?Nm(a,n):void 0,c=o?this.said.read(o.label)??"":"",h=o?this.said.read(o.note):void 0,d=h?`${c} — ${h}`:c;this.seekPreviewTitle.textContent=d,this.seekPreviewTime.textContent=this.formatPosition(n),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(s*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(n)}leaveSeek(){for(const e of this.seekSegmentList)e.hover.style.width="0",e.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(e){const t=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=t===void 0,t?.(e,this.seekPreviewCanvas)}paintChrome(e){const t=this.chromeCanvas.getContext("2d"),i=this.overlayPainter!==void 0||this.selectionShown;if(!i&&!this.chromeDirty)return;const s=this.chromeCanvas.clientWidth,n=this.chromeCanvas.clientHeight;if(!t||typeof t.setTransform!="function"||s===0||n===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(s*r)),o=Math.max(1,Math.round(n*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==o&&(this.chromeCanvas.height=o),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,a,o),this.chromeDirty=!1,i&&(t.setTransform(a/this.canvas.width,0,0,o/this.canvas.height,0,0),this.chromeRenderer??=new yh(t),this.chromeDirty=!0,e(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(e){if(e.pointerType!=="mouse"){this.scrubbingPointer=e.pointerId;try{this.seekInput.setPointerCapture(e.pointerId)}catch{}this.seekToPointer(e)}}touchScrub(e){e.pointerId===this.scrubbingPointer&&this.seekToPointer(e)}endTouchScrub(e){e.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(e))}seekToPointer(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(s*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(t<=0||i<=0)return;const s=Vt.MARK_SNAP_PX/i*t;let n;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>s||(!n||Math.abs(a-e)<Math.abs(n.t-e))&&(n={t:a,name:r.title})}return n}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=(e.clientX-t.left)/t.width*i,n=this.markNear(s);n?this.seekInput.title=n.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?Nm(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,this.showCurrentMoment(t),!t)return;const i=document.createElement("b");i.textContent=this.said.read(t.label)??"";const s=this.said.read(t.note),n=s?` — ${s}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(n))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(s=>({shapes:this.shapesAt(s),share:i}))}exposureTimes(e=this.currentTime){const t=Cr.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<Vt.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(Vt.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/Vt.SHORTEST_VISIBLE_EXPOSURE_MS))),s=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/Vt.EXPOSURE_STEP_PX),n=Math.min(Vt.MAX_TRAVEL_STEPS,Math.max(i,s)),r=[];for(let a=0;a<n;a++)r.push(t.fromMs+t.ms*a/(n-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),s=this.shapesAt(e+t);let n=0;for(const[r,a]of i){const o=s.get(r);if(!o)continue;const c=o.bounds.x+o.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=o.bounds.y+o.bounds.height/2-(a.bounds.y+a.bounds.height/2);n=Math.max(n,Math.hypot(c,h))}return n}shapeAt(e,t,i){if(!this.accountHidden)for(const s of this.exposureTimes()){const n=this.currentSighting.timeline.hitTest(s,e,t,i);if(n)return n}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const s=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);s&&t.set(i,s)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Yt.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:yI;this.canvasRenderer.setStarPoints(Yt.starPointsOf(this.sighting.instrument,at(this.sighting,e)?.fNumber));const s=(at(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(s*Math.PI/180);const n=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const o of n)for(const[,c]of o.shapes){const h=o.share,d=h===1?c:{...c,transparency:1-(1-c.transparency)*h};this.canvasRenderer.paintShape(this.shifted(d,r))}for(const[o,c]of n[0].shapes)!this.selectionShown||!i.has(o)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));const a=this.selectionShown&&i.size>1?Kt.groupBoundsFor([...t].filter(([o])=>i.has(o)).map(([,o])=>o.bounds)):void 0;this.chromeDraw=o=>{a&&o.paintGroupHandles(a),this.overlayPainter?.(o)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=n.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(e),this.paintSeekProgress(e),this.minified&&this.paintMiniProgress(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintObserverMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(rb(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new Z3(this.currentSighting.timeline,(t,i)=>this.onFrame(t,i));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=e=>{e.key.toLowerCase()!=="f"||e.altKey||e.ctrlKey||e.metaKey||!this.enableClickToPlay||e.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(e.preventDefault(),this.toggleFullscreen())};handleSeekKey=e=>{if(e.altKey||e.ctrlKey||e.metaKey)return;const t=e.key==="ArrowLeft"?-1:e.key==="ArrowRight"?1:0;if(t){e.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+t*Vt.SEEK_KEY_STEP_MS)))}else e.key===" "&&(e.preventDefault(),this.togglePlayPause())};togglePlayPause(){if(!(this.player.seekableDuration<=0)){if(this.player.playbackState==="playing")this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh();else if(this.clockHeld){this.playAfterHold=!this.playAfterHold,this.playAfterHold&&this.announcePlayRequest();return}else this.announcePlayRequest(),this.sightingAudio.resume(),this.player.play();this.updatePlayPauseButton(),this.flashPlayback()}}flashPlayback(){const e=this.playbackFlash;e.innerHTML=this.player.playbackState==="playing"?et.PLAY:et.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){Vt.icons.get(e)!==t&&(Vt.icons.set(e,t),e.innerHTML=t)}set captionHeld(e){this.stageElement.classList.toggle("caption-held",e)}set controlsHeld(e){this.stageElement.classList.toggle("controls-held",e)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(e){this.quietControlsValue=e,this.stageElement.classList.toggle("quiet",e)}tapRevealedOnly=!1;get hoverless(){return typeof matchMedia=="function"&&matchMedia("(hover: none)").matches}touchedStage(){if(!this.hoverless)return;this.player.playbackState==="playing"&&!this.stageElement.classList.contains("touched")&&(this.tapRevealedOnly=!0),this.revealControls()}pointerHeld=!1;handlePointerDown=()=>{this.pointerHeld=!0};resumeAfterScrub=!1;suspendForScrub(){this.player.playbackState==="playing"&&(this.resumeAfterScrub=!0,this.stopPlaying())}stopPlaying(){this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton()}resumeFromScrub(){this.resumeAfterScrub&&(this.resumeAfterScrub=!1,this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton())}handleHidden=()=>{this.player.playbackState==="playing"&&this.stopPlaying(),this.resumeAfterScrub=!1};handleVisibility=()=>{document.visibilityState==="hidden"&&this.handleHidden()};handlePointerRelease=()=>{this.resumeAfterScrub&&window.setTimeout(()=>this.resumeFromScrub(),0),this.pointerHeld&&(this.pointerHeld=!1,this.hoverless&&this.stageElement.classList.contains("touched")&&this.revealControls())};revealControls(){this.stageElement.classList.add("touched"),window.clearTimeout(this.controlsIdleTimer),this.player.playbackState==="playing"&&(this.pointerHeld||!this.momentsMenu.hidden||(this.controlsIdleTimer=window.setTimeout(()=>{this.stageElement.classList.remove("touched"),this.tapRevealedOnly=!1},Vt.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!e),e!==this.wasPlaying&&e&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=e,this.updateStartState(),Vt.setIcon(this.playPauseButton,e?et.PAUSE:et.PLAY);const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const i=t?e?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=i,this.playPauseButton.setAttribute("aria-label",i)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const e=this.observerMapPanel.hidden;this.observerMapAsked=e,this.setObserverMapOpen(e),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:e}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const e=this.getAttribute(sh),t=e===null?this.sighting.observerMap??this.observerPath?.travels===!0:e!=="false";this.setObserverMapOpen(t&&this.observerPath!==void 0)}setObserverMapOpen(e){this.observerMapPanel.hidden=!e,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(e)),this.updateObserverMapButton(),e&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const e=!this.observerMapPanel.hidden;Vt.setIcon(this.observerMapButton,e?et.MAP_ON:et.MAP_OFF);const t=e?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=t,this.observerMapButton.setAttribute("aria-label",t);const i=[[this.mapZoomInButton,this.messages.zoomMapIn],[this.mapZoomOutButton,this.messages.zoomMapOut],[this.mapFitButton,this.messages.fitMap]];for(const[s,n]of i)s.title=n,s.setAttribute("aria-label",n)}updateObserverMap(){const e=this.observerPath!==void 0;if(this.observerPath=Cl.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!e&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const t=this.tracesShownState?this.currentSighting.traces.flatMap(s=>s.points):[],i=ti.fitted(this.observerPath,t);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,i))&&(this.observerMapBounds&&this.observerMapView.refit(this.observerMapBounds,i),this.observerMapBounds=i,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||this.loadObserverMapImagery())}sameGround(e,t){const i=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<i&&Math.abs(e.south-t.south)<i&&Math.abs(e.west-t.west)<i&&Math.abs(e.east-t.east)<i}async loadObserverMapImagery(){const e=this.observerMapViewBounds;if(!e||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(e)))return;const t=this.observerMapView.changed,i=t?ti.expand(e,Vt.OBSERVER_MAP_IMAGERY_AHEAD):e,s=ti.IMAGERY_PX*(t?1+2*Vt.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const n=this.observerMapFrozenImagery,r=n?void 0:z2();try{const a=r?await r.getImageryTexture(i,{width:s,height:s}):await n.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??n).attribution,this.observerMapImageryFailed=!1}catch{if(this.observerMapImageryBounds!==i)return;this.observerMapImageryFailed=this.observerMapImagery===void 0}finally{this.observerMapImageryBounds===i&&(this.observerMapImageryLoading=!1)}this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}static OBSERVER_MAP_IMAGERY_AHEAD=.5;static OBSERVER_MAP_IMAGERY_LOOKAHEAD=.25;observerMapImageryNeededFor(e){const t=this.observerMapImageryBounds;if(!t)return!0;const i=this.observerMapImagery?.bounds??t,s=this.observerMapView.changed?ti.expand(e,Vt.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,n=s.west>=i.west&&s.east<=i.east&&s.south>=i.south&&s.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!n||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(e){e!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=e,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||(this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime)))}get observerMapFrozen(){return this.observerMapFrozenImagery}observerMapFrozenImagery;observerMapFrozenSource;get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const e=this.observerMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],i=(c,h,d)=>{for(const u of t)if(!(u.x+u.width<c-d||u.x>h+d)&&!(u.y>e.bottom+d||u.y+u.height<e.top-d))return!0;return!1},s=[this.canvas.width-e.width,this.canvas.width],n=[0,e.width],r=Vt.OBSERVER_MAP_CLEARANCE_PX,a=i(...s,0),o=i(...n,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&o&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(o||!i(s[0],s[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(s[0],s[1],0)&&!i(n[0],n[1],0)&&this.observerMapPanel.classList.add("on-the-left")}observerMapBoxPx;static OBSERVER_MAP_CLEARANCE_PX=24;sizeObserverMapCanvas(){const e=this.observerMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==t&&(this.observerMapCanvas.width=t,this.observerMapCanvas.height=t)}measureObserverMapBox(){const e=this.observerMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=this.canvas.width/t.width,s=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*s,bottom:(e.bottom-t.top)*s}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=at(this.currentSighting,e);t?.lat!==void 0&&t.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:t.lat,lng:t.lng},Vt.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,s=[],n=this.currentSighting.milestones.length>0?Nm(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?Ol(this.currentSighting.milestones):[]){const a=at(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||s.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===n})}this.observerMapRenderer.paint({bounds:this.observerMapViewBounds,imagery:this.observerMapImagery,path:this.observerPath,position:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?Bn.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Yt.aspectOf(i)):void 0,markers:s,traces:(this.tracesShownState?this.currentSighting.traces:[]).map(r=>({kind:r.kind,points:r.points,color:r.color,label:this.said.read(r.title)})),decor:this.observerMapDecorAt(e),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.momentsBox.hidden=!e||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,Ol(this.sighting.milestones).map(t=>t.t)),this.milestonesButton.setAttribute("aria-pressed",String(e)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintObserverMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0,this.momentsButton.title=this.messages.moments,Vt.setIcon(this.milestonesButton,this.milestonesShown?et.MILESTONES_ON:et.MILESTONES_OFF);const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}observerMapDecorAt(e){const t=at(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const s=tr(i,e),{lat:n,lng:r}=_n(s.eastM,-s.northM,t.lat,t.lng);return{lat:n,lng:r,headingDeg:s.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.observerMapNightFraction&&(this.observerMapNightFraction=t,this.paintObserverMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,i=this.lookPitchDeg+e.pitchDeg;if(t===0&&i===0)return{x:0,y:0};const s=at(this.currentSighting,this.currentTime),n=Bn.of(this.currentSighting.instrument,this.canvas.height,s?.fovDeg??60);return{x:-n.angleDegToRadiusPx(t),y:n.angleDegToRadiusPx(i)}}gaitAt(e){return ci.bodyAt(this.currentSighting,e,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(e){e!==this.mutedState&&(this.mutedState=e,!e&&this.volumeState===0&&(this.volumeState=Vt.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(e){this.setVolume(e)}setVolume(e){this.volumeState=Math.min(Math.max(e,0),1),this.mutedState=this.volumeState===0,this.applyLevel()}get level(){return this.mutedState?0:this.volumeState}applyLevel(){this.sightingAudio.setLevel(this.level),this.updateMuteButton(),this.dispatchEvent(new CustomEvent("mutedchange",{bubbles:!0,composed:!0,detail:{muted:this.mutedState,volume:this.volumeState}}))}toggleMuted(){this.hasSound&&(this.muted=!this.mutedState)}ambientSound;get hasSound(){return this.currentSighting.soundTrack.allKeyframes.length>0||this.ambientSound?.(this.currentSighting)===!0}updateMuteButton(){const e=!this.hasSound;this.miniMuteButton.hidden=e,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Vt.setIcon(this.miniMuteButton,this.mutedState?et.MUTED:et.VOLUME);const t=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=t,this.miniMuteButton.setAttribute("aria-label",t),this.muteButton.disabled=e,this.volumeInput.hidden=e,e){Vt.setIcon(this.muteButton,et.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Vt.setIcon(this.muteButton,this.mutedState?et.MUTED:et.VOLUME);const i=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=i,this.muteButton.setAttribute("aria-label",i),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Vt.setIcon(this.fullscreenButton,e?et.EXIT_FULLSCREEN:et.ENTER_FULLSCREEN),this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Tn(sr.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=Pd(sr.preferencesFor(this),Od);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await IE(e);this.messagesLanguage===e&&this.applyMessages(t)}messagesLanguage;updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t,this.timePill.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(this.timePill.setAttribute("role","button"),this.timePill.setAttribute("tabindex","0")):(this.timePill.removeAttribute("role"),this.timePill.removeAttribute("tabindex"))}applyMessages(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const e=this.currentSighting.event,t=mh(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?yg(e.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.paintMiniProgress(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return Qa(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?gy(my(this.realStartMs+i)):Qa(i)}formatElapsedAt(e){const t=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?Qa(e):Qa(t>0&&e<=t?e/t*this.realDurationMs:e)}formatRemaining(e){const t=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return Qa(Math.max(0,t-e));const i=t>0&&e<=t?e/t*this.realDurationMs:e;return Qa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?Qa(this.currentSighting.timeline.duration):this.canShowClockTime?gy(my(this.realStartMs+this.realDurationMs)):Qa(this.realDurationMs)}}function my(l){const e=new Date(l);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function gy(l){if(l.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return l.second?`${e(l.hour)}:${e(l.minute??0)}:${e(l.second)}`:`${e(l.hour)}:${e(l.minute??0)}`}function Qa(l){const e=Math.round(l/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Vg="rr0-ufo";function Mm(){customElements.get(Vg)||customElements.define(Vg,Vt)}const wI="recordingissues",V2="minifiedreset";class ud{constructor(e,t){this.seekInput=e,this.layer=t,e.addEventListener("pointerdown",i=>{this.snapArmed=!0,this.nameMarkUnder(i)}),e.addEventListener("pointerup",()=>this.snapArmed=!1),e.addEventListener("pointermove",i=>this.nameMarkUnder(i)),e.addEventListener("pointerleave",()=>e.removeAttribute("title"))}static SNAP_PX=6;marks=[];duration=0;drawn="";snapArmed=!1;show(e,t){const i=t>0?[...e].sort((n,r)=>n.t-r.t):[],s=`${t}|${i.map(n=>`${n.kind}:${n.t}:${n.label}`).join("|")}`;s!==this.drawn&&(this.drawn=s,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(n=>{const r=document.createElement("span");return r.className=`timeline-mark ${n.kind}`,r.style.left=`${Math.min(Math.max(n.t/t,0),1)*100}%`,r})))}snap(e){return this.snapArmed?(this.snapArmed=!1,this.markNear(e)?.t??e):e}next(e){return this.marks.find(t=>t.t>e+ud.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-ud.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=ud.SNAP_PX/t*this.duration;let s;for(const n of this.marks)Math.abs(n.t-e)>i||(!s||Math.abs(n.t-e)<Math.abs(s.t-e)||n.t===s.t&&n.kind==="milestone")&&(s=n);return s}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect();if(t.width<=0||this.duration<=0)return;const i=this.marksNear((e.clientX-t.left)/t.width*this.duration);i?this.seekInput.title=i:this.seekInput.removeAttribute("title")}marksNear(e){const t=this.markNear(e);if(t)return[...new Set(this.marks.filter(i=>i.t===t.t).map(i=>i.label))].join(" · ")}}class Hc{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const s=e.event.place?.[0],n=e.observerTrack;if(!s)return 0;const r=m=>{const g=n.getInterpolatedPoseAt(Math.max(0,m));if(!g||g.lat===void 0||g.lng===void 0)return;const v=ot(g.lat,g.lng,s.lat,s.lng);return{eastM:v.x,northM:-v.z,heading:g.headingDeg}},a=r(t-Hc.HALF_SPAN_MS),o=r(t+Hc.HALF_SPAN_MS),c=r(t);if(!a||!o||!c)return 0;const h=Math.hypot(o.eastM-a.eastM,o.northM-a.northM),d=2*Hc.HALF_SPAN_MS/1e3;if(h/d<Hc.MIN_SPEED_MS)return 0;const u=i.heightAt(o.eastM,o.northM)-i.heightAt(a.eastM,a.northM),p=Math.atan2(u,h)*180/Math.PI;if(c.heading===void 0)return p;const f=Math.atan2(o.eastM-a.eastM,o.northM-a.northM)*180/Math.PI;return p*Math.max(0,Math.cos((c.heading-f)*Math.PI/180))}}const MI=.08,vy=.15,by=2,xI=2e3;class SI{context;noiseBuffer;voices=new Map;level=1;master;paused=!0;requested=[];resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",e);return}}Ll.unlock(this.context),this.apply()}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}setPaused(e){e!==this.paused&&(this.paused=e,this.apply())}setVoices(e){this.requested=e,this.apply()}dispose(){for(const e of[...this.voices.keys()])this.release(e);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}apply(){const e=this.context;if(!e)return;const t=this.paused?[]:this.requested.filter(s=>s.inside||s.distanceM<xI),i=new Set(t.map(s=>s.id));for(const s of[...this.voices.keys()])i.has(s)||this.release(s);for(const s of t){const n=this.voices.get(s.id)??this.build(e,s.id);this.retarget(e,n,s)}}build(e,t){const i=e.createGain();i.gain.value=0;const s=e.createBiquadFilter();s.type="lowpass",s.connect(i).connect(this.masterOf(e));const n=e.createOscillator();n.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),o=e.createBiquadFilter();o.type="lowpass",o.frequency.value=900,n.connect(o),r.connect(o),o.connect(a).connect(s);const c=()=>{const M=e.createBufferSource();return M.buffer=this.noise(e),M.loop=!0,M.loopStart=Math.random()*by*.5,M},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(s);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const m=e.createGain();p.connect(f).connect(m).connect(s);const g=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const b=e.createGain();g.connect(v).connect(b).connect(s);const w=[n,r,h,p,g];for(const M of w)M.start();const y={nodes:[i,s,a,o,d,u,f,m,v,b,...w],sources:w,firing:n,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:m,windGain:b,cabin:s,output:i};return this.voices.set(t,y),y}retarget(e,t,{profile:i,state:s,noise:n,inside:r,windowsOpen:a,distanceM:o}){const c=e.currentTime,h=(b,w)=>b.setTargetAtTime(w,c,MI),d=s.rpm/60,u=d*i.cylinders/2,p=Math.min(1,s.rpm/i.shiftUpRpm),f=Math.min(1.5,s.speedMps/30);h(t.firing.frequency,u),h(t.crank.frequency,d),h(t.knock.frequency,u*3),h(t.engineGain.gain,i.engineGain*(.25+.75*s.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*s.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const m=!r||a;h(t.windGain.gain,f**2*(m?.5:.06));const g=r?a?3500:700:8e3/(1+o/60);h(t.cabin.frequency,g);const v=r?.5:Math.min(1,8/Math.max(o,1));h(t.output.gain,v*n)}release(e){const t=this.voices.get(e);if(!t)return;this.voices.delete(e);const i=this.context;i&&(t.output.gain.setTargetAtTime(0,i.currentTime,vy/3),setTimeout(()=>{for(const s of t.sources)try{s.stop()}catch{}for(const s of t.nodes)s.disconnect()},vy*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*by,e.sampleRate),i=t.getChannelData(0);for(let s=0;s<i.length;s++)i[s]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Wd{static BY_KIND={car:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},generic:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},van:{cylinders:4,idleRpm:750,kmhPer1000Rpm:[7,12,19,27,35,42],shiftUpRpm:2600,shiftDownRpm:1200,engineGain:.8,roadGain:.7,roughness:.45},truck:{cylinders:6,idleRpm:600,kmhPer1000Rpm:[5,8,12,17,23,30,38,48],shiftUpRpm:1900,shiftDownRpm:1e3,engineGain:1,roadGain:.9,roughness:.55},motorcycle:{cylinders:2,idleRpm:1100,kmhPer1000Rpm:[12,18,24,30,35,40],shiftUpRpm:6e3,shiftDownRpm:2500,engineGain:.9,roadGain:.3,roughness:.3}};static of(e){return Wd.BY_KIND[e??"generic"]??Wd.BY_KIND.generic}}class El{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,s){const n=El.SAMPLE_MS,r=[];for(let c=i;c<=s+n/2;c+=n){const h=t(c-n/2),d=t(c+n/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(n/1e3))}const a=[];let o=1;for(let c=0;c<r.length;c++){const h=r[c],d=(r[Math.min(c+1,r.length-1)]-r[Math.max(c-1,0)])/(2*n/1e3);if(h<El.STANDING_MPS){o=1,a.push({speedMps:h,rpm:e.idleRpm,load:.1,gear:0});continue}const u=h*3.6,p=v=>u/e.kmhPer1000Rpm[v-1]*1e3;for(;o<e.kmhPer1000Rpm.length&&p(o)>e.shiftUpRpm;)o++;for(;o>1&&p(o)<e.shiftDownRpm;)o--;const f=Math.max(p(o),e.idleRpm*(1+.3*Math.min(1,h/3))),m=.15+.5*Math.min(1,(h/35)**2),g=d>.15?Math.min(1,m+d/2.5):d<-.3?.05:m;a.push({speedMps:h,rpm:f,load:g,gear:o})}return new El(a,i)}at(e){const t=(e-this.startMs)/El.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),0),this.samples.length-1),s=this.samples[i],n=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(t-i,0),1);return{speedMps:s.speedMps+(n.speedMps-s.speedMps)*r,rpm:s.rpm+(n.rpm-s.rpm)*r,load:s.load+(n.load-s.load)*r,gear:r<.5?s.gear:n.gear}}}class Sf{drives=new Map;at(e,t){const i=[],s=e.event.place?.[0],n=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??s?.lat,u=h?.lng??s?.lng;if(d===void 0||u===void 0||!s)return;const p=ot(d,u,s.lat,s.lng);return{eastM:p.x,northM:-p.z}},r=Math.max(e.observerTrack.duration,(e.event.durationSeconds??0)*1e3),a=e.vehicle;if(a){const c=Wd.of(a.kind),h=this.drive(`observer:${a.kind}`,Sf.trackKey(e),()=>El.of(c,n,0,r));h&&i.push({id:"observer",profile:c,state:h.at(t),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const o=n(t);for(const c of e.decor){if(!c.engine||!o)continue;const h=Wd.of(c.engine.kind),d=m=>{const g=tr(c,m);return{eastM:g.eastM,northM:g.northM}},u=this.drive(`decor:${c.id}`,Sf.decorKey(c,r),()=>El.of(h,d,0,r));if(!u)continue;const p=tr(c,t),f=Math.hypot(p.eastM-o.eastM,p.northM-o.northM,p.altitudeM);i.push({id:`decor:${c.id}`,profile:h,state:u.at(t),noise:c.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:f})}return i}drive(e,t,i){const s=this.drives.get(e);if(s&&s.key===t)return s.drive;const n=i();return this.drives.set(e,{key:t,drive:n}),n}static trackKey(e){return e.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(e,t){return`${t}|${e.eastM},${e.northM}|`+(e.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const EI="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAARVBMVEX9sST/uyTfoCjNlSikfCqRcCx8Yy21hipTSi4TITEMHTEuMzBqWC3/wSRUX207SFj8/PyaoakmNUd5gYxBPy90fIfMz9RsB4kZAAACEUlEQVRo3u2XyXbDIAxFLeapjts6/f9PrQA3JymT25Cd3iY5xtYVIB6wLCQSiUQikUgk0nzBoVdFZ1xIpaTQbJnPACaNdYeskWwuAhaZoltnUemfnNkL4N49KEI8n0YAEXMvEWISAWQZPw2Xk1MIoF1dSNAzCMy6JsGyCR0wrkMwT3cBeDt+FH8aEHoA68LbM8HRHXQ3f0RE3/jXOOFX+s4djrKpIbzS7K+MmLrxlWCNR8mczjMw92Ar4dZLDXG4kzXinAECcOUPL3jMdN2294/GQGVG4EMHxORNJXoCfG6oT1trvDGM7iIA9N6aTOuuEbB9ra6FyCYr2gjge+fjA4CIi2uujYRoOBSw0A5/D0hT0X4PW0xtuotNpQPYtkt/fdtyM0LP6ZvOI2DtvoxtJWHvx38AxIkevLwXQ2TOA66DziYfLwC4r5wbIlwJo1ys8+VOBMy7/sxdjwIap49lVC3UePZp1mmyit4SuGUf11pjoTHVRVzXUaXFVt87kuEBsWZ055Q+2sXA76LbZYsvKR1ubvJqbKd5swl+GPI31p6L/sNYuDTe3jo+GBdr1J+P9PGawbRUw9VhleD/3ffT9uZ7DhtX1JNHL2CmNRXxYZhwSwBd3aJTyU85/GKOwhxBf5RnVk+75OSiuu+Ax4PQ3Jsg1hTeMUMwJgQp+PKCe2a+JuefFwQnkUgkEolEIpFerW8TL0hlNl2QVAAAAABJRU5ErkJggg==",AI=`
4251
+ `);let t=Fc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Fc.shared.set(e,t),t.then(i=>{i.length===0&&Fc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.1")}`,t=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(t&&t!==Um?[t,Um]:[Um]).map(i=>i+e)}}class bo{attribution="Roads © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Type autoroutier":{surface:"paved",widthM:11},"Route à 2 chaussées":{surface:"paved",widthM:7},"Route à 1 chaussée":{surface:"paved",widthM:5.5},"Rond-point":{surface:"paved",widthM:6},Bretelle:{surface:"paved",widthM:5},"Route empierrée":{surface:"gravel",widthM:3.5},Chemin:{surface:"dirt",widthM:3},"Piste cyclable":{surface:"paved",widthM:2.5}};static DEFAULT={surface:"paved",widthM:5};static KINDS={"Type autoroutier":"motorway","Route à 2 chaussées":"dual","Route à 1 chaussée":"road","Rond-point":"roundabout",Bretelle:"slip"};static DIRECTIONS={"Double sens":"both","Sens direct":"forward","Sens inverse":"backward"};platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRoads(e){return(await this.platform.roads(e)).flatMap((i,s)=>bo.wayOf(i,s))}static wayOf(e,t){if(e.geometry.type!=="LineString")return[];const i=e.geometry.coordinates.map(([u,p])=>({lat:p,lng:u}));if(i.length<2)return[];const s=String(e.properties.nature??""),n=bo.BY_NATURE[s]??bo.DEFAULT,r=Number(e.properties.largeur_de_chaussee),a=Number(e.properties.nombre_de_voies),o=Number(e.properties.vitesse_moyenne_vl),c=bo.DIRECTIONS[String(e.properties.sens_de_circulation??"")],h=bo.KINDS[s],d=[e.properties.cpx_toponyme_route_nommee,e.properties.nom_voie_ban_gauche,e.properties.nom_voie_ban_droite].find(u=>typeof u=="string"&&u.length>0);return[{id:String(e.properties.cleabs??`ign-${t}`),...d?{name:d}:{},surface:n.surface,widthM:Number.isFinite(r)&&r>0?r:n.widthM,...e.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...c?{direction:c}:{},...Number.isFinite(o)&&o>0?{speedKmh:o}:{},points:i}]}}class gI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(e){if(bo.covers(e))try{const t=await this.regional.getRoads(e);if(t.length>0)return t}catch{}return this.worldwide.getRoads(e)}}class Vd{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getWater(e){return(await this.platform.waterSurfaces(e)).flatMap((i,s)=>Vd.surfacesOf(i,s))}static surfacesOf(e,t){const{type:i,coordinates:s}=e.geometry,n=i==="Polygon"?[s]:i==="MultiPolygon"?s:[],r=String(e.properties.cleabs??`ign-water-${t}`);return n.flatMap((a,o)=>{const c=a.map(h=>Vd.open(h.map(d=>({lat:d[1],lng:d[0]})))).filter(h=>h.length>=3);return c.length>0?[{id:n.length>1?`${r}-${o}`:r,rings:c}]:[]})}static open(e){const t=e[0],i=e[e.length-1];return e.length>1&&t.lat===i.lat&&t.lng===i.lng?e.slice(0,-1):e}}class il{attribution="Water © OpenStreetMap contributors";client;constructor(e={}){this.client=new Fn(e)}async getWater(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:30];(way["natural"="water"](${t});way["waterway"="riverbank"](${t});)->.w;(relation["natural"="water"](${t});relation["waterway"="riverbank"](${t});)->.r;.w out geom;.r out body;way(r.r)(${t});out geom;`;return il.surfacesFrom(await this.client.query(i))}static surfacesFrom(e){const t=e.elements??[],i=new Map;for(const r of t)r.type==="way"&&r.id!==void 0&&r.geometry&&i.set(r.id,r.geometry.map(a=>({lat:a.lat,lng:a.lon})));const s=[],n=new Set;for(const r of t){if(r.type!=="relation")continue;const a=c=>(r.members??[]).filter(h=>h.type==="way"&&h.role===c&&h.ref!==void 0&&i.has(h.ref)).map(h=>(n.add(h.ref),i.get(h.ref))),o=il.rings(a("inner"));for(const[c,h]of il.rings(a("outer")).entries()){const d=o.filter(u=>il.contains(h,u[0]));s.push({id:`osm-r${r.id}-${c}`,rings:[h,...d]})}}for(const r of t)if(!(r.type!=="way"||!r.tags||r.id===void 0||n.has(r.id))&&!(r.tags.natural!=="water"&&r.tags.waterway!=="riverbank"))for(const a of il.rings([i.get(r.id)??[]]))s.push({id:`osm-w${r.id}`,rings:[a]});return s}static rings(e){const t=(n,r)=>n.lat===r.lat&&n.lng===r.lng,i=e.filter(n=>n.length>=2).map(n=>[...n]),s=[];for(;i.length>0;){let n=i.pop(),r=!0;for(;!t(n[0],n[n.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const o=i[a],c=n[n.length-1];if(t(c,o[0]))n=[...n,...o.slice(1)];else if(t(c,o[o.length-1]))n=[...n,...[...o].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}n.length>=4&&t(n[0],n[n.length-1])&&s.push(n.slice(0,-1))}return s}static contains(e,t){let i=!1;for(let s=0,n=e.length-1;s<e.length;n=s++){const r=e[s],a=e[n];r.lat>t.lat!=a.lat>t.lat&&t.lng<(a.lng-r.lng)*(t.lat-r.lat)/(a.lat-r.lat)+r.lng&&(i=!i)}return i}}class vI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(e){if(Vd.covers(e))try{const t=await this.regional.getWater(e);if(t.length>0)return t}catch{}return this.worldwide.getWater(e)}}const zm="https://ufoathome.org/water/index.json";class Uc{attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Uc.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Water © OpenStreetMap contributors"}async getWater(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getWater(e);return this.attributionRead=this.fallback.attribution,i}async held(e){const i=(await this.load().catch(()=>[])).find(({entry:s})=>s.north>=e.north&&s.south<=e.south&&s.east>=e.east&&s.west<=e.west);if(i)try{const s=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!s.ok)return;const n=await s.json();return Array.isArray(n?.surfaces)?(this.attributionRead=n.attribution,n.surfaces):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const e=this.indexUrls.join(`
4252
+ `);let t=Uc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Uc.shared.set(e,t),t.then(i=>{i.length===0&&Uc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.1")}`,t=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(t&&t!==zm?[t,zm]:[zm]).map(i=>i+e)}}class Ln{constructor(e){this.water=e}static CACHE_NAME="rr0-water";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static asked=new Map;get attribution(){return this.water.attribution}async getWater(e){const t=Ln.key(e);let i=Ln.asked.get(t);return i===void 0&&(i=this.recalled(t,e),Ln.asked.set(t,i),i.catch(()=>Ln.asked.delete(t))),structuredClone(await i)}static forget(){Ln.asked.clear()}static key(e){return`v${Ln.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}async recalled(e,t){const i=await Ln.openCache(),s=Ln.request(e);if(i)try{const r=await i.match(s);if(r){const{savedAt:a,surfaces:o}=await r.json();if(Date.now()-a<Ln.MAX_AGE_MS&&Array.isArray(o))return o;await i.delete(s)}}catch{}const n=await this.water.getWater(t);return i&&Ln.store(i,s,n),n}static async store(e,t,i){try{const s={savedAt:Date.now(),surfaces:i};await e.put(t,new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}}));const n=await e.keys();for(const r of n.slice(0,Math.max(0,n.length-Ln.MAX_STORED)))await e.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Ln.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__water__/${encodeURIComponent(e)}`)}}class yo{attribution="Railways © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Voie ferrée principale":{kind:"rail"},LGV:{kind:"rail",highSpeed:!0},"Voie de service":{kind:"rail",service:!0},Métro:{kind:"subway"},Tramway:{kind:"tram"},"Transport urbain":{kind:"light_rail"},"Funiculaire ou crémaillère":{kind:"funicular"}};static GAUGE_MM={Normale:1435,Etroite:1e3,Étroite:1e3,Large:1668};static NO_ALTITUDE=-1e3;platform;constructor(e={}){this.platform=new Ft(e)}static covers(e){return Ft.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRailways(e){return(await this.platform.railways(e)).flatMap((i,s)=>yo.linesOf(i,s))}static linesOf(e,t){const{type:i,coordinates:s}=e.geometry,n=i==="LineString"?[s]:i==="MultiLineString"?s:[],r=yo.BY_NATURE[String(e.properties.nature??"")];if(!r)return[];const a=String(e.properties.cleabs??`ign-rail-${t}`),o=Number(e.properties.nombre_de_voies),c=Number(e.properties.position_par_rapport_au_sol),h=e.properties.cpx_toponyme,d=yo.GAUGE_MM[String(e.properties.largeur??"")]??1435,u=yo.electrificationOf(r.kind,d,e.properties.electrifie);return n.flatMap((p,f)=>{const m=p.map(g=>({lat:g[1],lng:g[0],...g.length>2&&Number.isFinite(g[2])&&g[2]>yo.NO_ALTITUDE?{altitudeM:g[2]}:{}}));return m.length<2?[]:[{id:n.length>1?`${a}-${f}`:a,...typeof h=="string"&&h.length>0?{name:h}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:d,tracks:Number.isInteger(o)&&o>0?o:1,...u?{electrification:u}:{},level:Number.isFinite(c)?c:0,points:m}]})}static electrificationOf(e,t,i){if(i===!1)return"none";if(i===!0){if(e==="subway")return"third_rail";if(!(e==="funicular"||t<1435))return"overhead"}}}class zs{static NEAR_M=15;static ALIGNED_DEG=30;static SAMPLE_M=10;static ROUTES="train|subway|light_rail|tram|monorail";static KINDS="rail|light_rail|subway|tram|narrow_gauge|funicular|preserved";client;constructor(e={}){this.client=new Fn(e)}async named(e,t){if(e.length===0)return[...e];const i=`${t.south},${t.west},${t.north},${t.east}`,s=`[out:json][timeout:120];way["railway"~"^(${zs.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${zs.ROUTES})$"];out body;`;return zs.apply(e,await this.client.query(s),t)}static apply(e,t,i){const s={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},n=zs.ways(t,s);return n.length===0?[...e]:e.map(r=>{const a=r.points.map(v=>ot(v.lat,v.lng,s.lat,s.lng)),o=new Map,c=new Map,h=new Map;let d=0;const u=n.filter(v=>v.service===!!r.service);for(const v of zs.samples(a)){d++;const b=zs.waysAt(u,v);if(b.length===0)continue;const[w]=b;w.name&&o.set(w.name,(o.get(w.name)??0)+1),w.voltageV&&c.set(w.voltageV,(c.get(w.voltageV)??0)+1);for(const y of new Set(b.flatMap(M=>M.services)))h.set(y,(h.get(y)??0)+1)}const p=v=>[...v.entries()].sort((b,w)=>w[1]-b[1])[0]?.[0],f=r.name??p(o),m=r.voltageV??(r.electrification==="none"?void 0:p(c)),g=[...h.entries()].filter(([,v])=>v*4>=d).sort((v,b)=>b[1]-v[1]||v[0].localeCompare(b[0])).map(([v])=>v);return{...r,...f?{name:f}:{},...m?{voltageV:m}:{},...g.length>0?{services:g}:{}}})}static serviceOf(e){const t=e.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return t||[e.network,e.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(e){const t=new Map;for(const i of e.elements??[]){if(i.type!=="relation"||!i.tags)continue;const s=zs.serviceOf(i.tags);if(s)for(const n of i.members??[]){if(n.type!=="way"||n.ref===void 0)continue;const r=t.get(n.ref)??new Set;r.add(s),t.set(n.ref,r)}}return t}static voltageOf(e){const t=Number.parseInt((e.voltage??"").split(";")[0],10);return Number.isFinite(t)&&t>0?t:void 0}static ways(e,t){const i=zs.servicesByWay(e),s=[];for(const n of e.elements??[]){if(n.type!=="way"||!n.geometry||n.geometry.length<2)continue;const r=n.tags??{},a=zs.voltageOf(r);s.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(n.id??-1)??[]],path:n.geometry.map(o=>ot(o.lat,o.lon,t.lat,t.lng))})}return s}static samples(e){const t=[];for(let i=0;i<e.length-1;i++){const s=Math.hypot(e[i+1].x-e[i].x,e[i+1].z-e[i].z);if(s<1e-6)continue;const n=(e[i+1].x-e[i].x)/s,r=(e[i+1].z-e[i].z)/s;for(let a=zs.SAMPLE_M/2;a<s;a+=zs.SAMPLE_M)t.push({x:e[i].x+n*a,z:e[i].z+r*a,dx:n,dz:r})}return t}static waysAt(e,t){const i=Math.cos(zs.ALIGNED_DEG*Math.PI/180),s=[];for(const n of e){let r;for(let a=0;a<n.path.length-1;a++){const o=n.path[a],c=n.path[a+1],h=c.x-o.x,d=c.z-o.z,u=Math.hypot(h,d);if(u<1e-6||Math.abs((h*t.dx+d*t.dz)/u)<i)continue;const p=Math.max(0,Math.min(1,((t.x-o.x)*h+(t.z-o.z)*d)/(u*u))),f=Math.hypot(t.x-(o.x+h*p),t.z-(o.z+d*p));f<=zs.NEAR_M&&(r===void 0||f<r)&&(r=f)}r!==void 0&&s.push({way:n,distance:r})}return s.sort((n,r)=>n.distance-r.distance).map(({way:n})=>n)}}class zc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(e={}){this.client=new Fn(e)}async getRailways(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:25];way["railway"~"^(${zc.KINDS.join("|")})$"](${t})->.w;.w out tags geom;rel(bw.w)["route"~"^(${zs.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(e){const t=[],i=zs.servicesByWay(e);for(const s of e.elements??[]){const n=s.geometry,r=s.tags;if(s.type==="relation"||!r||!n||n.length<2)continue;const a=[...i.get(s.id??-1)??[]].sort(),o=zs.voltageOf(r),c=zc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),d=Number.parseInt(r.tracks??"",10),u=zc.electrificationOf(r.electrified),p=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;t.push({id:`osm-rail-${s.id??t.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...o?{voltageV:o}:{},kind:c,...r.service||r.usage==="industrial"?{service:!0}:{},...p?{highSpeed:!0}:{},gaugeMm:Number.isFinite(h)&&h>300?h:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(d)&&d>0?d:1,...u?{electrification:u}:{},level:zc.levelOf(r),points:n.map(f=>({lat:f.lat,lng:f.lon}))})}return t}static kindOf(e){switch(e.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(e){if(e!==void 0){if(e==="no")return"none";if(e==="contact_line"||e==="yes")return"overhead";if(e==="rail"||e==="4th_rail"||e==="ground-level_power_supply")return"third_rail"}}static levelOf(e){const t=Number.parseInt(e.layer??"",10);return e.tunnel&&e.tunnel!=="no"?Number.isFinite(t)&&t<0?t:-1:e.covered==="yes"&&e.location==="underground"?-1:e.bridge&&e.bridge!=="no"?Number.isFinite(t)&&t>0?t:1:0}}class bI{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(e){if(!yo.covers(e))return this.worldwide.getRailways(e);let t;try{if(t=await this.regional.getRailways(e),t.length>0)return t}catch{}try{return await this.worldwide.getRailways(e)}catch(i){if(t)return t;throw i}}}class vs{constructor(e,t=Date.now){this.railways=e,this.now=t}static CACHE_NAME="rr0-railways";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static RETRY_AFTER_MS=300*1e3;static asked=new Map;static failedAt=-1/0;get attribution(){return this.railways.attribution}get contemporary(){return this.railways.contemporary}async getRailways(e){const t=vs.key(e);let i=vs.asked.get(t)??vs.containing(e);if(i===void 0){const s=this.recalled(t,e);i={bounds:e,answer:s},vs.asked.set(t,i),s.catch(()=>vs.asked.delete(t))}return structuredClone(await i.answer)}static forget(){vs.asked.clear(),vs.failedAt=-1/0}static key(e){return`v${vs.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}static containing(e){for(const t of vs.asked.values()){const i=t.bounds;if(i.north>=e.north&&i.south<=e.south&&i.east>=e.east&&i.west<=e.west)return t}}async recalled(e,t){const i=await vs.openCache(),s=vs.request(e);let n;if(i)try{const a=await i.match(s);if(a){const{savedAt:o,lines:c}=await a.json();if(Array.isArray(c)){if(this.now()-o<vs.MAX_AGE_MS)return c;n=c}}}catch{}if(this.now()-vs.failedAt<vs.RETRY_AFTER_MS){if(n)return n;throw new Error("The railway survey failed a moment ago: not asked again yet")}let r;try{r=await this.railways.getRailways(t)}catch(a){if(vs.failedAt=this.now(),n)return n;throw a}return i&&vs.store(i,s,{savedAt:this.now(),lines:r}),r}static async store(e,t,i){try{await e.delete(t),await e.put(t,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const s=await e.keys();for(const n of s.slice(0,Math.max(0,s.length-vs.MAX_STORED)))await e.delete(n)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(vs.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__railways__/${encodeURIComponent(e)}`)}}const Bm="https://ufoathome.org/railways/index.json";class Bc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Bc.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getRailways(e);return this.attributionRead=this.fallback.attribution,i}async held(e){const i=(await this.load().catch(()=>[])).find(({entry:s})=>s.north>=e.north&&s.south<=e.south&&s.east>=e.east&&s.west<=e.west);if(i)try{const s=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!s.ok)return;const n=await s.json();return Array.isArray(n?.lines)?(this.attributionRead=n.attribution,n.lines):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const e=this.indexUrls.join(`
4253
+ `);let t=Bc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Bc.shared.set(e,t),t.then(i=>{i.length===0&&Bc.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(s=>({entry:s,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.152.1")}`,t=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(t&&t!==Bm?[t,Bm]:[Bm]).map(i=>i+e)}}function F2(){return{elevation:U2(),imagery:z2(),roads:B2(),water:H2(),railways:G2()}}function U2(){return new pI(new Ot,new O2)}function z2(){return new N2}function B2(){return new Fc({fallback:new gI(new bo,new fo)})}function H2(){return new Uc({fallback:new Ln(new vI(new Vd,new il))})}function G2(){return new Bc({fallback:new vs(new bI(new yo,new zc))})}const yI=new Set,sh="show-observer-map",nh="hide-milestones",Sl="minified";class Vt extends HTMLElement{static get observedAttributes(){return["src",sh,nh,Sl]}shadow;stageElement;canvas;canvasRenderer;chromeCanvas;chromeRenderer;chromeResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>{this.chromeDirty&&this.refresh()});chromeDirty=!1;tooltip;toolbar;issuesBox;issuesButton;issuesPanel;playPauseButton;fullscreenButton;cornerButtons;observerMapButton;referencesButton;tracesButton;tracesShownState=!0;referenceOpacityInput;referencesShownState=!0;accountHidden=!1;referenceViews=new Map;referencesMenu;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;mapZoomInButton;mapZoomOutButton;mapFitButton;observerMapView=new ti;observerMapDrag;suppressObserverMapClick=!1;observerMapImageryTimer;observerPlacing=!1;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;timePill;muteButton;volumeInput;controlsRow;momentsBox;momentsButton;momentsCurrent;momentsMenu;moreButton;controlsRight;seekSegments;seekDot;playerTitleBox;seekPreview;seekPreviewCanvas;seekPreviewTitle;seekPreviewTime;observerPath;observerMapBounds;observerMapImagery;observerMapImageryBounds;observerMapImageryViewWidth=0;observerMapImageryLoading=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=dm.create();issues=[];issueCheck=0;sightingAudio=new eI;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;static LIVE_BODY_MAX_RATE=2;get steadyBody(){return this.steadyObserver||this.player.playbackState!=="playing"||this.player.playbackRate>Vt.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=A2;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const e=this.controlsRow,t=e.classList.contains("more-open"),i=()=>e.scrollWidth>e.clientWidth+1,s=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,e.classList.remove("narrow","more-open","nomoments","compact","tiny"),e.clientWidth>0&&i()){e.classList.add("narrow");for(const n of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(n)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!s,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");Vt.setIcon(this.moreButton,e?et.UNFOLDED:et.FOLDED);const t=e?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=t,this.moreButton.setAttribute("aria-label",t),this.moreButton.setAttribute("aria-expanded",String(e))}addControl(e){this.controlsRight.insertBefore(e,this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null),this.fitControls()}observerMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeObserverMap());resizeObserverMap(){this.observerMapPanel.hidden||(this.sizeObserverMapCanvas(),this.paintObserverMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),i=t&&this.shapeAt(t.x,t.y),s=this.said.read(i?.shape.title);if(!s){this.tooltip.hidden=!0;return}this.tooltip.textContent=s,this.tooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-n.left+12}px`,this.tooltip.style.top=`${e.clientY-n.top+12}px`};handleObserverMapPointerMove=e=>{if(this.dragObserverMap(e))return;const t=this.observerMapTargetFrom(e);if(!t){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(e,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(e,t.label)};showObserverMapTooltip(e,t){this.tooltip.textContent=t,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-i.left+12}px`,this.tooltip.style.top=`${e.clientY-i.top+12}px`}handleObserverMapClick=e=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const t=this.observerMapTargetFrom(e);if(!t){this.observerPlacing&&this.placeObserverFrom(e);return}if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(e){const t=this.observerMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.observerMapRenderer.hitTest((e.clientX-t.left)/t.width*this.observerMapCanvas.width,(e.clientY-t.top)/t.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=e=>{e.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,moved:!1})};handleObserverMapPointerUp=e=>{const t=this.observerMapDrag;!t||t.pointerId!==e.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),t.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(e.pointerId)&&this.observerMapCanvas.releasePointerCapture(e.pointerId)))};dragObserverMap(e){const t=this.observerMapDrag;if(!t||t.pointerId!==e.pointerId)return!1;if(!t.moved){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<Vt.OBSERVER_MAP_DRAG_PX)return!1;t.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(e.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((e.clientX-t.lastX)/i.width,(e.clientY-t.lastY)/i.height),this.observerMapViewChanged()),t.lastX=e.clientX,t.lastY=e.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=e=>{e.preventDefault();const t=this.observerMapCanvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=e.deltaMode===0?e.deltaY:e.deltaY*40;this.zoomObserverMap((e.clientX-t.left)/t.width,(e.clientY-t.top)/t.height,Math.exp(-i*.002))};zoomObserverMap(e,t,i){this.observerMapView.zoomAt(e,t,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=ti.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=ti.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Vt.OBSERVER_MAP_IMAGERY_DELAY_MS))}static OBSERVER_MAP_FOLLOW_MARGIN=.1;static OBSERVER_MAP_IMAGERY_DELAY_MS=300;get observerMapViewBounds(){return this.observerMapBounds&&this.observerMapView.boundsWithin(this.observerMapBounds)}placeObserverFrom(e){const t=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!t||i.width===0||i.height===0)return;const s=ti.pointAt(t,(e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:s,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${j3}</style>${q3}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new yh(this.canvas.getContext("2d")),this.chromeCanvas=this.shadow.getElementById("chrome"),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.issuesBox=this.shadow.getElementById("issues"),this.issuesButton=this.shadow.getElementById("issues-button"),this.issuesPanel=this.shadow.getElementById("issues-panel"),this.issuesButton.addEventListener("click",a=>{a.stopPropagation(),this.issuesPanel.hidden=!this.issuesPanel.hidden,this.issuesButton.setAttribute("aria-expanded",String(!this.issuesPanel.hidden))}),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.tracesButton=this.shadow.getElementById("traces"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.referencesMenu=this.shadow.getElementById("references-menu"),this.milestonesButton=this.shadow.getElementById("milestones"),this.observerMapPanel=this.shadow.getElementById("observer-map-panel"),this.observerMapCanvas=this.shadow.getElementById("observer-map-canvas"),this.observerMapRenderer=new tl(this.observerMapCanvas.getContext("2d")),this.mapZoomInButton=this.shadow.getElementById("map-zoom-in"),this.mapZoomOutButton=this.shadow.getElementById("map-zoom-out"),this.mapFitButton=this.shadow.getElementById("map-fit"),this.seekInput=this.shadow.getElementById("seek"),this.playbackFlash=this.shadow.getElementById("playback-flash"),this.milestoneMarks=this.shadow.getElementById("milestone-marks"),this.milestoneCaption=this.shadow.getElementById("milestone-caption"),this.timeStartLabel=this.shadow.getElementById("time-start"),this.timeEndLabel=this.shadow.getElementById("time-end"),this.timePill=this.shadow.getElementById("time"),this.muteButton=this.shadow.getElementById("mute"),this.controlsRight=this.shadow.getElementById("controls-right"),this.seekSegments=this.shadow.getElementById("seek-segments"),this.seekDot=this.shadow.getElementById("seek-dot"),this.playerTitleBox=this.shadow.getElementById("player-title"),this.seekPreview=this.shadow.getElementById("seek-preview"),this.seekPreviewCanvas=this.shadow.getElementById("seek-preview-canvas"),this.seekPreviewTitle=this.shadow.getElementById("seek-preview-title"),this.seekPreviewTime=this.shadow.getElementById("seek-preview-time"),this.timePill.addEventListener("click",()=>this.toggleTimeDisplay()),this.timePill.addEventListener("keydown",a=>{a.key!=="Enter"&&a.key!==" "||(a.preventDefault(),this.toggleTimeDisplay())}),this.volumeInput=this.shadow.getElementById("volume"),this.controlsRow=this.shadow.querySelector(".controls"),this.momentsBox=this.shadow.getElementById("moments"),this.momentsButton=this.shadow.getElementById("moments-button"),this.momentsCurrent=this.shadow.getElementById("moments-current"),this.momentsMenu=this.shadow.getElementById("moments-menu"),this.momentsButton.addEventListener("click",()=>this.toggleMomentsMenu()),this.moreButton=this.shadow.getElementById("controls-more"),this.moreButton.addEventListener("click",()=>this.setControlsFolded(this.controlsRow.classList.contains("more-open"))),this.muteButton.addEventListener("click",()=>this.toggleMuted()),this.miniPlayed=this.shadow.getElementById("mini-played"),this.miniRemaining=this.shadow.getElementById("mini-remaining"),this.miniMuteButton=this.shadow.getElementById("mini-mute"),this.miniDot=this.shadow.getElementById("mini-dot"),this.miniScrubTime=this.shadow.getElementById("mini-scrub-time");const t=this.shadow.getElementById("mini-bar"),i=t.querySelector(".mini-track"),s=a=>{const o=i.getBoundingClientRect(),c=this.player.seekableDuration;if(o.width<=0||c<=0)return;const h=Math.min(Math.max((a.clientX-o.left)/o.width,0),1)*c;this.player.seek(h),this.miniScrubTime.textContent=this.formatElapsedAt(h),this.miniScrubTime.style.left=this.miniDot.style.left};let n=!1;t.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),t.setPointerCapture(a.pointerId),t.classList.add("scrubbing"),n=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,s(a))}),t.addEventListener("pointermove",a=>{t.hasPointerCapture(a.pointerId)&&s(a)});const r=a=>{t.classList.contains("scrubbing")&&(t.classList.remove("scrubbing"),t.hasPointerCapture(a.pointerId)&&t.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,n&&this.play())};t.addEventListener("pointerup",r),t.addEventListener("pointercancel",r),t.addEventListener("click",a=>a.stopPropagation()),this.miniMuteButton.addEventListener("click",a=>{a.stopPropagation(),this.toggleMuted()}),this.stageElement.addEventListener("pointerenter",this.handleMinifiedEnter),this.stageElement.addEventListener("pointerleave",this.handleMinifiedLeave),this.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>{this.player.seek(this.snapSeekToMark(Number(this.seekInput.value))),this.announceReveal()}),this.seekInput.addEventListener("pointerdown",a=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(a),this.beginTouchScrub(a)}),this.seekInput.addEventListener("pointerup",a=>{this.seekSnapArmed=!1,this.endTouchScrub(a)}),this.seekInput.addEventListener("pointercancel",a=>this.endTouchScrub(a)),this.seekInput.addEventListener("pointermove",a=>{this.nameMarkUnder(a),this.hoverSeek(a),this.touchScrub(a)}),this.seekInput.addEventListener("pointerleave",()=>{this.seekInput.removeAttribute("title"),this.leaveSeek()}),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.stageElement.addEventListener("pointerdown",()=>{this.handlePointerDown(),this.touchedStage()},!0);for(const a of["touchend","click"])this.stageElement.addEventListener(a,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",a=>{if(!(!this.enableClickToPlay||this.minified)){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}a.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",a=>{!this.enableClickToPlay||this.minified||(a.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),document.addEventListener("pointerdown",this.handleMomentsDismiss,!0),document.addEventListener("keydown",this.handleMomentsDismiss,!0),document.addEventListener("visibilitychange",this.handleVisibility),window.addEventListener("pagehide",this.handleHidden),document.addEventListener("pointerup",this.handlePointerRelease,!0),document.addEventListener("pointercancel",this.handlePointerRelease,!0),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.chromeResizeObserver?.observe(this.chromeCanvas),this.controlsFitObserver?.observe(this.controlsRow),this.controlsFitObserver?.observe(this.controlsRow.querySelector(".controls-left")),typeof MutationObserver<"u"&&(this.controlsMutations=new MutationObserver(()=>this.fitControls()),this.controlsMutations.observe(this.controlsRight,{attributes:!0,attributeFilter:["hidden"],childList:!0,subtree:!0})),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.refresh()}connectedCallback(){this.saidTexts=void 0,this.loadLocaleMessages();const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),document.removeEventListener("pointerdown",this.handleMomentsDismiss,!0),document.removeEventListener("keydown",this.handleMomentsDismiss,!0),document.removeEventListener("visibilitychange",this.handleVisibility),window.removeEventListener("pagehide",this.handleHidden),document.removeEventListener("pointerup",this.handlePointerRelease,!0),document.removeEventListener("pointercancel",this.handlePointerRelease,!0),window.clearTimeout(this.controlsIdleTimer),this.observerMapResizeObserver?.disconnect(),this.chromeResizeObserver?.disconnect(),this.controlsFitObserver?.disconnect(),this.controlsMutations?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(e,t,i){if(e==="src"&&i&&i!==t&&this.isConnected&&this.loadFromSrc(i),e===sh&&this.applyObserverMapDefault(),e===nh&&this.setMilestonesShown(!this.hasAttribute(nh)),e===Sl){const s=this.minified;this.stageElement.classList.toggle("minified",s),s&&t===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(Sl)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=e=>{!this.minified||e.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=e=>{!this.minified||e.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(V2)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const e=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",e),e&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(e){this.sightingData=await Ur.recording(e)}get sightingData(){return xf(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=bb(e),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(e,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.started=!1,this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault(),this.minified&&this.minifiedHovered&&this.play()}set playerTitle(e){this.titleOverride=e,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const e=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=e,this.playerTitleBox.hidden=e===""}get recordingIssues(){return this.issues}async reportIssues(e,t){const i=++this.issueCheck;let s=[];try{const{default:n}=await ae(async()=>{const{default:r}=await import("./sightingSchema-Bc1JhWrZ.js");return{default:r}},[],import.meta.url);s=new Ar(n).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...s,...t.loadIssues],wh.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(wI,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const e=this.issues.length;this.issuesBox.hidden=e===0,this.shadow.getElementById("issues-count").textContent=String(e);const t=this.messages.recordingIssues.replace("{count}",String(e));this.issuesButton.title=t,this.issuesButton.setAttribute("aria-label",t),this.shadow.getElementById("issues-title").textContent=t,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const s=document.createElement("li");return s.textContent=wh.text(i,this.messages.issueTemplates),s}))}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){if(!(this.player.seekableDuration<=0||this.playbackState==="playing")){if(this.clockHeld){this.playAfterHold=!0,this.announcePlayRequest();return}this.togglePlayPause()}}get playRequested(){return this.playbackState==="playing"||this.playAfterHold}announcePlayRequest(){this.announceReveal(),this.dispatchEvent(new CustomEvent("playrequest"))}announceReveal(){this.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("revealrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(e){if(e!==this.clockHeld){if(this.clockHeld=e,e){if(this.playbackState!=="playing")return;this.playAfterHold=!0,this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton();return}this.playAfterHold&&(this.playAfterHold=!1,!(this.player.seekableDuration<=0||this.playbackState==="playing")&&(this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton()))}}pause(){this.playAfterHold=!1,this.playbackState==="playing"&&this.togglePlayPause()}get positionLabel(){return this.timeStartLabel.textContent??""}get durationLabel(){return this.timeEndLabel.textContent??""}get showingClockTime(){return this.canShowClockTime}get canSwitchTimeDisplay(){return this.realStartMs!==void 0}toggleTimeDisplay(){this.canSwitchTimeDisplay&&(this.showClockTime=!this.showClockTime,this.updateTimeLabels(),this.updateTimeLabelTitles(),this.dispatchEvent(new CustomEvent("timedisplaychange",{bubbles:!0,composed:!0})))}get canShowClockTime(){return this.realStartMs!==void 0&&this.showClockTime}set showToolbar(e){this.toolbar.classList.toggle("hidden",!e),e?this.controlsRight.appendChild(this.fullscreenButton):this.cornerButtons.appendChild(this.fullscreenButton)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(s=>this.highlightedSourceIds.has(s))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==void 0}refresh(){this.applyFrameFormat(),this.updateMuteButton(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.updateTracesButton(),this.player.seek(this.player.time)}repaintOverlay(){this.quietFrame=!0;try{this.player.seek(this.player.time)}finally{this.quietFrame=!1}}quietFrame=!1;hostControls(e){const t=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(e)for(const i of t)e.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const s of t)this.controlsRight.insertBefore(s,i)}}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}get severalReferences(){return this.currentSighting.references.length>1}toggleReferences(){if(this.severalReferences){this.toggleReferencesMenu();return}this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity));for(const t of[...this.referenceViews.keys()])e.some(i=>i.id===t)||this.referenceViews.delete(t);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(e){let t=this.referenceViews.get(e.id);return t||(t={shown:!0,opacity:e.opacity},this.referenceViews.set(e.id,t)),t}toggleReferencesMenu(){this.referencesMenu.hidden?this.openReferencesMenu():this.closeReferencesMenu()}openReferencesMenu(){this.renderReferencesMenu(),this.referencesMenu.hidden=!1,this.placeReferencesMenu(),this.referencesButton.setAttribute("aria-expanded","true"),document.addEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.addEventListener("keydown",this.handleReferencesMenuKey,!0)}closeReferencesMenu(){this.referencesMenu.hidden||(this.referencesMenu.hidden=!0,this.referencesButton.setAttribute("aria-expanded","false"),document.removeEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.removeEventListener("keydown",this.handleReferencesMenuKey,!0))}handleReferencesMenuOutside=e=>{const t=e.composedPath();t.includes(this.referencesMenu)||t.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=e=>{e.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const e=this.referencesButton.getBoundingClientRect(),t=this.referencesMenu,i=4;t.style.bottom=`${Math.max(i,window.innerHeight-e.top+i)}px`,t.style.top="auto";const s=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-s-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),s=this.said.read(t.title)??t.id,n=document.createElement("div");n.className="reference-row";const r=document.createElement("label"),a=document.createElement("input");a.type="checkbox",a.checked=i.shown;const o=document.createElement("span");o.textContent=s,o.title=s,r.append(a,o);const c=document.createElement("input");return c.type="range",c.min="0",c.max="1",c.step="0.05",c.value=String(i.opacity),c.title=this.messages.referenceOpacity,c.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${s}`),c.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,c.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),c.addEventListener("input",()=>{i.opacity=Number(c.value),this.dispatchReferenceView()}),n.append(r,c),n});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...e)}updateReferencesButton(){const e=this.currentSighting.references.length>0,t=this.severalReferences,i=t?this.currentSighting.references.some(n=>this.viewOfReference(n).shown):this.referencesShownState;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState||t,this.referencesButton.setAttribute("aria-pressed",String(i)),t?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Vt.setIcon(this.referencesButton,i?et.PICTURES_ON:et.PICTURES_OFF);const s=t?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=s,this.referencesButton.setAttribute("aria-label",s),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}get tracesShown(){return this.tracesShownState}toggleTraces(){this.tracesShownState=!this.tracesShownState,this.updateTracesButton(),this.updateObserverMap(),this.dispatchEvent(new CustomEvent("traceview",{detail:{shown:this.tracesShown}}))}updateTracesButton(){this.tracesButton.hidden=this.currentSighting.traces.length===0,this.tracesButton.setAttribute("aria-pressed",String(this.tracesShownState)),Vt.setIcon(this.tracesButton,this.tracesShownState?et.TRACES_ON:et.TRACES_OFF);const e=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=e,this.tracesButton.setAttribute("aria-label",e)}dispatchReferenceView(){const e=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(t=>[t.id,{...this.viewOfReference(t)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:e}}))}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Ol(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const s=document.createElement("button");s.type="button",s.className="milestone-mark",s.style.left=`${Math.min(Math.max(i.t/e,0),1)*100}%`;const n=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${n} — ${r}`:n;return s.title=a,s.setAttribute("aria-label",a),s.dataset.t=String(i.t),s.addEventListener("click",()=>this.player.seek(i.t)),s})),this.refreshSeekSegments(e,t.map(i=>i.t)),this.refreshMomentsPicker(t)}refreshMomentsPicker(e){const t=this.milestonesShown&&e.length>0;this.momentsBox.hidden=!t,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...e.map(i=>{const s=document.createElement("li"),n=document.createElement("button");n.type="button",n.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return n.textContent=a?`${r} — ${a}`:r,n.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),s.appendChild(n),s})),this.momentsButton.title=this.messages.moments,this.showCurrentMoment(void 0)}showCurrentMoment(e){const i=(e?this.said.read(e.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const s of this.momentsMenu.querySelectorAll("button")){const n=e!==void 0&&Number(s.dataset.t)===e.t;s.getAttribute("aria-current")==="true"!==n&&s.setAttribute("aria-current",String(n))}}toggleMomentsMenu(){this.momentsMenu.hidden?(this.momentsMenu.hidden=!1,this.momentsButton.setAttribute("aria-expanded","true")):this.closeMomentsMenu()}closeMomentsMenu(){this.momentsMenu.hidden=!0,this.momentsButton.setAttribute("aria-expanded","false")}handleMomentsDismiss=e=>{if(!this.momentsMenu.hidden){if(e instanceof KeyboardEvent){e.key==="Escape"&&this.closeMomentsMenu();return}e.composedPath().some(t=>t===this.momentsMenu||t===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(e,t){const s=[0,...this.milestonesShown&&e>0?[...new Set(t.filter(r=>r>0&&r<e))].sort((r,a)=>r-a):[],Math.max(e,0)];this.seekSegmentList=[];const n=[];for(let r=0;r<s.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(s[r+1]-s[r],1));const o=document.createElement("i");o.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(o,c),n.push(a),this.seekSegmentList.push({start:s[r],end:s[r+1],element:a,played:c,hover:o})}this.seekSegments.replaceChildren(...n),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,s=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(s,0),1)*100}%`}paintMiniProgress(e){const t=this.player.seekableDuration,i=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(e)}miniDot;miniScrubTime;paintSeekProgress(e){for(const i of this.seekSegmentList)i.played.style.width=Vt.fillOf(i,e);const t=this.player.seekableDuration;this.seekDot.style.left=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`}hoverSeek(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),n=s*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=Vt.fillOf(p,n),p.element.classList.toggle("hovered",n>=p.start&&(n<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],o=a.length>0?Nm(a,n):void 0,c=o?this.said.read(o.label)??"":"",h=o?this.said.read(o.note):void 0,d=h?`${c} — ${h}`:c;this.seekPreviewTitle.textContent=d,this.seekPreviewTime.textContent=this.formatPosition(n),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(s*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(n)}leaveSeek(){for(const e of this.seekSegmentList)e.hover.style.width="0",e.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(e){const t=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=t===void 0,t?.(e,this.seekPreviewCanvas)}paintChrome(e){const t=this.chromeCanvas.getContext("2d"),i=this.overlayPainter!==void 0||this.selectionShown;if(!i&&!this.chromeDirty)return;const s=this.chromeCanvas.clientWidth,n=this.chromeCanvas.clientHeight;if(!t||typeof t.setTransform!="function"||s===0||n===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(s*r)),o=Math.max(1,Math.round(n*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==o&&(this.chromeCanvas.height=o),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,a,o),this.chromeDirty=!1,i&&(t.setTransform(a/this.canvas.width,0,0,o/this.canvas.height,0,0),this.chromeRenderer??=new yh(t),this.chromeDirty=!0,e(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(e){if(e.pointerType!=="mouse"){this.scrubbingPointer=e.pointerId;try{this.seekInput.setPointerCapture(e.pointerId)}catch{}this.seekToPointer(e)}}touchScrub(e){e.pointerId===this.scrubbingPointer&&this.seekToPointer(e)}endTouchScrub(e){e.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(e))}seekToPointer(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(s*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(t<=0||i<=0)return;const s=Vt.MARK_SNAP_PX/i*t;let n;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>s||(!n||Math.abs(a-e)<Math.abs(n.t-e))&&(n={t:a,name:r.title})}return n}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const s=(e.clientX-t.left)/t.width*i,n=this.markNear(s);n?this.seekInput.title=n.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?Nm(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,this.showCurrentMoment(t),!t)return;const i=document.createElement("b");i.textContent=this.said.read(t.label)??"";const s=this.said.read(t.note),n=s?` — ${s}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(n))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(s=>({shapes:this.shapesAt(s),share:i}))}exposureTimes(e=this.currentTime){const t=Cr.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<Vt.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(Vt.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/Vt.SHORTEST_VISIBLE_EXPOSURE_MS))),s=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/Vt.EXPOSURE_STEP_PX),n=Math.min(Vt.MAX_TRAVEL_STEPS,Math.max(i,s)),r=[];for(let a=0;a<n;a++)r.push(t.fromMs+t.ms*a/(n-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),s=this.shapesAt(e+t);let n=0;for(const[r,a]of i){const o=s.get(r);if(!o)continue;const c=o.bounds.x+o.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=o.bounds.y+o.bounds.height/2-(a.bounds.y+a.bounds.height/2);n=Math.max(n,Math.hypot(c,h))}return n}shapeAt(e,t,i){if(!this.accountHidden)for(const s of this.exposureTimes()){const n=this.currentSighting.timeline.hitTest(s,e,t,i);if(n)return n}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const s=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);s&&t.set(i,s)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Yt.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:yI;this.canvasRenderer.setStarPoints(Yt.starPointsOf(this.sighting.instrument,at(this.sighting,e)?.fNumber));const s=(at(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(s*Math.PI/180);const n=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const o of n)for(const[,c]of o.shapes){const h=o.share,d=h===1?c:{...c,transparency:1-(1-c.transparency)*h};this.canvasRenderer.paintShape(this.shifted(d,r))}for(const[o,c]of n[0].shapes)!this.selectionShown||!i.has(o)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));const a=this.selectionShown&&i.size>1?Kt.groupBoundsFor([...t].filter(([o])=>i.has(o)).map(([,o])=>o.bounds)):void 0;this.chromeDraw=o=>{a&&o.paintGroupHandles(a),this.overlayPainter?.(o)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=n.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(e),this.paintSeekProgress(e),this.minified&&this.paintMiniProgress(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintObserverMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(rb(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new Z3(this.currentSighting.timeline,(t,i)=>this.onFrame(t,i));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=e=>{e.key.toLowerCase()!=="f"||e.altKey||e.ctrlKey||e.metaKey||!this.enableClickToPlay||e.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(e.preventDefault(),this.toggleFullscreen())};handleSeekKey=e=>{if(e.altKey||e.ctrlKey||e.metaKey)return;const t=e.key==="ArrowLeft"?-1:e.key==="ArrowRight"?1:0;if(t){e.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+t*Vt.SEEK_KEY_STEP_MS)))}else e.key===" "&&(e.preventDefault(),this.togglePlayPause())};togglePlayPause(){if(!(this.player.seekableDuration<=0)){if(this.player.playbackState==="playing")this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh();else if(this.clockHeld){this.playAfterHold=!this.playAfterHold,this.playAfterHold&&this.announcePlayRequest();return}else this.announcePlayRequest(),this.sightingAudio.resume(),this.player.play();this.updatePlayPauseButton(),this.flashPlayback()}}flashPlayback(){const e=this.playbackFlash;e.innerHTML=this.player.playbackState==="playing"?et.PLAY:et.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){Vt.icons.get(e)!==t&&(Vt.icons.set(e,t),e.innerHTML=t)}set captionHeld(e){this.stageElement.classList.toggle("caption-held",e)}set controlsHeld(e){this.stageElement.classList.toggle("controls-held",e)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(e){this.quietControlsValue=e,this.stageElement.classList.toggle("quiet",e)}tapRevealedOnly=!1;get hoverless(){return typeof matchMedia=="function"&&matchMedia("(hover: none)").matches}touchedStage(){if(!this.hoverless)return;this.player.playbackState==="playing"&&!this.stageElement.classList.contains("touched")&&(this.tapRevealedOnly=!0),this.revealControls()}pointerHeld=!1;handlePointerDown=()=>{this.pointerHeld=!0};resumeAfterScrub=!1;suspendForScrub(){this.player.playbackState==="playing"&&(this.resumeAfterScrub=!0,this.stopPlaying())}stopPlaying(){this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton()}resumeFromScrub(){this.resumeAfterScrub&&(this.resumeAfterScrub=!1,this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton())}handleHidden=()=>{this.player.playbackState==="playing"&&this.stopPlaying(),this.resumeAfterScrub=!1};handleVisibility=()=>{document.visibilityState==="hidden"&&this.handleHidden()};handlePointerRelease=()=>{this.resumeAfterScrub&&window.setTimeout(()=>this.resumeFromScrub(),0),this.pointerHeld&&(this.pointerHeld=!1,this.hoverless&&this.stageElement.classList.contains("touched")&&this.revealControls())};revealControls(){this.stageElement.classList.add("touched"),window.clearTimeout(this.controlsIdleTimer),this.player.playbackState==="playing"&&(this.pointerHeld||!this.momentsMenu.hidden||(this.controlsIdleTimer=window.setTimeout(()=>{this.stageElement.classList.remove("touched"),this.tapRevealedOnly=!1},Vt.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!e),e!==this.wasPlaying&&e&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=e,this.updateStartState(),Vt.setIcon(this.playPauseButton,e?et.PAUSE:et.PLAY);const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const i=t?e?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=i,this.playPauseButton.setAttribute("aria-label",i)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const e=this.observerMapPanel.hidden;this.observerMapAsked=e,this.setObserverMapOpen(e),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:e}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const e=this.getAttribute(sh),t=e===null?this.sighting.observerMap??this.observerPath?.travels===!0:e!=="false";this.setObserverMapOpen(t&&this.observerPath!==void 0)}setObserverMapOpen(e){this.observerMapPanel.hidden=!e,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(e)),this.updateObserverMapButton(),e&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const e=!this.observerMapPanel.hidden;Vt.setIcon(this.observerMapButton,e?et.MAP_ON:et.MAP_OFF);const t=e?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=t,this.observerMapButton.setAttribute("aria-label",t);const i=[[this.mapZoomInButton,this.messages.zoomMapIn],[this.mapZoomOutButton,this.messages.zoomMapOut],[this.mapFitButton,this.messages.fitMap]];for(const[s,n]of i)s.title=n,s.setAttribute("aria-label",n)}updateObserverMap(){const e=this.observerPath!==void 0;if(this.observerPath=Cl.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!e&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const t=this.tracesShownState?this.currentSighting.traces.flatMap(s=>s.points):[],i=ti.fitted(this.observerPath,t);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,i))&&(this.observerMapBounds&&this.observerMapView.refit(this.observerMapBounds,i),this.observerMapBounds=i,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||this.loadObserverMapImagery())}sameGround(e,t){const i=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<i&&Math.abs(e.south-t.south)<i&&Math.abs(e.west-t.west)<i&&Math.abs(e.east-t.east)<i}async loadObserverMapImagery(){const e=this.observerMapViewBounds;if(!e||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(e)))return;const t=this.observerMapView.changed,i=t?ti.expand(e,Vt.OBSERVER_MAP_IMAGERY_AHEAD):e,s=ti.IMAGERY_PX*(t?1+2*Vt.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const n=this.observerMapFrozenImagery,r=n?void 0:z2();try{const a=r?await r.getImageryTexture(i,{width:s,height:s}):await n.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??n).attribution,this.observerMapImageryFailed=!1}catch{if(this.observerMapImageryBounds!==i)return;this.observerMapImageryFailed=this.observerMapImagery===void 0}finally{this.observerMapImageryBounds===i&&(this.observerMapImageryLoading=!1)}this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}static OBSERVER_MAP_IMAGERY_AHEAD=.5;static OBSERVER_MAP_IMAGERY_LOOKAHEAD=.25;observerMapImageryNeededFor(e){const t=this.observerMapImageryBounds;if(!t)return!0;const i=this.observerMapImagery?.bounds??t,s=this.observerMapView.changed?ti.expand(e,Vt.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,n=s.west>=i.west&&s.east<=i.east&&s.south>=i.south&&s.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!n||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(e){e!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=e,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||(this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime)))}get observerMapFrozen(){return this.observerMapFrozenImagery}observerMapFrozenImagery;observerMapFrozenSource;get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const e=this.observerMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],i=(c,h,d)=>{for(const u of t)if(!(u.x+u.width<c-d||u.x>h+d)&&!(u.y>e.bottom+d||u.y+u.height<e.top-d))return!0;return!1},s=[this.canvas.width-e.width,this.canvas.width],n=[0,e.width],r=Vt.OBSERVER_MAP_CLEARANCE_PX,a=i(...s,0),o=i(...n,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&o&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(o||!i(s[0],s[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(s[0],s[1],0)&&!i(n[0],n[1],0)&&this.observerMapPanel.classList.add("on-the-left")}observerMapBoxPx;static OBSERVER_MAP_CLEARANCE_PX=24;sizeObserverMapCanvas(){const e=this.observerMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==t&&(this.observerMapCanvas.width=t,this.observerMapCanvas.height=t)}measureObserverMapBox(){const e=this.observerMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=this.canvas.width/t.width,s=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*s,bottom:(e.bottom-t.top)*s}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=at(this.currentSighting,e);t?.lat!==void 0&&t.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:t.lat,lng:t.lng},Vt.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,s=[],n=this.currentSighting.milestones.length>0?Nm(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?Ol(this.currentSighting.milestones):[]){const a=at(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||s.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===n})}this.observerMapRenderer.paint({bounds:this.observerMapViewBounds,imagery:this.observerMapImagery,path:this.observerPath,position:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?Bn.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Yt.aspectOf(i)):void 0,markers:s,traces:(this.tracesShownState?this.currentSighting.traces:[]).map(r=>({kind:r.kind,points:r.points,color:r.color,label:this.said.read(r.title)})),decor:this.observerMapDecorAt(e),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.momentsBox.hidden=!e||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,Ol(this.sighting.milestones).map(t=>t.t)),this.milestonesButton.setAttribute("aria-pressed",String(e)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintObserverMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0,this.momentsButton.title=this.messages.moments,Vt.setIcon(this.milestonesButton,this.milestonesShown?et.MILESTONES_ON:et.MILESTONES_OFF);const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}observerMapDecorAt(e){const t=at(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const s=tr(i,e),{lat:n,lng:r}=_n(s.eastM,-s.northM,t.lat,t.lng);return{lat:n,lng:r,headingDeg:s.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.observerMapNightFraction&&(this.observerMapNightFraction=t,this.paintObserverMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,i=this.lookPitchDeg+e.pitchDeg;if(t===0&&i===0)return{x:0,y:0};const s=at(this.currentSighting,this.currentTime),n=Bn.of(this.currentSighting.instrument,this.canvas.height,s?.fovDeg??60);return{x:-n.angleDegToRadiusPx(t),y:n.angleDegToRadiusPx(i)}}gaitAt(e){return ci.bodyAt(this.currentSighting,e,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(e){e!==this.mutedState&&(this.mutedState=e,!e&&this.volumeState===0&&(this.volumeState=Vt.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(e){this.setVolume(e)}setVolume(e){this.volumeState=Math.min(Math.max(e,0),1),this.mutedState=this.volumeState===0,this.applyLevel()}get level(){return this.mutedState?0:this.volumeState}applyLevel(){this.sightingAudio.setLevel(this.level),this.updateMuteButton(),this.dispatchEvent(new CustomEvent("mutedchange",{bubbles:!0,composed:!0,detail:{muted:this.mutedState,volume:this.volumeState}}))}toggleMuted(){this.hasSound&&(this.muted=!this.mutedState)}ambientSound;get hasSound(){return this.currentSighting.soundTrack.allKeyframes.length>0||this.ambientSound?.(this.currentSighting)===!0}updateMuteButton(){const e=!this.hasSound;this.miniMuteButton.hidden=e,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Vt.setIcon(this.miniMuteButton,this.mutedState?et.MUTED:et.VOLUME);const t=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=t,this.miniMuteButton.setAttribute("aria-label",t),this.muteButton.disabled=e,this.volumeInput.hidden=e,e){Vt.setIcon(this.muteButton,et.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Vt.setIcon(this.muteButton,this.mutedState?et.MUTED:et.VOLUME);const i=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=i,this.muteButton.setAttribute("aria-label",i),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Vt.setIcon(this.fullscreenButton,e?et.EXIT_FULLSCREEN:et.ENTER_FULLSCREEN),this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Tn(sr.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=Pd(sr.preferencesFor(this),Od);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await IE(e);this.messagesLanguage===e&&this.applyMessages(t)}messagesLanguage;updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t,this.timePill.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(this.timePill.setAttribute("role","button"),this.timePill.setAttribute("tabindex","0")):(this.timePill.removeAttribute("role"),this.timePill.removeAttribute("tabindex"))}applyMessages(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const e=this.currentSighting.event,t=mh(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?yg(e.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.paintMiniProgress(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return Qa(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?gy(my(this.realStartMs+i)):Qa(i)}formatElapsedAt(e){const t=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?Qa(e):Qa(t>0&&e<=t?e/t*this.realDurationMs:e)}formatRemaining(e){const t=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return Qa(Math.max(0,t-e));const i=t>0&&e<=t?e/t*this.realDurationMs:e;return Qa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?Qa(this.currentSighting.timeline.duration):this.canShowClockTime?gy(my(this.realStartMs+this.realDurationMs)):Qa(this.realDurationMs)}}function my(l){const e=new Date(l);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function gy(l){if(l.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return l.second?`${e(l.hour)}:${e(l.minute??0)}:${e(l.second)}`:`${e(l.hour)}:${e(l.minute??0)}`}function Qa(l){const e=Math.round(l/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Vg="rr0-ufo";function Mm(){customElements.get(Vg)||customElements.define(Vg,Vt)}const wI="recordingissues",V2="minifiedreset";class ud{constructor(e,t){this.seekInput=e,this.layer=t,e.addEventListener("pointerdown",i=>{this.snapArmed=!0,this.nameMarkUnder(i)}),e.addEventListener("pointerup",()=>this.snapArmed=!1),e.addEventListener("pointermove",i=>this.nameMarkUnder(i)),e.addEventListener("pointerleave",()=>e.removeAttribute("title"))}static SNAP_PX=6;marks=[];duration=0;drawn="";snapArmed=!1;show(e,t){const i=t>0?[...e].sort((n,r)=>n.t-r.t):[],s=`${t}|${i.map(n=>`${n.kind}:${n.t}:${n.label}`).join("|")}`;s!==this.drawn&&(this.drawn=s,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(n=>{const r=document.createElement("span");return r.className=`timeline-mark ${n.kind}`,r.style.left=`${Math.min(Math.max(n.t/t,0),1)*100}%`,r})))}snap(e){return this.snapArmed?(this.snapArmed=!1,this.markNear(e)?.t??e):e}next(e){return this.marks.find(t=>t.t>e+ud.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-ud.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=ud.SNAP_PX/t*this.duration;let s;for(const n of this.marks)Math.abs(n.t-e)>i||(!s||Math.abs(n.t-e)<Math.abs(s.t-e)||n.t===s.t&&n.kind==="milestone")&&(s=n);return s}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect();if(t.width<=0||this.duration<=0)return;const i=this.marksNear((e.clientX-t.left)/t.width*this.duration);i?this.seekInput.title=i:this.seekInput.removeAttribute("title")}marksNear(e){const t=this.markNear(e);if(t)return[...new Set(this.marks.filter(i=>i.t===t.t).map(i=>i.label))].join(" · ")}}class Hc{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const s=e.event.place?.[0],n=e.observerTrack;if(!s)return 0;const r=m=>{const g=n.getInterpolatedPoseAt(Math.max(0,m));if(!g||g.lat===void 0||g.lng===void 0)return;const v=ot(g.lat,g.lng,s.lat,s.lng);return{eastM:v.x,northM:-v.z,heading:g.headingDeg}},a=r(t-Hc.HALF_SPAN_MS),o=r(t+Hc.HALF_SPAN_MS),c=r(t);if(!a||!o||!c)return 0;const h=Math.hypot(o.eastM-a.eastM,o.northM-a.northM),d=2*Hc.HALF_SPAN_MS/1e3;if(h/d<Hc.MIN_SPEED_MS)return 0;const u=i.heightAt(o.eastM,o.northM)-i.heightAt(a.eastM,a.northM),p=Math.atan2(u,h)*180/Math.PI;if(c.heading===void 0)return p;const f=Math.atan2(o.eastM-a.eastM,o.northM-a.northM)*180/Math.PI;return p*Math.max(0,Math.cos((c.heading-f)*Math.PI/180))}}const MI=.08,vy=.15,by=2,xI=2e3;class SI{context;noiseBuffer;voices=new Map;level=1;master;paused=!0;requested=[];resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",e);return}}Ll.unlock(this.context),this.apply()}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}setPaused(e){e!==this.paused&&(this.paused=e,this.apply())}setVoices(e){this.requested=e,this.apply()}dispose(){for(const e of[...this.voices.keys()])this.release(e);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}apply(){const e=this.context;if(!e)return;const t=this.paused?[]:this.requested.filter(s=>s.inside||s.distanceM<xI),i=new Set(t.map(s=>s.id));for(const s of[...this.voices.keys()])i.has(s)||this.release(s);for(const s of t){const n=this.voices.get(s.id)??this.build(e,s.id);this.retarget(e,n,s)}}build(e,t){const i=e.createGain();i.gain.value=0;const s=e.createBiquadFilter();s.type="lowpass",s.connect(i).connect(this.masterOf(e));const n=e.createOscillator();n.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),o=e.createBiquadFilter();o.type="lowpass",o.frequency.value=900,n.connect(o),r.connect(o),o.connect(a).connect(s);const c=()=>{const M=e.createBufferSource();return M.buffer=this.noise(e),M.loop=!0,M.loopStart=Math.random()*by*.5,M},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(s);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const m=e.createGain();p.connect(f).connect(m).connect(s);const g=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const b=e.createGain();g.connect(v).connect(b).connect(s);const w=[n,r,h,p,g];for(const M of w)M.start();const y={nodes:[i,s,a,o,d,u,f,m,v,b,...w],sources:w,firing:n,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:m,windGain:b,cabin:s,output:i};return this.voices.set(t,y),y}retarget(e,t,{profile:i,state:s,noise:n,inside:r,windowsOpen:a,distanceM:o}){const c=e.currentTime,h=(b,w)=>b.setTargetAtTime(w,c,MI),d=s.rpm/60,u=d*i.cylinders/2,p=Math.min(1,s.rpm/i.shiftUpRpm),f=Math.min(1.5,s.speedMps/30);h(t.firing.frequency,u),h(t.crank.frequency,d),h(t.knock.frequency,u*3),h(t.engineGain.gain,i.engineGain*(.25+.75*s.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*s.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const m=!r||a;h(t.windGain.gain,f**2*(m?.5:.06));const g=r?a?3500:700:8e3/(1+o/60);h(t.cabin.frequency,g);const v=r?.5:Math.min(1,8/Math.max(o,1));h(t.output.gain,v*n)}release(e){const t=this.voices.get(e);if(!t)return;this.voices.delete(e);const i=this.context;i&&(t.output.gain.setTargetAtTime(0,i.currentTime,vy/3),setTimeout(()=>{for(const s of t.sources)try{s.stop()}catch{}for(const s of t.nodes)s.disconnect()},vy*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*by,e.sampleRate),i=t.getChannelData(0);for(let s=0;s<i.length;s++)i[s]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Wd{static BY_KIND={car:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},generic:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},van:{cylinders:4,idleRpm:750,kmhPer1000Rpm:[7,12,19,27,35,42],shiftUpRpm:2600,shiftDownRpm:1200,engineGain:.8,roadGain:.7,roughness:.45},truck:{cylinders:6,idleRpm:600,kmhPer1000Rpm:[5,8,12,17,23,30,38,48],shiftUpRpm:1900,shiftDownRpm:1e3,engineGain:1,roadGain:.9,roughness:.55},motorcycle:{cylinders:2,idleRpm:1100,kmhPer1000Rpm:[12,18,24,30,35,40],shiftUpRpm:6e3,shiftDownRpm:2500,engineGain:.9,roadGain:.3,roughness:.3}};static of(e){return Wd.BY_KIND[e??"generic"]??Wd.BY_KIND.generic}}class El{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,s){const n=El.SAMPLE_MS,r=[];for(let c=i;c<=s+n/2;c+=n){const h=t(c-n/2),d=t(c+n/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(n/1e3))}const a=[];let o=1;for(let c=0;c<r.length;c++){const h=r[c],d=(r[Math.min(c+1,r.length-1)]-r[Math.max(c-1,0)])/(2*n/1e3);if(h<El.STANDING_MPS){o=1,a.push({speedMps:h,rpm:e.idleRpm,load:.1,gear:0});continue}const u=h*3.6,p=v=>u/e.kmhPer1000Rpm[v-1]*1e3;for(;o<e.kmhPer1000Rpm.length&&p(o)>e.shiftUpRpm;)o++;for(;o>1&&p(o)<e.shiftDownRpm;)o--;const f=Math.max(p(o),e.idleRpm*(1+.3*Math.min(1,h/3))),m=.15+.5*Math.min(1,(h/35)**2),g=d>.15?Math.min(1,m+d/2.5):d<-.3?.05:m;a.push({speedMps:h,rpm:f,load:g,gear:o})}return new El(a,i)}at(e){const t=(e-this.startMs)/El.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),0),this.samples.length-1),s=this.samples[i],n=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(t-i,0),1);return{speedMps:s.speedMps+(n.speedMps-s.speedMps)*r,rpm:s.rpm+(n.rpm-s.rpm)*r,load:s.load+(n.load-s.load)*r,gear:r<.5?s.gear:n.gear}}}class Sf{drives=new Map;at(e,t){const i=[],s=e.event.place?.[0],n=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??s?.lat,u=h?.lng??s?.lng;if(d===void 0||u===void 0||!s)return;const p=ot(d,u,s.lat,s.lng);return{eastM:p.x,northM:-p.z}},r=Math.max(e.observerTrack.duration,(e.event.durationSeconds??0)*1e3),a=e.vehicle;if(a){const c=Wd.of(a.kind),h=this.drive(`observer:${a.kind}`,Sf.trackKey(e),()=>El.of(c,n,0,r));h&&i.push({id:"observer",profile:c,state:h.at(t),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const o=n(t);for(const c of e.decor){if(!c.engine||!o)continue;const h=Wd.of(c.engine.kind),d=m=>{const g=tr(c,m);return{eastM:g.eastM,northM:g.northM}},u=this.drive(`decor:${c.id}`,Sf.decorKey(c,r),()=>El.of(h,d,0,r));if(!u)continue;const p=tr(c,t),f=Math.hypot(p.eastM-o.eastM,p.northM-o.northM,p.altitudeM);i.push({id:`decor:${c.id}`,profile:h,state:u.at(t),noise:c.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:f})}return i}drive(e,t,i){const s=this.drives.get(e);if(s&&s.key===t)return s.drive;const n=i();return this.drives.set(e,{key:t,drive:n}),n}static trackKey(e){return e.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(e,t){return`${t}|${e.eastM},${e.northM}|`+(e.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const EI="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAARVBMVEX9sST/uyTfoCjNlSikfCqRcCx8Yy21hipTSi4TITEMHTEuMzBqWC3/wSRUX207SFj8/PyaoakmNUd5gYxBPy90fIfMz9RsB4kZAAACEUlEQVRo3u2XyXbDIAxFLeapjts6/f9PrQA3JymT25Cd3iY5xtYVIB6wLCQSiUQikUgk0nzBoVdFZ1xIpaTQbJnPACaNdYeskWwuAhaZoltnUemfnNkL4N49KEI8n0YAEXMvEWISAWQZPw2Xk1MIoF1dSNAzCMy6JsGyCR0wrkMwT3cBeDt+FH8aEHoA68LbM8HRHXQ3f0RE3/jXOOFX+s4djrKpIbzS7K+MmLrxlWCNR8mczjMw92Ar4dZLDXG4kzXinAECcOUPL3jMdN2294/GQGVG4EMHxORNJXoCfG6oT1trvDGM7iIA9N6aTOuuEbB9ra6FyCYr2gjge+fjA4CIi2uujYRoOBSw0A5/D0hT0X4PW0xtuotNpQPYtkt/fdtyM0LP6ZvOI2DtvoxtJWHvx38AxIkevLwXQ2TOA66DziYfLwC4r5wbIlwJo1ys8+VOBMy7/sxdjwIap49lVC3UePZp1mmyit4SuGUf11pjoTHVRVzXUaXFVt87kuEBsWZ055Q+2sXA76LbZYsvKR1ubvJqbKd5swl+GPI31p6L/sNYuDTe3jo+GBdr1J+P9PGawbRUw9VhleD/3ffT9uZ7DhtX1JNHL2CmNRXxYZhwSwBd3aJTyU85/GKOwhxBf5RnVk+75OSiuu+Ax4PQ3Jsg1hTeMUMwJgQp+PKCe2a+JuefFwQnkUgkEolEIpFerW8TL0hlNl2QVAAAAABJRU5ErkJggg==",AI=`
4254
4254
  <div class="stage" id="stage">
4255
4255
  <div class="frame" id="frame">
4256
4256
  <canvas id="scene-canvas"></canvas>
@@ -10689,7 +10689,7 @@ uniform float uWindowLuminance;
10689
10689
  varying float vLitRank;
10690
10690
  ${c.fragmentShader.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
10691
10691
  totalEmissiveRadiance *= step(vLitRank, uLitShare) * uWindowLuminance * ${de.WINDOW_VARIETY_GLSL};`)}`},a.customProgramCacheKey=()=>"facade-lit-windows";const o=new Me(r,a);return o.castShadow=!0,o.receiveShadow=!0,t.add(o),t}static CLOSED_AT_NIGHT_SHARE=.2;static litWindowShare={value:0};static WINDOW_LUMINANCE_CD_M2=15;static ROOM_LIGHT_K=2900;static COLD_ROOM_LIGHT_K=4e3;static windowLuminance={value:0};static get WINDOW_VARIETY_GLSL(){const e=s=>`vec3(${s.map(n=>n.toFixed(4)).join(", ")})`,t=hh.ofTemperature(de.ROOM_LIGHT_K),i=hh.ofTemperature(de.COLD_ROOM_LIGHT_K);return`(mix(0.35, 2.0, fract(vLitRank * 97.13) * fract(vLitRank * 97.13)) * mix(${e(t)}, ${e(i)}, step(0.86, fract(vLitRank * 53.71))))`}static setWindowLuminance(e){de.windowLuminance.value=de.WINDOW_LUMINANCE_CD_M2*e}static setLitWindowShare(e){de.litWindowShare.value=Math.max(0,Math.min(1,e))}static build(e,t){const i=de.hasFacade(e)?de.buildFacade(e):e.kind==="building"?iM(e.floors??bh,e.windows,e.observerSide,e.occupiedFloor,e.observerFacing):e.kind==="tree"?nM():e.kind==="shrub"?sM():e.kind==="bridge"?SO(e):e.kind==="wire"?EO(e):e.kind==="wall"?bs.build(e):e.kind==="crop"?aM():e.kind==="terrace"?CO():e.kind==="mound"?oM():e.kind==="streetlight"?lM(t,e.lamp?.mount,e.lamp):e.kind==="trafficlight"?Tt.trafficLight(ht.isPedestrian(e.lights)):e.kind==="crossing"?Tt.crossing(de.sizeOf(e).widthM,de.sizeOf(e).lengthM):e.kind==="roadsign"?Tt.roadSign(e.sign):e.kind==="vehicle"?cM(t,e.windows,e.observerSide,e.observerFacing):e.kind==="aircraft"?mM():e.kind==="entity"?pM():qv();e.color&&this.paint(i,e.color);const s=this.scaleFor(e),n=new Ht;return e.kind==="building"&&e.roof&&this.addRoof(n,e),i.name=de.BODY_NAME,i.scale.copy(s),n.add(i),e.headingDeg!==void 0&&(n.rotation.y=-e.headingDeg*C0),this.addLights(n,e.lights),de.fitLights(n,e,e.sizeM??{}),n}static scaleFor(e){const t=e.sizeM;if(!t||de.hasFacade(e)||e.kind==="bridge"||e.kind==="wire"||e.kind==="terrace"||e.kind==="wall"||e.kind==="crossing")return new I(1,1,1);const i=this.naturalSize(e.kind,e.floors);return new I(t.widthM===void 0?1:N0(t.widthM,i.widthM),t.heightM===void 0?1:N0(e.kind==="building"?this.wallHeightOf(e,t.heightM):t.heightM,i.heightM),t.lengthM===void 0?1:N0(t.lengthM,i.lengthM))}static naturalSize(e,t){const i=e==="building"?Math.max(1,(t??bh)+1):0;if(e==="bridge")return Ti.NATURAL_SIZE;if(e==="wire")return _l.NATURAL_SIZE;if(e==="terrace"||e==="wall")return{widthM:1,lengthM:1,heightM:1};if(e==="crossing")return{widthM:6,lengthM:2.5,heightM:Tt.CROSSING_LIFT_M};const s=`${e}:${i}`,n=hM.get(s);if(n)return n;const r=e==="building"?iM(i-1,void 0,void 0,void 0):e==="tree"?nM():e==="shrub"?sM():e==="crop"?aM():e==="mound"?oM():e==="streetlight"?lM(!1):e==="trafficlight"?Tt.trafficLight(!1):e==="roadsign"?Tt.roadSign(void 0):e==="vehicle"?cM(!1,void 0,void 0):e==="aircraft"?mM():e==="entity"?pM():qv(),a=new us().setFromObject(r),o={widthM:a.max.x-a.min.x,heightM:a.max.y-a.min.y,lengthM:a.max.z-a.min.z};return this.dispose(r),hM.set(s,o),o}static usesModel(e){return Gd(e)!==void 0&&!(e.observerSide!==void 0&&Oo(e.kind))}static applyModel(e,t,i,s={}){const n=this.bodyOf(e),r=new Ht;r.name=de.BODY_NAME,i.rotation.y=-(s.headingOffsetDeg??0)*C0,i.updateMatrixWorld(!0);const a=new us().setFromObject(i),o={lengthM:a.max.z-a.min.z,heightM:a.max.y-a.min.y,widthM:a.max.x-a.min.x},c=t.kind==="tree"&&t.sizeM?.heightM!==void 0?{heightM:t.sizeM.heightM}:t.sizeM,h=dM(c,o)??dM(s.depictedSizeM,o)??1;i.scale.multiplyScalar(h);const d=a.getCenter(new I).multiplyScalar(h);i.position.x-=d.x,i.position.z-=d.z,i.position.y-=t.kind==="aircraft"?d.y:a.min.y*h,i.traverse(u=>{u instanceof Me&&(u.castShadow=!0,u.receiveShadow=!0)}),r.add(i),t.kind==="tree"&&r.add(de.trunkShadow(o.heightM*h)),n.parent?(n.parent.add(r),n.removeFromParent()):e.add(r),this.dispose(n),de.fitLights(e,t,{widthM:o.widthM*h,heightM:o.heightM*h,lengthM:o.lengthM*h})}static fitLights(e,t,i){const s=vh.byId(Nr.rigOf(t)||void 0)?.referenceSizeM;if(!s||!t.lights)return;const n=(h,d)=>h===void 0||d===0?1:h/d,r=n(i.widthM,s.widthM),a=n(i.heightM,s.heightM),o=n(i.lengthM,s.lengthM),c=new Map(t.lights.map(h=>[h.id,h.offsetM]));e.traverse(h=>{const d=h.userData.lightId,u=d===void 0?void 0:c.get(d);u&&h.position.set(u.x*r,u.y*a,u.z*o)})}static trunkShadow(e){de.trunkProxy??={geometry:new ln(1,1.15,1,8),material:new Vn({colorWrite:!1,depthWrite:!1})};const t=new Me(de.trunkProxy.geometry,de.trunkProxy.material),i=Math.min(.3,Math.max(.12,e*.035)),s=e*.45;return t.scale.set(i,s,i),t.position.y=s/2,t.castShadow=!0,t.receiveShadow=!1,t.userData.sharedModel=!0,t.name="trunk-shadow",t}static trunkProxy;static sizeOf(e){const t=this.naturalSize(e.kind,e.floors);return{widthM:e.sizeM?.widthM??t.widthM,lengthM:e.sizeM?.lengthM??t.lengthM,heightM:e.sizeM?.heightM??t.heightM}}static addLights(e,t){for(const i of t??[]){const s=fO(i.color),n=ht.figureOf(i),r=n?Tt.pedestrianFigure(n,1.8*(i.radiusM??L0)):new fs(i.radiusM??L0,8,6),a=Qt(e,r,s,i.offsetM.y,!0);a.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),a.userData={emissive:!0,lightId:i.id,lightColor:s},a.visible=!1;const o=a.material;YS.apply(o),o.transparent=!0,o.depthWrite=!1,o.fog=!1}}static setLights(e,t,i,s,n=0,r=1,a=lO,o=[1,1,1],c){if(!t||t.length===0)return;const h=new Map(t.map(u=>[u.id,u]));let d;c&&t.some(u=>u.beamDeg!==void 0)&&(e.updateWorldMatrix(!0,!1),d=e.worldToLocal(de.eyeScratch.copy(c)));for(const u of e.children){if(!(u instanceof Me))continue;const p=u.userData.lightId;if(!p)continue;const f=h.get(p);if(!f)continue;const m=n>0?M2(f,i,i+n):U3(f,i)?1:0,g=d&&f.beamDeg!==void 0?de.beamShare(f.beamDeg,u.position,d):1;u.visible=m>0&&g>0;const v=f.radiusM??L0,b=Math.max(1,s*a/v),w=v*b,y=r/(Math.PI*w*w),M=u.material,S=u.userData.lightColor;if(S){const E=m*g*cO*(f.intensity??1)*y,x=[S[0]*E*o[0],S[1]*E*o[1],S[2]*E*o[2]],A=Math.min(1,eM/Math.max(x[0],x[1],x[2],1e-30));M.color.setRGB(x[0]*A,x[1]*A,x[2]*A)}u.scale.setScalar(b)}}static eyeScratch=new I;static beamShare(e,t,i){const s=i.x-t.x,n=i.y-t.y,r=i.z-t.z,a=Math.hypot(s,n,r);if(a===0)return 1;const o=-r/a;if(o<=0)return 0;const c=Math.log(.5)/Math.log(Math.cos(e*Math.PI/180));return Math.pow(o,c)}static setLit(e,t,i,s=1,n){const[r,a,o]=t==="streetlight"?[hO*de.lampShare(n),dO,de.lampHue(n)]:[uO,pO,jS],c=i?r*s/(Math.PI*a*a):0,h=Math.min(1,eM/Math.max(o[0]*c,o[1]*c,o[2]*c,1e-30)),d=[o[0]*c*h,o[1]*c*h,o[2]*c*h];e.traverse(u=>{const p=u.userData;!(u instanceof Me)||!p.emissive||p.lightId||(u.material instanceof wr?u.material.emissive.setRGB(...d):u.material.color.setRGB(...d))})}static REFERENCE_LUMENS=1e4;static lampShare(e){return e?.lumens?e.lumens/de.REFERENCE_LUMENS:1}static lampHue(e){return e?.colorTemperatureK?hh.ofTemperature(e.colorTemperatureK):gO}static dispose(e){e.traverse(t=>{if(!(t instanceof Me))return;if(t.userData.sharedModel){for(const s of t.userData.tintedMaterials??[])s.dispose();return}t.geometry.dispose();const i=t.material;for(const s of Array.isArray(i)?i:[i])s.dispose()})}}const U0="https://ufoathome.org/models/index.json";class Td{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??NO()}async entries(e){const t=await this.load();return e?t.filter(i=>[i.kind].flat().includes(e)):t}async entry(e){return(await this.load()).find(t=>t.id===e)}load(){if(this.loading)return this.loading;if(!this.sharing)return this.loading=this.fetchFirstAvailable();const e=this.indexUrls.join(`
10692
- `);let t=Td.shared.get(e);return t||(t=this.fetchFirstAvailable(),Td.shared.set(e,t),t.then(i=>{i.length===0&&Td.shared.delete(e)})),this.loading=t}async fetchFirstAvailable(){for(const e of this.indexUrls){const t=await this.fetchIndex(e);if(t)return t}return[]}async fetchIndex(e){try{const t=await this.fetchImpl(e);if(!t.ok)return;const i=await t.json();return Array.isArray(i?.models)?i.models.map(({file:s,...n})=>({...n,url:new URL(s,e).href})):void 0}catch{return}}}function NO(){const l=`?v=${encodeURIComponent("0.152.0")}`,e=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(e&&e!==U0?[e,U0]:[U0]).map(t=>t+l)}const Up=[{id:"ufoathome",name:"UFO@home",credit:"3D models re-hosted by UFO@home, each under its own author's licence",creditUrl:"https://ufoathome.org/models/",create:()=>new Td}];async function z0(l){const{GLTFLoader:e}=await ae(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-DHQ7X9p5.js");return{GLTFLoader:i}},[],import.meta.url),t=new e;return new Promise((i,s)=>{t.load(l,n=>i(Object.assign(n.scene,{animations:n.animations})),void 0,n=>s(new Error(`Could not load 3D model ${l}: ${n instanceof Error?n.message:String(n)}`)))})}class Qn{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(e,t){this.mesh=new Me(new cn(2,2),new kt({uniforms:{uColor:{value:new re(0,0,0)},uRadius:{value:1}},vertexShader:Qn.VERTEX,fragmentShader:Qn.FRAGMENT,transparent:!0,depthWrite:!1,blending:Is,toneMapped:!1})),this.mesh.name=e,this.mesh.frustumCulled=!1,this.mesh.renderOrder=t,this.mesh.visible=!1}shine(e,t,i){this.mesh.visible=!0,this.mesh.position.set(e.x,e.y,e.z),this.mesh.material.uniforms.uRadius.value=t,this.mesh.material.uniforms.uColor.value.setRGB(i[0],i[1],i[2])}hide(){this.mesh.visible=!1}dispose(){this.mesh.geometry.dispose(),this.mesh.material.dispose()}static spread(e,t,i,s){const n=Math.max(e,s*Qn.MIN_ANGLE_RAD),r=Qn.FILL*Math.PI*n*n;return{radiusM:n,luminanceCdM2:i*Math.min(Qn.MAX_SHARE,t/r)}}static conserving(e){return Math.sqrt(e/(Qn.MAX_SHARE*Qn.FILL*Math.PI))}static VERTEX=`
10692
+ `);let t=Td.shared.get(e);return t||(t=this.fetchFirstAvailable(),Td.shared.set(e,t),t.then(i=>{i.length===0&&Td.shared.delete(e)})),this.loading=t}async fetchFirstAvailable(){for(const e of this.indexUrls){const t=await this.fetchIndex(e);if(t)return t}return[]}async fetchIndex(e){try{const t=await this.fetchImpl(e);if(!t.ok)return;const i=await t.json();return Array.isArray(i?.models)?i.models.map(({file:s,...n})=>({...n,url:new URL(s,e).href})):void 0}catch{return}}}function NO(){const l=`?v=${encodeURIComponent("0.152.1")}`,e=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(e&&e!==U0?[e,U0]:[U0]).map(t=>t+l)}const Up=[{id:"ufoathome",name:"UFO@home",credit:"3D models re-hosted by UFO@home, each under its own author's licence",creditUrl:"https://ufoathome.org/models/",create:()=>new Td}];async function z0(l){const{GLTFLoader:e}=await ae(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-DHQ7X9p5.js");return{GLTFLoader:i}},[],import.meta.url),t=new e;return new Promise((i,s)=>{t.load(l,n=>i(Object.assign(n.scene,{animations:n.animations})),void 0,n=>s(new Error(`Could not load 3D model ${l}: ${n instanceof Error?n.message:String(n)}`)))})}class Qn{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(e,t){this.mesh=new Me(new cn(2,2),new kt({uniforms:{uColor:{value:new re(0,0,0)},uRadius:{value:1}},vertexShader:Qn.VERTEX,fragmentShader:Qn.FRAGMENT,transparent:!0,depthWrite:!1,blending:Is,toneMapped:!1})),this.mesh.name=e,this.mesh.frustumCulled=!1,this.mesh.renderOrder=t,this.mesh.visible=!1}shine(e,t,i){this.mesh.visible=!0,this.mesh.position.set(e.x,e.y,e.z),this.mesh.material.uniforms.uRadius.value=t,this.mesh.material.uniforms.uColor.value.setRGB(i[0],i[1],i[2])}hide(){this.mesh.visible=!1}dispose(){this.mesh.geometry.dispose(),this.mesh.material.dispose()}static spread(e,t,i,s){const n=Math.max(e,s*Qn.MIN_ANGLE_RAD),r=Qn.FILL*Math.PI*n*n;return{radiusM:n,luminanceCdM2:i*Math.min(Qn.MAX_SHARE,t/r)}}static conserving(e){return Math.sqrt(e/(Qn.MAX_SHARE*Qn.FILL*Math.PI))}static VERTEX=`
10693
10693
  uniform float uRadius;
10694
10694
  varying vec2 vOffset;
10695
10695
  void main() {