@rr0/ufoathome 0.136.0 → 0.136.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.
|
@@ -236,9 +236,7 @@ ${e} :is(select:not([multiple]):not([size]), .rr0-select) {
|
|
|
236
236
|
}
|
|
237
237
|
.share-link {
|
|
238
238
|
display: flex;
|
|
239
|
-
|
|
240
|
-
gap: 0.5em;
|
|
241
|
-
padding: 0.5em 0.6em 0.5em 0.8em;
|
|
239
|
+
padding: 0.5em 0.8em;
|
|
242
240
|
border: 1px solid var(--pop-border);
|
|
243
241
|
border-radius: 0.9em;
|
|
244
242
|
}
|
|
@@ -271,12 +269,19 @@ ${e} :is(select:not([multiple]):not([size]), .rr0-select) {
|
|
|
271
269
|
.share-copy:hover, .share-copy:focus-visible {
|
|
272
270
|
background: var(--pop-soft);
|
|
273
271
|
}
|
|
274
|
-
/*
|
|
272
|
+
/* Under the link or the code, the same line for both: what is copied, frozen or not, and the copying. */
|
|
273
|
+
.share-actions {
|
|
274
|
+
display: flex;
|
|
275
|
+
align-items: center;
|
|
276
|
+
gap: 0.8em;
|
|
277
|
+
margin-top: 0.6em;
|
|
278
|
+
}
|
|
275
279
|
.share-freeze {
|
|
276
|
-
display: block;
|
|
277
|
-
margin-bottom: 0.6em;
|
|
278
280
|
font-size: 0.9em;
|
|
279
281
|
}
|
|
282
|
+
.share-actions .share-copy {
|
|
283
|
+
margin-left: auto;
|
|
284
|
+
}
|
|
280
285
|
/* The embed code is edited in CodeMirror once its chunk has loaded; the textarea is the stand-in until then, and the model the
|
|
281
286
|
editor mirrors. */
|
|
282
287
|
.embed-code:empty, .embed-code[hidden], .embed-markup[hidden] {
|
|
@@ -292,11 +297,6 @@ ${e} :is(select:not([multiple]):not([size]), .rr0-select) {
|
|
|
292
297
|
white-space: pre-wrap;
|
|
293
298
|
overflow-wrap: anywhere;
|
|
294
299
|
}
|
|
295
|
-
.embed-row {
|
|
296
|
-
display: flex;
|
|
297
|
-
justify-content: flex-end;
|
|
298
|
-
margin-top: 0.5em;
|
|
299
|
-
}
|
|
300
300
|
</style>
|
|
301
301
|
<dialog id="dialog" class="share-dialog" aria-labelledby="title">
|
|
302
302
|
<div class="share-head">
|
|
@@ -317,22 +317,22 @@ ${e} :is(select:not([multiple]):not([size]), .rr0-select) {
|
|
|
317
317
|
<!-- What the element that holds the dialog lets its reader choose of what is shared: the player's position and options. -->
|
|
318
318
|
<slot name="options"></slot>
|
|
319
319
|
<p id="note" class="share-note" role="status" hidden></p>
|
|
320
|
-
<!-- Unticked, what is shared follows each release; ticked, it keeps this one for good (see EmbedScript). -->
|
|
321
|
-
<label class="share-freeze"><input id="freeze" type="checkbox"/> <span id="freeze-label">Freeze this version</span></label>
|
|
322
320
|
<div id="link-box" class="share-link">
|
|
323
321
|
<textarea id="link" class="share-link-input" rows="2" spellcheck="false" aria-label="Link"></textarea>
|
|
324
|
-
<button id="link-copy" class="share-copy" type="button">Copy</button>
|
|
325
322
|
</div>
|
|
326
323
|
<div id="embed-box" class="share-embed" hidden>
|
|
327
324
|
<div id="embed-code" class="embed-code"></div>
|
|
328
325
|
<textarea id="embed-markup" class="embed-markup" rows="6" spellcheck="false"></textarea>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
</div>
|
|
327
|
+
<div class="share-actions">
|
|
328
|
+
<!-- Unticked, what is shared follows each release; ticked, it keeps this one for good (see EmbedScript). -->
|
|
329
|
+
<label class="share-freeze"><input id="freeze" type="checkbox"/> <span id="freeze-label">Freeze this version</span></label>
|
|
330
|
+
<!-- Copies what is on show: the link, or the code. -->
|
|
331
|
+
<button id="copy" class="share-copy" type="button">Copy</button>
|
|
332
332
|
</div>
|
|
333
333
|
</dialog>
|
|
334
|
-
`;class Nc extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(Nc.TAG)||customElements.define(Nc.TAG,Nc)}subject;messages=J0;languageToken=0;shadow;dialog;linkField;
|
|
335
|
-
${e.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const e=this.messages,t=(i,n)=>{this.shadow.getElementById(i).textContent=n};t("title",e.share),t("link-label",e.link),t("embed-label",e.embed),t("link-copy",e.copy),t("embed-copy",e.copy),t("freeze-label",e.freeze.replace("{version}","0.136.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??=oe(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,i){try{await navigator.clipboard.writeText(e),i.textContent=this.messages.copied,window.setTimeout(()=>i.textContent=this.messages.copy,1500)}catch{t.select()}}}class hs{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 n=e[i]??e[hs.base(i)];if(n)return n}const t=new Set(this.preferences.map(i=>hs.base(i)));for(const[i,n]of Object.entries(e))if(n&&t.has(hs.base(i)))return n;return Object.values(e).find(i=>i)??void 0}write(e,t,i){const n=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return n;const s={...e},r=Object.keys(s).find(a=>a===i)??Object.keys(s).find(a=>hs.base(a)===hs.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(e){return e.toLowerCase().split("-")[0]}}function wd(l,e){for(const t of l){const i=t.toLowerCase().split("-")[0];if(e.includes(i))return i}return"en"}class Gs{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 n=t.getRootNode();t=n instanceof ShadowRoot?n.host:void 0}}}class ns{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=ns.ISO.exec(t);if(!i||t==="P"||t.endsWith("T"))return;const[,n,s,r,a,o]=i,c=d=>d===void 0?0:Number(d.replace(",",".")),h=c(n)*604800+c(s)*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),n="?~%".includes(i)?i:"";n!==""&&(t=t.slice(0,-1).trim());const s=t.split("/");if(s.length>2)return;const r=s.map(d=>ns.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:n,minSeconds:c,maxSeconds:h,chosenSeconds:(c+h)/2}}static isExact(e){const t=ns.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),n=Math.floor(t%3600/60),s=Math.round(t%60*10)/10;return`PT${`${i>0?`${i}H`:""}${n>0?`${n}M`:""}${s>0||i===0&&n===0?`${s}S`:""}`}`}static say(e){const t=Math.round(e*10)/10;if(t<60)return`${t} s`;const i=Math.floor(t/3600),n=Math.floor(t%3600/60),s=Math.round(t%60*10)/10,r=[];return i>0&&r.push(`${i} h`),n>0&&r.push(`${n} min`),s>0&&r.push(`${s} s`),r.join(" ")}}class xt{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/xt.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 SE(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 cx(l,e="#39ff14"){return{kind:"oval",bounds:l,color:e,angle:0,transparency:0,haloScale:0,selected:!1}}function hx(l,e,t="#39ff14"){return{kind:"polygon",bounds:l,points:e,color:t,angle:0,transparency:0,haloScale:0,selected:!1}}function EE(l,e="#39ff14"){const{width:t,height:i}=l;return hx(l,[{x:0,y:0},{x:t,y:0},{x:t,y:i},{x:0,y:i}],e)}const AE={oval:cx,polygon:EE};function Jb(l,e){return{...AE[e.presetId](l,e.color),transparency:e.transparency,haloScale:e.haloScale,blur:e.blur,brightness:e.brightness}}function TE(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 dx(l,e,t){const i=l.bounds.width,n=l.bounds.height;return{...l,bounds:{x:e-i/2,y:t-n/2,width:i,height:n}}}function Ss(l,e,t){return l+(e-l)*t}function Qb(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 IE(l,e,t){const i=Qb(l),n=Qb(e);return!i||!n?t<1?l:e:_E([Ss(i[0],n[0],t),Ss(i[1],n[1],t),Ss(i[2],n[2],t)])}function DE(l,e,t){const i={x:Ss(l.bounds.x,e.bounds.x,t),y:Ss(l.bounds.y,e.bounds.y,t),width:Ss(l.bounds.width,e.bounds.width,t),height:Ss(l.bounds.height,e.bounds.height,t)},n=Ss(l.angle,e.angle,t),s=Ss(l.transparency,e.transparency,t),r=Ss(l.haloScale,e.haloScale,t),a=Ss(l.blur??0,e.blur??0,t),o=Ss(l.brightness??0,e.brightness??0,t),c=IE(l.color,e.color,t),h=xt.lerpAngular(l.angular,e.angular,t),d=SE(l.aim,e.aim,t);return l.kind==="polygon"&&e.kind==="polygon"&&l.points.length===e.points.length?{...l,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d,points:l.points.map((u,p)=>({x:Ss(u.x,e.points[p].x,t),y:Ss(u.y,e.points[p].y,t)}))}:{...t<1?l:e,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d}}class ya{static DEFAULT_COLOR="#e8e6df";static complete(e,t=[]){const i=new Map;return e.map((n,s)=>({keyframe:n,index:s})).sort((n,s)=>n.keyframe.t-s.keyframe.t).map(({keyframe:n,index:s})=>({t:n.t,shapes:(n.shapes??[]).map((r,a)=>{const o=`timeline.keyframes.${s}.shapes.${a}.shape`,c=ya.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,n=new Set;return e.map((s,r)=>({t:s.t,shapes:s.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=ya.thinned(a.shape,o);if(t){const h=c;t(r,a.sourceId)?(delete h.bounds,delete h.points,n.add(a.sourceId)):n.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,n={};for(const[s,r]of Object.entries(e))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[s]&&JSON.stringify(r)!==JSON.stringify(i[s]))&&(n[s]=r);return"bounds"in n&&(e.aim&&(n.aim=e.aim),e.angular&&(n.angular=e.angular)),n}static completed(e,t,i,n){const s=e.shape??{},r=t??ya.firstAppearance(s,i,n),a={...r};s.bounds&&t&&(t.aim||t.angular)&&!s.aim&&!s.angular&&n.push({kind:"pixels-over-angles",path:i}),s.bounds&&(s.aim||delete a.aim,s.angular||delete a.angular);const o=s.kind??r.kind??"oval",c={...a,...s,kind:o};if(o==="polygon"&&!c.points){n.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:`"${ya.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:{...ya.NEUTRAL_BOUNDS},color:ya.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:xt.CANVAS_WIDTH_PX/2,y:xt.CANVAS_HEIGHT_PX/2,width:1,height:1}}class $f{keyframes=[];order=[];groups=[];span=0;addKeyframe(e,t){const i=this.findInsertIndex(e);if(this.keyframes[i]?.t===e){const n=new Set(t.map(s=>s.sourceId));this.keyframes[i]={t:e,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...t]}}else this.keyframes.splice(i,0,{t:e,shapes:[...t]});for(const n of t)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return n.shape}}getInterpolatedShapeAt(e,t){const i=this.findShapeAtOrBefore(e,t);if(i?.t===e)return i.shape;const n=this.findShapeAtOrAfter(e,t);return i?n?DE(i.shape,n.shape,(e-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(e,t){for(let i=this.findInsertIndex(e);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(e,t,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const a=this.getInterpolatedShapeAt(e,s[r]);if(a&&TE(a,t,i))return{sourceId:s[r],shape:a}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const i=this.keyframes[t].shapes.filter(n=>n.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),n=this.keyframes[i];if(n?.t!==e)return;const s=n.shapes.filter(r=>r.sourceId!==t);s.length===0?this.keyframes.splice(i,1):s.length!==n.shapes.length&&(this.keyframes[i]={t:e,shapes:s})}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(n=>n.includes(e));if(t===-1)return;const i=this.groups[t].filter(n=>n!==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 $f;for(const n of ya.complete(e.keyframes??[],t))i.addKeyframe(n.t,n.shapes);if(e.span!==void 0&&e.span>0&&(i.span=e.span),e.order){const n=i.order.filter(s=>!e.order.includes(s));i.order=[...e.order,...n]}return e.groups&&(i.groups=e.groups.map(n=>n.filter(s=>i.order.includes(s))).filter(n=>n.length>=2)),i}}function RE(l,e,t){return Math.max(e,Math.min(t,l))}function kE(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function Ul(l,e,t){return l+(e-l)*t}function CE(l,e,t){return{lat:l.lat===void 0||e.lat===void 0?void 0:Ul(l.lat,e.lat,t),lng:l.lng===void 0||e.lng===void 0?void 0:Ul(l.lng,e.lng,t),elevationM:Ul(l.elevationM,e.elevationM,t),headingDeg:l.headingDeg===void 0||e.headingDeg===void 0?void 0:kE(l.headingDeg,e.headingDeg,t),pitchDeg:Ul(l.pitchDeg,e.pitchDeg,t),rollDeg:Ul(l.rollDeg??0,e.rollDeg??0,t),fovDeg:Ul(l.fovDeg,e.fovDeg,t),fNumber:l.fNumber,focusDistanceM:l.focusDistanceM,filter:l.filter}}class Gn{static at(e,t,i,n,s){const r=e[i],o=e[i+1]-r;if(o<=0)return t[i];const c=Gn.tangent(e,t,i,s),h=Gn.tangent(e,t,i+1,s),d=(n-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,n){const s=e[i],a=e[i+1]-s;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=Gn.tangent(e,t,i,!0),d=Gn.ARRIVAL*(t[i+1]-t[i])/a;return Gn.hermite(t[i],h,t[i+1],d,a,(n-s)/a)}return!c&&i>0&&t[i-1]!==t[i]?t[i]+Gn.settle(e,t,i,n-s,a):Gn.at(e,t,i,n,!0)}static settle(e,t,i,n,s){const r=e[i]-e[i-1];if(r<=0||n<=0)return 0;const a=Gn.ARRIVAL*(t[i]-t[i-1])/r,o=Math.min(Gn.SETTLE_MS,.4*r),c=Number.isFinite(s)?(1-Math.min(1,n/s))**2:1;return a*n*Math.exp(-n/o)*c}static hermite(e,t,i,n,s,r){const a=r*r,o=a*r;return(2*o-3*a+1)*e+(o-2*a+r)*s*t+(-2*o+3*a)*i+(o-a)*s*n}static BRAKE_S=.8;static paced(e,t,i,n){if(!i&&!n)return e;const s=t>0?Math.min(.5,Gn.BRAKE_S/t):.5;if(i&&n){const a=1/(1-s);return e<=s?a*e*e/(2*s):e>=1-s?1-a*(1-e)*(1-e)/(2*s):a*(e-s/2)}const r=a=>{const o=1/(1-s/2);if(a<=1-s)return o*a;const c=a-(1-s);return o*(1-s)+o*(c-c*c/(2*s))};return n?r(e):1-r(1-e)}static tangent(e,t,i,n){const s=e.length-1,r=p=>(t[p+1]-t[p])/(e[p+1]-e[p]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-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 Md{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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.pose;if(!n)return this.settledAfterEnd(t-1,e);const s=CE(i.pose,n.pose,RE((e-i.t)/(n.t-i.t),0,1));return this.humanly(t-1,e,s)}settledAfterEnd(e,t){const i=this.keyframes[e];if(e<1)return i.pose;const n=this.keyframes[e-1],s=[n.t,i.t],r=(h,d)=>h===void 0||d===void 0?0:Gn.settle(s,[h,d],1,t-i.t,1/0),a=n.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-n.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(n.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 n=Math.max(0,e-1),s=Math.min(this.keyframes.length-1,e+2),r=this.keyframes.slice(n,s+1),a=e-n,o=r.map(b=>b.t),c=(b,M)=>{const S=r.map(E=>b(E.pose));if(!S.some(E=>E===void 0))return Gn.at(o,S,a,t,M)},h=b=>{const M=r.map(S=>b(S.pose));if(!M.some(S=>S===void 0))return Gn.gaze(o,M,a,t)},d=r.map(b=>b.pose.headingDeg);let u;if(d.every(b=>b!==void 0)){const b=[d[0]];for(let M=1;M<d.length;M++)b.push(b[M-1]+((d[M]-d[M-1])%360+540)%360-180);u=(Gn.gaze(o,b,a,t)%360+360)%360}const p=this.keyframes[e],f=this.keyframes[e+1],g=(b,M)=>b.lat===M.lat&&b.lng===M.lng&&b.elevationM===M.elevationM,m=!g(p.pose,f.pose),v=m&&e>0&&g(this.keyframes[e-1].pose,p.pose),y=m&&e+2<this.keyframes.length&&g(f.pose,this.keyframes[e+2].pose);let w;if(v||y){const b=Gn.paced((t-p.t)/(f.t-p.t),(f.t-p.t)/1e3,v,y),M=(S,E)=>S===void 0||E===void 0?void 0:S+(E-S)*b;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(b=>b.lat,!1)??i.lat,lng:w?w.lng:c(b=>b.lng,!1)??i.lng,elevationM:w?w.elevationM:c(b=>b.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:h(b=>b.pitchDeg)??i.pitchDeg,rollDeg:c(b=>b.rollDeg??0,!0)??i.rollDeg,fovDeg:c(b=>b.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 Md;for(const i of e.keyframes)t.addKeyframe(i.t,i.pose);return t}}class Za{static MAX_CHANGE_PER_S=.05;points;followed;constructor(e){let t="none",i=0;this.points=e.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(t=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:t,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(Za.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.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],n=this.points[t+1],s=n?Za.follow(this.followed[t],i.intensity,n.intensity,(n.t-i.t)/1e3,(e-i.t)/1e3):Za.follow(this.followed[t],i.intensity,i.intensity,1,(e-i.t)/1e3);return{type:Za.typeBetween(i,n,e,s),intensity:s,character:Za.characterBetween(i,n,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,n){return e.type==="none"?t&&t.type!=="none"&&i>e.t?t.type:n>0?e.lastFalling:"none":t&&t.type==="none"&&n<=0?"none":e.type}static follow(e,t,i,n,s){const r=Za.MAX_CHANGE_PER_S,a=n>0?(i-t)/n:0,o=d=>t+a*Math.min(Math.max(d,0),n);let c=e,h=0;for(let d=0;d<8&&h<s;d++){const u=o(h)-c;if(Math.abs(u)<1e-9){const w=h<n?a:0;if(Math.abs(w)<=r){const M=h<n?Math.min(s,n):s;c=o(M),h=M;continue}const b=Math.min(s,n);c+=Math.sign(w)*r*(b-h),h=b;continue}const p=Math.sign(u),f=h<n?a:0,g=r-p*f,m=g>0?h+Math.abs(u)/g:1/0,v=h<n?n:1/0,y=Math.min(s,m,v);c+=p*r*(y-h),h=y,y===m&&(c=o(h))}return Math.min(1,Math.max(0,c))}}const Ov=1e3,Dp=.65,ux=.05,Xf={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function mo(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??Ov,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 yi(l,e,t){return l+(e-l)*t}function Pv(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function LE(l,e,t){return Math.max(e,Math.min(t,l))}function OE(l=[],e=[],t){if(!(!l.length&&!e.length))return[...new Set([...l.map(i=>i.id),...e.map(i=>i.id)])].map(i=>{const n=l.find(o=>o.id===i),s=e.find(o=>o.id===i),r=n??{...s,density:0},a=s??{...n,density:0};return{...r,eastM:yi(r.eastM,a.eastM,t),northM:yi(r.northM,a.northM,t),baseM:yi(r.baseM,a.baseM,t),thicknessM:yi(r.thicknessM,a.thicknessM,t),widthM:yi(r.widthM,a.widthM,t),depthM:yi(r.depthM,a.depthM,t),rotationDeg:Pv(r.rotationDeg,a.rotationDeg,t),density:yi(r.density,a.density,t),darkness:yi(r.darkness??0,a.darkness??0,t)}})}function PE(l,e,t){if(l.cloudLayers===void 0&&e.cloudLayers===void 0)return;const i=mo(l),n=mo(e);return t>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const a=i.find(d=>d.id===r),o=n.find(d=>d.id===r),c=a??{...o,coverage:0},h=o??{...a,coverage:0};return{...c,instances:OE(a?.instances,o?.instances,t),baseM:yi(c.baseM,h.baseM,t),thicknessM:yi(c.thicknessM,h.thicknessM,t),coverage:yi(c.coverage,h.coverage,t),sizeM:yi(c.sizeM,h.sizeM,t),density:yi(c.density,h.density,t),darkness:yi(c.darkness??l.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:c.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:yi(c.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:c.windSpeed===void 0&&h.windSpeed===void 0?void 0:yi(c.windSpeed??l.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:c.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Pv(c.windDirectionDeg??l.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function NE(l,e,t){return{cloudLayers:PE(l,e,t),cloudCover:yi(l.cloudCover,e.cloudCover,t),cloudDarkness:yi(l.cloudDarkness,e.cloudDarkness,t),highCloudCover:l.highCloudCover===void 0||e.highCloudCover===void 0?void 0:yi(l.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:yi(l.iceCrystalAlignment,e.iceCrystalAlignment,t),rareIceCrystals:l.rareIceCrystals===void 0||e.rareIceCrystals===void 0?void 0:yi(l.rareIceCrystals,e.rareIceCrystals,t),lowerCloudCover:l.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:yi(l.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:l.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:yi(l.cloudBaseM,e.cloudBaseM,t),relativeHumidity:l.relativeHumidity===void 0||e.relativeHumidity===void 0?void 0:yi(l.relativeHumidity,e.relativeHumidity,t),precipitationType:t<1?l.precipitationType:e.precipitationType,precipitationIntensity:yi(l.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Pv(l.windDirectionDeg,e.windDirectionDeg,t),windSpeed:yi(l.windSpeed,e.windSpeed,t),storm:t<1?l.storm:e.storm}}class xd{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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return i?n?NE(i.weather,n.weather,LE((e-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(e){const t=this.getInterpolatedWeatherAt(e);if(!t)return;const i=(this.ramp??=new Za(this.keyframes)).at(e);if(!i)return t;const{type:n,intensity:s,character:r}=i,a=r>0?Math.min(1,s/r):n==="none"?0:1;return{...t,precipitationType:n,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 xd;for(const i of e.keyframes)t.addKeyframe(i.t,{...Xf,...i.weather});return t}}class Sd{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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.sound;if(!n)return i.sound;const s=(e-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}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 Sd;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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}}const FE=["none","hum","whistle","rumble","crackle"],UE=100,zE={kind:"none",volume:0,pitchHz:UE};class bc{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 bc.BODIES.map(e=>({id:e.id,category:"dslr",name:e.name,projection:"rectilinear",frame:{widthMm:e.widthMm,heightMm:e.heightMm,focalLengthMm:bc.DEFAULT_FOCAL_MM,focalRangeMm:bc.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(bc.BODIES.map(e=>[e.id,e.name]))}}class ar{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*ar.DEFAULT_EYEPIECE_MM*Math.tan(ar.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=ar.BINOCULARS.map(n=>({id:n.id,category:"binoculars",name:n.name,projection:"rectilinear",visualAid:{apertureMm:n.apertureMm,magnification:n.magnification,trueFieldDeg:n.trueFieldDeg},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}})),t=ar.FIELD_STOP_MM,i=ar.TELESCOPES.map(n=>({id:n.id,category:"telescope",name:n.name,projection:"rectilinear",frame:{widthMm:t*16/9,heightMm:t,focalLengthMm:n.focalLengthMm,focalRangeMm:{minMm:n.focalLengthMm*ar.RANGE.min,maxMm:n.focalLengthMm*ar.RANGE.max}},visualAid:{apertureMm:n.apertureMm,eyepieceFocalMm:ar.DEFAULT_EYEPIECE_MM},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}}));return[...e,...i]}static names(){return Object.fromEntries(ar.instruments().map(e=>[e.id,e.name]))}}const Xh=[{id:"eye",category:"eye",name:"Naked eye",flare:0,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}},{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}},...bc.instruments(),...ar.instruments()];class Yt{static get default(){return Xh[0]}static byId(e){return Xh.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?2*Math.atan(t.heightMm/(2*t.focalLengthMm))*180/Math.PI:e.visualAid?.trueFieldDeg??Yt.UNAIDED_FIELD_DEG}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","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?Xh:Xh.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 2*Math.atan(i.heightMm/(2*t))*180/Math.PI}static focalLengthMmFor(e,t){const i=e.frame;if(!(!i||t<=0||t>=180))return i.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){const i=t??e.fNumber;if(i===void 0||e.apertureBlades===void 0)return 0;const n=e.fNumberRange;return!n||n.max<=n.min?1:Math.max(0,Math.min(1,(i-n.min)/(n.max-n.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(e){return e.flare??Yt.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class Al extends Error{}class Yf{constructor(e){this.name=e}validate(e){return!0}}class px extends Yf{min;max;constructor(e,t,i){super(e),this.min=t,this.max=i}validate(e){if(typeof e!="number")throw new Al(`${this.name} value must be a number, but was ${e}`);if(e<this.min||e>this.max)throw new Al(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${e}`);return super.validate(e)}}class cn{name;min;max;duration;subUnit;validator;constructor(e,t,i,n,s=new px(e,t,i)){this.name=e,this.min=t,this.max=i,this.subUnit=n,this.duration=n?(n.max-n.min+1)*n.duration:1,this.validator=s}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 fx{millisecond;second;minute;hour;day;month;year}class BE extends fx{}class mx extends BE{millisecond=new cn("millisecond",0,999,void 0);second=new cn("second",0,59,this.millisecond);minute=new cn("minute",0,59,this.second);hour=new cn("hour",0,23,this.minute);day=new cn("day",1,31,this.hour);month=new cn("month",1,12,this.day);year=new cn("year",0,9999,this.month)}const ot=new mx;class HE extends px{constructor(e=1,t=12){super("month",e,t)}}class Kr{static instance=new Kr;render(e){return e.value.toString()}}class Xn{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 Yf(`${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=Kr.instance){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class fi{static#e=new Map;static register(e,t){fi.#e.set(e,t)}static get(e){const t=fi.#e.get(e);if(!t)throw new Al(`No default parser registered for ${e.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return t()}}class Rp extends Xn{constructor(e=new Date().getFullYear(),t=ot.year){super(e,t)}static fromString(e,t=fi.get(Rp)){return new Rp(t.parse(e))}}class aa extends Kr{static default=new aa("0",2);constructor(e,t){super(),this.char=e,this.size=t}render(e){return super.render(e).padStart(this.size,this.char)}}class kp extends Xn{constructor(e=new Date().getMonth()+1,t=ot.month){super(e,t)}static fromString(e,t=fi.get(kp)){return new kp(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Cp extends Xn{constructor(e=new Date().getDate(),t=ot.day){super(e,t)}static fromString(e,t=fi.get(Cp)){const i=t.parse(e);return new Cp(i)}toString(e=aa.default){return super.toString(e)}}class Lp extends Xn{constructor(e=new Date().getHours(),t=ot.hour){super(e,t)}static fromString(e,t=fi.get(Lp)){return new Lp(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Op extends Xn{constructor(e=new Date().getMinutes(),t=ot.minute){super(e,t)}static fromString(e,t=fi.get(Op)){return new Op(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Pp extends Xn{constructor(e=new Date().getSeconds(),t=ot.second){super(e,t)}static fromString(e,t=fi.get(Pp)){return new Pp(t.parse(e),ot.second)}toString(e=aa.default){return super.toString(e)}}class Ol extends Xn{static renderer=new aa("0",3);constructor(e,t=ot.millisecond){super(e,t)}static parseFraction(e){return parseInt(e.padEnd(3,"0").substring(0,3),10)}toString(e=Ol.renderer){return super.toString(e)}}class GE{render(e){return e.toString()}}class VE extends GE{render(e){const t=e.value,i=Math.abs(t),n=Math.floor(i/60),s=i%60;if(n===0&&s===0)return"Z";{const r=t<0?"-":"+",a=n.toString().padStart(2,"0"),o=s>0?":"+s.toString().padEnd(2,"0"):"";return r+a+o}}}class Qc{value;name="timeshift";renderer;constructor(e=0){this.value=e}static fromString(e,t=fi.get(Qc),i=void 0){const n=t.parse(e,i);return new Qc(n)}toString(e=new VE){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class Bn{static timeshift(e,t){return e+(Bn.isDaylight(t)?60:0)}static isDaylight(e){const{year:t,month:i,day:n}=e,s=e.hour??12;if(![t,i,n].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=Bn.rule(t);if(!r)return!1;const a=Bn.rank(i,n,s);return a>=Bn.rank(r.start.month,r.start.day,2)&&a<Bn.rank(r.end.month,r.end.day,2)}static rule(e){if(e<1967)return;const t={month:10,day:Bn.sunday(e,10,-1)};return e>=2007?{start:{month:3,day:Bn.sunday(e,3,2)},end:{month:11,day:Bn.sunday(e,11,1)}}:e>=1987?{start:{month:4,day:Bn.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:Bn.sunday(e,4,-1)},end:t}}static sunday(e,t,i){const n=new Date(Date.UTC(2e3,t-1,1));n.setUTCFullYear(e);const s=1+(7-n.getUTCDay())%7;if(i>0)return s+7*(i-1);const r=[31,Bn.isLeap(e)?29:28,31,30,31,30,31,31,30,31,30,31][t-1];let a=s;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 WE={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},$E={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},XE={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},YE={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},KE={name:"PT",timeshift:l=>Bn.timeshift(-480,l),title:"Pacific Time (US)"},qE={name:"MT",timeshift:l=>Bn.timeshift(-420,l),title:"Mountain Time (US)"},jE={name:"CT",timeshift:l=>Bn.timeshift(-360,l),title:"Central Time (US)"},ZE={name:"ET",timeshift:l=>Bn.timeshift(-300,l),title:"Eastern Time (US)"},JE={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},QE={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},eA={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},tA={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},iA={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},nA={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},sA={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},rA={name:"Z",timeshift:"Z",title:"UTC"},aA={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},oA={name:"BST",timeshift:"+01",title:"British Summer Time"},lA={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},cA={name:"CET",timeshift:"+01",title:"Central European Time"},hA={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},dA={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},uA={name:"BJT",timeshift:"+08",title:"Beijing Time"},pA={name:"CST",timeshift:"-06",title:"Central Standard Time"},fA={name:"JST",timeshift:"+09",title:"Japan Standard Time"},mA={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},gA={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},vA={name:"LST",timeshift:"?",title:"Local Sideral Time"},e1=[nA,mA,iA,uA,oA,pA,QE,cA,lA,jE,JE,tA,eA,ZE,aA,dA,fA,vA,XE,hA,YE,qE,gA,$E,WE,KE,sA,rA];class Kf{static instance=new Kf;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 n=t.join("-"),s=e.timeshift?e.timeshift.toString():"",r=i.join(":")+s;return n+(r.length>0?"T"+r:"")}}class No extends Al{constructor(e="method is abstract"){super(e)}}class Nv{units;constructor(e){this.units=e}newYear(e){throw new No}newMonth(e){throw new No}newDay(e){throw new No}newHour(e){throw new No}newMinute(e){throw new No}newSecond(e){throw new No}}class bA extends fx{millisecond=new cn("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new cn("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new cn("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new cn("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new cn("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new cn("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new cn("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Fv=new bA;class Uv{static instance=new Uv;render(e){const t=Yo.toSpec(e);let i="P";const n=t.years;n&&(i+=n.toString()+"Y");const s=t.months;s&&(i+=s.toString(Kr.instance)+"MM");const r=t.days;r&&(i+=r.toString(Kr.instance)+"D");const a=t.hours;a&&(i+=a.toString(Kr.instance)+"H");const o=t.minutes;o&&(i+=o.toString(Kr.instance)+"M");const c=t.seconds;return c&&(i+=c.toString(Kr.instance)+"S"),i}}class Yo extends Xn{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*ot.year.duration:0)+(e.months?e.months*ot.month.duration:0)+(e.days?e.days*ot.day.duration:0)+(e.hours?e.hours*ot.hour.duration:0)+(e.minutes?e.minutes*ot.minute.duration:0)+(e.seconds?e.seconds*ot.second.duration:0)},new cn("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(e,t=wA){let i=typeof e=="number"?e:e.value;const n=i>0?1:-1;i=Math.abs(i);const s={},r=i/ot.year.duration,a=Math.floor(r);a>0&&(s.years=t.newYear(n*a),i-=a*ot.year.duration);const o=i/ot.month.duration,c=Math.floor(o);c>0&&(s.months=t.newMonth(n*c),i-=c*ot.month.duration);const h=i/ot.day.duration,d=Math.floor(h);d>0&&(s.days=t.newDay(n*d),i-=d*ot.day.duration);const u=i/ot.hour.duration,p=Math.floor(u);p>0&&(s.hours=t.newHour(n*p),i-=p*ot.hour.duration);const f=i/ot.minute.duration,g=Math.floor(f);g>0&&(s.minutes=t.newMinute(n*g),i-=g*ot.minute.duration);const m=i/ot.second.duration,v=Math.floor(n*m);return v>0&&(s.seconds=t.newSecond(v)),s}static fromString(e,t=fi.get(Yo)){return new Yo(t.parse(e))}static between(e,t){const i=t.getTime(),n=e.getTime();return new Yo(i-n)}toSpec(){return Yo.toSpec(this)}toString(e=Uv.instance){return e.render(this)}}class gx extends Nv{constructor(e){super(e)}newYear(e){return new Rp(e,this.units.year)}newMonth(e){return new kp(e,this.units.month)}newDay(e){return new Cp(e,this.units.day)}newHour(e){return new Lp(e,this.units.hour)}newMinute(e){return new Op(e,this.units.minute)}newSecond(e){return new Pp(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new Qc(typeof e=="number"?e:e.value)}}const yA=new gx(ot),wA=new gx(Fv);class ur{#e;#t;#i;#n;#s;#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:ur.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 Xn?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 Xn?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 Xn?e:this.factory.newDay(e)}get hour(){return this.#n}set hour(e){const t=typeof e=="number";this.#n&&t?this.#n.value=e:this.#n=t?this.factory.newHour(e):!e||e.start||e instanceof Xn?e:this.factory.newHour(e)}get minute(){return this.#s}set minute(e){const t=typeof e=="number";this.#s&&t?this.#s.value=e:this.#s=t?this.factory.newMinute(e):!e||e.start||e instanceof Xn?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 Xn?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 Xn)?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 Qc)?this.factory.newTimeshift(e):e}get factory(){return yA}static fromString(e,t=fi.get(ur)){const{year:i,month:n,day:s,hour:r,minute:a,second:o,millisecond:c,timeshift:h}=t.parse(e);return new ur({year:i,month:n,day:s,hour:r,minute:a,second:o,millisecond:c,timeshift:h})}static timeshiftOf(e){return-e.getTimezoneOffset()||0}static fromDate(e){return new ur({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return ur.fromString(i)}#l(e){if(this.constructor.name!==e.constructor.name)throw new Yf(`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 Yo(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 ur(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=Kf.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 n=this.day?.toSpec();n&&(e.day=n);const s=this.hour?.toSpec();s&&(e.hour=s);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 Wd extends Kr{static instance=new Wd(aa.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 Pl extends Xn{#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=Wd.instance){return super.toString(e)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class vx extends mx{year=new cn("year",-9999,9999,this.month);yearExtended=new cn("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const dp=new vx;class Ko extends Pl{constructor(e,t=dp.year){super(e,t)}static fromString(e,t=dp.year,i=fi.get(Ko)){const n=i.parse(e),s=n.value.start;if(e.startsWith("Y")&&(t=dp.yearExtended),s!==void 0){const r=new Ko(Object.assign({...n},{value:Math.max(s,t.min)})),a=new Ko(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new Ko(n,t)}}class bx extends Yf{monthValidator=new HE;validate(e){switch(e){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(e)}}}class qo extends Pl{constructor(e,t=new cn(ot.month.name,1,24,ot.day,new bx)){super(e,t)}static fromString(e,t=fi.get(qo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.month;const r=new qo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new qo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new qo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class jo extends Pl{constructor(e,t=ot.day){super(e,t)}static fromString(e,t=fi.get(jo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.day;const r=new jo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new jo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new jo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class Zo extends Pl{constructor(e,t=ot.hour){super(e,t)}static fromString(e,t=fi.get(Zo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.hour;const r=new Zo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Zo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Zo(i)}}class Jo extends Pl{constructor(e,t=ot.minute){super(e,t)}static fromString(e,t=fi.get(Jo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.minute,r=new Jo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Jo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Jo(i)}toString(e=Wd.instance){return super.toString(e)}}class Qo extends Pl{constructor(e,t=ot.second){super(e,t)}static fromString(e,t=fi.get(Qo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.second,r=new Qo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Qo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Qo(i)}}class eh extends Qc{static fromString(e,t=fi.get(eh),i=void 0){return new eh(t.parse(e,i))}}class yx extends Nv{constructor(e){super(e)}newYear(e){return new Ko(e,this.units.year)}newMonth(e){return new qo(e,this.units.month)}newDay(e){return new jo(e,this.units.day)}newHour(e){return new Zo(e,this.units.hour)}newMinute(e){return new Jo(e,this.units.minute)}newSecond(e){return new Qo(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new eh(typeof e=="number"?e:e.value)}}const MA=new yx(dp);new yx(Fv);class Fo extends ur{constructor(e){super(e)}get factory(){return MA}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 Fo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static fromString(e,t=fi.get(Fo)){const i=t.parse(e);return new Fo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Fo.fromString(i)}clone(){return new Fo(this.toSpec())}}class fh extends Pl{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 xA extends vx{year=new cn("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Q0=new xA;class el extends fh{constructor(e,t=Q0.year){super(e,t)}static fromString(e,t=Q0.year,i=fi.get(el)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new el(Object.assign({...n},{value:Math.max(s,t.min)})),a=new el(Object.assign({...n},{value:Math.min(n.value.end,t.max)})),o={start:r,end:a},c=n.value.estimate;return c&&(o.estimate=c),o}else return new el(n)}}class SA extends bx{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 tl extends fh{constructor(e,t=new cn(ot.month.name,1,41,ot.day,new SA)){super(e,t)}static fromString(e,t=fi.get(tl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.month,r=new tl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new tl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new tl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class il extends fh{constructor(e,t=ot.day){super(e,t)}static fromString(e,t=fi.get(il)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.day,r=new il(Object.assign({...i},{value:Math.max(n,s.min)})),a=new il(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new il(i)}toString(e){return super.toString(e).padStart(2,"0")}}class nl extends fh{constructor(e,t=ot.hour){super(e,t)}static fromString(e,t=fi.get(nl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.hour,r=new nl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new nl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new nl(i)}}class sl extends fh{constructor(e,t=ot.minute){super(e,t)}static fromString(e,t=fi.get(sl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.minute,r=new sl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new sl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new sl(i)}}class rl extends fh{constructor(e,t=ot.second){super(e,t)}static fromString(e,t=ot.second,i=fi.get(rl)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new rl(Object.assign({...n},{value:Math.max(s,t.min)})),a=new rl(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new rl(n,t)}}class wx extends eh{}class EA extends Wd{qualifier(){return""}}class Ja extends Kf{static instance=new Ja;static valueRenderer=new EA(aa.default);static names=["year","month","day","hour","minute","second"];static qualifier(e,t){return e?t?"%":"?":t?"~":""}renderComponent(e,t){const i=e[t],n=Ja.names.slice(Ja.names.indexOf(t)+1).map(a=>e[a]).filter(Boolean),s=Ja.qualifier(i.uncertainComponent,i.approximateComponent),r=Ja.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!n.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!n.some(a=>a.approximate));return s+i.toString(Ja.valueRenderer)+r}}class Mx extends Nv{constructor(e){super(e)}newYear(e){return new el(e,this.units.year)}newMonth(e){return new tl(e,this.units.month)}newDay(e){return new il(e,this.units.day)}newHour(e){return new nl(e,this.units.hour)}newMinute(e){return new sl(e,this.units.minute)}newSecond(e){return new rl(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new wx(typeof e=="number"?e:e.value)}}const AA=new Mx(Q0);new Mx(Fv);class Uo extends Fo{constructor(e){super(e)}toString(e=Ja.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 AA}static fromDate(e){return new Uo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static fromString(e,t=fi.get(Uo)){const i=t.parse(e);return new Uo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Uo.fromString(i)}clone(){return new Uo(this.toSpec())}}class qf{regExp;constructor(e,t){this.name=e,this.regExp=new RegExp(`^(?:${t})$`)}regexGroups(e){const t=this.regExp.exec(e);if(!t)throw new Al(`Invalid ${this.name} "${e}"`);return t.groups}parseGroups(e){throw new No(`${this.constructor.name} is abstract`)}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}class zv extends qf{constructor(e,t){super(e,t)}static read(e){return{value:e?parseInt(e,10):void 0}}parseGroups(e){return zv.read(e[this.name])}parse(e){if(e.startsWith("-"))throw new Al(`${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,n="\\d"){return ce.group(e,`${i||""}[${n}]${t}`)}}const t1="timeshiftValue",i1="shiftHour",n1="shiftMinute";class Bv extends qf{static format(e=""){return e1.map(t=>t.name).join("|")+"|"+ce.nonCapturingGroup(ce.group(e+i1,ce.numberGroup(ce.groupName(e,t1),"{2}","[+-]")),ce.optionalNonCapturingGroup(":?",ce.numberGroup(ce.groupName(e,n1),"{2}",void 0)))}constructor(){super(t1,Bv.format())}parse(e,t){let i=0;const n=e1.find(s=>s.name===e);if(n){if(typeof n.timeshift=="function")try{return n.timeshift(t??{})}catch(s){throw new Al(`The time zone ${e} depends on the date: ${s.message}`)}e=n.timeshift}if(e!=="Z"){const s=this.regexGroups(e),r=s[i1];r&&(i+=parseInt(r,10)*60);const a=s[n1];a&&(i+=parseInt(a,10))}return i}}class Ui extends zv{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=Ui.uncertainGroup+Ui.approximateGroup;constructor(e,t){super(e,t)}static qualifierFormat(e,t){return ce.optionalGroup(e,`\\${t}`)}static formatSuffix(e){return this.qualifierFormat(ce.groupName(Ui.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(Ui.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(Ui.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 n=0,s;for(s=0;s<t.length;s++){const c=t[s];if(c==="X")break;n=n*10+parseInt(c,10)}if(s<t.length){let c=1;for(let u=0;u<t.length-s;u++)c*=10;const h=i*n*c,d=h+c-1;n={start:h,end:d}}else n*=i;const r=e[ce.groupName(Ui.uncertainAndApproximateGroup,this.name)],a=e[ce.groupName(Ui.approximateGroup,this.name)]||r,o=e[ce.groupName(Ui.uncertainGroup,this.name)]||r;return{value:n,approximate:a?!!a:!1,uncertain:o?!!o:!1}}}const s1="yearValue";class Np extends Ui{constructor(){super(s1,Np.format())}static format(e=""){return"Y?"+Ui.numberFormat(ce.groupName(e,s1),"+","[-]?")}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const r1="monthValue";class Fp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,r1),"{1,2}",void 0)}constructor(){super(r1,Fp.format())}}const a1="dayValue";class Up extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,a1),"{1,2}",void 0)}constructor(){super(a1,Up.format())}}const o1="hourValue";class zp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,o1),"{1,2}",void 0)}constructor(){super(o1,zp.format())}}const l1="minuteValue";class Bp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,l1),"{1,2}",void 0)}constructor(){super(l1,Bp.format())}}const c1="secondValue";class Hp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,c1),"{1,2}",void 0)}constructor(){super(c1,Hp.format())}}class Gp extends Bv{}class un extends qf{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=un.format()){super("date",e)}static format(e=""){return ce.group(ce.groupName(e,un.yearGroup),Np.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,un.monthGroup),Fp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,un.dayGroup),Up.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,un.hourGroup),zp.format(e)),":",ce.group(ce.groupName(e,un.minuteGroup),Bp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,un.secondGroup),Hp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,un.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,un.timeshiftGroup),Gp.format(e)))))}parseGroups(e){const t=e[un.millisecondGroup],i=t?Ol.parseFraction(t):void 0,n=e[un.secondGroup],s=n?Qo.fromString(n,new Hp):void 0,r=e[un.minuteGroup];let a;r&&(a=Jo.fromString(r,new Bp),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const o=e[un.hourGroup];let c;o&&(c=Zo.fromString(o,new zp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[un.dayGroup];let d;h&&(d=jo.fromString(h,new Up),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[un.monthGroup];let p;u&&(p=qo.fromString(u,new Fp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[un.yearGroup];let g;f&&(g=Ko.fromString(f,void 0,new Np),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[un.timeshiftGroup],v=m?eh.fromString(m,new Gp,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}class nn extends Ui{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=nn.uncertainGroup+nn.approximateGroup;constructor(e,t){super(e,t)}static numberFormat(e,t,i){return this.qualifierFormat(ce.groupName(nn.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(nn.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(nn.uncertainAndApproximateGroup,e),"%")+Ui.numberFormat(e,t,i)}parseGroups(e){const t=super.parseGroups(e),i=e[ce.groupName(nn.uncertainAndApproximateGroup,this.name)];return(e[ce.groupName(nn.uncertainGroup,this.name)]||i)&&(t.uncertainComponent=!0),(e[ce.groupName(nn.approximateGroup,this.name)]||i)&&(t.approximateComponent=!0),t}}const yh="yearValue",h1="exp",d1="signif";class Vp extends nn{constructor(){super(yh,Vp.format())}static format(e=""){return"Y?"+ce.nonCapturingGroup(ce.group(ce.groupName(e,h1),"[-]?\\d+E\\d+")+"|"+nn.numberFormat(ce.groupName(e,yh),"+","[-]?")+ce.optionalGroup(ce.groupName(e,d1),"S\\d+"))}parseGroups(e){const t=e[h1];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[yh]=c.toString()}const i=e[d1],n=e[yh];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[yh]=(o<0?"-":"")+c}const s=super.parseGroups(e);return i&&(s.value.estimate=parseInt(n,10)),s}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const u1="monthValue";class Wp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,u1),"{1,2}",void 0)}constructor(){super(u1,Wp.format())}}const p1="dayValue";class $p extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,p1),"{1,2}",void 0)}constructor(){super(p1,$p.format())}}const f1="hourValue";class Xp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,f1),"{1,2}",void 0)}constructor(){super(f1,Xp.format())}}const m1="secondValue";class Yp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,m1),"{1,2}",void 0)}constructor(){super(m1,Yp.format())}}const g1="minuteValue";class Kp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,g1),"{1,2}",void 0)}constructor(){super(g1,Kp.format())}}class TA extends Gp{}class pn extends qf{static yearGroup=un.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",pn.format())}static format(e=""){return ce.group(ce.groupName(e,pn.yearGroup),Vp.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,pn.monthGroup),Wp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,pn.dayGroup),$p.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,pn.hourGroup),Xp.format(e)),":",ce.group(ce.groupName(e,pn.minuteGroup),Kp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,pn.secondGroup),Yp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,pn.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,pn.timeshiftGroup),TA.format(e)))))}parseGroups(e){const t=e[pn.millisecondGroup],i=t?Ol.parseFraction(t):void 0,n=e[pn.secondGroup];let s;n&&(s=rl.fromString(n,void 0,new Yp),s.uncertain=s?.uncertain||!1,s.approximate=s?.approximate||!1);const r=e[pn.minuteGroup];let a;r&&(a=sl.fromString(r,new Kp),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const o=e[pn.hourGroup];let c;o&&(c=nl.fromString(o,new Xp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[pn.dayGroup];let d;h&&(d=il.fromString(h,new $p),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[pn.monthGroup];let p;u&&(p=tl.fromString(u,new Wp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[pn.yearGroup];let g;f&&(g=el.fromString(f,void 0,new Vp),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[pn.timeshiftGroup],v=m?wx.fromString(m,new Gp,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}const xx=["spring","summer","autumn","winter"],eg=21,_A=32,IA=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let DA;function RA(){return DA??=new pn}function zl(l){return typeof l?.value=="number"?l.value:void 0}function up(l){const e=l.trim();if(/^\d{1,2}:/.test(e)){const r=IA.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=Uo.fromString(e,RA())}catch{return}const i=zl(t.year),n=zl(t.month),s=n!==void 0&&n>=eg&&n<=_A;if(!(t.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(n!==void 0&&n>12&&!s)&&!(s&&(t.day||t.hour)))return{year:i,month:s?void 0:n,...s?{season:xx[(n-eg)%4]}:{},day:zl(t.day),hour:zl(t.hour),minute:zl(t.minute),second:zl(t.second),raw:e}}function al(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}-${eg+xx.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 tg(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 v1(l){return(((l.day??0)*24+(l.hour??0))*60+(l.minute??0))*6e4+(l.second??0)*1e3}const kA=["year","month","day","hour","minute"],CA=["day","hour","minute"];function b1(l,e){return e.filter(t=>l[t]!==void 0).join(",")}function th(l){if(l.durationSeconds!==void 0)return l.durationSeconds*1e3;const e=l.durationText===void 0?void 0:ns.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?kA:CA,n=b1(l.time,i);if(!(n===""||n!==b1(l.endTime,i)))return t?tg(l.endTime)-tg(l.time):v1(l.endTime)-v1(l.time)}function LA(l){if(l.durationSeconds===void 0&&!(!l.time||!l.endTime))return th(l)===void 0?"imprecise":void 0}class jf{constructor(e,t,i,n,s,r,a,o,c=[],h,d,u,p=[],f=[],g=[],m=[]){this.event=e,this.timeline=t,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,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=g,this.traces=m}provenance=rs.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;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 jf({eventType:"sighting",time:e,place:t},new $f,new Md,new xd,new Sd,i)}}const OA=0,PA=0;function ut(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:OA,headingDeg:void 0,pitchDeg:PA,fovDeg:Yt.fieldOfViewDeg(l.instrument)}}function Ki(l,e){return l.weatherTrack.getInterpolatedWeatherAt(e)??l.weather??Xf}function Jd(l,e){return l.weatherTrack.getActualWeatherAt(e)??l.weather??Xf}function Hv(l,e){return l.soundTrack.getInterpolatedSoundAt(e)??zE}class Ed{constructor(e,t){this.json=e,this.url=t,this.tracks=(e.events??[]).filter(i=>i.eventType===wi.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,n,s){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:wi.SIGHTING_EVENT,...t!==void 0?{time:t}:{},...i!==void 0?{title:i}:{},url:`observer-${r}.json`}]},o=new Ed(a,new URL("case.json",s).href),c=o.tracks[0];return c.recording=e,c.base={url:n},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(n=>n.kind==="observer");return i.find(n=>n.event.id!==void 0&&t.includes(n.event.id))??i.find(n=>n.recording?.id!==void 0&&t.includes(n.recording.id))}get interviews(){return(this.json.events??[]).filter(e=>e.eventType===wi.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 n=t.find(s=>s.event.id===i)??t.find(s=>s.recording?.id===i);return n?[n]:[]})}addInterview(e,t,i,n,s){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:wi.INTERVIEW_EVENT,id:`interview-${a}-${o}`,...e?{interviewOf:this.ensureId(e)}:{},time:t,...s!==void 0?{medium:s}:{},...n!==void 0&&n.length>0?{by:n}:{},...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(s=>s.eventType===wi.SIGHTING_EVENT&&typeof s.url=="string"&&s.url!=="").map(s=>{const r=new URL(s.url,this.url).href,a=s.interpretationOf===void 0?"observer":"reading",o=this.tracks.find(c=>c.url===r);return o?(o.event=s,o.kind=a,o):{event:s,url:r,kind:a}});this.tracks.splice(0,this.tracks.length,...i);const n=new Map;for(const[s,r]of this.transcripts){const a=(e.events??[]).find(o=>o.eventType===wi.INTERVIEW_EVENT&&(s.id!==void 0&&o.id===s.id||s.url!==void 0&&o.url===s.url));a&&n.set(a,r)}this.transcripts.clear();for(const[s,r]of n)this.transcripts.set(s,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,n=t(e.recording?.observer?.lastName)||t(e.recording?.observer?.id)||t(i),s=this.eventIds(e);if(n!==""){let a=n;for(let o=2;s.has(a);o++)a=`${n}-${o}`;return a}let r=1;for(;s.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,n=a=>a===i||a===e.recording?.id,s=(this.json.events??[]).filter(a=>a.eventType===wi.SIGHTING_EVENT&&a.interpretationOf!==void 0&&[a.interpretationOf].flat().some(o=>o!==void 0&&n(o))),r=this.interviews.filter(a=>[a.interviewOf].flat().some(o=>o!==void 0&&n(o)));if(t==="")return i===void 0?"ok":s.length>0||r.length>0?"empty":(delete e.event.id,this.caseChanged=!0,"ok");if(!Ed.ID_PATTERN.test(t))return"invalid";if(this.eventIds(e).has(t))return"taken";if(t===i)return"ok";for(const a of s){const o=[a.interpretationOf].flat().map(c=>n(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&&n(c)?t:c);a.interviewOf=Array.isArray(a.interviewOf)?o:o[0]}return e.event.id=t,this.caseChanged=!0,"ok"}problems(){return wi.problems(this.json,this.tracks.map(e=>e.recording?.id).filter(e=>e!==void 0))}addReading(e,t,i,n){const s=e.recording;if(!s)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(`${s.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:g,description:m,sources:v,tags:y,timeline:w,milestones:b,interpretation:M,...S}=structuredClone(s),E={version:1,id:`${s.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,...n!==void 0&&n.length>0?{by:n}:{},...i!==void 0?{title:i}:{},url:d+h};this.json.events=[...this.json.events??[],x],this.caseChanged=!0;const T={event:x,url:new URL(x.url,this.url).href,kind:"reading",recording:E};return this.tracks.push(T),T}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(n=>n!==void 0&&t.includes(n)))}addObservation(e,t,i,n){const s=new Set(this.tracks.map(g=>g.event.url)),r=new Set(this.tracks.map(g=>g.recording?.id)),a=(e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",o=n?"interpretation":"observer";let c=`${o}-${a}.json`,h=e.id??a;for(let g=2;s.has(c)||r.has(h);g++)c=`${o}-${a}-${g}.json`,h=`${e.id??a}-${g}`;const d={...e,id:h},u=this.tracks[0]?.event.url?.includes("/")?this.tracks[0].event.url.replace(/[^/]*$/,""):"",p={type:"event",eventType:"sighting",...n?{interpretationOf:this.ensureId(n.account)}:{},...t!==void 0?{time:t}:{},...n?.by&&n.by.length>0?{by:n.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:n?"reading":"observer",recording:d};return this.tracks.push(f),n||(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(n=>n!==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(/[^/]*$/,""),n=o=>o.startsWith(i)?o.slice(i.length):o,s=this.tracks.filter(o=>e&&o.recording!==void 0&&(t||this.changed(o))).map(o=>({path:n(o.url),content:JSON.stringify(o.recording,null,2)+`
|
|
334
|
+
`;class Nc extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(Nc.TAG)||customElements.define(Nc.TAG,Nc)}subject;messages=J0;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=xE;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"?J0:await pE(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?Hr.frozenLink(e.link(),"0.136.1"):e.link(),this.fitLink();const n=`<script type="module" src="${t?Hr.frozen(e.module,"0.136.1"):Hr.current(e.module,import.meta.url,Jc.home())}"><\/script>
|
|
335
|
+
${e.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const e=this.messages,t=(i,n)=>{this.shadow.getElementById(i).textContent=n};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.136.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??=oe(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 hs{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 n=e[i]??e[hs.base(i)];if(n)return n}const t=new Set(this.preferences.map(i=>hs.base(i)));for(const[i,n]of Object.entries(e))if(n&&t.has(hs.base(i)))return n;return Object.values(e).find(i=>i)??void 0}write(e,t,i){const n=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return n;const s={...e},r=Object.keys(s).find(a=>a===i)??Object.keys(s).find(a=>hs.base(a)===hs.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(e){return e.toLowerCase().split("-")[0]}}function wd(l,e){for(const t of l){const i=t.toLowerCase().split("-")[0];if(e.includes(i))return i}return"en"}class Gs{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 n=t.getRootNode();t=n instanceof ShadowRoot?n.host:void 0}}}class ns{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=ns.ISO.exec(t);if(!i||t==="P"||t.endsWith("T"))return;const[,n,s,r,a,o]=i,c=d=>d===void 0?0:Number(d.replace(",",".")),h=c(n)*604800+c(s)*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),n="?~%".includes(i)?i:"";n!==""&&(t=t.slice(0,-1).trim());const s=t.split("/");if(s.length>2)return;const r=s.map(d=>ns.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:n,minSeconds:c,maxSeconds:h,chosenSeconds:(c+h)/2}}static isExact(e){const t=ns.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),n=Math.floor(t%3600/60),s=Math.round(t%60*10)/10;return`PT${`${i>0?`${i}H`:""}${n>0?`${n}M`:""}${s>0||i===0&&n===0?`${s}S`:""}`}`}static say(e){const t=Math.round(e*10)/10;if(t<60)return`${t} s`;const i=Math.floor(t/3600),n=Math.floor(t%3600/60),s=Math.round(t%60*10)/10,r=[];return i>0&&r.push(`${i} h`),n>0&&r.push(`${n} min`),s>0&&r.push(`${s} s`),r.join(" ")}}class xt{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/xt.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 SE(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 cx(l,e="#39ff14"){return{kind:"oval",bounds:l,color:e,angle:0,transparency:0,haloScale:0,selected:!1}}function hx(l,e,t="#39ff14"){return{kind:"polygon",bounds:l,points:e,color:t,angle:0,transparency:0,haloScale:0,selected:!1}}function EE(l,e="#39ff14"){const{width:t,height:i}=l;return hx(l,[{x:0,y:0},{x:t,y:0},{x:t,y:i},{x:0,y:i}],e)}const AE={oval:cx,polygon:EE};function Jb(l,e){return{...AE[e.presetId](l,e.color),transparency:e.transparency,haloScale:e.haloScale,blur:e.blur,brightness:e.brightness}}function TE(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 dx(l,e,t){const i=l.bounds.width,n=l.bounds.height;return{...l,bounds:{x:e-i/2,y:t-n/2,width:i,height:n}}}function Ss(l,e,t){return l+(e-l)*t}function Qb(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 IE(l,e,t){const i=Qb(l),n=Qb(e);return!i||!n?t<1?l:e:_E([Ss(i[0],n[0],t),Ss(i[1],n[1],t),Ss(i[2],n[2],t)])}function DE(l,e,t){const i={x:Ss(l.bounds.x,e.bounds.x,t),y:Ss(l.bounds.y,e.bounds.y,t),width:Ss(l.bounds.width,e.bounds.width,t),height:Ss(l.bounds.height,e.bounds.height,t)},n=Ss(l.angle,e.angle,t),s=Ss(l.transparency,e.transparency,t),r=Ss(l.haloScale,e.haloScale,t),a=Ss(l.blur??0,e.blur??0,t),o=Ss(l.brightness??0,e.brightness??0,t),c=IE(l.color,e.color,t),h=xt.lerpAngular(l.angular,e.angular,t),d=SE(l.aim,e.aim,t);return l.kind==="polygon"&&e.kind==="polygon"&&l.points.length===e.points.length?{...l,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d,points:l.points.map((u,p)=>({x:Ss(u.x,e.points[p].x,t),y:Ss(u.y,e.points[p].y,t)}))}:{...t<1?l:e,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:o,color:c,angular:h,aim:d}}class ya{static DEFAULT_COLOR="#e8e6df";static complete(e,t=[]){const i=new Map;return e.map((n,s)=>({keyframe:n,index:s})).sort((n,s)=>n.keyframe.t-s.keyframe.t).map(({keyframe:n,index:s})=>({t:n.t,shapes:(n.shapes??[]).map((r,a)=>{const o=`timeline.keyframes.${s}.shapes.${a}.shape`,c=ya.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,n=new Set;return e.map((s,r)=>({t:s.t,shapes:s.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=ya.thinned(a.shape,o);if(t){const h=c;t(r,a.sourceId)?(delete h.bounds,delete h.points,n.add(a.sourceId)):n.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,n={};for(const[s,r]of Object.entries(e))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[s]&&JSON.stringify(r)!==JSON.stringify(i[s]))&&(n[s]=r);return"bounds"in n&&(e.aim&&(n.aim=e.aim),e.angular&&(n.angular=e.angular)),n}static completed(e,t,i,n){const s=e.shape??{},r=t??ya.firstAppearance(s,i,n),a={...r};s.bounds&&t&&(t.aim||t.angular)&&!s.aim&&!s.angular&&n.push({kind:"pixels-over-angles",path:i}),s.bounds&&(s.aim||delete a.aim,s.angular||delete a.angular);const o=s.kind??r.kind??"oval",c={...a,...s,kind:o};if(o==="polygon"&&!c.points){n.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:`"${ya.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:{...ya.NEUTRAL_BOUNDS},color:ya.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:xt.CANVAS_WIDTH_PX/2,y:xt.CANVAS_HEIGHT_PX/2,width:1,height:1}}class $f{keyframes=[];order=[];groups=[];span=0;addKeyframe(e,t){const i=this.findInsertIndex(e);if(this.keyframes[i]?.t===e){const n=new Set(t.map(s=>s.sourceId));this.keyframes[i]={t:e,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...t]}}else this.keyframes.splice(i,0,{t:e,shapes:[...t]});for(const n of t)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return n.shape}}getInterpolatedShapeAt(e,t){const i=this.findShapeAtOrBefore(e,t);if(i?.t===e)return i.shape;const n=this.findShapeAtOrAfter(e,t);return i?n?DE(i.shape,n.shape,(e-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(e,t){for(let i=this.findInsertIndex(e);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(e,t,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const a=this.getInterpolatedShapeAt(e,s[r]);if(a&&TE(a,t,i))return{sourceId:s[r],shape:a}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const i=this.keyframes[t].shapes.filter(n=>n.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),n=this.keyframes[i];if(n?.t!==e)return;const s=n.shapes.filter(r=>r.sourceId!==t);s.length===0?this.keyframes.splice(i,1):s.length!==n.shapes.length&&(this.keyframes[i]={t:e,shapes:s})}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(n=>n.includes(e));if(t===-1)return;const i=this.groups[t].filter(n=>n!==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 $f;for(const n of ya.complete(e.keyframes??[],t))i.addKeyframe(n.t,n.shapes);if(e.span!==void 0&&e.span>0&&(i.span=e.span),e.order){const n=i.order.filter(s=>!e.order.includes(s));i.order=[...e.order,...n]}return e.groups&&(i.groups=e.groups.map(n=>n.filter(s=>i.order.includes(s))).filter(n=>n.length>=2)),i}}function RE(l,e,t){return Math.max(e,Math.min(t,l))}function kE(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function Ul(l,e,t){return l+(e-l)*t}function CE(l,e,t){return{lat:l.lat===void 0||e.lat===void 0?void 0:Ul(l.lat,e.lat,t),lng:l.lng===void 0||e.lng===void 0?void 0:Ul(l.lng,e.lng,t),elevationM:Ul(l.elevationM,e.elevationM,t),headingDeg:l.headingDeg===void 0||e.headingDeg===void 0?void 0:kE(l.headingDeg,e.headingDeg,t),pitchDeg:Ul(l.pitchDeg,e.pitchDeg,t),rollDeg:Ul(l.rollDeg??0,e.rollDeg??0,t),fovDeg:Ul(l.fovDeg,e.fovDeg,t),fNumber:l.fNumber,focusDistanceM:l.focusDistanceM,filter:l.filter}}class Gn{static at(e,t,i,n,s){const r=e[i],o=e[i+1]-r;if(o<=0)return t[i];const c=Gn.tangent(e,t,i,s),h=Gn.tangent(e,t,i+1,s),d=(n-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,n){const s=e[i],a=e[i+1]-s;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=Gn.tangent(e,t,i,!0),d=Gn.ARRIVAL*(t[i+1]-t[i])/a;return Gn.hermite(t[i],h,t[i+1],d,a,(n-s)/a)}return!c&&i>0&&t[i-1]!==t[i]?t[i]+Gn.settle(e,t,i,n-s,a):Gn.at(e,t,i,n,!0)}static settle(e,t,i,n,s){const r=e[i]-e[i-1];if(r<=0||n<=0)return 0;const a=Gn.ARRIVAL*(t[i]-t[i-1])/r,o=Math.min(Gn.SETTLE_MS,.4*r),c=Number.isFinite(s)?(1-Math.min(1,n/s))**2:1;return a*n*Math.exp(-n/o)*c}static hermite(e,t,i,n,s,r){const a=r*r,o=a*r;return(2*o-3*a+1)*e+(o-2*a+r)*s*t+(-2*o+3*a)*i+(o-a)*s*n}static BRAKE_S=.8;static paced(e,t,i,n){if(!i&&!n)return e;const s=t>0?Math.min(.5,Gn.BRAKE_S/t):.5;if(i&&n){const a=1/(1-s);return e<=s?a*e*e/(2*s):e>=1-s?1-a*(1-e)*(1-e)/(2*s):a*(e-s/2)}const r=a=>{const o=1/(1-s/2);if(a<=1-s)return o*a;const c=a-(1-s);return o*(1-s)+o*(c-c*c/(2*s))};return n?r(e):1-r(1-e)}static tangent(e,t,i,n){const s=e.length-1,r=p=>(t[p+1]-t[p])/(e[p+1]-e[p]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-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 Md{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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.pose;if(!n)return this.settledAfterEnd(t-1,e);const s=CE(i.pose,n.pose,RE((e-i.t)/(n.t-i.t),0,1));return this.humanly(t-1,e,s)}settledAfterEnd(e,t){const i=this.keyframes[e];if(e<1)return i.pose;const n=this.keyframes[e-1],s=[n.t,i.t],r=(h,d)=>h===void 0||d===void 0?0:Gn.settle(s,[h,d],1,t-i.t,1/0),a=n.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-n.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(n.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 n=Math.max(0,e-1),s=Math.min(this.keyframes.length-1,e+2),r=this.keyframes.slice(n,s+1),a=e-n,o=r.map(b=>b.t),c=(b,M)=>{const S=r.map(E=>b(E.pose));if(!S.some(E=>E===void 0))return Gn.at(o,S,a,t,M)},h=b=>{const M=r.map(S=>b(S.pose));if(!M.some(S=>S===void 0))return Gn.gaze(o,M,a,t)},d=r.map(b=>b.pose.headingDeg);let u;if(d.every(b=>b!==void 0)){const b=[d[0]];for(let M=1;M<d.length;M++)b.push(b[M-1]+((d[M]-d[M-1])%360+540)%360-180);u=(Gn.gaze(o,b,a,t)%360+360)%360}const p=this.keyframes[e],f=this.keyframes[e+1],g=(b,M)=>b.lat===M.lat&&b.lng===M.lng&&b.elevationM===M.elevationM,m=!g(p.pose,f.pose),v=m&&e>0&&g(this.keyframes[e-1].pose,p.pose),y=m&&e+2<this.keyframes.length&&g(f.pose,this.keyframes[e+2].pose);let w;if(v||y){const b=Gn.paced((t-p.t)/(f.t-p.t),(f.t-p.t)/1e3,v,y),M=(S,E)=>S===void 0||E===void 0?void 0:S+(E-S)*b;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(b=>b.lat,!1)??i.lat,lng:w?w.lng:c(b=>b.lng,!1)??i.lng,elevationM:w?w.elevationM:c(b=>b.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:h(b=>b.pitchDeg)??i.pitchDeg,rollDeg:c(b=>b.rollDeg??0,!0)??i.rollDeg,fovDeg:c(b=>b.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 Md;for(const i of e.keyframes)t.addKeyframe(i.t,i.pose);return t}}class Za{static MAX_CHANGE_PER_S=.05;points;followed;constructor(e){let t="none",i=0;this.points=e.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(t=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:t,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(Za.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.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],n=this.points[t+1],s=n?Za.follow(this.followed[t],i.intensity,n.intensity,(n.t-i.t)/1e3,(e-i.t)/1e3):Za.follow(this.followed[t],i.intensity,i.intensity,1,(e-i.t)/1e3);return{type:Za.typeBetween(i,n,e,s),intensity:s,character:Za.characterBetween(i,n,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,n){return e.type==="none"?t&&t.type!=="none"&&i>e.t?t.type:n>0?e.lastFalling:"none":t&&t.type==="none"&&n<=0?"none":e.type}static follow(e,t,i,n,s){const r=Za.MAX_CHANGE_PER_S,a=n>0?(i-t)/n:0,o=d=>t+a*Math.min(Math.max(d,0),n);let c=e,h=0;for(let d=0;d<8&&h<s;d++){const u=o(h)-c;if(Math.abs(u)<1e-9){const w=h<n?a:0;if(Math.abs(w)<=r){const M=h<n?Math.min(s,n):s;c=o(M),h=M;continue}const b=Math.min(s,n);c+=Math.sign(w)*r*(b-h),h=b;continue}const p=Math.sign(u),f=h<n?a:0,g=r-p*f,m=g>0?h+Math.abs(u)/g:1/0,v=h<n?n:1/0,y=Math.min(s,m,v);c+=p*r*(y-h),h=y,y===m&&(c=o(h))}return Math.min(1,Math.max(0,c))}}const Ov=1e3,Dp=.65,ux=.05,Xf={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function mo(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??Ov,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 yi(l,e,t){return l+(e-l)*t}function Pv(l,e,t){const i=((e-l)%360+540)%360-180;return((l+i*t)%360+360)%360}function LE(l,e,t){return Math.max(e,Math.min(t,l))}function OE(l=[],e=[],t){if(!(!l.length&&!e.length))return[...new Set([...l.map(i=>i.id),...e.map(i=>i.id)])].map(i=>{const n=l.find(o=>o.id===i),s=e.find(o=>o.id===i),r=n??{...s,density:0},a=s??{...n,density:0};return{...r,eastM:yi(r.eastM,a.eastM,t),northM:yi(r.northM,a.northM,t),baseM:yi(r.baseM,a.baseM,t),thicknessM:yi(r.thicknessM,a.thicknessM,t),widthM:yi(r.widthM,a.widthM,t),depthM:yi(r.depthM,a.depthM,t),rotationDeg:Pv(r.rotationDeg,a.rotationDeg,t),density:yi(r.density,a.density,t),darkness:yi(r.darkness??0,a.darkness??0,t)}})}function PE(l,e,t){if(l.cloudLayers===void 0&&e.cloudLayers===void 0)return;const i=mo(l),n=mo(e);return t>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const a=i.find(d=>d.id===r),o=n.find(d=>d.id===r),c=a??{...o,coverage:0},h=o??{...a,coverage:0};return{...c,instances:OE(a?.instances,o?.instances,t),baseM:yi(c.baseM,h.baseM,t),thicknessM:yi(c.thicknessM,h.thicknessM,t),coverage:yi(c.coverage,h.coverage,t),sizeM:yi(c.sizeM,h.sizeM,t),density:yi(c.density,h.density,t),darkness:yi(c.darkness??l.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:c.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:yi(c.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:c.windSpeed===void 0&&h.windSpeed===void 0?void 0:yi(c.windSpeed??l.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:c.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Pv(c.windDirectionDeg??l.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function NE(l,e,t){return{cloudLayers:PE(l,e,t),cloudCover:yi(l.cloudCover,e.cloudCover,t),cloudDarkness:yi(l.cloudDarkness,e.cloudDarkness,t),highCloudCover:l.highCloudCover===void 0||e.highCloudCover===void 0?void 0:yi(l.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:yi(l.iceCrystalAlignment,e.iceCrystalAlignment,t),rareIceCrystals:l.rareIceCrystals===void 0||e.rareIceCrystals===void 0?void 0:yi(l.rareIceCrystals,e.rareIceCrystals,t),lowerCloudCover:l.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:yi(l.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:l.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:yi(l.cloudBaseM,e.cloudBaseM,t),relativeHumidity:l.relativeHumidity===void 0||e.relativeHumidity===void 0?void 0:yi(l.relativeHumidity,e.relativeHumidity,t),precipitationType:t<1?l.precipitationType:e.precipitationType,precipitationIntensity:yi(l.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Pv(l.windDirectionDeg,e.windDirectionDeg,t),windSpeed:yi(l.windSpeed,e.windSpeed,t),storm:t<1?l.storm:e.storm}}class xd{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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return i?n?NE(i.weather,n.weather,LE((e-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(e){const t=this.getInterpolatedWeatherAt(e);if(!t)return;const i=(this.ramp??=new Za(this.keyframes)).at(e);if(!i)return t;const{type:n,intensity:s,character:r}=i,a=r>0?Math.min(1,s/r):n==="none"?0:1;return{...t,precipitationType:n,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 xd;for(const i of e.keyframes)t.addKeyframe(i.t,{...Xf,...i.weather});return t}}class Sd{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 n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.sound;if(!n)return i.sound;const s=(e-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}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 Sd;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 n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}}const FE=["none","hum","whistle","rumble","crackle"],UE=100,zE={kind:"none",volume:0,pitchHz:UE};class bc{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 bc.BODIES.map(e=>({id:e.id,category:"dslr",name:e.name,projection:"rectilinear",frame:{widthMm:e.widthMm,heightMm:e.heightMm,focalLengthMm:bc.DEFAULT_FOCAL_MM,focalRangeMm:bc.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(bc.BODIES.map(e=>[e.id,e.name]))}}class ar{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*ar.DEFAULT_EYEPIECE_MM*Math.tan(ar.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=ar.BINOCULARS.map(n=>({id:n.id,category:"binoculars",name:n.name,projection:"rectilinear",visualAid:{apertureMm:n.apertureMm,magnification:n.magnification,trueFieldDeg:n.trueFieldDeg},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}})),t=ar.FIELD_STOP_MM,i=ar.TELESCOPES.map(n=>({id:n.id,category:"telescope",name:n.name,projection:"rectilinear",frame:{widthMm:t*16/9,heightMm:t,focalLengthMm:n.focalLengthMm,focalRangeMm:{minMm:n.focalLengthMm*ar.RANGE.min,maxMm:n.focalLengthMm*ar.RANGE.max}},visualAid:{apertureMm:n.apertureMm,eyepieceFocalMm:ar.DEFAULT_EYEPIECE_MM},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}}));return[...e,...i]}static names(){return Object.fromEntries(ar.instruments().map(e=>[e.id,e.name]))}}const Xh=[{id:"eye",category:"eye",name:"Naked eye",flare:0,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}},{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}},...bc.instruments(),...ar.instruments()];class Yt{static get default(){return Xh[0]}static byId(e){return Xh.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?2*Math.atan(t.heightMm/(2*t.focalLengthMm))*180/Math.PI:e.visualAid?.trueFieldDeg??Yt.UNAIDED_FIELD_DEG}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","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?Xh:Xh.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 2*Math.atan(i.heightMm/(2*t))*180/Math.PI}static focalLengthMmFor(e,t){const i=e.frame;if(!(!i||t<=0||t>=180))return i.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){const i=t??e.fNumber;if(i===void 0||e.apertureBlades===void 0)return 0;const n=e.fNumberRange;return!n||n.max<=n.min?1:Math.max(0,Math.min(1,(i-n.min)/(n.max-n.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(e){return e.flare??Yt.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class Al extends Error{}class Yf{constructor(e){this.name=e}validate(e){return!0}}class px extends Yf{min;max;constructor(e,t,i){super(e),this.min=t,this.max=i}validate(e){if(typeof e!="number")throw new Al(`${this.name} value must be a number, but was ${e}`);if(e<this.min||e>this.max)throw new Al(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${e}`);return super.validate(e)}}class cn{name;min;max;duration;subUnit;validator;constructor(e,t,i,n,s=new px(e,t,i)){this.name=e,this.min=t,this.max=i,this.subUnit=n,this.duration=n?(n.max-n.min+1)*n.duration:1,this.validator=s}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 fx{millisecond;second;minute;hour;day;month;year}class BE extends fx{}class mx extends BE{millisecond=new cn("millisecond",0,999,void 0);second=new cn("second",0,59,this.millisecond);minute=new cn("minute",0,59,this.second);hour=new cn("hour",0,23,this.minute);day=new cn("day",1,31,this.hour);month=new cn("month",1,12,this.day);year=new cn("year",0,9999,this.month)}const ot=new mx;class HE extends px{constructor(e=1,t=12){super("month",e,t)}}class Kr{static instance=new Kr;render(e){return e.value.toString()}}class Xn{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 Yf(`${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=Kr.instance){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class fi{static#e=new Map;static register(e,t){fi.#e.set(e,t)}static get(e){const t=fi.#e.get(e);if(!t)throw new Al(`No default parser registered for ${e.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return t()}}class Rp extends Xn{constructor(e=new Date().getFullYear(),t=ot.year){super(e,t)}static fromString(e,t=fi.get(Rp)){return new Rp(t.parse(e))}}class aa extends Kr{static default=new aa("0",2);constructor(e,t){super(),this.char=e,this.size=t}render(e){return super.render(e).padStart(this.size,this.char)}}class kp extends Xn{constructor(e=new Date().getMonth()+1,t=ot.month){super(e,t)}static fromString(e,t=fi.get(kp)){return new kp(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Cp extends Xn{constructor(e=new Date().getDate(),t=ot.day){super(e,t)}static fromString(e,t=fi.get(Cp)){const i=t.parse(e);return new Cp(i)}toString(e=aa.default){return super.toString(e)}}class Lp extends Xn{constructor(e=new Date().getHours(),t=ot.hour){super(e,t)}static fromString(e,t=fi.get(Lp)){return new Lp(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Op extends Xn{constructor(e=new Date().getMinutes(),t=ot.minute){super(e,t)}static fromString(e,t=fi.get(Op)){return new Op(t.parse(e))}toString(e=aa.default){return super.toString(e)}}class Pp extends Xn{constructor(e=new Date().getSeconds(),t=ot.second){super(e,t)}static fromString(e,t=fi.get(Pp)){return new Pp(t.parse(e),ot.second)}toString(e=aa.default){return super.toString(e)}}class Ol extends Xn{static renderer=new aa("0",3);constructor(e,t=ot.millisecond){super(e,t)}static parseFraction(e){return parseInt(e.padEnd(3,"0").substring(0,3),10)}toString(e=Ol.renderer){return super.toString(e)}}class GE{render(e){return e.toString()}}class VE extends GE{render(e){const t=e.value,i=Math.abs(t),n=Math.floor(i/60),s=i%60;if(n===0&&s===0)return"Z";{const r=t<0?"-":"+",a=n.toString().padStart(2,"0"),o=s>0?":"+s.toString().padEnd(2,"0"):"";return r+a+o}}}class Qc{value;name="timeshift";renderer;constructor(e=0){this.value=e}static fromString(e,t=fi.get(Qc),i=void 0){const n=t.parse(e,i);return new Qc(n)}toString(e=new VE){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class Bn{static timeshift(e,t){return e+(Bn.isDaylight(t)?60:0)}static isDaylight(e){const{year:t,month:i,day:n}=e,s=e.hour??12;if(![t,i,n].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=Bn.rule(t);if(!r)return!1;const a=Bn.rank(i,n,s);return a>=Bn.rank(r.start.month,r.start.day,2)&&a<Bn.rank(r.end.month,r.end.day,2)}static rule(e){if(e<1967)return;const t={month:10,day:Bn.sunday(e,10,-1)};return e>=2007?{start:{month:3,day:Bn.sunday(e,3,2)},end:{month:11,day:Bn.sunday(e,11,1)}}:e>=1987?{start:{month:4,day:Bn.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:Bn.sunday(e,4,-1)},end:t}}static sunday(e,t,i){const n=new Date(Date.UTC(2e3,t-1,1));n.setUTCFullYear(e);const s=1+(7-n.getUTCDay())%7;if(i>0)return s+7*(i-1);const r=[31,Bn.isLeap(e)?29:28,31,30,31,30,31,31,30,31,30,31][t-1];let a=s;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 WE={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},$E={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},XE={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},YE={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},KE={name:"PT",timeshift:l=>Bn.timeshift(-480,l),title:"Pacific Time (US)"},qE={name:"MT",timeshift:l=>Bn.timeshift(-420,l),title:"Mountain Time (US)"},jE={name:"CT",timeshift:l=>Bn.timeshift(-360,l),title:"Central Time (US)"},ZE={name:"ET",timeshift:l=>Bn.timeshift(-300,l),title:"Eastern Time (US)"},JE={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},QE={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},eA={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},tA={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},iA={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},nA={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},sA={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},rA={name:"Z",timeshift:"Z",title:"UTC"},aA={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},oA={name:"BST",timeshift:"+01",title:"British Summer Time"},lA={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},cA={name:"CET",timeshift:"+01",title:"Central European Time"},hA={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},dA={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},uA={name:"BJT",timeshift:"+08",title:"Beijing Time"},pA={name:"CST",timeshift:"-06",title:"Central Standard Time"},fA={name:"JST",timeshift:"+09",title:"Japan Standard Time"},mA={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},gA={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},vA={name:"LST",timeshift:"?",title:"Local Sideral Time"},e1=[nA,mA,iA,uA,oA,pA,QE,cA,lA,jE,JE,tA,eA,ZE,aA,dA,fA,vA,XE,hA,YE,qE,gA,$E,WE,KE,sA,rA];class Kf{static instance=new Kf;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 n=t.join("-"),s=e.timeshift?e.timeshift.toString():"",r=i.join(":")+s;return n+(r.length>0?"T"+r:"")}}class No extends Al{constructor(e="method is abstract"){super(e)}}class Nv{units;constructor(e){this.units=e}newYear(e){throw new No}newMonth(e){throw new No}newDay(e){throw new No}newHour(e){throw new No}newMinute(e){throw new No}newSecond(e){throw new No}}class bA extends fx{millisecond=new cn("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new cn("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new cn("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new cn("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new cn("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new cn("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new cn("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Fv=new bA;class Uv{static instance=new Uv;render(e){const t=Yo.toSpec(e);let i="P";const n=t.years;n&&(i+=n.toString()+"Y");const s=t.months;s&&(i+=s.toString(Kr.instance)+"MM");const r=t.days;r&&(i+=r.toString(Kr.instance)+"D");const a=t.hours;a&&(i+=a.toString(Kr.instance)+"H");const o=t.minutes;o&&(i+=o.toString(Kr.instance)+"M");const c=t.seconds;return c&&(i+=c.toString(Kr.instance)+"S"),i}}class Yo extends Xn{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*ot.year.duration:0)+(e.months?e.months*ot.month.duration:0)+(e.days?e.days*ot.day.duration:0)+(e.hours?e.hours*ot.hour.duration:0)+(e.minutes?e.minutes*ot.minute.duration:0)+(e.seconds?e.seconds*ot.second.duration:0)},new cn("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(e,t=wA){let i=typeof e=="number"?e:e.value;const n=i>0?1:-1;i=Math.abs(i);const s={},r=i/ot.year.duration,a=Math.floor(r);a>0&&(s.years=t.newYear(n*a),i-=a*ot.year.duration);const o=i/ot.month.duration,c=Math.floor(o);c>0&&(s.months=t.newMonth(n*c),i-=c*ot.month.duration);const h=i/ot.day.duration,d=Math.floor(h);d>0&&(s.days=t.newDay(n*d),i-=d*ot.day.duration);const u=i/ot.hour.duration,p=Math.floor(u);p>0&&(s.hours=t.newHour(n*p),i-=p*ot.hour.duration);const f=i/ot.minute.duration,g=Math.floor(f);g>0&&(s.minutes=t.newMinute(n*g),i-=g*ot.minute.duration);const m=i/ot.second.duration,v=Math.floor(n*m);return v>0&&(s.seconds=t.newSecond(v)),s}static fromString(e,t=fi.get(Yo)){return new Yo(t.parse(e))}static between(e,t){const i=t.getTime(),n=e.getTime();return new Yo(i-n)}toSpec(){return Yo.toSpec(this)}toString(e=Uv.instance){return e.render(this)}}class gx extends Nv{constructor(e){super(e)}newYear(e){return new Rp(e,this.units.year)}newMonth(e){return new kp(e,this.units.month)}newDay(e){return new Cp(e,this.units.day)}newHour(e){return new Lp(e,this.units.hour)}newMinute(e){return new Op(e,this.units.minute)}newSecond(e){return new Pp(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new Qc(typeof e=="number"?e:e.value)}}const yA=new gx(ot),wA=new gx(Fv);class ur{#e;#t;#i;#n;#s;#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:ur.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 Xn?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 Xn?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 Xn?e:this.factory.newDay(e)}get hour(){return this.#n}set hour(e){const t=typeof e=="number";this.#n&&t?this.#n.value=e:this.#n=t?this.factory.newHour(e):!e||e.start||e instanceof Xn?e:this.factory.newHour(e)}get minute(){return this.#s}set minute(e){const t=typeof e=="number";this.#s&&t?this.#s.value=e:this.#s=t?this.factory.newMinute(e):!e||e.start||e instanceof Xn?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 Xn?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 Xn)?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 Qc)?this.factory.newTimeshift(e):e}get factory(){return yA}static fromString(e,t=fi.get(ur)){const{year:i,month:n,day:s,hour:r,minute:a,second:o,millisecond:c,timeshift:h}=t.parse(e);return new ur({year:i,month:n,day:s,hour:r,minute:a,second:o,millisecond:c,timeshift:h})}static timeshiftOf(e){return-e.getTimezoneOffset()||0}static fromDate(e){return new ur({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return ur.fromString(i)}#l(e){if(this.constructor.name!==e.constructor.name)throw new Yf(`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 Yo(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 ur(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=Kf.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 n=this.day?.toSpec();n&&(e.day=n);const s=this.hour?.toSpec();s&&(e.hour=s);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 Wd extends Kr{static instance=new Wd(aa.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 Pl extends Xn{#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=Wd.instance){return super.toString(e)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class vx extends mx{year=new cn("year",-9999,9999,this.month);yearExtended=new cn("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const dp=new vx;class Ko extends Pl{constructor(e,t=dp.year){super(e,t)}static fromString(e,t=dp.year,i=fi.get(Ko)){const n=i.parse(e),s=n.value.start;if(e.startsWith("Y")&&(t=dp.yearExtended),s!==void 0){const r=new Ko(Object.assign({...n},{value:Math.max(s,t.min)})),a=new Ko(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new Ko(n,t)}}class bx extends Yf{monthValidator=new HE;validate(e){switch(e){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(e)}}}class qo extends Pl{constructor(e,t=new cn(ot.month.name,1,24,ot.day,new bx)){super(e,t)}static fromString(e,t=fi.get(qo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.month;const r=new qo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new qo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new qo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class jo extends Pl{constructor(e,t=ot.day){super(e,t)}static fromString(e,t=fi.get(jo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.day;const r=new jo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new jo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new jo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class Zo extends Pl{constructor(e,t=ot.hour){super(e,t)}static fromString(e,t=fi.get(Zo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=ot.hour;const r=new Zo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Zo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Zo(i)}}class Jo extends Pl{constructor(e,t=ot.minute){super(e,t)}static fromString(e,t=fi.get(Jo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.minute,r=new Jo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Jo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Jo(i)}toString(e=Wd.instance){return super.toString(e)}}class Qo extends Pl{constructor(e,t=ot.second){super(e,t)}static fromString(e,t=fi.get(Qo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.second,r=new Qo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Qo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Qo(i)}}class eh extends Qc{static fromString(e,t=fi.get(eh),i=void 0){return new eh(t.parse(e,i))}}class yx extends Nv{constructor(e){super(e)}newYear(e){return new Ko(e,this.units.year)}newMonth(e){return new qo(e,this.units.month)}newDay(e){return new jo(e,this.units.day)}newHour(e){return new Zo(e,this.units.hour)}newMinute(e){return new Jo(e,this.units.minute)}newSecond(e){return new Qo(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new eh(typeof e=="number"?e:e.value)}}const MA=new yx(dp);new yx(Fv);class Fo extends ur{constructor(e){super(e)}get factory(){return MA}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 Fo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static fromString(e,t=fi.get(Fo)){const i=t.parse(e);return new Fo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Fo.fromString(i)}clone(){return new Fo(this.toSpec())}}class fh extends Pl{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 xA extends vx{year=new cn("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Q0=new xA;class el extends fh{constructor(e,t=Q0.year){super(e,t)}static fromString(e,t=Q0.year,i=fi.get(el)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new el(Object.assign({...n},{value:Math.max(s,t.min)})),a=new el(Object.assign({...n},{value:Math.min(n.value.end,t.max)})),o={start:r,end:a},c=n.value.estimate;return c&&(o.estimate=c),o}else return new el(n)}}class SA extends bx{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 tl extends fh{constructor(e,t=new cn(ot.month.name,1,41,ot.day,new SA)){super(e,t)}static fromString(e,t=fi.get(tl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.month,r=new tl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new tl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new tl(i)}toString(e){return super.toString(e).padStart(2,"0")}}class il extends fh{constructor(e,t=ot.day){super(e,t)}static fromString(e,t=fi.get(il)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.day,r=new il(Object.assign({...i},{value:Math.max(n,s.min)})),a=new il(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new il(i)}toString(e){return super.toString(e).padStart(2,"0")}}class nl extends fh{constructor(e,t=ot.hour){super(e,t)}static fromString(e,t=fi.get(nl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.hour,r=new nl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new nl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new nl(i)}}class sl extends fh{constructor(e,t=ot.minute){super(e,t)}static fromString(e,t=fi.get(sl)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=ot.minute,r=new sl(Object.assign({...i},{value:Math.max(n,s.min)})),a=new sl(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new sl(i)}}class rl extends fh{constructor(e,t=ot.second){super(e,t)}static fromString(e,t=ot.second,i=fi.get(rl)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new rl(Object.assign({...n},{value:Math.max(s,t.min)})),a=new rl(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new rl(n,t)}}class wx extends eh{}class EA extends Wd{qualifier(){return""}}class Ja extends Kf{static instance=new Ja;static valueRenderer=new EA(aa.default);static names=["year","month","day","hour","minute","second"];static qualifier(e,t){return e?t?"%":"?":t?"~":""}renderComponent(e,t){const i=e[t],n=Ja.names.slice(Ja.names.indexOf(t)+1).map(a=>e[a]).filter(Boolean),s=Ja.qualifier(i.uncertainComponent,i.approximateComponent),r=Ja.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!n.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!n.some(a=>a.approximate));return s+i.toString(Ja.valueRenderer)+r}}class Mx extends Nv{constructor(e){super(e)}newYear(e){return new el(e,this.units.year)}newMonth(e){return new tl(e,this.units.month)}newDay(e){return new il(e,this.units.day)}newHour(e){return new nl(e,this.units.hour)}newMinute(e){return new sl(e,this.units.minute)}newSecond(e){return new rl(e,this.units.second)}newMillisecond(e){return new Ol(e,this.units.millisecond)}newTimeshift(e){return new wx(typeof e=="number"?e:e.value)}}const AA=new Mx(Q0);new Mx(Fv);class Uo extends Fo{constructor(e){super(e)}toString(e=Ja.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 AA}static fromDate(e){return new Uo({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:ur.timeshiftOf(e)})}static fromString(e,t=fi.get(Uo)){const i=t.parse(e);return new Uo(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Uo.fromString(i)}clone(){return new Uo(this.toSpec())}}class qf{regExp;constructor(e,t){this.name=e,this.regExp=new RegExp(`^(?:${t})$`)}regexGroups(e){const t=this.regExp.exec(e);if(!t)throw new Al(`Invalid ${this.name} "${e}"`);return t.groups}parseGroups(e){throw new No(`${this.constructor.name} is abstract`)}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}class zv extends qf{constructor(e,t){super(e,t)}static read(e){return{value:e?parseInt(e,10):void 0}}parseGroups(e){return zv.read(e[this.name])}parse(e){if(e.startsWith("-"))throw new Al(`${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,n="\\d"){return ce.group(e,`${i||""}[${n}]${t}`)}}const t1="timeshiftValue",i1="shiftHour",n1="shiftMinute";class Bv extends qf{static format(e=""){return e1.map(t=>t.name).join("|")+"|"+ce.nonCapturingGroup(ce.group(e+i1,ce.numberGroup(ce.groupName(e,t1),"{2}","[+-]")),ce.optionalNonCapturingGroup(":?",ce.numberGroup(ce.groupName(e,n1),"{2}",void 0)))}constructor(){super(t1,Bv.format())}parse(e,t){let i=0;const n=e1.find(s=>s.name===e);if(n){if(typeof n.timeshift=="function")try{return n.timeshift(t??{})}catch(s){throw new Al(`The time zone ${e} depends on the date: ${s.message}`)}e=n.timeshift}if(e!=="Z"){const s=this.regexGroups(e),r=s[i1];r&&(i+=parseInt(r,10)*60);const a=s[n1];a&&(i+=parseInt(a,10))}return i}}class Ui extends zv{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=Ui.uncertainGroup+Ui.approximateGroup;constructor(e,t){super(e,t)}static qualifierFormat(e,t){return ce.optionalGroup(e,`\\${t}`)}static formatSuffix(e){return this.qualifierFormat(ce.groupName(Ui.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(Ui.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(Ui.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 n=0,s;for(s=0;s<t.length;s++){const c=t[s];if(c==="X")break;n=n*10+parseInt(c,10)}if(s<t.length){let c=1;for(let u=0;u<t.length-s;u++)c*=10;const h=i*n*c,d=h+c-1;n={start:h,end:d}}else n*=i;const r=e[ce.groupName(Ui.uncertainAndApproximateGroup,this.name)],a=e[ce.groupName(Ui.approximateGroup,this.name)]||r,o=e[ce.groupName(Ui.uncertainGroup,this.name)]||r;return{value:n,approximate:a?!!a:!1,uncertain:o?!!o:!1}}}const s1="yearValue";class Np extends Ui{constructor(){super(s1,Np.format())}static format(e=""){return"Y?"+Ui.numberFormat(ce.groupName(e,s1),"+","[-]?")}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const r1="monthValue";class Fp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,r1),"{1,2}",void 0)}constructor(){super(r1,Fp.format())}}const a1="dayValue";class Up extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,a1),"{1,2}",void 0)}constructor(){super(a1,Up.format())}}const o1="hourValue";class zp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,o1),"{1,2}",void 0)}constructor(){super(o1,zp.format())}}const l1="minuteValue";class Bp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,l1),"{1,2}",void 0)}constructor(){super(l1,Bp.format())}}const c1="secondValue";class Hp extends Ui{static format(e=""){return Ui.numberFormat(ce.groupName(e,c1),"{1,2}",void 0)}constructor(){super(c1,Hp.format())}}class Gp extends Bv{}class un extends qf{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=un.format()){super("date",e)}static format(e=""){return ce.group(ce.groupName(e,un.yearGroup),Np.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,un.monthGroup),Fp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,un.dayGroup),Up.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,un.hourGroup),zp.format(e)),":",ce.group(ce.groupName(e,un.minuteGroup),Bp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,un.secondGroup),Hp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,un.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,un.timeshiftGroup),Gp.format(e)))))}parseGroups(e){const t=e[un.millisecondGroup],i=t?Ol.parseFraction(t):void 0,n=e[un.secondGroup],s=n?Qo.fromString(n,new Hp):void 0,r=e[un.minuteGroup];let a;r&&(a=Jo.fromString(r,new Bp),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const o=e[un.hourGroup];let c;o&&(c=Zo.fromString(o,new zp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[un.dayGroup];let d;h&&(d=jo.fromString(h,new Up),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[un.monthGroup];let p;u&&(p=qo.fromString(u,new Fp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[un.yearGroup];let g;f&&(g=Ko.fromString(f,void 0,new Np),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[un.timeshiftGroup],v=m?eh.fromString(m,new Gp,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}class nn extends Ui{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=nn.uncertainGroup+nn.approximateGroup;constructor(e,t){super(e,t)}static numberFormat(e,t,i){return this.qualifierFormat(ce.groupName(nn.uncertainGroup,e),"?")+this.qualifierFormat(ce.groupName(nn.approximateGroup,e),"~")+this.qualifierFormat(ce.groupName(nn.uncertainAndApproximateGroup,e),"%")+Ui.numberFormat(e,t,i)}parseGroups(e){const t=super.parseGroups(e),i=e[ce.groupName(nn.uncertainAndApproximateGroup,this.name)];return(e[ce.groupName(nn.uncertainGroup,this.name)]||i)&&(t.uncertainComponent=!0),(e[ce.groupName(nn.approximateGroup,this.name)]||i)&&(t.approximateComponent=!0),t}}const yh="yearValue",h1="exp",d1="signif";class Vp extends nn{constructor(){super(yh,Vp.format())}static format(e=""){return"Y?"+ce.nonCapturingGroup(ce.group(ce.groupName(e,h1),"[-]?\\d+E\\d+")+"|"+nn.numberFormat(ce.groupName(e,yh),"+","[-]?")+ce.optionalGroup(ce.groupName(e,d1),"S\\d+"))}parseGroups(e){const t=e[h1];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[yh]=c.toString()}const i=e[d1],n=e[yh];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[yh]=(o<0?"-":"")+c}const s=super.parseGroups(e);return i&&(s.value.estimate=parseInt(n,10)),s}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const u1="monthValue";class Wp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,u1),"{1,2}",void 0)}constructor(){super(u1,Wp.format())}}const p1="dayValue";class $p extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,p1),"{1,2}",void 0)}constructor(){super(p1,$p.format())}}const f1="hourValue";class Xp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,f1),"{1,2}",void 0)}constructor(){super(f1,Xp.format())}}const m1="secondValue";class Yp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,m1),"{1,2}",void 0)}constructor(){super(m1,Yp.format())}}const g1="minuteValue";class Kp extends nn{static format(e=""){return nn.numberFormat(ce.groupName(e,g1),"{1,2}",void 0)}constructor(){super(g1,Kp.format())}}class TA extends Gp{}class pn extends qf{static yearGroup=un.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",pn.format())}static format(e=""){return ce.group(ce.groupName(e,pn.yearGroup),Vp.format(e))+ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,pn.monthGroup),Wp.format(e)),ce.optionalNonCapturingGroup("-",ce.group(ce.groupName(e,pn.dayGroup),$p.format(e)),ce.optionalNonCapturingGroup("[T ]",ce.group(ce.groupName(e,pn.hourGroup),Xp.format(e)),":",ce.group(ce.groupName(e,pn.minuteGroup),Kp.format(e)),ce.optionalNonCapturingGroup(":",ce.group(ce.groupName(e,pn.secondGroup),Yp.format(e)),ce.optionalNonCapturingGroup("[.,]",ce.group(ce.groupName(e,pn.millisecondGroup),"\\d+"))),ce.optionalGroup(ce.groupName(e,pn.timeshiftGroup),TA.format(e)))))}parseGroups(e){const t=e[pn.millisecondGroup],i=t?Ol.parseFraction(t):void 0,n=e[pn.secondGroup];let s;n&&(s=rl.fromString(n,void 0,new Yp),s.uncertain=s?.uncertain||!1,s.approximate=s?.approximate||!1);const r=e[pn.minuteGroup];let a;r&&(a=sl.fromString(r,new Kp),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const o=e[pn.hourGroup];let c;o&&(c=nl.fromString(o,new Xp),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[pn.dayGroup];let d;h&&(d=il.fromString(h,new $p),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[pn.monthGroup];let p;u&&(p=tl.fromString(u,new Wp),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[pn.yearGroup];let g;f&&(g=el.fromString(f,void 0,new Vp),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[pn.timeshiftGroup],v=m?wx.fromString(m,new Gp,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}const xx=["spring","summer","autumn","winter"],eg=21,_A=32,IA=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let DA;function RA(){return DA??=new pn}function zl(l){return typeof l?.value=="number"?l.value:void 0}function up(l){const e=l.trim();if(/^\d{1,2}:/.test(e)){const r=IA.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=Uo.fromString(e,RA())}catch{return}const i=zl(t.year),n=zl(t.month),s=n!==void 0&&n>=eg&&n<=_A;if(!(t.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(n!==void 0&&n>12&&!s)&&!(s&&(t.day||t.hour)))return{year:i,month:s?void 0:n,...s?{season:xx[(n-eg)%4]}:{},day:zl(t.day),hour:zl(t.hour),minute:zl(t.minute),second:zl(t.second),raw:e}}function al(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}-${eg+xx.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 tg(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 v1(l){return(((l.day??0)*24+(l.hour??0))*60+(l.minute??0))*6e4+(l.second??0)*1e3}const kA=["year","month","day","hour","minute"],CA=["day","hour","minute"];function b1(l,e){return e.filter(t=>l[t]!==void 0).join(",")}function th(l){if(l.durationSeconds!==void 0)return l.durationSeconds*1e3;const e=l.durationText===void 0?void 0:ns.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?kA:CA,n=b1(l.time,i);if(!(n===""||n!==b1(l.endTime,i)))return t?tg(l.endTime)-tg(l.time):v1(l.endTime)-v1(l.time)}function LA(l){if(l.durationSeconds===void 0&&!(!l.time||!l.endTime))return th(l)===void 0?"imprecise":void 0}class jf{constructor(e,t,i,n,s,r,a,o,c=[],h,d,u,p=[],f=[],g=[],m=[]){this.event=e,this.timeline=t,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,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=g,this.traces=m}provenance=rs.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;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 jf({eventType:"sighting",time:e,place:t},new $f,new Md,new xd,new Sd,i)}}const OA=0,PA=0;function ut(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:OA,headingDeg:void 0,pitchDeg:PA,fovDeg:Yt.fieldOfViewDeg(l.instrument)}}function Ki(l,e){return l.weatherTrack.getInterpolatedWeatherAt(e)??l.weather??Xf}function Jd(l,e){return l.weatherTrack.getActualWeatherAt(e)??l.weather??Xf}function Hv(l,e){return l.soundTrack.getInterpolatedSoundAt(e)??zE}class Ed{constructor(e,t){this.json=e,this.url=t,this.tracks=(e.events??[]).filter(i=>i.eventType===wi.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,n,s){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:wi.SIGHTING_EVENT,...t!==void 0?{time:t}:{},...i!==void 0?{title:i}:{},url:`observer-${r}.json`}]},o=new Ed(a,new URL("case.json",s).href),c=o.tracks[0];return c.recording=e,c.base={url:n},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(n=>n.kind==="observer");return i.find(n=>n.event.id!==void 0&&t.includes(n.event.id))??i.find(n=>n.recording?.id!==void 0&&t.includes(n.recording.id))}get interviews(){return(this.json.events??[]).filter(e=>e.eventType===wi.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 n=t.find(s=>s.event.id===i)??t.find(s=>s.recording?.id===i);return n?[n]:[]})}addInterview(e,t,i,n,s){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:wi.INTERVIEW_EVENT,id:`interview-${a}-${o}`,...e?{interviewOf:this.ensureId(e)}:{},time:t,...s!==void 0?{medium:s}:{},...n!==void 0&&n.length>0?{by:n}:{},...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(s=>s.eventType===wi.SIGHTING_EVENT&&typeof s.url=="string"&&s.url!=="").map(s=>{const r=new URL(s.url,this.url).href,a=s.interpretationOf===void 0?"observer":"reading",o=this.tracks.find(c=>c.url===r);return o?(o.event=s,o.kind=a,o):{event:s,url:r,kind:a}});this.tracks.splice(0,this.tracks.length,...i);const n=new Map;for(const[s,r]of this.transcripts){const a=(e.events??[]).find(o=>o.eventType===wi.INTERVIEW_EVENT&&(s.id!==void 0&&o.id===s.id||s.url!==void 0&&o.url===s.url));a&&n.set(a,r)}this.transcripts.clear();for(const[s,r]of n)this.transcripts.set(s,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,n=t(e.recording?.observer?.lastName)||t(e.recording?.observer?.id)||t(i),s=this.eventIds(e);if(n!==""){let a=n;for(let o=2;s.has(a);o++)a=`${n}-${o}`;return a}let r=1;for(;s.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,n=a=>a===i||a===e.recording?.id,s=(this.json.events??[]).filter(a=>a.eventType===wi.SIGHTING_EVENT&&a.interpretationOf!==void 0&&[a.interpretationOf].flat().some(o=>o!==void 0&&n(o))),r=this.interviews.filter(a=>[a.interviewOf].flat().some(o=>o!==void 0&&n(o)));if(t==="")return i===void 0?"ok":s.length>0||r.length>0?"empty":(delete e.event.id,this.caseChanged=!0,"ok");if(!Ed.ID_PATTERN.test(t))return"invalid";if(this.eventIds(e).has(t))return"taken";if(t===i)return"ok";for(const a of s){const o=[a.interpretationOf].flat().map(c=>n(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&&n(c)?t:c);a.interviewOf=Array.isArray(a.interviewOf)?o:o[0]}return e.event.id=t,this.caseChanged=!0,"ok"}problems(){return wi.problems(this.json,this.tracks.map(e=>e.recording?.id).filter(e=>e!==void 0))}addReading(e,t,i,n){const s=e.recording;if(!s)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(`${s.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:g,description:m,sources:v,tags:y,timeline:w,milestones:b,interpretation:M,...S}=structuredClone(s),E={version:1,id:`${s.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,...n!==void 0&&n.length>0?{by:n}:{},...i!==void 0?{title:i}:{},url:d+h};this.json.events=[...this.json.events??[],x],this.caseChanged=!0;const T={event:x,url:new URL(x.url,this.url).href,kind:"reading",recording:E};return this.tracks.push(T),T}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(n=>n!==void 0&&t.includes(n)))}addObservation(e,t,i,n){const s=new Set(this.tracks.map(g=>g.event.url)),r=new Set(this.tracks.map(g=>g.recording?.id)),a=(e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",o=n?"interpretation":"observer";let c=`${o}-${a}.json`,h=e.id??a;for(let g=2;s.has(c)||r.has(h);g++)c=`${o}-${a}-${g}.json`,h=`${e.id??a}-${g}`;const d={...e,id:h},u=this.tracks[0]?.event.url?.includes("/")?this.tracks[0].event.url.replace(/[^/]*$/,""):"",p={type:"event",eventType:"sighting",...n?{interpretationOf:this.ensureId(n.account)}:{},...t!==void 0?{time:t}:{},...n?.by&&n.by.length>0?{by:n.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:n?"reading":"observer",recording:d};return this.tracks.push(f),n||(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(n=>n!==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(/[^/]*$/,""),n=o=>o.startsWith(i)?o.slice(i.length):o,s=this.tracks.filter(o=>e&&o.recording!==void 0&&(t||this.changed(o))).map(o=>({path:n(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:n(new URL(o.url,this.url).href),content:c.text}));return[{path:r,content:JSON.stringify(this.json,null,2)+`
|
|
337
337
|
`},...s,...a]}}class qp{constructor(e,t,i,n){this.button=e,this.onPick=i,this.idOf=n;const s=this.panel=e.ownerDocument.createElement("div");s.id=t,s.className="add-menu",s.setAttribute("popover",""),s.setAttribute("role","menu");const r=`--add-menu-${t}`;e.style.setProperty("anchor-name",r),s.style.setProperty("position-anchor",r),e.setAttribute("popovertarget",t),e.setAttribute("aria-haspopup","menu"),e.after(s)}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;
|
|
@@ -4154,9 +4154,9 @@ canvas[data-cursor="rotate"] {
|
|
|
4154
4154
|
`;class gl{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const i of e.observerTrack.allKeyframes){const{lat:n,lng:s,headingDeg:r}=i.pose;n===void 0||s===void 0||t.push({t:i.t,lat:n,lng:s,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 gl(t)}static TRAVEL_M=50;get travels(){return this.spanM>gl.TRAVEL_M}get moved(){return this.spanM>gl.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(at(t,e.east,t,e.west).x),Math.abs(at(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:n}=this.center,s=Math.max(this.spanM*(1+t),e)/2;return{north:Bs(0,-s,i,n).lat,south:Bs(0,s,i,n).lat,east:Bs(s,0,i,n).lng,west:Bs(-s,0,i,n).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 Ys{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)>Ys.HAND_HELD_S,i=e.sway??(t?0:1);if(i>0)return new Ys(Math.max(1-(e.instrument.stabilization??0),Ys.GAZE_DRIFT_SHARE),i)}offsetAt(e){const t=e/1e3,i=this.scale,n=(d,u)=>Math.sin(2*Math.PI*d*t+u),[s,r,a,o,c,h]=Ys.HZ;return{eastM:i*Ys.SWAY_M*(.7*n(s,.3)+.3*n(o,1.9)),northM:i*Ys.SWAY_M*(.6*n(a,2.2)+.4*n(c,.8)),upM:i*Ys.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*Ys.DRIFT_YAW_DEG*(.6*n(h,1.1)+.4*n(o,2.7)),pitchDeg:i*this.rotationPassed*Ys.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(a,.4)),rollDeg:i*this.rotationPassed*Ys.DRIFT_ROLL_DEG*n(s,2.9)}}}class ni{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=gl.of(e);if(!t||t.points.length<2)return;const i=[];let n=0;for(let s=1;s<t.points.length;s++){const r=t.points[s-1],a=t.points[s],o=(a.t-r.t)/1e3;if(o<=0)continue;const c=at(a.lat,a.lng,r.lat,r.lng),h=c.x,d=-c.z,u=Math.hypot(h,d),p=u/o,f=ni.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:n,rampsIn:!0,rampsOut:!0}),n+=f*o}for(let s=0;s<i.length;s++){const r=i[s-1],a=i[s+1];i[s].rampsIn=r===void 0||r.stepHz===0,i[s].rampsOut=a===void 0||a.stepHz===0}if(i.some(s=>s.stepHz>0))return new ni(i,1-(e.instrument.stabilization??0))}static bodyAt(e,t,i=!1){const n=ni.of(e)?.offsetAt(t)??ni.STILL;return i?n:ni.add(n,Ys.of(e)?.offsetAt(t))}static stepHzFor(e){return e<ni.SLOWEST_WALK_M_PER_S||e>ni.FASTEST_WALK_M_PER_S?0:ni.REFERENCE_STEP_HZ*Math.pow(e/ni.REFERENCE_SPEED_M_PER_S,ni.CADENCE_EXPONENT)}offsetAt(e){return ni.add(this.cycleAt(e),this.joltAt(e))}joltAt(e){for(const t of this.stretches){if(t.stepHz===0)continue;const i=t.speedMPerS/ni.REFERENCE_SPEED_M_PER_S,n=(a,o,c,h)=>{if(a<0||a>ni.JOLT_LASTS_MS)return;const d=a/1e3,u=Math.exp(-d/ni.JOLT_DECAY_S)*Math.sin(2*Math.PI*ni.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}},s=t.rampsOut?n(e-t.endMs,ni.STOP_LURCH_M,ni.STOP_PITCH_DEG,1):void 0;if(s)return s;const r=t.rampsIn?n(e-t.startMs,ni.START_LURCH_M,ni.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 ni.STILL;const i=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,n=2*Math.PI*i,s=this.amplitudeAt(t,e),r=ni.SWAY_M*s*Math.cos(n/2),a=s*this.rotationPassed*t.speedMPerS/ni.REFERENCE_SPEED_M_PER_S;return{eastM:r*t.northUnit,northM:-r*t.eastUnit,upM:ni.RISE_M_PER_M_PER_S*t.speedMPerS*s*Math.cos(n),rollDeg:ni.HEAD_ROLL_DEG*a*Math.cos(n/2),pitchDeg:-1.25*a*Math.cos(n),yawDeg:ni.HEAD_YAW_DEG*a*Math.cos(n/2)}}amplitudeAt(e,t){const i=1e3/e.stepHz,n=Math.min(i,(e.endMs-e.startMs)/2);if(n<=0)return 1;const s=t-e.startMs,r=e.endMs-t,a=Math.min(e.rampsIn?s/n:1,e.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class kT{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 n=this.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}this.onFrame(e,t)}}class vl{static sessionDeclared=!1;static unlock(e){if(vl.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(!(vl.sessionDeclared||typeof navigator>"u")){vl.sessionDeclared=!0;try{const e=navigator.audioSession;e&&(e.type="playback")}catch{}}}}const K1=.05,q1=.08,j1=2,Z1=3,CT=14,LT=.02;class OT{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}}vl.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 n=i.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,n,K1);for(const{param:s,ratio:r}of e.pitch)s.setTargetAtTime(Math.min(t.pitchHz*r,i.sampleRate/2-1),n,K1)}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 n=e.createOscillator();n.type="sawtooth";const s=e.createBiquadFilter();s.type="lowpass",s.Q.value=1;const r=e.createGain();return r.gain.value=0,i.connect(s),n.connect(s),s.connect(r).connect(this.output(e)),i.start(),n.start(),{key:t,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.16,pitch:[{param:i.frequency,ratio:1},{param:n.frequency,ratio:1.006},{param:s.frequency,ratio:6}]}}buildWhistle(e,t){const i=e.createOscillator();i.type="sine";const n=e.createOscillator();n.type="sine",n.frequency.value=5;const s=e.createGain(),r=e.createGain();return r.gain.value=0,n.connect(s).connect(i.frequency),i.connect(r).connect(this.output(e)),i.start(),n.start(),{key:t,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:s.gain,ratio:.012}]}}buildRumble(e,t){const i=e.createBufferSource();i.buffer=this.brownNoise(e),i.loop=!0;const n=e.createBiquadFilter();n.type="lowpass",n.Q.value=.8;const s=e.createGain();return s.gain.value=0,i.connect(n).connect(s).connect(this.output(e)),i.start(),{key:t,nodes:[n,s],sources:[i],volumeParam:s.gain,gainScale:1.4,pitch:[{param:n.frequency,ratio:1}]}}buildCrackle(e,t){const i=e.createBufferSource();i.buffer=this.whiteNoise(e),i.loop=!0;const n=e.createBiquadFilter();n.type="bandpass",n.Q.value=1.2;const s=e.createGain();s.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(s.gain),i.connect(n).connect(s).connect(this.output(e)),i.start(),r.start(),{key:t,nodes:[n,s,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:n.frequency,ratio:4}]}}async buildRecordedVoice(e,t,i){const n=this.context;if(!n)return;let s;try{s=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=n.createBufferSource();r.buffer=s,r.loop=!0;const a=n.createGain();a.gain.value=0,r.connect(a).connect(this.output(n)),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(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${e}`);return n.arrayBuffer()}).then(n=>t.decodeAudioData(n)),this.buffers.set(e,i)),i}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*j1),e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*j1),e.sampleRate),i=t.getChannelData(0);let n=0,s=0;for(let r=0;r<i.length;r++)n=(n+.02*(Math.random()*2-1))/1.02,i[r]=n,s=Math.max(s,Math.abs(n));if(s>0)for(let r=0;r<i.length;r++)i[r]/=s;return t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*Z1),e.sampleRate),i=t.getChannelData(0),n=Math.max(1,Math.floor(LT*e.sampleRate)),s=Math.round(Z1*CT);for(let r=0;r<s;r++){const a=Math.floor(Math.random()*i.length),o=.4+Math.random()*.6;for(let c=0;c<n&&a+c<i.length;c++)i[a+c]=Math.max(i[a+c],o*(1-c/n))}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,q1/3);const n=i+q1;for(const s of e.sources){s.onended=()=>{s.disconnect();for(const r of e.nodes)r.disconnect()};try{s.stop(n)}catch{s.disconnect();for(const r of e.nodes)r.disconnect()}}}}class zr{static KINDS=["beams","launches","reentries"];static isEmpty(e){return!e||zr.KINDS.every(t=>!e[t]?.length)}static written(e){if(zr.isEmpty(e))return;const t={};for(const i of zr.KINDS)e[i]?.length&&(t[i]=e[i]);return t}static read(e,t){const i=t,n={};for(const r of zr.KINDS){const a=[...e?.[r]??[],...i?.[r]??[]];a.length>0&&(n[r]=a)}let s=t;if(i&&zr.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:o,...c}=i;s=zr.isReading(c)?c:void 0}return{skyEvents:zr.written(n),interpretation:s}}static isReading(e){return(e.bodies?.length??0)>0||e.title!==void 0||(e.smoke?.length??0)>0}}function bl(l){return[...l].sort((e,t)=>e.t-t.t)}function wm(l,e){let t;for(const i of bl(l)){if(i.t>e)break;t=i}return t}const Mm=Math.PI/180,ou=180/Math.PI;class Ts{constructor(e,t,i){this.kind=e,this.canvasHeightPx=t,this.fovDeg=i;const n=i*Mm/2;this.focalPx=e==="equidistant"?t/2/n:t/2/Math.tan(n)}focalPx;static of(e,t,i){return new Ts(e.projection,t,i)}degToPx(e){const t=e*Mm;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*ou:2*Math.atan(e/(2*this.focalPx))*ou}angleDegToRadiusPx(e){const t=e*Mm;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*ou:Math.atan(e/this.focalPx)*ou}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(xt.angularWidthDeg(e))}}class Di{static fovOf(e,t){return ut(e,t)?.fovDeg??Yt.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,i)=>{const n=i.ofBounds(t.bounds);return t.angular?.widthDeg===n.widthDeg&&t.angular.heightDeg===n.heightDeg?t:{...t,angular:n}})}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:n}=t.toBoundsSize(e.angular),s={x:e.bounds.x+(e.bounds.width-i)/2,y:e.bounds.y+(e.bounds.height-n)/2,width:i,height:n};if(e.kind!=="polygon")return{...e,bounds:s};const r=e.bounds.width===0?1:i/e.bounds.width,a=e.bounds.height===0?1:n/e.bounds.height;return{...e,bounds:s,points:e.points.map(o=>({x:o.x*r,y:o.y*a}))}}static toAim(e){this.eachKeyframe(e,(t,i,n)=>{const s=t.aim&&this.positionOf(e,t.aim,t.bounds,i,n);if(s&&Math.abs(s.x-t.bounds.x)<Di.UNMOVED_PX&&Math.abs(s.y-t.bounds.y)<Di.UNMOVED_PX)return t;const r=this.aimFrom(e,i,n,t.bounds);return r?{...t,aim:r}:t})}static UNMOVED_PX=.01;static aimOf(e,t,i){const n=Ts.of(e.instrument,xt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,n,ut(e,t),i)}static aimFrom(e,t,i,n){if(i?.headingDeg===void 0)return;const s=this.frameCentre(e),r=t.radiusPxToAngleDeg(n.x+n.width/2-s.x),a=t.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(e){this.eachKeyframe(e,(t,i,n)=>this.placedByAim(e,t,i,n))}static placedByAim(e,t,i,n){const s=t.aim&&this.positionOf(e,t.aim,t.bounds,i,n);return s?{...t,bounds:{...t.bounds,...s}}:t}static derivable(e){const t=new Set,i=new Map,n=new Map;return e.timeline.allKeyframes.forEach((s,r)=>{const a=ut(e,s.t),o=Ts.of(e.instrument,xt.CANVAS_HEIGHT_PX,this.fovOf(e,s.t));for(const{sourceId:c,shape:h}of s.shapes){const d=n.get(c),u=i.get(c);if(n.set(c,h),!d||!u){i.set(c,h);continue}const p=Object.fromEntries(Object.entries(h).filter(([m,v])=>m!=="bounds"&&m!=="points"&&JSON.stringify(v)!==JSON.stringify(d[m]))),f={...u,...p},g=this.placedByAim(e,this.sizedFromAngle(f,o),o,a);Di.near(g,h)?(t.add(`${r}:${c}`),i.set(c,f)):i.set(c,h)}}),(s,r)=>t.has(`${s}:${r}`)}static SAME_PX=1e-6;static near(e,t){const i=(r,a)=>Math.abs(r-a)<=Di.SAME_PX*Math.max(1,Math.abs(a)),n=e.bounds,s=t.bounds;return!i(n.x,s.x)||!i(n.y,s.y)||!i(n.width,s.width)||!i(n.height,s.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,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(e),a=this.shortestArc(t.azimuthDeg-s.headingDeg),o=t.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,a)-i.width/2,y:r.y-this.offAxisPx(n,o)-i.height/2}}static frameCentre(e){return{x:Yt.frameWidthPx(e.instrument,xt.CANVAS_HEIGHT_PX)/2,y:xt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=Di.OFF_CANVAS_DEG?Math.sign(t)*Di.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,i){const n=Yt.frameWidthPx(t,xt.CANVAS_HEIGHT_PX)/2,s=Yt.frameWidthPx(e.instrument,xt.CANVAS_HEIGHT_PX)/2,r=xt.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=Ts.of(t,xt.CANVAS_HEIGHT_PX,c),d=Ts.of(e.instrument,xt.CANVAS_HEIGHT_PX,o);e.timeline.addKeyframe(a.t,a.shapes.map(u=>{const{bounds:p}=u.shape,f=p.x+p.width/2-n,g=p.y+p.height/2-r,m=Math.hypot(f,g),v=m===0?1:d.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,y={...p,x:s+f*v-p.width/2,y:r+g*v-p.height/2};return{...u,shape:{...u.shape,bounds:y}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:i}=e;for(const n of[...i.allKeyframes]){const s=ut(e,n.t),r=this.fovOf(e,n.t),a=Ts.of(e.instrument,xt.CANVAS_HEIGHT_PX,r);let o=!1;const c=n.shapes.map(h=>{const d=t(h.shape,a,s);return d===h.shape?h:(o=!0,{...h,shape:d})});o&&i.addKeyframe(n.t,c)}}}function cf(l){return rs.restore(Eg(l),l.provenance)}function Eg(l){return Di.toAngular(l),Di.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:l.observerTrack.toJSON(),weatherTrack:l.weatherTrack.toJSON(),soundTrack:l.soundTrack.toJSON(),weather:l.weather,decor:l.decor,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,lightPollution:l.lightPollution,observerMap:l.observerMap,interpretation:l.interpretation,variants:l.variants.length>0?l.variants:void 0,skyEvents:zr.written(l.skyEvents),frozen:l.frozen}}function eb(l){Xo.check(l,"sighting");const{recording:e,provenance:t}=rs.strip(l),i=PT(e);return i.provenance=t,i}function PT(l){const e=[],t=new jf({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},$f.fromJSON(l.timeline,e),l.observerTrack?Md.fromJSON(l.observerTrack):new Md,l.weatherTrack?xd.fromJSON(l.weatherTrack):new xd,l.soundTrack?Sd.fromJSON(l.soundTrack):new Sd,l.observer&&{id:l.observer.id,title:l.observer.title,lastName:l.observer.lastName,firstNames:l.observer.firstNames},l.id,l.weather,l.decor??[],l.weatherSource,l.instrument,l.exposureSeconds??l.observerTrack?.keyframes.map(n=>n.pose.exposureSeconds).find(n=>n!==void 0),bl(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.lightPollution=l.lightPollution,t.observerMap=l.observerMap,t.vehicle=l.vehicle;const i=zr.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,Di.toBounds(t),Di.toPosition(t),t}class ah{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=ah.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(n=>` ${ah.text(n)}`);console.warn(`UFO@home: ${e.length} problem(s) in ${t??"this recording"}:
|
|
4155
4155
|
${i.join(`
|
|
4156
4156
|
`)}`)}}class or{constructor(e){this.format=e}issues(e){const t=[];return this.object(e,this.format,"",t),t}object(e,t,i,n){if(!or.isObject(e)){n.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:or.typeOf(e)});return}for(const[s,r]of Object.entries(e)){const a=i?`${i}.${s}`:s,o=t[s];o?this.field(r,o,a,n):n.push({kind:"unknown-key",path:a})}}field(e,t,i,n){if(or.isStated(e)){this.field(e.value,t,i,n);return}if(!(t.loose||e===void 0||e===null))switch(t.type){case"enum":(typeof e!="string"||!t.values?.includes(e))&&n.push({kind:"not-in-list",path:i,expected:(t.values??[]).map(s=>`"${s}"`).join(", "),found:JSON.stringify(e)});return;case"object":t.fields?this.object(e,t.fields,i,n):or.isObject(e)||n.push({kind:"wrong-type",path:i,expected:"object",found:or.typeOf(e)});return;case"array":Array.isArray(e)?t.fields&&e.forEach((s,r)=>{const a=or.isStated(s)?s.value:s;this.object(a,t.fields,`${i}.${r}`,n)}):n.push({kind:"wrong-type",path:i,expected:"array",found:or.typeOf(e)});return;default:typeof e!==t.type&&n.push({kind:"wrong-type",path:i,expected:t.type,found:or.typeOf(e)})}}static isObject(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}static isStated(e){return or.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 pr{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,n=Math.max(0,e-i*1e3),s=Math.max(0,e-n);return{fromMs:n,toMs:e,ms:s,seconds:s/1e3}}static instants(e,t,i,n,s){if(!(n>0))return 1;const r=s>0?pr.travelDegOver(e,t,i,i+n*1e3)/s/pr.PIXELS_PER_INSTANT:0,a=pr.flashesOver(e,n)*pr.INSTANTS_PER_FLASH,o=Math.ceil(Math.max(r,a));return o<2?1:Math.min(pr.MAX_INSTANTS,o)}static travelDegOver(e,t,i,n){let s=0;for(const r of e){if(!r.track||r.track.length<2)continue;const a=pr.directionAt(r,t,i),o=pr.directionAt(r,t,n),c=Math.min(1,Math.max(-1,a.x*o.x+a.y*o.y+a.z*o.z));s=Math.max(s,Math.acos(c)*180/Math.PI)}return s}static flashesOver(e,t){let i=0;for(const n of e)for(const s of n.lights??[])s.pattern.kind==="flash"&&(i=Math.max(i,s.pattern.perMinute));return i/60*t}static directionAt(e,t,i){const n=Mr(e,i),s=n.eastM,r=n.altitudeM-t,a=n.northM,o=Math.hypot(s,r,a);return o===0?{x:0,y:1,z:0}:{x:s/o,y:r/o,z:a/o}}}const p2={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:ah.EN},NT=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:p2},Symbol.toStringTag,{value:"Module"})),f2=Math.PI/180,FT=180/Math.PI,UT=256,m2=19,zT=1.25;function g2(l,e){return 156543.03392*Math.cos(l*f2)/2**e}function v2(l,e){return g2(l,e)*UT}function BT(l,e){let t=0;for(;t<m2&&v2(l,t+1)>=e;)t++;return t}function b2(l,e){return v2(l,e)}function HT(l,e){const t=e*zT;let i=0;for(;i<m2&&g2(l,i)>t;)i++;return i}function gp(l){const e=l*f2;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function y2(l,e,t){const i=2**t;return{x:(l+180)/360*i,y:gp(e)*i}}function w2(l,e,t){const i=gp(l.north),n=gp(l.south);return{x:(e-l.west)/(l.east-l.west),y:(gp(t)-i)/(n-i)}}function GT(l,e,t){const{x:i,y:n}=y2(l,e,t);return{x:Math.floor(i),y:Math.floor(n),z:t}}function VT(l){const e=2**l.z,t=l.x/e*360-180,i=(l.x+1)/e*360-180,n=J1(l.y,e);return{south:J1(l.y+1,e),north:n,west:t,east:i}}function J1(l,e){const t=l/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*FT}function M2(l,e,t,i){const n=GT(l,e,t),s=Math.floor(i/2),r=[];for(let c=-s;c<=s;c++)for(let h=-s;h<=s;h++)r.push({x:n.x+h,y:n.y+c,z:t});const a=r.map(VT),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 WT="#2ec4ff";class Ho{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,n=1/0;for(const s of this.targets){const r=Math.hypot(s.x-e,s.y-t);r>s.radius||r>n||(i=s,n=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 n=w2(e,i,t);return{x:n.x*this.width,y:n.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 n=this.toCanvas(e.bounds,i.bounds.north,i.bounds.west),s=this.toCanvas(e.bounds,i.bounds.south,i.bounds.east);t.drawImage(i.source,n.x,n.y,s.x-n.x,s.y-n.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 n=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:n.x,y:n.y,radius:7}),t.beginPath(),t.rect(n.x-3.5,n.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 s=(i.headingDeg-90)*Math.PI/180;t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(n.x+Math.cos(s)*10,n.y+Math.sin(s)*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(n=>this.toCanvas(e.bounds,n.lat,n.lng));t.beginPath(),t.moveTo(i[0].x,i[0].y);for(const n of i.slice(1))t.lineTo(n.x,n.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 n=i.points.map(r=>this.toCanvas(e.bounds,r.lat,r.lng));if(n.length===0)continue;const s=i.color??WT;if(i.kind==="point")t.beginPath(),t.moveTo(n[0].x,n[0].y-6),t.lineTo(n[0].x+6,n[0].y),t.lineTo(n[0].x,n[0].y+6),t.lineTo(n[0].x-6,n[0].y),t.closePath(),t.fillStyle=s,t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.8)",t.stroke();else{t.beginPath(),t.moveTo(n[0].x,n[0].y);for(const r of n.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=s,t.lineWidth=2.5,t.stroke(),t.setLineDash([])}if(i.label){t.font="11px sans-serif",t.textAlign="left",t.textBaseline="middle";let r=n[0];if(i.kind==="line"&&e.position){const a=this.toCanvas(e.bounds,e.position.lat,e.position.lng);r=n.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:n}=e;if(i===void 0||n===void 0)return;const{ctx:s}=this,r=this.toCanvas(e.bounds,t.lat,t.lng),a=Math.hypot(this.width,this.height),o=(i-90)*Math.PI/180,c=n*Math.PI/180;s.save(),s.beginPath(),s.moveTo(r.x,r.y),s.arc(r.x,r.y,a,o-c,o+c),s.closePath();const h=s.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)"),s.fillStyle=h,s.fill(),s.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((n,s)=>Number(n.current)-Number(s.current))){const n=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:n.x,y:n.y,radius:Ho.MARKER_RADIUS_PX}),t.beginPath(),t.arc(n.x,n.y,Ho.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,n.x,n.y)}}paintObserver(e,t){const{ctx:i}=this,n=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:n.x,y:n.y,radius:8});const s=e.markers.some(r=>{if(!r.current)return!1;const a=at(r.lat,r.lng,t.lat,t.lng);return Math.hypot(a.x,a.z)<=Ho.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?Ho.MARKER_RADIUS_PX+2.5:5.5,0,Math.PI*2),s||(i.fillStyle="#ff5a3c",i.fill()),i.lineWidth=4,i.strokeStyle="rgba(0, 0, 0, 0.5)",i.stroke(),i.lineWidth=s?3:2.5,i.strokeStyle=s?"#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 n=t?this.wrap(t,this.width-20):[];let s=this.height-4;i.textAlign="right";for(const p of n.slice().reverse())this.paintOutlinedText(p,this.width-6,s),s-=11;const r=(e.south+e.north)/2,o=Math.abs(at(r,e.east,r,e.west).x)/this.width,c=Ho.SCALE_STEPS_M.find(p=>p/o<=this.width/3);if(c===void 0)return;const h=c/o,d=8,u=s-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:n}=this;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.75)",n.strokeText(e,t,i),n.fillStyle="#fff",n.fillText(e,t,i)}wrap(e,t){const i=[];let n="";for(const s of e.split(" ")){const r=n?`${n} ${s}`:s;n&&this.ctx.measureText(r).width>t?(i.push(n),n=s):n=r}return n&&i.push(n),i}}class jt{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 jt.including(e.boundsAround(jt.MIN_SPAN_M,jt.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 n=Math.min(jt.MAX_ZOOM,Math.max(jt.MIN_ZOOM,this.zoom*i)),s=this.centerX+(e-.5)/this.zoom,r=this.centerY+(t-.5)/this.zoom;this.centerX=s-(e-.5)/n,this.centerY=r-(t-.5)/n,this.zoom=n}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),n=jt.mercatorY01(t.north),s=jt.mercatorY01(t.south),r=jt.mercatorY01(i.north),a=jt.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-n)/(s-n)}keepInView(e,t,i){if(!this.changed)return!1;const n=this.boundsWithin(e),s=jt.mercatorY01(n.north),r=jt.mercatorY01(n.south),a=(t.lng-n.west)/(n.east-n.west),o=(jt.mercatorY01(t.lat)-s)/(r-s);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=jt.mercatorY01(e.north),n=jt.mercatorY01(e.south),s=e.east-e.west;return{west:e.west+(this.centerX-t)*s,east:e.west+(this.centerX+t)*s,north:jt.latitudeAt(i+(this.centerY-t)*(n-i)),south:jt.latitudeAt(i+(this.centerY+t)*(n-i))}}static including(e,t,i=3){const n=(e.north+e.south)/2,s=(e.east+e.west)/2,r=at(n,e.east,n,s).x;let a=r;for(const o of t){const{x:c,z:h}=at(o.lat,o.lng,n,s),d=Math.max(Math.abs(c),Math.abs(h));d<=r*i&&(a=Math.max(a,d*1.15))}return a<=r?e:{north:Bs(0,-a,n,s).lat,south:Bs(0,a,n,s).lat,east:Bs(a,0,n,s).lng,west:Bs(-a,0,n,s).lng}}static expand(e,t){const i=e.east-e.west,n=e.north-e.south;return{west:e.west-i*t,east:e.east+i*t,south:e.south-n*t,north:e.north+n*t}}static pointAt(e,t,i){const n=jt.mercatorY01(e.north),s=jt.mercatorY01(e.south);return{lat:jt.latitudeAt(n+i*(s-n)),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 $s=256,Q1=3,$T=32768;class x2{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,n=(e.west+e.east)/2,s=Math.abs(at(i,e.east,i,e.west).x),r=Math.abs(at(e.north,n,e.south,n).z),a=BT(i,Math.max(s,r)),{tiles:o}=M2(n,i,a,Q1),c=Q1*$s,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 g=0;g<t.width;g++){const m=e.west+(e.east-e.west)*(g/(t.width-1));u[p*t.width+g]=this.sampleAt(f,m,a,d,h,c)}}return{heights:u,width:t.width,height:t.height,bounds:e}}async decodeTileInto(e,t,i,n){const s=this.tileUrlTemplate.replace("{z}",String(e.z)).replace("{x}",String(e.x)).replace("{y}",String(e.y)),r=await this.fetchImpl(s);if(!r.ok)throw new Error(`Elevation tile fetch failed (${r.status}): ${s}`);const a=await createImageBitmap(await r.blob()),o=document.createElement("canvas");o.width=$s,o.height=$s;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,$s,$s),d=(e.x-t.x)*$s,u=(e.y-t.y)*$s;for(let p=0;p<$s;p++)for(let f=0;f<$s;f++){const g=(p*$s+f)*4,m=h[g]*256+h[g+1]+h[g+2]/256-$T,v=d+f,y=u+p;i[y*n+v]=m}}sampleAt(e,t,i,n,s,r){const{x:a,y:o}=y2(t,e,i),c=(a-n.x)*$s,h=(o-n.y)*$s,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),g=c-d,m=h-u,v=s[u*r+d],y=s[u*r+p],w=s[f*r+d],b=s[f*r+p],M=v+(y-v)*g,S=w+(b-w)*g;return M+(S-M)*m}}class rm{constructor(e,t,i,n){this.width=e,this.height=t,this.samples=i,this.values=n}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),n=t.getUint16(i,!0),s=new Map;for(let v=0;v<n;v++){const y=i+2+v*12;s.set(t.getUint16(y,!0),{type:t.getUint16(y+2,!0),count:t.getUint32(y+4,!0),value:t.getUint32(y+8,!0)})}const r=(v,y)=>{const w=s.get(v);if(w===void 0){if(y===void 0)throw new Error(`TIFF without tag ${v}`);return y}return w.type===3?w.value&65535:w.value},a=v=>{const y=s.get(v);if(y===void 0)throw new Error(`TIFF without tag ${v}`);const w=y.type===3?2:4,b=[];if(y.count*w<=4){const M=new DataView(new ArrayBuffer(4));M.setUint32(0,y.value,!0);for(let S=0;S<y.count;S++)b.push(w===2?M.getUint16(S*2,!0):M.getUint32(0,!0))}else for(let M=0;M<y.count;M++)b.push(w===2?t.getUint16(y.value+M*2,!0):t.getUint32(y.value+M*4,!0));return b};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(s.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),g=new Uint8Array(o*c*h*(d/8));let m=0;for(let v=0;v<p.length&&m<g.length;v++){const y=Math.min(f[v],g.length-m);g.set(new Uint8Array(e,p[v],y),m),m+=y}if(m<g.length)throw new Error("Truncated TIFF");return new rm(o,c,h,u?new Float32Array(g.buffer):g)}}class XT{constructor(e,t,i,n,s){this.heights=e,this.plants=t,this.buildings=i,this.size=n,this.metresPerPixel=s}structureAt(e,t){const i=Math.floor(e/this.metresPerPixel+this.size/2),n=Math.floor(this.size/2-t/this.metresPerPixel);if(i<0||n<0||i>=this.size||n>=this.size)return;const s=n*this.size+i;if(!(this.plants[s]||this.buildings[s]))return this.heights[s]}tallestStructureNear(e,t,i){let n;const s=Math.ceil(i/this.metresPerPixel);for(let r=-s;r<=s;r++)for(let a=-s;a<=s;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&&(n===void 0||o>n)&&(n=o)}return n}}class _e{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,n]=e;return{east:(i-t.lng)*_e.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180),north:(n-t.lat)*_e.METRES_PER_DEGREE}}static path(e,t){return e.geometry.type!=="LineString"?[]:e.geometry.coordinates.map(i=>_e.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 n=i.east-t.east,s=i.north-t.north,r=n*n+s*s,a=r===0?0:Math.max(0,Math.min(1,((e.east-t.east)*n+(e.north-t.north)*s)/r));return Math.hypot(e.east-(t.east+a*n),e.north-(t.north+a*s))}static bridges(e,t,i,n){const s=e.elevatedRoads.map(o=>({path:_e.path(o,t),properties:o.properties})),r=(e.elevatedRailways??[]).map(o=>_e.path(o,t)),a=[];for(const o of _e.joined(e.bridges.map(c=>_e.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<_e.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||_e.carriesRailway(c,h,r))continue;const[p,f]=_e.deckReach(c,h,n);a.push({eastM:_e.tenth((p.east+f.east)/2),northM:_e.tenth((p.north+f.north)/2),lengthM:_e.tenth(Math.hypot(f.east-p.east,f.north-p.north)),widthM:_e.roadOf(u,s).width,heightM:_e.tenth(_e.deckHeight(c,h,n)),headingDeg:_e.tenth(_e.bearing(c,h)%180),..._e.roadOf(u,s).name?{name:_e.roadOf(u,s).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 n={east:(e.east+t.east)/2,north:(e.north+t.north)/2},s=_e.bearing(e,t)%180;for(const r of i)for(let a=0;a+1<r.length;a++){if(_e.distanceToSegment(n,r[a],r[a+1])>_e.RAIL_MATCH_M)continue;const o=Math.abs(_e.bearing(r[a],r[a+1])%180-s);if(Math.min(o,180-o)<=_e.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 n=i+1;n<t.length;n++){const s=_e.join(t[i],t[n]);s!==void 0&&(t[i]=s,t.splice(n,1),n=i)}return t}static join(e,t){for(const i of[e,[...e].reverse()])for(const n of[t,[...t].reverse()]){const s=i[i.length-1],r=n[0];if(Math.hypot(s.east-r.east,s.north-r.north)>_e.JOIN_M)continue;const a=Math.abs(_e.bearing(i[0],s)-_e.bearing(r,n[n.length-1]));if(Math.min(a,360-a)<=_e.JOIN_DEG)return[...i,...n.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=_e.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>_e.ROAD_MATCH_M)return{width:_e.DEFAULT_DECK_M};const n=[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),s=Number(i.properties.largeur_de_chaussee),r=Number.isFinite(s)&&s>0?_e.tenth(s+_e.DECK_MARGIN_M):i.properties.nature==="Sentier"?_e.FOOTBRIDGE_DECK_M:_e.DEFAULT_DECK_M;return n?{width:r,name:n}:{width:r}}static deckReach(e,t,i){const n=Math.hypot(t.east-e.east,t.north-e.north);if(i===void 0||n===0)return[e,t];const s={east:(e.east+t.east)/2,north:(e.north+t.north)/2},r={east:(t.east-e.east)/n,north:(t.north-e.north)/n},a=u=>(i.structureAt(s.east+r.east*u,s.north+r.north*u)??0)>=_e.DECK_SEEN_M,o=u=>i.structureAt(s.east+r.east*u,s.north+r.north*u)??0,c=u=>{let p;for(let g=0;g<=n/2+_e.DECK_REACH_M;g+=_e.DECK_STEP_M)if(a(u*g))p=g;else if(p!==void 0&&g-p>_e.DECK_GAP_M)break;if(p===void 0)return n/2;let f=p;for(;f-p<_e.DECK_REACH_M&&o(u*(f+_e.DECK_STEP_M))>=_e.DECK_MEETS_M;)f+=_e.DECK_STEP_M;return Math.max(n/2,f+_e.DECK_BEARING_M)},h=c(-1),d=c(1);return[{east:s.east-r.east*h,north:s.north-r.north*h},{east:s.east+r.east*d,north:s.north+r.north*d}]}static deckHeight(e,t,i){if(i===void 0)return _e.DEFAULT_DECK_HEIGHT_M;const n=[],s=20;for(let r=4;r<=s-4;r++){const a=i.structureAt(e.east+(t.east-e.east)*r/s,e.north+(t.north-e.north)*r/s);a!==void 0&&a>=1.5&&n.push(a)}return n.length===0?_e.DEFAULT_DECK_HEIGHT_M:(n.sort((r,a)=>r-a),n[Math.floor(n.length/2)])}static lines(e,t,i,n){const s=[];for(const r of e.lines){const a=String(r.properties.voltage??""),o=_e.kilovolts(a);if(o===void 0)continue;const c=_e.BY_VOLTAGE.find(d=>o<=d.upToKv)??_e.BY_VOLTAGE[_e.BY_VOLTAGE.length-1],h=_e.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>_e.MAX_SPAN_M||_e.distanceToSegment({east:0,north:0},u,p)>i)continue;const g=_e.poleHeight(u,p,n)??c.poleM;s.push({eastM:_e.tenth((u.east+p.east)/2),northM:_e.tenth((u.north+p.north)/2),lengthM:_e.tenth(f),headingDeg:_e.tenth(_e.bearing(u,p)),heightM:_e.tenth(Math.max(4,g-c.dropM)),poleHeightM:_e.tenth(g),acrossM:[-c.spreadM,0,c.spreadM],voltage:a})}}return s.sort((r,a)=>Math.hypot(r.eastM,r.northM)-Math.hypot(a.eastM,a.northM)),s.slice(0,_e.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 n=[e,t].map(s=>i.tallestStructureNear(s.east,s.north,3)).filter(s=>s!==void 0&&s>=_e.MIN_POLE_M&&s<=_e.MAX_POLE_M);return n.length===0?void 0:n.reduce((s,r)=>s+r,0)/n.length}static tenth(e){return Math.round(e*10)/10}}class kt{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??kt.WMS,this.wfs=e.wfsEndpoint??kt.WFS}static radius(e){return Math.min(e,kt.MAX_RADIUS_M)}static lidarRadius(e){return Math.min(e,kt.MAX_LIDAR_RADIUS_M)}async lidar(e,t){const i=kt.lidarRadius(t),n=Math.ceil(2*i/kt.METRES_PER_PIXEL),[s,r]=await Promise.all([this.raster(e,i,n,kt.HEIGHT_LAYER),this.raster(e,i,n,kt.CLASS_LAYER)]);if(s.samples!==1||r.samples<3)throw new cr("unreachable","The survey answered in a layout this does not read");const a=s.values;if(a.every(d=>d===kt.NO_DATA))throw new cr("no-coverage","No LiDAR HD survey here yet");const o=new Uint8Array(n*n),c=new Uint8Array(n*n);for(let d=0;d<n*n;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/n;return{size:n,metresPerPixel:h,heights:a,vegetation:o,building:c,structures:new XT(a,o,c,n,h)}}async laserDate(e){return kt.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",e))}async photoDate(e){return kt.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,n){const r=[n.lng-1e-4,n.lat-1e-4,n.lng+1e-4,n.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=kt.radius(t),n=Math.min(kt.MAX_PHOTO_PIXELS,Math.ceil(2*i/kt.METRES_PER_PIXEL)),s=await this.raster(e,i,n,kt.PHOTO_LAYER);if(s.samples<3)throw new cr("unreachable","The photograph came in a layout this does not read");return{size:n,metresPerPixel:2*i/n,samples:s.samples,values:s.values}}async vectors(e,t,i){const n=kt.radius(t),s=n/kt.METRES_PER_DEGREE,r=n/(kt.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),o=`BBOX(geometrie,${[e.lng-r,e.lat-s,e.lng+r,e.lat+s].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,kt.BUILDING_PROPERTIES,5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",o,"toponyme,categorie,geometrie",100).catch(()=>[]):Promise.resolve([])]),g=i?await this.wholeWorship(f,p,[e.lng-r,e.lat-s,e.lng+r,e.lat+s]):[],m=[...p,...g];return{bridges:c,elevatedRoads:h,elevatedRailways:d,lines:u,buildings:m,zones:f,mapDate:kt.latest(m.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[n,s,r,a]=i,o=kt.MAX_WHOLE_M/kt.METRES_PER_DEGREE;let c;for(const d of e){if(d.properties.categorie!=="Religieux")continue;const[u,p,f,g]=kt.extent(d);if(u>=n&&p>=s&&f<=r&&g<=a)continue;const m=[Math.max(u,n-o),Math.max(p,s-o),Math.min(f,r+o),Math.min(g,a+o)];c=c?[Math.min(c[0],m[0]),Math.min(c[1],m[1]),Math.max(c[2],m[2]),Math.max(c[3],m[3])]:m}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')`,kt.BUILDING_PROPERTIES,1e3)).filter(u=>!h.has(u.properties.cleabs))}catch{return[]}}static extent(e){let t=1/0,i=1/0,n=-1/0,s=-1/0;const r=a=>{Array.isArray(a)&&typeof a[0]=="number"?(t=Math.min(t,a[0]),n=Math.max(n,a[0]),i=Math.min(i,a[1]),s=Math.max(s,a[1])):Array.isArray(a)&&a.forEach(r)};return r(e.geometry.coordinates),[t,i,n,s]}async elevatedRoadLines(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(s=>s.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${t} AND position_par_rapport_au_sol>'0'`,"geometrie",300),n=[];for(const s of i){const{type:r,coordinates:a}=s.geometry,o=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const c of o)n.push(c.map(h=>({lat:h[1],lng:h[0]})))}return n}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,n){const s=t/kt.METRES_PER_DEGREE,r=t/(kt.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:n,STYLES:"",CRS:"EPSG:4326",BBOX:[e.lat-s,e.lng-r,e.lat+s,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 cr("unreachable",c instanceof Error?c.message:String(c))}if(!o.ok)throw new cr("unreachable",`The survey answered ${o.status}`);try{return rm.parse(await o.arrayBuffer())}catch(c){throw new cr("unreachable",c instanceof Error?c.message:String(c))}}async features(e,t,i,n=200){const s=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(n),CQL_FILTER:t,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${s}`)}catch(o){throw new cr("unreachable",o instanceof Error?o.message:String(o))}if(!r.ok)throw new cr("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class eo{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],n=t.map(a=>at(a.lat,a.lng,i.lat,i.lng)),s=e.map(a=>at(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<s.length-1;a++){const o=s[a],c=s[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/eo.SAMPLE_M)),u=Math.atan2(c.x-o.x,-(c.z-o.z));for(let p=0;p<=d;p++){const f=p/d,g=eo.nearest(n,o.x+(c.x-o.x)*f,o.z+(c.z-o.z)*f);g.distanceM>eo.NEAR_M||eo.angleBetween(u,g.heading)<=eo.ALIGNED_DEG&&(r+=h/d)}}return r>=eo.LONG_ENOUGH_M}static nearest(e,t,i){let n={distanceM:1/0,heading:0};for(let s=0;s<e.length-1;s++){const r=e[s],a=e[s+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<n.distanceM&&(n={distanceM:u,heading:Math.atan2(o,-c)})}return n}static angleBetween(e,t){const i=Math.abs((e-t)*180/Math.PI%180);return Math.min(i,180-i)}}class Tt{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??Tt.WMS,this.timeoutMs=e.timeoutMs??Tt.DEFAULT_TIMEOUT_MS,this.maxWindowM=e.maxWindowM??Tt.MAX_WINDOW_M,this.geoplatform=new kt({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:e.wfsEndpoint})}async getElevationGrid(e,t,i){const n={lat:(e.south+e.north)/2,lng:(e.west+e.east)/2};if(!kt.covers(n.lat,n.lng))throw new Error("The IGN's relief covers France only");const s=Math.abs(at(n.lat,e.east,n.lat,e.west).x),r=Math.abs(at(e.north,n.lng,e.south,n.lng).z);t=this.finer(t,s,r);const a={x:s/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/Tt.METRES_PER_DEGREE,north:e.north+o.y/Tt.METRES_PER_DEGREE,west:e.west-o.x/(Tt.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180)),east:e.east+o.x/(Tt.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180))},h=g=>Math.min(Tt.MAX_PIXELS,Math.max(Tt.MIN_PIXELS,Math.ceil(g/Tt.METRES_PER_PIXEL))),d={width:h(s+2*o.x),height:h(r+2*o.y)},u={x:(s+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)>Tt.COARSE_METRES_PER_PIXEL;for(const g of f?[...Tt.LAYERS].reverse():Tt.LAYERS)try{const m=await this.heights(c,d,g);g===Tt.LAYERS[0]&&await this.layBridgeDecks(m,c,d,i?.route);const v=this.sample(m,t,e,c,u,a);if(v)return{heights:v,width:t.width,height:t.height,bounds:e};p=new Error(`${g} does not cover this place`)}catch(m){p=m}throw p}finer(e,t,i){if(e.width<Tt.MESH_FROM_VERTICES||e.height<Tt.MESH_FROM_VERTICES)return e;const n=(s,r)=>{const a=Math.ceil(s/Tt.FINE_SPACING_M),o=Math.max(r-1,Math.min(Tt.MAX_SEGMENTS,a));return o%2===0?o:o+1};return{width:n(t,e.width)+1,height:n(i,e.height)+1}}async raster(e,t,i){const n=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"}),s=await this.fetchImpl(`${this.wms}?${n}`,{signal:AbortSignal.timeout(this.timeoutMs)});if(!s.ok)throw new Error(`The IGN's relief answered ${s.status}`);return rm.parse(await s.arrayBuffer())}async heights(e,t,i){const n=await this.raster(e,t,i);if(n.samples!==1||!(n.values instanceof Float32Array))throw new Error("The IGN's relief came in a layout this does not read");return n}async layBridgeDecks(e,t,i,n){if(!(!n||n.length<2)&&!(!(e.values instanceof Float32Array)||!e.values.some(s=>s>Tt.NO_DATA_BELOW)))try{const s=(await this.geoplatform.elevatedRoadLines({west:t.west,south:t.south,east:t.east,north:t.north})).filter(a=>eo.follows(n,a));if(s.length===0)return;const r=Float32Array.from(e.values);await this.layClassifiedDecks(e,t,i,s),this.layRouteDecks(e,r,t,s)}catch{}}async layClassifiedDecks(e,t,i,n){try{const s=await this.raster(t,i,Tt.CLASS_LAYER);if(s.samples<3||s.width!==e.width||s.height!==e.height)return;const r=(m,[v,y,w])=>s.values[m*s.samples]===v&&s.values[m*s.samples+1]===y&&s.values[m*s.samples+2]===w,a=e.width,o=e.height,c=new Uint8Array(a*o);let h=!1;for(let m=0;m<c.length;m++)r(m,Tt.DECK)&&(c[m]=1,h=!0);if(!h)return;const d=Tt.DECK_END_PIXELS,u=[];for(let m=0;m<c.length;m++){if(c[m]!==1)continue;const v=m%a,y=(m-v)/a;for(let w=-d;w<=d;w++)for(let b=-d;b<=d;b++){const M=v+b,S=y+w;if(M<0||S<0||M>=a||S>=o)continue;const E=S*a+M;c[E]===0&&r(E,Tt.NO_CLASS)&&u.push(E)}}for(const m of u)c[m]=1;const p=this.paint(n,t,a,o),f=this.touching(c,p,a,o);if(f.every(m=>m===0))return;const g=await this.heights(t,i,Tt.SURFACE_LAYER);if(g.width!==a||g.height!==o)return;for(let m=0;m<f.length;m++){if(f[m]===0)continue;const v=g.values[m];Number.isFinite(v)&&v>Tt.NO_DATA_BELOW&&v>e.values[m]&&(e.values[m]=v)}}catch{}}layRouteDecks(e,t,i,n){const{width:s,height:r}=e,a=(i.north+i.south)/2,o=(i.east-i.west)*Tt.METRES_PER_DEGREE*Math.cos(a*Math.PI/180),c=(i.north-i.south)*Tt.METRES_PER_DEGREE,h=o/s,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,y)=>{const w=Math.floor(v/h),b=Math.floor(y/d);if(w<0||b<0||w>=s||b>=r)return;const M=t[b*s+w];return Number.isFinite(M)&&M>Tt.NO_DATA_BELOW?M:void 0},f=Tt.DECK_HALF_WIDTH_M,g=Tt.DECK_APPROACH_M,m=(v,y)=>{const w=Math.hypot(v.x-y.x,v.y-y.y)||1,b={x:(v.x-y.x)/w,y:(v.y-y.y)/w},M=[0,g/2,g].map(S=>p(v.x+b.x*S,v.y+b.y*S)).filter(S=>S!==void 0);return M.length>0?Math.max(...M):void 0};for(const v of Tt.chains(n.map(y=>y.map(u)))){const y=[0];for(let D=1;D<v.length;D++)y.push(y[D-1]+Math.hypot(v[D].x-v[D-1].x,v[D].y-v[D-1].y));const w=y[y.length-1];if(w<1||w>Tt.DECK_STRAIGHT_MAX_M)continue;const b=m(v[0],v[1]),M=m(v[v.length-1],v[v.length-2]);if(b===void 0||M===void 0)continue;const S=f+g,E=Math.max(0,Math.floor((Math.min(...v.map(D=>D.x))-S)/h)),x=Math.min(s-1,Math.ceil((Math.max(...v.map(D=>D.x))+S)/h)),T=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=T;D<=R;D++)for(let O=E;O<=x;O++){const C=Tt.nearestAlong(v,y,{x:(O+.5)*h,y:(D+.5)*d});if(C.distance>f||C.s<-g||C.s>w+g)continue;const P=b+(M-b)*Math.min(1,Math.max(0,C.s/w)),k=D*s+O;t[k]>=P||(e.values[k]=P)}}}static chains(e){const t=e.filter(s=>s.length>=2).map(s=>[...s]),i=[],n=(s,r)=>Math.hypot(s.x-r.x,s.y-r.y)<=1;for(;t.length>0;){let s=t.shift(),r=!0;for(;r;){r=!1;for(let a=0;a<t.length;a++){const o=t[a],c=s[0],h=s[s.length-1];if(n(h,o[0]))s=[...s,...o.slice(1)];else if(n(h,o[o.length-1]))s=[...s,...[...o].reverse().slice(1)];else if(n(c,o[o.length-1]))s=[...o.slice(0,-1),...s];else if(n(c,o[0]))s=[...[...o].reverse().slice(0,-1),...s];else continue;t.splice(a,1),r=!0;break}}i.push(s)}return i}static nearestAlong(e,t,i){let n={s:0,distance:1/0};for(let s=0;s<e.length-1;s++){const r=e[s],a=e[s+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;s>0&&(d=Math.max(0,d)),s<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<n.distance&&(n={s:t[s]+d*Math.sqrt(h),distance:u})}return n}paint(e,t,i,n){const s=new Uint8Array(i*n),r=o=>(o-t.west)/(t.east-t.west)*i,a=o=>(t.north-o)/(t.north-t.south)*n;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 g=0;g<=f;g++){const m=Math.floor(h+(u-h)*g/f),v=Math.floor(d+(p-d)*g/f);for(let y=-1;y<=1;y++)for(let w=-1;w<=1;w++){const b=m+w,M=v+y;b>=0&&M>=0&&b<i&&M<n&&(s[M*i+b]=1)}}}return s}touching(e,t,i,n){const s=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 g=-1;g<=1;g++){const m=u+g,v=p+f;if(m<0||v<0||m>=i||v>=n)continue;const y=v*i+m;e[y]===1&&r[y]===0&&(r[y]=1,c.push(y))}}if(h)for(const d of o)s[d]=1}return s}sample(e,t,i,n,s,r){const{width:a,height:o}=t,c=new Float32Array(a*o),h=new Uint8Array(a*o),d=Math.min(r.x,this.maxWindowM)/s.x,u=Math.min(r.y,this.maxWindowM)/s.y;let p=0;for(let f=0;f<o;f++){const g=i.north+(i.south-i.north)*(o===1?.5:f/(o-1)),m=(n.north-g)/(n.north-n.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))-n.west)/(n.east-n.west)*e.width-.5,b=d>1||u>1?this.tent(e,w,m,Math.max(1,d),Math.max(1,u)):this.bilinear(e,w,m),M=f*a+v;b===void 0?p++:(c[M]=b,h[M]=1)}}if(!(p===a*o||p/(a*o)>Tt.MAX_HOLE_SHARE))return this.fill(c,h,a,o),c}tent(e,t,i,n,s){let r=0,a=0,o=0;const c=Math.max(0,Math.ceil(i-s)),h=Math.min(e.height-1,Math.floor(i+s)),d=Math.max(0,Math.ceil(t-n)),u=Math.min(e.width-1,Math.floor(t+n));for(let p=c;p<=h;p++){const f=1-Math.abs(p-i)/s;if(!(f<=0))for(let g=d;g<=u;g++){const m=f*(1-Math.abs(g-t)/n);if(m<=0)continue;o+=m;const v=e.at(g,p);!Number.isFinite(v)||v<Tt.NO_DATA_BELOW||(r+=m*v,a+=m)}}return o>0&&a>=o*.5?r/a:void 0}bilinear(e,t,i){const n=Math.max(0,Math.min(e.width-1,Math.floor(t))),s=Math.max(0,Math.min(e.height-1,Math.floor(i))),r=Math.min(e.width-1,n+1),a=Math.min(e.height-1,s+1),o=Math.max(0,Math.min(1,t-n)),c=Math.max(0,Math.min(1,i-s)),h=e.at(n,s),d=e.at(r,s),u=e.at(n,a),p=e.at(r,a);for(const m of[h,d,u,p])if(!Number.isFinite(m)||m<Tt.NO_DATA_BELOW)return;const f=h+(d-h)*o,g=u+(p-u)*o;return f+(g-f)*c}fill(e,t,i,n){let s=t.reduce((r,a)=>r+(a?0:1),0);for(;s>0;){const r=[];for(let a=0;a<n;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,g=o+p;f<0||g<0||f>=n||g>=i||!t[f*i+g]||(h+=e[f*i+g],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;s-=r.length}}}class YT{providers;constructor(...e){this.providers=e}async getElevationGrid(e,t,i){let n=new Error("No source of relief to ask");for(const s of this.providers)try{return await s.getElevationGrid(e,t,i)}catch(r){n=r}throw n}}const vp=256,KT=5;async function S2(l,e,t,i){const n=(l.south+l.north)/2,s=(l.west+l.east)/2,r=Math.abs(at(n,l.east,n,l.west).x),a=Math.abs(at(l.north,s,l.south,s).z),o=Math.max(r,a),{zoom:c,gridSize:h}=qT(n,o,Math.max(e.width,e.height)),{tiles:d,bounds:u}=M2(s,n,c,h),p=h*vp,f=document.createElement("canvas");f.width=p,f.height=p;const g=f.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");const m=d[0];await Promise.all(d.map(async b=>{const M=t(b),S=await i(M);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${M}`);const E=await createImageBitmap(await S.blob());g.drawImage(E,(b.x-m.x)*vp,(b.y-m.y)*vp)}));const v=Math.min(Math.max(e.width,e.height),p);if(v===p)return{source:f,width:p,height:p,bounds:u};const y=document.createElement("canvas");y.width=v,y.height=v;const w=y.getContext("2d");if(!w)throw new Error("2D canvas context unavailable");return w.drawImage(f,0,0,p,p,0,0,v,v),{source:y,width:v,height:v,bounds:u}}function qT(l,e,t){let i=HT(l,e/Math.max(1,t)),n=ey(l,i,e);for(;n>KT&&i>0;)i--,n=ey(l,i,e);return{zoom:i,gridSize:n,mPerPixel:b2(l,i)/vp}}function ey(l,e,t){const i=Math.ceil(t/2/b2(l,e));return Math.max(3,2*i+1)}class E2{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 S2(e,t,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class Es{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=Es.ENDPOINTS){const i=/\((-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\)/.exec(e);if(!i)return[...t];const[n,s,r,a]=i.slice(1).map(Number),o=(n+r)/2,c=(s+a)/2,h=Es.FRANCE;return o>=h.south&&o<=h.north&&c>=h.west&&c<=h.east?[Es.FRANCE_ENDPOINT,...t.filter(u=>u!==Es.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=Es.queue.then(e,e);return Es.queue=t.catch(()=>{}),t}async ask(e){let t;for(const i of this.endpoints??Es.endpointsFor(e))for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(Es.HANG_MS)});if(s.ok)return await s.json();if(t=new Error(`${new URL(i).host} refused (${s.status})`),s.status!==429&&s.status!==504)break}catch(s){t=new Error(`${new URL(i).host} unreachable (${String(s)})`);break}await new Promise(s=>setTimeout(s,Es.RETRY_MS))}throw t??new Error("No Overpass instance answered")}}class to{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 Es(e)}async getRoads(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:30];way["highway"~"^(${to.DRIVABLE.join("|")})$"](${t});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(e){const t=[];for(const i of e.elements??[]){const n=i.geometry,s=i.tags;!s||!n||n.length<2||t.push({id:`osm-${i.id??t.length}`,name:s.name,surface:to.surfaceOf(s),widthM:to.widthOf(s),...to.paintOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return t}static paintOf(e){const t=e.highway??"",i=e.junction==="roundabout"||e.junction==="circular",n=e.oneway,s=n==="yes"||n==="1"||n==="true"||n===void 0&&(t==="motorway"||i),r=n==="-1"||n==="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")&&(s||r)?"dual":t?"road":void 0;return{...c?{kind:c}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...n!==void 0||t==="motorway"||i?{direction:r?"backward":s?"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:to.WIDTH_M[e.highway]??to.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 xm="https://ufoathome.org/roads/index.json";class Mc{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??Mc.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:n})=>n.north>=e.north&&n.south<=e.south&&n.east>=e.east&&n.west<=e.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.ways)?(this.attributionRead=s.attribution,this.contemporaryRead=s.contemporary,s.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(`
|
|
4157
|
-
`);let t=Mc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Mc.shared.set(e,t),t.then(i=>{i.length===0&&Mc.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.
|
|
4158
|
-
`);let t=xc.shared.get(e);return t||(t=this.fetchFirstAvailable(),xc.shared.set(e,t),t.then(i=>{i.length===0&&xc.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.0")}`,t=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(t&&t!==Sm?[t,Sm]:[Sm]).map(i=>i+e)}}class ys{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=ys.key(e);let i=ys.asked.get(t);return i===void 0&&(i=this.recalled(t,e),ys.asked.set(t,i),i.catch(()=>ys.asked.delete(t))),structuredClone(await i)}static forget(){ys.asked.clear()}static key(e){return`v${ys.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}async recalled(e,t){const i=await ys.openCache(),n=ys.request(e);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:o}=await r.json();if(Date.now()-a<ys.MAX_AGE_MS&&Array.isArray(o))return o;await i.delete(n)}}catch{}const s=await this.water.getWater(t);return i&&ys.store(i,n,s),s}static async store(e,t,i){try{const n={savedAt:Date.now(),surfaces:i};await e.put(t,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await e.keys();for(const r of s.slice(0,Math.max(0,s.length-ys.MAX_STORED)))await e.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(ys.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__water__/${encodeURIComponent(e)}`)}}class ao{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 kt(e)}static covers(e){return kt.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRailways(e){return(await this.platform.railways(e)).flatMap((i,n)=>ao.linesOf(i,n))}static linesOf(e,t){const{type:i,coordinates:n}=e.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=ao.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=ao.GAUGE_MM[String(e.properties.largeur??"")]??1435,u=ao.electrificationOf(r.kind,d,e.properties.electrifie);return s.flatMap((p,f)=>{const g=p.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>ao.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.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:g}]})}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 kn{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 Es(e)}async named(e,t){if(e.length===0)return[...e];const i=`${t.south},${t.west},${t.north},${t.east}`,n=`[out:json][timeout:120];way["railway"~"^(${kn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${kn.ROUTES})$"];out body;`;return kn.apply(e,await this.client.query(n),t)}static apply(e,t,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=kn.ways(t,n);return s.length===0?[...e]:e.map(r=>{const a=r.points.map(v=>at(v.lat,v.lng,n.lat,n.lng)),o=new Map,c=new Map,h=new Map;let d=0;const u=s.filter(v=>v.service===!!r.service);for(const v of kn.samples(a)){d++;const y=kn.waysAt(u,v);if(y.length===0)continue;const[w]=y;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 b of new Set(y.flatMap(M=>M.services)))h.set(b,(h.get(b)??0)+1)}const p=v=>[...v.entries()].sort((y,w)=>w[1]-y[1])[0]?.[0],f=r.name??p(o),g=r.voltageV??(r.electrification==="none"?void 0:p(c)),m=[...h.entries()].filter(([,v])=>v*4>=d).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...f?{name:f}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}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 n=kn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=t.get(s.ref)??new Set;r.add(n),t.set(s.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=kn.servicesByWay(e),n=[];for(const s of e.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=kn.voltageOf(r);n.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(s.id??-1)??[]],path:s.geometry.map(o=>at(o.lat,o.lon,t.lat,t.lng))})}return n}static samples(e){const t=[];for(let i=0;i<e.length-1;i++){const n=Math.hypot(e[i+1].x-e[i].x,e[i+1].z-e[i].z);if(n<1e-6)continue;const s=(e[i+1].x-e[i].x)/n,r=(e[i+1].z-e[i].z)/n;for(let a=kn.SAMPLE_M/2;a<n;a+=kn.SAMPLE_M)t.push({x:e[i].x+s*a,z:e[i].z+r*a,dx:s,dz:r})}return t}static waysAt(e,t){const i=Math.cos(kn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of e){let r;for(let a=0;a<s.path.length-1;a++){const o=s.path[a],c=s.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<=kn.NEAR_M&&(r===void 0||f<r)&&(r=f)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Sc{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 Es(e)}async getRailways(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Sc.KINDS.join("|")})$"](${t})->.w;.w out tags geom;rel(bw.w)["route"~"^(${kn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(e){const t=[],i=kn.servicesByWay(e);for(const n of e.elements??[]){const s=n.geometry,r=n.tags;if(n.type==="relation"||!r||!s||s.length<2)continue;const a=[...i.get(n.id??-1)??[]].sort(),o=kn.voltageOf(r),c=Sc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),d=Number.parseInt(r.tracks??"",10),u=Sc.electrificationOf(r.electrified),p=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;t.push({id:`osm-rail-${n.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:Sc.levelOf(r),points:s.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 JT{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(!ao.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 on{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=on.key(e);let i=on.asked.get(t)??on.containing(e);if(i===void 0){const n=this.recalled(t,e);i={bounds:e,answer:n},on.asked.set(t,i),n.catch(()=>on.asked.delete(t))}return structuredClone(await i.answer)}static forget(){on.asked.clear(),on.failedAt=-1/0}static key(e){return`v${on.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}static containing(e){for(const t of on.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 on.openCache(),n=on.request(e);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:o,lines:c}=await a.json();if(Array.isArray(c)){if(this.now()-o<on.MAX_AGE_MS)return c;s=c}}}catch{}if(this.now()-on.failedAt<on.RETRY_AFTER_MS){if(s)return s;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(on.failedAt=this.now(),s)return s;throw a}return i&&on.store(i,n,{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 n=await e.keys();for(const s of n.slice(0,Math.max(0,n.length-on.MAX_STORED)))await e.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(on.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__railways__/${encodeURIComponent(e)}`)}}const Em="https://ufoathome.org/railways/index.json";class Ec{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??Ec.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:n})=>n.north>=e.north&&n.south<=e.south&&n.east>=e.east&&n.west<=e.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.lines)?(this.attributionRead=s.attribution,s.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(`
|
|
4159
|
-
`);let t=Ec.shared.get(e);return t||(t=this.fetchFirstAvailable(),Ec.shared.set(e,t),t.then(i=>{i.length===0&&Ec.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.0")}`,t=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(t&&t!==Em?[t,Em]:[Em]).map(i=>i+e)}}function A2(){return{elevation:T2(),imagery:_2(),roads:I2(),water:D2(),railways:R2()}}function T2(){return new YT(new Tt,new x2)}function _2(){return new E2}function I2(){return new Mc({fallback:new jT(new ro,new to)})}function D2(){return new xc({fallback:new ys(new ZT(new Dd,new Go))})}function R2(){return new Ec({fallback:new on(new JT(new ao,new Sc))})}const QT=new Set,Hc="show-observer-map",Gc="hide-milestones",ll="minified";class Ut extends HTMLElement{static get observedAttributes(){return["src",Hc,Gc,ll]}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 jt;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=jf.create();issues=[];issueCheck=0;sightingAudio=new OT;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>Ut.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=p2;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,n=!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 s of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(s)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");Ut.setIcon(this.moreButton,e?qe.UNFOLDED:qe.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),n=this.said.read(i?.shape.title);if(!n){this.tooltip.hidden=!0;return}this.tooltip.textContent=n,this.tooltip.hidden=!1;const s=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-s.left+12}px`,this.tooltip.style.top=`${e.clientY-s.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)<Ut.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>=jt.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=jt.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Ut.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 n=jt.pointAt(t,(e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:n,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${RT}</style>${DT}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new rh(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 Ho(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"),n=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 s=!1;t.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),t.setPointerCapture(a.pointerId),t.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),t.addEventListener("pointermove",a=>{t.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{t.classList.contains("scrubbing")&&(t.classList.remove("scrubbing"),t.hasPointerCapture(a.pointerId)&&t.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&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.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===Hc&&this.applyObserverMapDefault(),e===Gc&&this.setMilestonesShown(!this.hasAttribute(Gc)),e===ll){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&t===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(ll)}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(k2)))};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 wr.recording(e)}get sightingData(){return cf(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=eb(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.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 n=[];try{const{default:s}=await oe(async()=>{const{default:r}=await import("./sightingSchema-DqeNTmuQ.js");return{default:r}},[],import.meta.url);n=new or(s).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...n,...t.loadIssues],ah.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(e_,{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 n=document.createElement("li");return n.textContent=ah.text(i,this.messages.issueTemplates),n}))}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.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("playrequest"))}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(n=>this.highlightedSourceIds.has(n))||(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 n of t)this.controlsRight.insertBefore(n,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 n=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),n=this.said.read(t.title)??t.id,s=document.createElement("div");s.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=n,o.title=n,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}: ${n}`),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()}),s.append(r,c),s});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(s=>this.viewOfReference(s).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"),Ut.setIcon(this.referencesButton,i?qe.PICTURES_ON:qe.PICTURES_OFF);const n=t?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=n,this.referencesButton.setAttribute("aria-label",n),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)),Ut.setIcon(this.tracesButton,this.tracesShownState?qe.TRACES_ON:qe.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?bl(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/e,0),1)*100}%`;const s=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${s} — ${r}`:s;return n.title=a,n.setAttribute("aria-label",a),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n})),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 n=document.createElement("li"),s=document.createElement("button");s.type="button",s.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return s.textContent=a?`${r} — ${a}`:r,s.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),n.appendChild(s),n})),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 n of this.momentsMenu.querySelectorAll("button")){const s=e!==void 0&&Number(n.dataset.t)===e.t;n.getAttribute("aria-current")==="true"!==s&&n.setAttribute("aria-current",String(s))}}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 n=[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 s=[];for(let r=0;r<n.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(n[r+1]-n[r],1));const o=document.createElement("i");o.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(o,c),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:c,hover:o})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,n=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(n,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=Ut.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 n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=Ut.fillOf(p,s),p.element.classList.toggle("hovered",s>=p.start&&(s<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],o=a.length>0?wm(a,s):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(s),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(s)}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 n=this.chromeCanvas.clientWidth,s=this.chromeCanvas.clientHeight;if(!t||typeof t.setTransform!="function"||n===0||s===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),o=Math.max(1,Math.round(s*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 rh(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 n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(n*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 n=Ut.MARK_SNAP_PX/i*t;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>n||(!s||Math.abs(a-e)<Math.abs(s.t-e))&&(s={t:a,name:r.title})}return s}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 n=(e.clientX-t.left)/t.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?wm(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 n=this.said.read(t.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(e=this.currentTime){const t=pr.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<Ut.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(Ut.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/Ut.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/Ut.EXPOSURE_STEP_PX),s=Math.min(Ut.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(t.fromMs+t.ms*a/(s-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),n=this.shapesAt(e+t);let s=0;for(const[r,a]of i){const o=n.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);s=Math.max(s,Math.hypot(c,h))}return s}shapeAt(e,t,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,e,t,i);if(s)return s}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}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:QT;this.canvasRenderer.setStarPoints(Yt.starPointsOf(this.sighting.instrument));const n=(ut(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const o of s)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 s[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?Bt.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=s.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(Hv(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 kT(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*Ut.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"?qe.PLAY:qe.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){Ut.icons.get(e)!==t&&(Ut.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},Ut.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(),Ut.setIcon(this.playPauseButton,e?qe.PAUSE:qe.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(Hc),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;Ut.setIcon(this.observerMapButton,e?qe.MAP_ON:qe.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[n,s]of i)n.title=s,n.setAttribute("aria-label",s)}updateObserverMap(){const e=this.observerPath!==void 0;if(this.observerPath=gl.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(n=>n.points):[],i=jt.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?jt.expand(e,Ut.OBSERVER_MAP_IMAGERY_AHEAD):e,n=jt.IMAGERY_PX*(t?1+2*Ut.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:_2();try{const a=r?await r.getImageryTexture(i,{width:n,height:n}):await s.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??s).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,n=this.observerMapView.changed?jt.expand(e,Ut.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!s||!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},n=[this.canvas.width-e.width,this.canvas.width],s=[0,e.width],r=Ut.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),o=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&o&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(o||!i(n[0],n[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(n[0],n[1],0)&&!i(s[0],s[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,n=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*n,bottom:(e.bottom-t.top)*n}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=ut(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},Ut.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?wm(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?bl(this.currentSighting.milestones):[]){const a=ut(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===s})}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?Ts.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Yt.aspectOf(i)):void 0,markers:n,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,bl(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,Ut.setIcon(this.milestonesButton,this.milestonesShown?qe.MILESTONES_ON:qe.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=ut(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Mr(i,e),{lat:s,lng:r}=Bs(n.eastM,-n.northM,t.lat,t.lng);return{lat:s,lng:r,headingDeg:n.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 n=ut(this.currentSighting,this.currentTime),s=Ts.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(t),y:s.angleDegToRadiusPx(i)}}gaitAt(e){return ni.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=Ut.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)),Ut.setIcon(this.miniMuteButton,this.mutedState?qe.MUTED:qe.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){Ut.setIcon(this.muteButton,qe.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Ut.setIcon(this.muteButton,this.mutedState?qe.MUTED:qe.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;Ut.setIcon(this.fullscreenButton,e?qe.EXIT_FULLSCREEN:qe.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 hs(Gs.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=wd(Gs.preferencesFor(this),yd);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await hE(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=th(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?tg(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 Ba(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?iy(ty(this.realStartMs+i)):Ba(i)}formatElapsedAt(e){const t=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?Ba(e):Ba(t>0&&e<=t?e/t*this.realDurationMs:e)}formatRemaining(e){const t=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return Ba(Math.max(0,t-e));const i=t>0&&e<=t?e/t*this.realDurationMs:e;return Ba(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?Ba(this.currentSighting.timeline.duration):this.canShowClockTime?iy(ty(this.realStartMs+this.realDurationMs)):Ba(this.realDurationMs)}}function ty(l){const e=new Date(l);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function iy(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 Ba(l){const e=Math.round(l/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Ag="rr0-ufo";function am(){customElements.get(Ag)||customElements.define(Ag,Ut)}const e_="recordingissues",k2="minifiedreset";class ed{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((s,r)=>s.t-r.t):[],n=`${t}|${i.map(s=>`${s.kind}:${s.t}:${s.label}`).join("|")}`;n!==this.drawn&&(this.drawn=n,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(s=>{const r=document.createElement("span");return r.className=`timeline-mark ${s.kind}`,r.style.left=`${Math.min(Math.max(s.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+ed.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-ed.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=ed.SNAP_PX/t*this.duration;let n;for(const s of this.marks)Math.abs(s.t-e)>i||(!n||Math.abs(s.t-e)<Math.abs(n.t-e)||s.t===n.t&&s.kind==="milestone")&&(n=s);return n}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 Ac{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const n=e.event.place?.[0],s=e.observerTrack;if(!n)return 0;const r=g=>{const m=s.getInterpolatedPoseAt(Math.max(0,g));if(!m||m.lat===void 0||m.lng===void 0)return;const v=at(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(t-Ac.HALF_SPAN_MS),o=r(t+Ac.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*Ac.HALF_SPAN_MS/1e3;if(h/d<Ac.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 t_=.08,ny=.15,sy=2,i_=2e3;class n_{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}}vl.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(n=>n.inside||n.distanceM<i_),i=new Set(t.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of t){const s=this.voices.get(n.id)??this.build(e,n.id);this.retarget(e,s,n)}}build(e,t){const i=e.createGain();i.gain.value=0;const n=e.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(e));const s=e.createOscillator();s.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),o=e.createBiquadFilter();o.type="lowpass",o.frequency.value=900,s.connect(o),r.connect(o),o.connect(a).connect(n);const c=()=>{const M=e.createBufferSource();return M.buffer=this.noise(e),M.loop=!0,M.loopStart=Math.random()*sy*.5,M},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(n);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const g=e.createGain();p.connect(f).connect(g).connect(n);const m=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const y=e.createGain();m.connect(v).connect(y).connect(n);const w=[s,r,h,p,m];for(const M of w)M.start();const b={nodes:[i,n,a,o,d,u,f,g,v,y,...w],sources:w,firing:s,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:g,windGain:y,cabin:n,output:i};return this.voices.set(t,b),b}retarget(e,t,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:o}){const c=e.currentTime,h=(y,w)=>y.setTargetAtTime(w,c,t_),d=n.rpm/60,u=d*i.cylinders/2,p=Math.min(1,n.rpm/i.shiftUpRpm),f=Math.min(1.5,n.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*n.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const g=!r||a;h(t.windGain.gain,f**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+o/60);h(t.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(o,1));h(t.output.gain,v*s)}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,ny/3),setTimeout(()=>{for(const n of t.sources)try{n.stop()}catch{}for(const n of t.nodes)n.disconnect()},ny*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*sy,e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Rd{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 Rd.BY_KIND[e??"generic"]??Rd.BY_KIND.generic}}class cl{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,n){const s=cl.SAMPLE_MS,r=[];for(let c=i;c<=n+s/2;c+=s){const h=t(c-s/2),d=t(c+s/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(s/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*s/1e3);if(h<cl.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))),g=.15+.5*Math.min(1,(h/35)**2),m=d>.15?Math.min(1,g+d/2.5):d<-.3?.05:g;a.push({speedMps:h,rpm:f,load:m,gear:o})}return new cl(a,i)}at(e){const t=(e-this.startMs)/cl.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),0),this.samples.length-1),n=this.samples[i],s=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(t-i,0),1);return{speedMps:n.speedMps+(s.speedMps-n.speedMps)*r,rpm:n.rpm+(s.rpm-n.rpm)*r,load:n.load+(s.load-n.load)*r,gear:r<.5?n.gear:s.gear}}}class hf{drives=new Map;at(e,t){const i=[],n=e.event.place?.[0],s=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??n?.lat,u=h?.lng??n?.lng;if(d===void 0||u===void 0||!n)return;const p=at(d,u,n.lat,n.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=Rd.of(a.kind),h=this.drive(`observer:${a.kind}`,hf.trackKey(e),()=>cl.of(c,s,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=s(t);for(const c of e.decor){if(!c.engine||!o)continue;const h=Rd.of(c.engine.kind),d=g=>{const m=Mr(c,g);return{eastM:m.eastM,northM:m.northM}},u=this.drive(`decor:${c.id}`,hf.decorKey(c,r),()=>cl.of(h,d,0,r));if(!u)continue;const p=Mr(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 n=this.drives.get(e);if(n&&n.key===t)return n.drive;const s=i();return this.drives.set(e,{key:t,drive:s}),s}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 s_="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==",r_=`
|
|
4157
|
+
`);let t=Mc.shared.get(e);return t||(t=this.fetchFirstAvailable(),Mc.shared.set(e,t),t.then(i=>{i.length===0&&Mc.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.1")}`,t=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(t&&t!==xm?[t,xm]:[xm]).map(i=>i+e)}}class ro{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 kt(e)}static covers(e){return kt.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRoads(e){return(await this.platform.roads(e)).flatMap((i,n)=>ro.wayOf(i,n))}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 n=String(e.properties.nature??""),s=ro.BY_NATURE[n]??ro.DEFAULT,r=Number(e.properties.largeur_de_chaussee),a=Number(e.properties.nombre_de_voies),o=Number(e.properties.vitesse_moyenne_vl),c=ro.DIRECTIONS[String(e.properties.sens_de_circulation??"")],h=ro.KINDS[n],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:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.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 jT{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(ro.covers(e))try{const t=await this.regional.getRoads(e);if(t.length>0)return t}catch{}return this.worldwide.getRoads(e)}}class Dd{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(e={}){this.platform=new kt(e)}static covers(e){return kt.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getWater(e){return(await this.platform.waterSurfaces(e)).flatMap((i,n)=>Dd.surfacesOf(i,n))}static surfacesOf(e,t){const{type:i,coordinates:n}=e.geometry,s=i==="Polygon"?[n]:i==="MultiPolygon"?n:[],r=String(e.properties.cleabs??`ign-water-${t}`);return s.flatMap((a,o)=>{const c=a.map(h=>Dd.open(h.map(d=>({lat:d[1],lng:d[0]})))).filter(h=>h.length>=3);return c.length>0?[{id:s.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 Go{attribution="Water © OpenStreetMap contributors";client;constructor(e={}){this.client=new Es(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 Go.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 n=[],s=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=>(s.add(h.ref),i.get(h.ref))),o=Go.rings(a("inner"));for(const[c,h]of Go.rings(a("outer")).entries()){const d=o.filter(u=>Go.contains(h,u[0]));n.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||s.has(r.id))&&!(r.tags.natural!=="water"&&r.tags.waterway!=="riverbank"))for(const a of Go.rings([i.get(r.id)??[]]))n.push({id:`osm-w${r.id}`,rings:[a]});return n}static rings(e){const t=(s,r)=>s.lat===r.lat&&s.lng===r.lng,i=e.filter(s=>s.length>=2).map(s=>[...s]),n=[];for(;i.length>0;){let s=i.pop(),r=!0;for(;!t(s[0],s[s.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const o=i[a],c=s[s.length-1];if(t(c,o[0]))s=[...s,...o.slice(1)];else if(t(c,o[o.length-1]))s=[...s,...[...o].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}s.length>=4&&t(s[0],s[s.length-1])&&n.push(s.slice(0,-1))}return n}static contains(e,t){let i=!1;for(let n=0,s=e.length-1;n<e.length;s=n++){const r=e[n],a=e[s];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 ZT{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(e){if(Dd.covers(e))try{const t=await this.regional.getWater(e);if(t.length>0)return t}catch{}return this.worldwide.getWater(e)}}const Sm="https://ufoathome.org/water/index.json";class xc{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??xc.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:n})=>n.north>=e.north&&n.south<=e.south&&n.east>=e.east&&n.west<=e.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.surfaces)?(this.attributionRead=s.attribution,s.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(`
|
|
4158
|
+
`);let t=xc.shared.get(e);return t||(t=this.fetchFirstAvailable(),xc.shared.set(e,t),t.then(i=>{i.length===0&&xc.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.1")}`,t=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(t&&t!==Sm?[t,Sm]:[Sm]).map(i=>i+e)}}class ys{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=ys.key(e);let i=ys.asked.get(t);return i===void 0&&(i=this.recalled(t,e),ys.asked.set(t,i),i.catch(()=>ys.asked.delete(t))),structuredClone(await i)}static forget(){ys.asked.clear()}static key(e){return`v${ys.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}async recalled(e,t){const i=await ys.openCache(),n=ys.request(e);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:o}=await r.json();if(Date.now()-a<ys.MAX_AGE_MS&&Array.isArray(o))return o;await i.delete(n)}}catch{}const s=await this.water.getWater(t);return i&&ys.store(i,n,s),s}static async store(e,t,i){try{const n={savedAt:Date.now(),surfaces:i};await e.put(t,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await e.keys();for(const r of s.slice(0,Math.max(0,s.length-ys.MAX_STORED)))await e.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(ys.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__water__/${encodeURIComponent(e)}`)}}class ao{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 kt(e)}static covers(e){return kt.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRailways(e){return(await this.platform.railways(e)).flatMap((i,n)=>ao.linesOf(i,n))}static linesOf(e,t){const{type:i,coordinates:n}=e.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=ao.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=ao.GAUGE_MM[String(e.properties.largeur??"")]??1435,u=ao.electrificationOf(r.kind,d,e.properties.electrifie);return s.flatMap((p,f)=>{const g=p.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>ao.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.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:g}]})}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 kn{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 Es(e)}async named(e,t){if(e.length===0)return[...e];const i=`${t.south},${t.west},${t.north},${t.east}`,n=`[out:json][timeout:120];way["railway"~"^(${kn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${kn.ROUTES})$"];out body;`;return kn.apply(e,await this.client.query(n),t)}static apply(e,t,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=kn.ways(t,n);return s.length===0?[...e]:e.map(r=>{const a=r.points.map(v=>at(v.lat,v.lng,n.lat,n.lng)),o=new Map,c=new Map,h=new Map;let d=0;const u=s.filter(v=>v.service===!!r.service);for(const v of kn.samples(a)){d++;const y=kn.waysAt(u,v);if(y.length===0)continue;const[w]=y;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 b of new Set(y.flatMap(M=>M.services)))h.set(b,(h.get(b)??0)+1)}const p=v=>[...v.entries()].sort((y,w)=>w[1]-y[1])[0]?.[0],f=r.name??p(o),g=r.voltageV??(r.electrification==="none"?void 0:p(c)),m=[...h.entries()].filter(([,v])=>v*4>=d).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...f?{name:f}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}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 n=kn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=t.get(s.ref)??new Set;r.add(n),t.set(s.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=kn.servicesByWay(e),n=[];for(const s of e.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=kn.voltageOf(r);n.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(s.id??-1)??[]],path:s.geometry.map(o=>at(o.lat,o.lon,t.lat,t.lng))})}return n}static samples(e){const t=[];for(let i=0;i<e.length-1;i++){const n=Math.hypot(e[i+1].x-e[i].x,e[i+1].z-e[i].z);if(n<1e-6)continue;const s=(e[i+1].x-e[i].x)/n,r=(e[i+1].z-e[i].z)/n;for(let a=kn.SAMPLE_M/2;a<n;a+=kn.SAMPLE_M)t.push({x:e[i].x+s*a,z:e[i].z+r*a,dx:s,dz:r})}return t}static waysAt(e,t){const i=Math.cos(kn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of e){let r;for(let a=0;a<s.path.length-1;a++){const o=s.path[a],c=s.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<=kn.NEAR_M&&(r===void 0||f<r)&&(r=f)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Sc{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 Es(e)}async getRailways(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Sc.KINDS.join("|")})$"](${t})->.w;.w out tags geom;rel(bw.w)["route"~"^(${kn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(e){const t=[],i=kn.servicesByWay(e);for(const n of e.elements??[]){const s=n.geometry,r=n.tags;if(n.type==="relation"||!r||!s||s.length<2)continue;const a=[...i.get(n.id??-1)??[]].sort(),o=kn.voltageOf(r),c=Sc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),d=Number.parseInt(r.tracks??"",10),u=Sc.electrificationOf(r.electrified),p=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;t.push({id:`osm-rail-${n.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:Sc.levelOf(r),points:s.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 JT{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(!ao.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 on{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=on.key(e);let i=on.asked.get(t)??on.containing(e);if(i===void 0){const n=this.recalled(t,e);i={bounds:e,answer:n},on.asked.set(t,i),n.catch(()=>on.asked.delete(t))}return structuredClone(await i.answer)}static forget(){on.asked.clear(),on.failedAt=-1/0}static key(e){return`v${on.FORMAT}/${[e.north,e.south,e.east,e.west].map(t=>t.toFixed(5)).join("/")}`}static containing(e){for(const t of on.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 on.openCache(),n=on.request(e);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:o,lines:c}=await a.json();if(Array.isArray(c)){if(this.now()-o<on.MAX_AGE_MS)return c;s=c}}}catch{}if(this.now()-on.failedAt<on.RETRY_AFTER_MS){if(s)return s;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(on.failedAt=this.now(),s)return s;throw a}return i&&on.store(i,n,{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 n=await e.keys();for(const s of n.slice(0,Math.max(0,n.length-on.MAX_STORED)))await e.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(on.CACHE_NAME)}catch{return}}static request(e){const t=typeof location>"u"?"http://localhost":location.origin;return new Request(`${t}/__railways__/${encodeURIComponent(e)}`)}}const Em="https://ufoathome.org/railways/index.json";class Ec{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??Ec.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:n})=>n.north>=e.north&&n.south<=e.south&&n.east>=e.east&&n.west<=e.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.lines)?(this.attributionRead=s.attribution,s.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(`
|
|
4159
|
+
`);let t=Ec.shared.get(e);return t||(t=this.fetchFirstAvailable(),Ec.shared.set(e,t),t.then(i=>{i.length===0&&Ec.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(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.136.1")}`,t=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(t&&t!==Em?[t,Em]:[Em]).map(i=>i+e)}}function A2(){return{elevation:T2(),imagery:_2(),roads:I2(),water:D2(),railways:R2()}}function T2(){return new YT(new Tt,new x2)}function _2(){return new E2}function I2(){return new Mc({fallback:new jT(new ro,new to)})}function D2(){return new xc({fallback:new ys(new ZT(new Dd,new Go))})}function R2(){return new Ec({fallback:new on(new JT(new ao,new Sc))})}const QT=new Set,Hc="show-observer-map",Gc="hide-milestones",ll="minified";class Ut extends HTMLElement{static get observedAttributes(){return["src",Hc,Gc,ll]}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 jt;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=jf.create();issues=[];issueCheck=0;sightingAudio=new OT;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>Ut.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=p2;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,n=!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 s of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(s)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");Ut.setIcon(this.moreButton,e?qe.UNFOLDED:qe.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),n=this.said.read(i?.shape.title);if(!n){this.tooltip.hidden=!0;return}this.tooltip.textContent=n,this.tooltip.hidden=!1;const s=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-s.left+12}px`,this.tooltip.style.top=`${e.clientY-s.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)<Ut.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>=jt.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=jt.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Ut.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 n=jt.pointAt(t,(e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:n,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${RT}</style>${DT}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new rh(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 Ho(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"),n=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 s=!1;t.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),t.setPointerCapture(a.pointerId),t.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),t.addEventListener("pointermove",a=>{t.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{t.classList.contains("scrubbing")&&(t.classList.remove("scrubbing"),t.hasPointerCapture(a.pointerId)&&t.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&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.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===Hc&&this.applyObserverMapDefault(),e===Gc&&this.setMilestonesShown(!this.hasAttribute(Gc)),e===ll){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&t===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(ll)}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(k2)))};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 wr.recording(e)}get sightingData(){return cf(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=eb(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.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 n=[];try{const{default:s}=await oe(async()=>{const{default:r}=await import("./sightingSchema-DqeNTmuQ.js");return{default:r}},[],import.meta.url);n=new or(s).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...n,...t.loadIssues],ah.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(e_,{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 n=document.createElement("li");return n.textContent=ah.text(i,this.messages.issueTemplates),n}))}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.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("playrequest"))}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(n=>this.highlightedSourceIds.has(n))||(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 n of t)this.controlsRight.insertBefore(n,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 n=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),n=this.said.read(t.title)??t.id,s=document.createElement("div");s.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=n,o.title=n,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}: ${n}`),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()}),s.append(r,c),s});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(s=>this.viewOfReference(s).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"),Ut.setIcon(this.referencesButton,i?qe.PICTURES_ON:qe.PICTURES_OFF);const n=t?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=n,this.referencesButton.setAttribute("aria-label",n),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)),Ut.setIcon(this.tracesButton,this.tracesShownState?qe.TRACES_ON:qe.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?bl(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/e,0),1)*100}%`;const s=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${s} — ${r}`:s;return n.title=a,n.setAttribute("aria-label",a),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n})),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 n=document.createElement("li"),s=document.createElement("button");s.type="button",s.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return s.textContent=a?`${r} — ${a}`:r,s.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),n.appendChild(s),n})),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 n of this.momentsMenu.querySelectorAll("button")){const s=e!==void 0&&Number(n.dataset.t)===e.t;n.getAttribute("aria-current")==="true"!==s&&n.setAttribute("aria-current",String(s))}}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 n=[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 s=[];for(let r=0;r<n.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(n[r+1]-n[r],1));const o=document.createElement("i");o.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(o,c),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:c,hover:o})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,n=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(n,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=Ut.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 n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=Ut.fillOf(p,s),p.element.classList.toggle("hovered",s>=p.start&&(s<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],o=a.length>0?wm(a,s):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(s),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(s)}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 n=this.chromeCanvas.clientWidth,s=this.chromeCanvas.clientHeight;if(!t||typeof t.setTransform!="function"||n===0||s===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),o=Math.max(1,Math.round(s*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 rh(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 n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(n*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 n=Ut.MARK_SNAP_PX/i*t;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>n||(!s||Math.abs(a-e)<Math.abs(s.t-e))&&(s={t:a,name:r.title})}return s}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 n=(e.clientX-t.left)/t.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?wm(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 n=this.said.read(t.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(e=this.currentTime){const t=pr.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<Ut.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(Ut.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/Ut.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/Ut.EXPOSURE_STEP_PX),s=Math.min(Ut.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(t.fromMs+t.ms*a/(s-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),n=this.shapesAt(e+t);let s=0;for(const[r,a]of i){const o=n.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);s=Math.max(s,Math.hypot(c,h))}return s}shapeAt(e,t,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,e,t,i);if(s)return s}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}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:QT;this.canvasRenderer.setStarPoints(Yt.starPointsOf(this.sighting.instrument));const n=(ut(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const o of s)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 s[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?Bt.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=s.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(Hv(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 kT(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*Ut.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"?qe.PLAY:qe.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){Ut.icons.get(e)!==t&&(Ut.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},Ut.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(),Ut.setIcon(this.playPauseButton,e?qe.PAUSE:qe.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(Hc),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;Ut.setIcon(this.observerMapButton,e?qe.MAP_ON:qe.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[n,s]of i)n.title=s,n.setAttribute("aria-label",s)}updateObserverMap(){const e=this.observerPath!==void 0;if(this.observerPath=gl.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(n=>n.points):[],i=jt.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?jt.expand(e,Ut.OBSERVER_MAP_IMAGERY_AHEAD):e,n=jt.IMAGERY_PX*(t?1+2*Ut.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:_2();try{const a=r?await r.getImageryTexture(i,{width:n,height:n}):await s.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??s).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,n=this.observerMapView.changed?jt.expand(e,Ut.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!s||!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},n=[this.canvas.width-e.width,this.canvas.width],s=[0,e.width],r=Ut.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),o=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&o&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(o||!i(n[0],n[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(n[0],n[1],0)&&!i(s[0],s[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,n=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*n,bottom:(e.bottom-t.top)*n}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=ut(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},Ut.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?wm(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?bl(this.currentSighting.milestones):[]){const a=ut(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===s})}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?Ts.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Yt.aspectOf(i)):void 0,markers:n,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,bl(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,Ut.setIcon(this.milestonesButton,this.milestonesShown?qe.MILESTONES_ON:qe.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=ut(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Mr(i,e),{lat:s,lng:r}=Bs(n.eastM,-n.northM,t.lat,t.lng);return{lat:s,lng:r,headingDeg:n.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 n=ut(this.currentSighting,this.currentTime),s=Ts.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(t),y:s.angleDegToRadiusPx(i)}}gaitAt(e){return ni.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=Ut.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)),Ut.setIcon(this.miniMuteButton,this.mutedState?qe.MUTED:qe.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){Ut.setIcon(this.muteButton,qe.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Ut.setIcon(this.muteButton,this.mutedState?qe.MUTED:qe.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;Ut.setIcon(this.fullscreenButton,e?qe.EXIT_FULLSCREEN:qe.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 hs(Gs.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=wd(Gs.preferencesFor(this),yd);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await hE(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=th(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?tg(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 Ba(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?iy(ty(this.realStartMs+i)):Ba(i)}formatElapsedAt(e){const t=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?Ba(e):Ba(t>0&&e<=t?e/t*this.realDurationMs:e)}formatRemaining(e){const t=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return Ba(Math.max(0,t-e));const i=t>0&&e<=t?e/t*this.realDurationMs:e;return Ba(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?Ba(this.currentSighting.timeline.duration):this.canShowClockTime?iy(ty(this.realStartMs+this.realDurationMs)):Ba(this.realDurationMs)}}function ty(l){const e=new Date(l);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function iy(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 Ba(l){const e=Math.round(l/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Ag="rr0-ufo";function am(){customElements.get(Ag)||customElements.define(Ag,Ut)}const e_="recordingissues",k2="minifiedreset";class ed{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((s,r)=>s.t-r.t):[],n=`${t}|${i.map(s=>`${s.kind}:${s.t}:${s.label}`).join("|")}`;n!==this.drawn&&(this.drawn=n,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(s=>{const r=document.createElement("span");return r.className=`timeline-mark ${s.kind}`,r.style.left=`${Math.min(Math.max(s.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+ed.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-ed.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=ed.SNAP_PX/t*this.duration;let n;for(const s of this.marks)Math.abs(s.t-e)>i||(!n||Math.abs(s.t-e)<Math.abs(n.t-e)||s.t===n.t&&s.kind==="milestone")&&(n=s);return n}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 Ac{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const n=e.event.place?.[0],s=e.observerTrack;if(!n)return 0;const r=g=>{const m=s.getInterpolatedPoseAt(Math.max(0,g));if(!m||m.lat===void 0||m.lng===void 0)return;const v=at(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(t-Ac.HALF_SPAN_MS),o=r(t+Ac.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*Ac.HALF_SPAN_MS/1e3;if(h/d<Ac.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 t_=.08,ny=.15,sy=2,i_=2e3;class n_{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}}vl.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(n=>n.inside||n.distanceM<i_),i=new Set(t.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of t){const s=this.voices.get(n.id)??this.build(e,n.id);this.retarget(e,s,n)}}build(e,t){const i=e.createGain();i.gain.value=0;const n=e.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(e));const s=e.createOscillator();s.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),o=e.createBiquadFilter();o.type="lowpass",o.frequency.value=900,s.connect(o),r.connect(o),o.connect(a).connect(n);const c=()=>{const M=e.createBufferSource();return M.buffer=this.noise(e),M.loop=!0,M.loopStart=Math.random()*sy*.5,M},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(n);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const g=e.createGain();p.connect(f).connect(g).connect(n);const m=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const y=e.createGain();m.connect(v).connect(y).connect(n);const w=[s,r,h,p,m];for(const M of w)M.start();const b={nodes:[i,n,a,o,d,u,f,g,v,y,...w],sources:w,firing:s,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:g,windGain:y,cabin:n,output:i};return this.voices.set(t,b),b}retarget(e,t,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:o}){const c=e.currentTime,h=(y,w)=>y.setTargetAtTime(w,c,t_),d=n.rpm/60,u=d*i.cylinders/2,p=Math.min(1,n.rpm/i.shiftUpRpm),f=Math.min(1.5,n.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*n.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const g=!r||a;h(t.windGain.gain,f**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+o/60);h(t.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(o,1));h(t.output.gain,v*s)}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,ny/3),setTimeout(()=>{for(const n of t.sources)try{n.stop()}catch{}for(const n of t.nodes)n.disconnect()},ny*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*sy,e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Rd{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 Rd.BY_KIND[e??"generic"]??Rd.BY_KIND.generic}}class cl{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,n){const s=cl.SAMPLE_MS,r=[];for(let c=i;c<=n+s/2;c+=s){const h=t(c-s/2),d=t(c+s/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(s/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*s/1e3);if(h<cl.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))),g=.15+.5*Math.min(1,(h/35)**2),m=d>.15?Math.min(1,g+d/2.5):d<-.3?.05:g;a.push({speedMps:h,rpm:f,load:m,gear:o})}return new cl(a,i)}at(e){const t=(e-this.startMs)/cl.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),0),this.samples.length-1),n=this.samples[i],s=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(t-i,0),1);return{speedMps:n.speedMps+(s.speedMps-n.speedMps)*r,rpm:n.rpm+(s.rpm-n.rpm)*r,load:n.load+(s.load-n.load)*r,gear:r<.5?n.gear:s.gear}}}class hf{drives=new Map;at(e,t){const i=[],n=e.event.place?.[0],s=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??n?.lat,u=h?.lng??n?.lng;if(d===void 0||u===void 0||!n)return;const p=at(d,u,n.lat,n.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=Rd.of(a.kind),h=this.drive(`observer:${a.kind}`,hf.trackKey(e),()=>cl.of(c,s,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=s(t);for(const c of e.decor){if(!c.engine||!o)continue;const h=Rd.of(c.engine.kind),d=g=>{const m=Mr(c,g);return{eastM:m.eastM,northM:m.northM}},u=this.drive(`decor:${c.id}`,hf.decorKey(c,r),()=>cl.of(h,d,0,r));if(!u)continue;const p=Mr(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 n=this.drives.get(e);if(n&&n.key===t)return n.drive;const s=i();return this.drives.set(e,{key:t,drive:s}),s}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 s_="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==",r_=`
|
|
4160
4160
|
<div class="stage" id="stage">
|
|
4161
4161
|
<div class="frame" id="frame">
|
|
4162
4162
|
<canvas id="scene-canvas"></canvas>
|
|
@@ -10454,7 +10454,7 @@ uniform float uWindowLuminance;
|
|
|
10454
10454
|
varying float vLitRank;
|
|
10455
10455
|
${o.fragmentShader.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
|
|
10456
10456
|
totalEmissiveRadiance *= step(vLitRank, uLitShare) * uWindowLuminance * ${ye.WINDOW_VARIETY_GLSL};`)}`},r.customProgramCacheKey=()=>"facade-lit-windows";const a=new Se(s,r);return a.castShadow=!0,a.receiveShadow=!0,t.add(a),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=n=>`vec3(${n.map(s=>s.toFixed(4)).join(", ")})`,t=jc.ofTemperature(ye.ROOM_LIGHT_K),i=jc.ofTemperature(ye.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){ye.windowLuminance.value=ye.WINDOW_LUMINANCE_CD_M2*e}static setLitWindowShare(e){ye.litWindowShare.value=Math.max(0,Math.min(1,e))}static build(e,t){const i=ye.hasFacade(e)?ye.buildFacade(e):e.kind==="building"?Ww(e.floors??sh,e.windows,e.observerSide,e.occupiedFloor,e.observerFacing):e.kind==="tree"?Xw():e.kind==="shrub"?$w():e.kind==="bridge"?nO(e):e.kind==="wire"?sO(e):e.kind==="wall"?ln.build(e):e.kind==="crop"?Kw():e.kind==="terrace"?uO():e.kind==="mound"?qw():e.kind==="streetlight"?jw(t,e.lamp?.mount,e.lamp):e.kind==="trafficlight"?yt.trafficLight(rt.isPedestrian(e.lights)):e.kind==="crossing"?yt.crossing(ye.sizeOf(e).widthM,ye.sizeOf(e).lengthM):e.kind==="roadsign"?yt.roadSign(e.sign):e.kind==="vehicle"?Zw(t,e.windows,e.observerSide,e.observerFacing):e.kind==="aircraft"?nM():e.kind==="entity"?tM():kv();e.color&&this.paint(i,e.color);const n=this.scaleFor(e),s=new Pt;return e.kind==="building"&&e.roof&&this.addRoof(s,e),i.name=ye.BODY_NAME,i.scale.copy(n),s.add(i),e.headingDeg!==void 0&&(s.rotation.y=-e.headingDeg*g0),this.addLights(s,e.lights),ye.fitLights(s,e,e.sizeM??{}),s}static scaleFor(e){const t=e.sizeM;if(!t||ye.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:w0(t.widthM,i.widthM),t.heightM===void 0?1:w0(e.kind==="building"?this.wallHeightOf(e,t.heightM):t.heightM,i.heightM),t.lengthM===void 0?1:w0(t.lengthM,i.lengthM))}static naturalSize(e,t){const i=e==="building"?Math.max(1,(t??sh)+1):0;if(e==="bridge")return vi.NATURAL_SIZE;if(e==="wire")return ul.NATURAL_SIZE;if(e==="terrace"||e==="wall")return{widthM:1,lengthM:1,heightM:1};if(e==="crossing")return{widthM:6,lengthM:2.5,heightM:yt.CROSSING_LIFT_M};const n=`${e}:${i}`,s=Jw.get(n);if(s)return s;const r=e==="building"?Ww(i-1,void 0,void 0,void 0):e==="tree"?Xw():e==="shrub"?$w():e==="crop"?Kw():e==="mound"?qw():e==="streetlight"?jw(!1):e==="trafficlight"?yt.trafficLight(!1):e==="roadsign"?yt.roadSign(void 0):e==="vehicle"?Zw(!1,void 0,void 0):e==="aircraft"?nM():e==="entity"?tM():kv(),a=new _n().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),Jw.set(n,o),o}static usesModel(e){return Id(e)!==void 0&&!(e.observerSide!==void 0&&Mo(e.kind))}static applyModel(e,t,i,n={}){const s=this.bodyOf(e),r=new Pt;r.name=ye.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*g0,i.updateMatrixWorld(!0);const a=new _n().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=Qw(c,o)??Qw(n.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 Se&&(u.castShadow=!0,u.receiveShadow=!0)}),r.add(i),t.kind==="tree"&&r.add(ye.trunkShadow(o.heightM*h)),s.parent?(s.parent.add(r),s.removeFromParent()):e.add(r),this.dispose(s),ye.fitLights(e,t,{widthM:o.widthM*h,heightM:o.heightM*h,lengthM:o.lengthM*h})}static fitLights(e,t,i){const n=nh.byId(vr.rigOf(t)||void 0)?.referenceSizeM;if(!n||!t.lights)return;const s=(h,d)=>h===void 0||d===0?1:h/d,r=s(i.widthM,n.widthM),a=s(i.heightM,n.heightM),o=s(i.lengthM,n.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){ye.trunkProxy??={geometry:new Zn(1,1.15,1,8),material:new ps({colorWrite:!1,depthWrite:!1})};const t=new Se(ye.trunkProxy.geometry,ye.trunkProxy.material),i=Math.min(.3,Math.max(.12,e*.035)),n=e*.45;return t.scale.set(i,n,i),t.position.y=n/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 n=KL(i.color),s=rt.figureOf(i),r=s?yt.pedestrianFigure(s,1.8*(i.radiusM??v0)):new Zi(i.radiusM??v0,8,6),a=Kt(e,r,n,i.offsetM.y,!0);a.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),a.userData={emissive:!0,lightId:i.id,lightColor:n},a.visible=!1;const o=a.material;CS.apply(o),o.transparent=!0,o.depthWrite=!1,o.fog=!1}}static setLights(e,t,i,n,s=0,r=1,a=GL,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(ye.eyeScratch.copy(c)));for(const u of e.children){if(!(u instanceof Se))continue;const p=u.userData.lightId;if(!p)continue;const f=h.get(p);if(!f)continue;const g=s>0?c2(f,i,i+s):bT(f,i)?1:0,m=d&&f.beamDeg!==void 0?ye.beamShare(f.beamDeg,u.position,d):1;u.visible=g>0&&m>0;const v=f.radiusM??v0,y=Math.max(1,n*a/v),w=v*y,b=r/(Math.PI*w*w),M=u.material,S=u.userData.lightColor;if(S){const E=g*m*VL*(f.intensity??1)*b,x=[S[0]*E*o[0],S[1]*E*o[1],S[2]*E*o[2]],T=Math.min(1,Gw/Math.max(x[0],x[1],x[2],1e-30));M.color.setRGB(x[0]*T,x[1]*T,x[2]*T)}u.scale.setScalar(y)}}static eyeScratch=new I;static beamShare(e,t,i){const n=i.x-t.x,s=i.y-t.y,r=i.z-t.z,a=Math.hypot(n,s,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,n=1,s){const[r,a,o]=t==="streetlight"?[WL*ye.lampShare(s),$L,ye.lampHue(s)]:[XL,YL,LS],c=i?r*n/(Math.PI*a*a):0,h=Math.min(1,Gw/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 Se)||!p.emissive||p.lightId||(u.material instanceof ir?u.material.emissive.setRGB(...d):u.material.color.setRGB(...d))})}static REFERENCE_LUMENS=1e4;static lampShare(e){return e?.lumens?e.lumens/ye.REFERENCE_LUMENS:1}static lampHue(e){return e?.colorTemperatureK?jc.ofTemperature(e.colorTemperatureK):jL}static dispose(e){e.traverse(t=>{if(!(t instanceof Se))return;if(t.userData.sharedModel){for(const n of t.userData.tintedMaterials??[])n.dispose();return}t.geometry.dispose();const i=t.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const x0="https://ufoathome.org/models/index.json";class pd{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??gO()}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(`
|
|
10457
|
-
`);let t=pd.shared.get(e);return t||(t=this.fetchFirstAvailable(),pd.shared.set(e,t),t.then(i=>{i.length===0&&pd.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:n,...s})=>({...s,url:new URL(n,e).href})):void 0}catch{return}}}function gO(){const l=`?v=${encodeURIComponent("0.136.
|
|
10457
|
+
`);let t=pd.shared.get(e);return t||(t=this.fetchFirstAvailable(),pd.shared.set(e,t),t.then(i=>{i.length===0&&pd.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:n,...s})=>({...s,url:new URL(n,e).href})):void 0}catch{return}}}function gO(){const l=`?v=${encodeURIComponent("0.136.1")}`,e=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(e&&e!==x0?[e,x0]:[x0]).map(t=>t+l)}const Tp=[{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 pd}];async function S0(l){const{GLTFLoader:e}=await oe(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-Clgrcwp4.js");return{GLTFLoader:i}},[],import.meta.url),t=new e;return new Promise((i,n)=>{t.load(l,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${l}: ${s instanceof Error?s.message:String(s)}`)))})}class Us{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(e,t){this.mesh=new Se(new ms(2,2),new Nt({uniforms:{uColor:{value:new ne(0,0,0)},uRadius:{value:1}},vertexShader:Us.VERTEX,fragmentShader:Us.FRAGMENT,transparent:!0,depthWrite:!1,blending:vn,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,n){const s=Math.max(e,n*Us.MIN_ANGLE_RAD),r=Us.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(Us.MAX_SHARE,t/r)}}static conserving(e){return Math.sqrt(e/(Us.MAX_SHARE*Us.FILL*Math.PI))}static VERTEX=`
|
|
10458
10458
|
uniform float uRadius;
|
|
10459
10459
|
varying vec2 vOffset;
|
|
10460
10460
|
void main() {
|