@rr0/ufoathome 0.144.0 → 0.145.0

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.
@@ -2398,10 +2398,10 @@ canvas[data-cursor="rotate"] {
2398
2398
  }
2399
2399
  `;class $c{constructor(t){this.points=t}static STATIONARY_M=5;static of(t){const e=[];for(const i of t.observerTrack.allKeyframes){const{lat:n,lng:s,headingDeg:r}=i.pose;n===void 0||s===void 0||e.push({t:i.t,lat:n,lng:s,headingDeg:r})}if(e.length===0){const i=t.event.place?.[0];if(!i)return;e.push({t:0,lat:i.lat,lng:i.lng})}return new $c(e)}static TRAVEL_M=50;get travels(){return this.spanM>$c.TRAVEL_M}get moved(){return this.spanM>$c.STATIONARY_M}get spanM(){const t=this.box,e=(t.south+t.north)/2,i=(t.west+t.east)/2;return Math.max(Math.abs(ae(e,t.east,e,t.west).x),Math.abs(ae(t.north,i,t.south,i).z))}get center(){const t=this.box;return{lat:(t.south+t.north)/2,lng:(t.west+t.east)/2}}boundsAround(t,e){const{lat:i,lng:n}=this.center,s=Math.max(this.spanM*(1+e),t)/2;return{north:fs(0,-s,i,n).lat,south:fs(0,s,i,n).lat,east:fs(s,0,i,n).lng,west:fs(-s,0,i,n).lng}}get box(){const t=this.points.map(i=>i.lat),e=this.points.map(i=>i.lng);return{south:Math.min(...t),north:Math.max(...t),west:Math.min(...e),east:Math.max(...e)}}}class xs{constructor(t,e){this.rotationPassed=t,this.scale=e}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(t){const e=t.event.tags?.includes("paralysis")||(t.exposure??0)>xs.HAND_HELD_S,i=t.sway??(e?0:1);if(i>0)return new xs(Math.max(1-(t.instrument.stabilization??0),xs.GAZE_DRIFT_SHARE),i)}offsetAt(t){const e=t/1e3,i=this.scale,n=(u,d)=>Math.sin(2*Math.PI*u*e+d),[s,r,a,c,l,h]=xs.HZ;return{eastM:i*xs.SWAY_M*(.7*n(s,.3)+.3*n(c,1.9)),northM:i*xs.SWAY_M*(.6*n(a,2.2)+.4*n(l,.8)),upM:i*xs.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*xs.DRIFT_YAW_DEG*(.6*n(h,1.1)+.4*n(c,2.7)),pitchDeg:i*this.rotationPassed*xs.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(a,.4)),rollDeg:i*this.rotationPassed*xs.DRIFT_ROLL_DEG*n(s,2.9)}}}class Xe{constructor(t,e){this.stretches=t,this.rotationPassed=e}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(t){const e=$c.of(t);if(!e||e.points.length<2)return;const i=[];let n=0;for(let s=1;s<e.points.length;s++){const r=e.points[s-1],a=e.points[s],c=(a.t-r.t)/1e3;if(c<=0)continue;const l=ae(a.lat,a.lng,r.lat,r.lng),h=l.x,u=-l.z,d=Math.hypot(h,u),f=d/c,p=Xe.stepHzFor(f);i.push({startMs:r.t,endMs:a.t,speedMPerS:f,eastUnit:d>0?h/d:0,northUnit:d>0?u/d:0,stepHz:p,stepsBefore:n,rampsIn:!0,rampsOut:!0}),n+=p*c}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 Xe(i,1-(t.instrument.stabilization??0))}static bodyAt(t,e,i=!1){const n=Xe.of(t)?.offsetAt(e)??Xe.STILL;return i?n:Xe.add(n,xs.of(t)?.offsetAt(e))}static stepHzFor(t){return t<Xe.SLOWEST_WALK_M_PER_S||t>Xe.FASTEST_WALK_M_PER_S?0:Xe.REFERENCE_STEP_HZ*Math.pow(t/Xe.REFERENCE_SPEED_M_PER_S,Xe.CADENCE_EXPONENT)}offsetAt(t){return Xe.add(this.cycleAt(t),this.joltAt(t))}joltAt(t){for(const e of this.stretches){if(e.stepHz===0)continue;const i=e.speedMPerS/Xe.REFERENCE_SPEED_M_PER_S,n=(a,c,l,h)=>{if(a<0||a>Xe.JOLT_LASTS_MS)return;const u=a/1e3,d=Math.exp(-u/Xe.JOLT_DECAY_S)*Math.sin(2*Math.PI*Xe.JOLT_HZ*u),f=h*c*i*d;return{eastM:f*e.eastUnit,northM:f*e.northUnit,upM:-Math.abs(f)*.3,rollDeg:0,pitchDeg:-h*l*i*d*this.rotationPassed,yawDeg:0}},s=e.rampsOut?n(t-e.endMs,Xe.STOP_LURCH_M,Xe.STOP_PITCH_DEG,1):void 0;if(s)return s;const r=e.rampsIn?n(t-e.startMs,Xe.START_LURCH_M,Xe.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(t,e){return e?{eastM:t.eastM+e.eastM,northM:t.northM+e.northM,upM:t.upM+e.upM,rollDeg:t.rollDeg+e.rollDeg,pitchDeg:t.pitchDeg+e.pitchDeg,yawDeg:t.yawDeg+e.yawDeg}:t}cycleAt(t){const e=this.stretches.find(c=>t>=c.startMs&&t<=c.endMs);if(!e||e.stepHz===0)return Xe.STILL;const i=e.stepsBefore+e.stepHz*(t-e.startMs)/1e3,n=2*Math.PI*i,s=this.amplitudeAt(e,t),r=Xe.SWAY_M*s*Math.cos(n/2),a=s*this.rotationPassed*e.speedMPerS/Xe.REFERENCE_SPEED_M_PER_S;return{eastM:r*e.northUnit,northM:-r*e.eastUnit,upM:Xe.RISE_M_PER_M_PER_S*e.speedMPerS*s*Math.cos(n),rollDeg:Xe.HEAD_ROLL_DEG*a*Math.cos(n/2),pitchDeg:-1.25*a*Math.cos(n),yawDeg:Xe.HEAD_YAW_DEG*a*Math.cos(n/2)}}amplitudeAt(t,e){const i=1e3/t.stepHz,n=Math.min(i,(t.endMs-t.startMs)/2);if(n<=0)return 1;const s=e-t.startMs,r=t.endMs-e,a=Math.min(t.rampsIn?s/n:1,t.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class RS{constructor(t,e){this.timeline=t,this.onFrame=e}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 t=()=>{if(this.state!=="playing")return;const e=performance.now();if(this.currentT+=(e-this.lastWallTime)*this.playbackRate,this.lastWallTime=e,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t)};this.rafId=requestAnimationFrame(t)}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(t){this.currentT=Math.max(0,Math.min(t,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(t){const e=new Map;for(const i of this.timeline.sourceIds){const n=this.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}this.onFrame(t,e)}}const Ry=["nw","n","ne","e","se","s","sw","w"],IS=24,qh=8,DS=3,CS=8;function Kh(o,t,e){const i=o.x-t.x,n=o.y-t.y,s=Math.cos(e),r=Math.sin(e);return{x:t.x+i*s-n*r,y:t.y+i*r+n*s}}function Sl(o){return{x:o.x+o.width/2,y:o.y+o.height/2}}const OS={nw:{left:!0,top:!0},n:{top:!0},ne:{right:!0,top:!0},e:{right:!0},se:{right:!0,bottom:!0},s:{bottom:!0},sw:{left:!0,bottom:!0},w:{left:!0}};class hs{static handlePointsFor(t){const{x:e,y:i,width:n,height:s}=t.bounds,r={nw:{x:e,y:i},n:{x:e+n/2,y:i},ne:{x:e+n,y:i},e:{x:e+n,y:i+s/2},se:{x:e+n,y:i+s},s:{x:e+n/2,y:i+s},sw:{x:e,y:i+s},w:{x:e,y:i+s/2},rotate:{x:e+n/2,y:i-IS}},a=Sl(t.bounds),c={};for(const l of Object.keys(r))c[l]=Kh(r[l],a,t.angle);return c}static hitTestHandle(t,e,i=8,n=[...Ry,"rotate"]){const s=hs.handlePointsFor(t);for(const r of n)if(Math.hypot(e.x-s[r].x,e.y-s[r].y)<=i)return r}static HANDLE_DIRECTION_DEG={e:0,se:45,s:90,sw:135,w:180,nw:225,n:270,ne:315};static resizeAxisFor(t,e){const n=((hs.HANDLE_DIRECTION_DEG[t]+e*180/Math.PI)%180+180)%180/45,s=["ew","nwse","ns","nesw"];return s[Math.round(n)%s.length]}static resizeBounds(t,e,i,n){const s=Sl(t),r=Kh(n,s,-e),{x:a,y:c,width:l,height:h}=t,u=OS[i];let d=a,f=c,p=a+l,g=c+h;return u.left&&(d=Math.min(r.x,p-qh)),u.right&&(p=Math.max(r.x,d+qh)),u.top&&(f=Math.min(r.y,g-qh)),u.bottom&&(g=Math.max(r.y,f+qh)),{x:d,y:f,width:p-d,height:g-f}}static resizeShape(t,e,i){if(e==="rotate")throw new Error("resizeShape does not accept the rotate handle");const{width:n,height:s}=t.bounds,r=hs.resizeBounds(t.bounds,t.angle,e,i);if(t.kind==="oval")return{...t,bounds:r};const a=n===0?1:r.width/n,c=s===0?1:r.height/s;return{...t,bounds:r,points:t.points.map(l=>({x:l.x*a,y:l.y*c}))}}static rotateShape(t,e){const i=Sl(t.bounds),n=Math.atan2(e.y-i.y,e.x-i.x)+Math.PI/2;return{...t,angle:n}}static groupBoundsFor(t){const e=Math.min(...t.map(r=>r.x)),i=Math.min(...t.map(r=>r.y)),n=Math.max(...t.map(r=>r.x+r.width)),s=Math.max(...t.map(r=>r.y+r.height));return{x:e,y:i,width:n-e,height:s-i}}static vertexPointsFor(t){const e=Sl(t.bounds);return t.points.map(i=>Kh({x:t.bounds.x+i.x,y:t.bounds.y+i.y},e,t.angle))}static hitTestVertex(t,e,i=CS){const n=hs.vertexPointsFor(t);let s,r=i;return n.forEach((a,c)=>{const l=Math.hypot(e.x-a.x,e.y-a.y);l<=r&&(r=l,s=c)}),s}static toLocalPoint(t,e){const i=Sl(t.bounds),n=Kh(e,i,-t.angle);return{x:n.x-t.bounds.x,y:n.y-t.bounds.y}}static moveVertex(t,e,i){const n=t.points.map((u,d)=>d===e?hs.toLocalPoint(t,i):u),s=Math.min(...n.map(u=>u.x)),r=Math.min(...n.map(u=>u.y)),a=Math.max(...n.map(u=>u.x)),c=Math.max(...n.map(u=>u.y)),l={x:t.bounds.x+s,y:t.bounds.y+r,width:a-s,height:c-r},h=n.map(u=>({x:u.x-s,y:u.y-r}));return{...t,bounds:l,points:h}}static insertVertexNear(t,e){const i=hs.toLocalPoint(t,e),{points:n}=t;let s=n.length-1,r=1/0;for(let c=0;c<n.length;c++){const l=n[c],h=n[(c+1)%n.length],u=hs.distanceToSegment(i,l,h);u<r&&(r=u,s=c)}const a=[...n.slice(0,s+1),i,...n.slice(s+1)];return{...t,points:a}}static distanceToSegment(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=n*n+s*s,a=r===0?0:Math.max(0,Math.min(1,((t.x-e.x)*n+(t.y-e.y)*s)/r)),c=e.x+a*n,l=e.y+a*s;return Math.hypot(t.x-c,t.y-l)}static deleteVertex(t,e){return t.points.length<=DS?t:{...t,points:t.points.filter((i,n)=>n!==e)}}}const Op=6,Zh=Op/2,K1=20,Z1=24,J1=9,j1=6,Q1=7,tv=6,js=4;class ol{constructor(t){this.ctx=t}starPoints=0;roll=0;clear(t,e){this.ctx.clearRect(0,0,t,e)}static paintExtent(t){const{x:e,y:i,width:n,height:s}=t.bounds,r=e+n/2,a=i+s/2,c=t.angle%(2*Math.PI)!==0,l=Math.hypot(n,s)/2,h=c?l:n/2,u=c?l:s/2,d=Math.max(n,s)/2,f=t.brightness??0,p=f>0?Math.max(d*(1+J1*f),tv*f)-d:0,g=f>0?d*(1+Q1*f)-d:0,m=3*Z1*(t.blur??0)+1.5*K1*t.haloScale,v=Math.max(p,g,0)+m+2;return{x:r-h-v,y:a-u-v,width:2*(h+v),height:2*(u+v)}}paintInto(t,e,i,n=!1){this.ctx.save(),this.ctx.scale(i,i),this.ctx.translate(-e.x,-e.y);const s=t.selected?{...t,selected:!1}:t;n?this.paintGhost(s,1.5):this.paintShape(s),this.ctx.restore()}paintShape(t){this.ctx.save(),this.ctx.globalAlpha=1-t.transparency;const e=t.blur??0;e>0&&(this.ctx.filter=`blur(${(Z1*e).toFixed(2)}px)`);const i=t.brightness??0;i>0&&this.paintDazzle(t,i),t.haloScale>0&&this.paintHalo(t),this.paintBase(t),this.ctx.restore(),t.selected&&this.paintSelectionHandles(t)}setStarPoints(t){this.starPoints=Math.max(0,Math.floor(t))}setRoll(t){this.roll=t}paintDazzle(t,e){const{x:i,y:n,width:s,height:r}=t.bounds,a=i+s/2,c=n+r/2,l=Math.max(s,r)/2,h=Math.max(l*(1+J1*e),tv*e);if(h<=0)return;this.ctx.save(),this.ctx.globalCompositeOperation="lighter";const u=this.ctx.createRadialGradient(a,c,0,a,c,h);for(let d=0;d<=j1;d++){const f=d/j1,p=1/(1+24*f*f);this.ctx.globalAlpha=1,u.addColorStop(f,this.withAlpha(t.color,p*e*.55))}if(this.ctx.fillStyle=u,this.ctx.beginPath(),this.ctx.arc(a,c,h,0,2*Math.PI),this.ctx.fill(),this.starPoints>0){const d=l*(1+Q1*e);this.ctx.lineWidth=Math.max(1,l*.12),this.ctx.lineCap="round";for(let f=0;f<this.starPoints;f++){const p=f/this.starPoints*Math.PI*2+this.roll,g=a+Math.cos(p)*d,m=c+Math.sin(p)*d,v=this.ctx.createLinearGradient(a,c,g,m);v.addColorStop(0,this.withAlpha(t.color,e*.55)),v.addColorStop(.35,this.withAlpha(t.color,e*.22)),v.addColorStop(1,this.withAlpha(t.color,0)),this.ctx.strokeStyle=v,this.ctx.beginPath(),this.ctx.moveTo(a,c),this.ctx.lineTo(g,m),this.ctx.stroke()}}this.ctx.restore()}dazzledFill(t,e){if(e<=0)return t.color;const i=/^#([0-9a-f]{6})$/i.exec(t.color.trim());if(!i)return t.color;const n=Number.parseInt(i[1],16),s=r=>Math.round(r+(255-r)*e);return`rgb(${s(n>>16&255)}, ${s(n>>8&255)}, ${s(n&255)})`}withAlpha(t,e){const i=Math.max(0,Math.min(1,e)),n=/^#([0-9a-f]{6})$/i.exec(t.trim());if(!n)return t;const s=Number.parseInt(n[1],16);return`rgba(${s>>16&255}, ${s>>8&255}, ${s&255}, ${i.toFixed(3)})`}paintBase(t){this.ctx.fillStyle=this.dazzledFill(t,t.brightness??0),this.tracePath(t),this.ctx.fill()}paintGhost(t,e){this.ctx.save(),this.tracePath(t),this.ctx.setLineDash([e*3,e*2]),this.ctx.lineWidth=e,this.ctx.strokeStyle=t.color,this.ctx.stroke(),this.ctx.restore()}tracePath(t){if(this.ctx.beginPath(),t.kind==="oval"){const{x:e,y:i,width:n,height:s}=t.bounds,r=n/2,a=s/2;this.ctx.ellipse(e+r,i+a,r,a,t.angle,0,2*Math.PI)}else{const{x:e,y:i,width:n,height:s}=t.bounds;this.ctx.save(),this.ctx.translate(e+n/2,i+s/2),this.ctx.rotate(t.angle),this.ctx.translate(-n/2,-s/2),t.points.forEach((r,a)=>{a===0?this.ctx.moveTo(r.x,r.y):this.ctx.lineTo(r.x,r.y)}),this.ctx.closePath(),this.ctx.restore()}}paintHalo(t){this.ctx.save(),this.ctx.shadowColor=t.color,this.ctx.shadowBlur=K1*t.haloScale,this.paintBase(t),this.ctx.restore()}paintSelectionHandles(t){this.paintHandleFrame(hs.handlePointsFor(t),{includeRotate:!0}),t.kind==="polygon"&&this.paintVertexHandles(t)}paintVertexHandles(t){this.ctx.fillStyle="#39f";for(const e of hs.vertexPointsFor(t))this.ctx.beginPath(),this.ctx.ellipse(e.x,e.y,js,js,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(t){this.paintOutline(hs.handlePointsFor(t))}paintSelectionOnly(t){this.paintSelectionHandles(t)}paintPictureFrame(t,e,i){const n=this.ctx;if(n.save(),t&&t.length===4){n.strokeStyle="#39f",n.lineWidth=1.5,n.setLineDash([6,4]),n.beginPath(),n.moveTo(t[0].x,t[0].y);for(const s of t.slice(1))n.lineTo(s.x,s.y);n.closePath(),n.stroke(),n.setLineDash([])}for(const s of e){const r=ol.landmarkColour(s.residualDeg),a=s.selected?3:2;s.selected&&(n.strokeStyle="#fff",n.lineWidth=a+3,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,js+2,js+2,0,0,2*Math.PI),n.stroke()),s.scene&&(n.strokeStyle=r,n.lineWidth=1,n.beginPath(),n.moveTo(s.picture.x,s.picture.y),n.lineTo(s.scene.x,s.scene.y),n.stroke(),n.fillStyle=r,n.beginPath(),n.ellipse(s.scene.x,s.scene.y,js,js,0,0,2*Math.PI),n.fill()),n.strokeStyle=r,n.lineWidth=a,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,js+2,js+2,0,0,2*Math.PI),n.stroke(),this.paintLabel(s.label,s.picture.x+js+5,s.picture.y-js-2,r)}i&&this.paintLabel(i,8,8,"#fff",13),n.restore()}paintGhosts(t,e,i){const n=this.ctx;n.save();const s=(c,l,h,u=[])=>{n.setLineDash(u),n.lineWidth=h+2,n.strokeStyle="rgba(0, 0, 0, 0.6)",c(),n.lineWidth=h,n.strokeStyle=l,c(),n.setLineDash([])},r=(c,l)=>()=>{n.beginPath(),n.arc(c.x,c.y,l,0,2*Math.PI),n.stroke()},a=(c,l,h)=>()=>{const[u,d]=h?[l,l]:[l,0];n.beginPath(),n.moveTo(c.x-u,c.y-d),n.lineTo(c.x+u,c.y+d),n.moveTo(c.x+d,c.y-u),n.lineTo(c.x-d,c.y+u),n.stroke()};for(const c of t)s(()=>{n.beginPath(),n.moveTo(c.ghost.x,c.ghost.y),n.lineTo(c.light.x,c.light.y),n.stroke()},"rgba(255, 255, 255, 0.85)",1,[4,4]),s(r(c.light,7),"#ffffff",1.5),s(r(c.ghost,Math.max(9,c.ghostRadius)),"#ffd23f",2);e&&s(a(e,8,!1),"#ffd23f",2),i&&s(a(i,5,!0),"rgba(255, 255, 255, 0.7)",1),n.restore()}static landmarkColour(t){return t===void 0?"#ffb000":t<=1?"#3c3":t<=3?"#ffb000":"#f33"}paintLabel(t,e,i,n,s=11){const r=this.ctx;r.save(),r.font=`${s}px system-ui, sans-serif`,r.textBaseline="top";const a=r.measureText(t).width;r.fillStyle="rgba(0, 0, 0, 0.6)",r.fillRect(e-3,i-2,a+6,s+4),r.fillStyle=n,r.fillText(t,e,i),r.restore()}paintGroupHandles(t){this.paintHandleFrame(hs.handlePointsFor({bounds:t,angle:0}),{includeRotate:!0})}paintOutline(t){this.ctx.strokeStyle="lightgray",this.ctx.beginPath(),this.ctx.moveTo(t.nw.x,t.nw.y),this.ctx.lineTo(t.ne.x,t.ne.y),this.ctx.lineTo(t.se.x,t.se.y),this.ctx.lineTo(t.sw.x,t.sw.y),this.ctx.closePath(),this.ctx.stroke()}paintHandleFrame(t,{includeRotate:e}){this.paintOutline(t),this.ctx.fillStyle="lightgray";for(const i of Ry){const n=t[i];this.ctx.fillRect(n.x-Zh,n.y-Zh,Op,Op)}e&&(this.ctx.beginPath(),this.ctx.moveTo(t.n.x,t.n.y),this.ctx.lineTo(t.rotate.x,t.rotate.y),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.ellipse(t.rotate.x,t.rotate.y,Zh+1,Zh+1,0,0,2*Math.PI),this.ctx.fill())}}const ev=.05,iv=.08,nv=2,sv=3,PS=14,LS=.02;class NS{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",t);return}}Io.unlock(this.context)}setSound(t){if(this.requested=t,!this.context)return;const e=this.keyFor(t);if(!e){this.silence();return}if(this.voice?.key!==e){this.stopVoice();const i=++this.voiceToken;e.startsWith("src:")?this.buildRecordedVoice(t.src,e,i):this.voice=this.buildSynthesizedVoice(t,e)}this.applyTo(this.voice,t)}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(t){if(!(t.volume<=0))return t.src?`src:${t.src}`:t.kind==="none"?void 0:t.kind}applyTo(t,e){const i=this.context;if(!t||!i)return;const n=i.currentTime;t.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,e.volume))*t.gainScale,n,ev);for(const{param:s,ratio:r}of t.pitch)s.setTargetAtTime(Math.min(e.pitchHz*r,i.sampleRate/2-1),n,ev)}buildSynthesizedVoice(t,e){const i=this.context;if(i)switch(t.kind){case"hum":return this.buildHum(i,e);case"whistle":return this.buildWhistle(i,e);case"rumble":return this.buildRumble(i,e);case"crackle":return this.buildCrackle(i,e);default:return}}buildHum(t,e){const i=t.createOscillator();i.type="sawtooth";const n=t.createOscillator();n.type="sawtooth";const s=t.createBiquadFilter();s.type="lowpass",s.Q.value=1;const r=t.createGain();return r.gain.value=0,i.connect(s),n.connect(s),s.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,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(t,e){const i=t.createOscillator();i.type="sine";const n=t.createOscillator();n.type="sine",n.frequency.value=5;const s=t.createGain(),r=t.createGain();return r.gain.value=0,n.connect(s).connect(i.frequency),i.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:s.gain,ratio:.012}]}}buildRumble(t,e){const i=t.createBufferSource();i.buffer=this.brownNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="lowpass",n.Q.value=.8;const s=t.createGain();return s.gain.value=0,i.connect(n).connect(s).connect(this.output(t)),i.start(),{key:e,nodes:[n,s],sources:[i],volumeParam:s.gain,gainScale:1.4,pitch:[{param:n.frequency,ratio:1}]}}buildCrackle(t,e){const i=t.createBufferSource();i.buffer=this.whiteNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="bandpass",n.Q.value=1.2;const s=t.createGain();s.gain.value=0;const r=t.createBufferSource();r.buffer=this.crackleEnvelope(t),r.loop=!0;const a=t.createGain();return a.gain.value=0,r.connect(a).connect(s.gain),i.connect(n).connect(s).connect(this.output(t)),i.start(),r.start(),{key:e,nodes:[n,s,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:n.frequency,ratio:4}]}}async buildRecordedVoice(t,e,i){const n=this.context;if(!n)return;let s;try{s=await this.getBuffer(t)}catch(c){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",c);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:e,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(t){const e=this.context;if(!e)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(t);return i||(i=fetch(t).then(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${t}`);return n.arrayBuffer()}).then(n=>e.decodeAudioData(n)),this.buffers.set(t,i)),i}whiteNoise(t){if(!this.noiseBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*nv),t.sampleRate),i=e.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;this.noiseBuffer=e}return this.noiseBuffer}brownNoise(t){const e=t.createBuffer(1,Math.floor(t.sampleRate*nv),t.sampleRate),i=e.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 e}crackleEnvelope(t){if(!this.crackleBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*sv),t.sampleRate),i=e.getChannelData(0),n=Math.max(1,Math.floor(LS*t.sampleRate)),s=Math.round(sv*PS);for(let r=0;r<s;r++){const a=Math.floor(Math.random()*i.length),c=.4+Math.random()*.6;for(let l=0;l<n&&a+l<i.length;l++)i[a+l]=Math.max(i[a+l],c*(1-l/n))}this.crackleBuffer=e}return this.crackleBuffer}stopVoice(){const t=this.voice,e=this.context;if(this.voice=void 0,!t||!e)return;const i=e.currentTime;t.volumeParam.cancelScheduledValues(i),t.volumeParam.setTargetAtTime(0,i,iv/3);const n=i+iv;for(const s of t.sources){s.onended=()=>{s.disconnect();for(const r of t.nodes)r.disconnect()};try{s.stop(n)}catch{s.disconnect();for(const r of t.nodes)r.disconnect()}}}}class or{static KINDS=["beams","launches","reentries"];static isEmpty(t){return!t||or.KINDS.every(e=>!t[e]?.length)}static written(t){if(or.isEmpty(t))return;const e={};for(const i of or.KINDS)t[i]?.length&&(e[i]=t[i]);return e}static read(t,e){const i=e,n={};for(const r of or.KINDS){const a=[...t?.[r]??[],...i?.[r]??[]];a.length>0&&(n[r]=a)}let s=e;if(i&&or.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:c,...l}=i;s=or.isReading(l)?l:void 0}return{skyEvents:or.written(n),interpretation:s}}static isReading(t){return(t.bodies?.length??0)>0||t.title!==void 0||(t.smoke?.length??0)>0}}function ih(o){return[...o].sort((t,e)=>t.t-e.t)}function Zf(o,t){let e;for(const i of ih(o)){if(i.t>t)break;e=i}return e}const Jf=Math.PI/180,Jh=180/Math.PI;class yr{constructor(t,e,i){this.kind=t,this.canvasHeightPx=e,this.fovDeg=i;const n=i*Jf/2;this.focalPx=t==="equidistant"?e/2/n:e/2/Math.tan(n)}focalPx;static of(t,e,i){return new yr(t.projection,e,i)}degToPx(t){const e=t*Jf;return this.kind==="equidistant"?this.focalPx*e:2*this.focalPx*Math.tan(e/2)}pxToDeg(t){return this.kind==="equidistant"?t/this.focalPx*Jh:2*Math.atan(t/(2*this.focalPx))*Jh}angleDegToRadiusPx(t){const e=t*Jf;return this.kind==="equidistant"?this.focalPx*e:this.focalPx*Math.tan(e)}halfWidthAngleDeg(t){return this.radiusPxToAngleDeg(this.canvasHeightPx*t/2)}radiusPxToAngleDeg(t){return this.kind==="equidistant"?t/this.focalPx*Jh:Math.atan(t/this.focalPx)*Jh}ofBounds(t){return{widthDeg:this.pxToDeg(t.width),heightDeg:this.pxToDeg(t.height)}}toBoundsSize(t){return{width:this.degToPx(t.widthDeg),height:this.degToPx(t.heightDeg)}}widthPx(t){return this.degToPx(Ze.angularWidthDeg(t))}}class In{static fovOf(t,e){return ze(t,e)?.fovDeg??Bi.fieldOfViewDeg(t.instrument)}static toAngular(t){this.eachKeyframe(t,(e,i)=>{const n=i.ofBounds(e.bounds);return e.angular?.widthDeg===n.widthDeg&&e.angular.heightDeg===n.heightDeg?e:{...e,angular:n}})}static toBounds(t){this.eachKeyframe(t,(e,i)=>this.sizedFromAngle(e,i))}static sizedFromAngle(t,e){if(!t.angular)return t;const{width:i,height:n}=e.toBoundsSize(t.angular),s={x:t.bounds.x+(t.bounds.width-i)/2,y:t.bounds.y+(t.bounds.height-n)/2,width:i,height:n};if(t.kind!=="polygon")return{...t,bounds:s};const r=t.bounds.width===0?1:i/t.bounds.width,a=t.bounds.height===0?1:n/t.bounds.height;return{...t,bounds:s,points:t.points.map(c=>({x:c.x*r,y:c.y*a}))}}static toAim(t){this.eachKeyframe(t,(e,i,n)=>{const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);if(s&&Math.abs(s.x-e.bounds.x)<In.UNMOVED_PX&&Math.abs(s.y-e.bounds.y)<In.UNMOVED_PX)return e;const r=this.aimFrom(t,i,n,e.bounds);return r?{...e,aim:r}:e})}static UNMOVED_PX=.01;static aimOf(t,e,i){const n=yr.of(t.instrument,Ze.CANVAS_HEIGHT_PX,this.fovOf(t,e));return this.aimFrom(t,n,ze(t,e),i)}static aimFrom(t,e,i,n){if(i?.headingDeg===void 0)return;const s=this.frameCentre(t),r=e.radiusPxToAngleDeg(n.x+n.width/2-s.x),a=e.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(t){this.eachKeyframe(t,(e,i,n)=>this.placedByAim(t,e,i,n))}static placedByAim(t,e,i,n){const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);return s?{...e,bounds:{...e.bounds,...s}}:e}static derivable(t){const e=new Set,i=new Map,n=new Map;return t.timeline.allKeyframes.forEach((s,r)=>{const a=ze(t,s.t),c=yr.of(t.instrument,Ze.CANVAS_HEIGHT_PX,this.fovOf(t,s.t));for(const{sourceId:l,shape:h}of s.shapes){const u=n.get(l),d=i.get(l);if(n.set(l,h),!u||!d){i.set(l,h);continue}const f=Object.fromEntries(Object.entries(h).filter(([m,v])=>m!=="bounds"&&m!=="points"&&JSON.stringify(v)!==JSON.stringify(u[m]))),p={...d,...f},g=this.placedByAim(t,this.sizedFromAngle(p,c),c,a);In.near(g,h)?(e.add(`${r}:${l}`),i.set(l,p)):i.set(l,h)}}),(s,r)=>e.has(`${s}:${r}`)}static SAME_PX=1e-6;static near(t,e){const i=(r,a)=>Math.abs(r-a)<=In.SAME_PX*Math.max(1,Math.abs(a)),n=t.bounds,s=e.bounds;return!i(n.x,s.x)||!i(n.y,s.y)||!i(n.width,s.width)||!i(n.height,s.height)?!1:e.kind!=="polygon"||t.kind!=="polygon"?!0:t.points.length===e.points.length&&t.points.every((r,a)=>i(r.x,e.points[a].x)&&i(r.y,e.points[a].y))}static positionOf(t,e,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(t),a=this.shortestArc(e.azimuthDeg-s.headingDeg),c=e.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,a)-i.width/2,y:r.y-this.offAxisPx(n,c)-i.height/2}}static frameCentre(t){return{x:Bi.frameWidthPx(t.instrument,Ze.CANVAS_HEIGHT_PX)/2,y:Ze.CANVAS_HEIGHT_PX/2}}static shortestArc(t){return(t%360+540)%360-180}static offAxisPx(t,e){return Math.abs(e)>=In.OFF_CANVAS_DEG?Math.sign(e)*In.OFF_CANVAS_PX:t.angleDegToRadiusPx(e)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(t,e,i){const n=Bi.frameWidthPx(e,Ze.CANVAS_HEIGHT_PX)/2,s=Bi.frameWidthPx(t.instrument,Ze.CANVAS_HEIGHT_PX)/2,r=Ze.CANVAS_HEIGHT_PX/2;for(const a of[...t.timeline.allKeyframes]){const c=this.fovOf(t,a.t),l=i?.get(a.t)??c,h=yr.of(e,Ze.CANVAS_HEIGHT_PX,l),u=yr.of(t.instrument,Ze.CANVAS_HEIGHT_PX,c);t.timeline.addKeyframe(a.t,a.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-n,g=f.y+f.height/2-r,m=Math.hypot(p,g),v=m===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,y={...f,x:s+p*v-f.width/2,y:r+g*v-f.height/2};return{...d,shape:{...d.shape,bounds:y}}}))}this.toBounds(t)}static eachKeyframe(t,e){const{timeline:i}=t;for(const n of[...i.allKeyframes]){const s=ze(t,n.t),r=this.fovOf(t,n.t),a=yr.of(t.instrument,Ze.CANVAS_HEIGHT_PX,r);let c=!1;const l=n.shapes.map(h=>{const u=e(h.shape,a,s);return u===h.shape?h:(c=!0,{...h,shape:u})});c&&i.addKeyframe(n.t,l)}}}function kS(o){return Fn.restore(US(o),o.provenance)}function US(o){return In.toAngular(o),In.toAim(o),{version:1,id:o.id,time:o.event.time,endTime:o.event.endTime,durationSeconds:o.event.durationSeconds,durationText:o.event.durationText,utcOffsetHours:o.event.utcOffsetHours,timeZone:o.event.timeZone,place:o.event.place,observer:o.observer,account:o.account,sources:o.sources?.length?o.sources:void 0,sway:o.sway,vehicle:o.vehicle,description:o.event.description,image:o.event.image,summary:o.event.summary,summaryTime:o.event.summaryTime,tags:o.event.tags,timeline:o.timeline.toJSON(),observerTrack:o.observerTrack.toJSON(),weatherTrack:o.weatherTrack.toJSON(),soundTrack:o.soundTrack.toJSON(),weather:o.weather,decor:o.decor,milestones:o.milestones.length>0?o.milestones:void 0,references:o.references.length>0?o.references:void 0,roads:o.roads.length>0?o.roads:void 0,traces:o.traces.length>0?o.traces:void 0,weatherSource:o.weatherSource,instrument:o.instrumentId,exposureSeconds:o.exposureSeconds,iso:o.iso,lens:o.lens,lightPollution:o.lightPollution,observerMap:o.observerMap,interpretation:o.interpretation,variants:o.variants.length>0?o.variants:void 0,skyEvents:or.written(o.skyEvents),frozen:o.frozen}}function FS(o){ro.check(o,"sighting");const{recording:t,provenance:e}=Fn.strip(o),i=zS(t);return i.provenance=e,i}function zS(o){const t=[],e=new Rf({eventType:"sighting",time:o.time,endTime:o.endTime,durationSeconds:o.durationSeconds,durationText:o.durationText,utcOffsetHours:o.utcOffsetHours,timeZone:o.timeZone,place:o.place,description:o.description,image:o.image,summary:o.summary,summaryTime:o.summaryTime,tags:o.tags},Sf.fromJSON(o.timeline,t),o.observerTrack?yh.fromJSON(o.observerTrack):new yh,o.weatherTrack?xh.fromJSON(o.weatherTrack):new xh,o.soundTrack?bh.fromJSON(o.soundTrack):new bh,o.observer&&{id:o.observer.id,title:o.observer.title,lastName:o.observer.lastName,firstNames:o.observer.firstNames},o.id,o.weather,o.decor??[],o.weatherSource,o.instrument,o.exposureSeconds??o.observerTrack?.keyframes.map(n=>n.pose.exposureSeconds).find(n=>n!==void 0),ih(o.milestones??[]),o.references??[],o.roads??[],o.traces??[]);e.account=o.account,e.sources=o.sources,e.sway=o.sway,e.iso=o.iso,e.lens=o.lens,e.lightPollution=o.lightPollution,e.observerMap=o.observerMap,e.vehicle=o.vehicle;const i=or.read(o.skyEvents,o.interpretation);return e.interpretation=i.interpretation,e.variants=Array.isArray(o.variants)?o.variants:[],e.skyEvents=i.skyEvents,e.frozen=o.frozen,e.loadIssues=t,In.toBounds(e),In.toPosition(e),e}class cl{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(t,e=cl.EN){return e[t.kind].replace("{path}",t.path).replace("{expected}",t.expected??"").replace("{found}",t.found??"")}static warn(t,e){if(t.length===0)return;const i=t.map(n=>` ${cl.text(n)}`);console.warn(`UFO@home: ${t.length} problem(s) in ${e??"this recording"}:
2400
2400
  ${i.join(`
2401
- `)}`)}}class Ls{constructor(t){this.format=t}issues(t){const e=[];return this.object(t,this.format,"",e),e}object(t,e,i,n){if(!Ls.isObject(t)){n.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:Ls.typeOf(t)});return}for(const[s,r]of Object.entries(t)){const a=i?`${i}.${s}`:s,c=e[s];c?this.field(r,c,a,n):n.push({kind:"unknown-key",path:a})}}field(t,e,i,n){if(Ls.isStated(t)){this.field(t.value,e,i,n);return}if(!(e.loose||t===void 0||t===null))switch(e.type){case"enum":(typeof t!="string"||!e.values?.includes(t))&&n.push({kind:"not-in-list",path:i,expected:(e.values??[]).map(s=>`"${s}"`).join(", "),found:JSON.stringify(t)});return;case"object":e.fields?this.object(t,e.fields,i,n):Ls.isObject(t)||n.push({kind:"wrong-type",path:i,expected:"object",found:Ls.typeOf(t)});return;case"array":Array.isArray(t)?e.fields&&t.forEach((s,r)=>{const a=Ls.isStated(s)?s.value:s;this.object(a,e.fields,`${i}.${r}`,n)}):n.push({kind:"wrong-type",path:i,expected:"array",found:Ls.typeOf(t)});return;default:typeof t!==e.type&&n.push({kind:"wrong-type",path:i,expected:e.type,found:Ls.typeOf(t)})}}static isObject(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}static isStated(t){return Ls.isObject(t)&&"value"in t&&Object.keys(t).every(e=>e==="value"||e==="basis"||e==="rationale")}static typeOf(t){return Array.isArray(t)?"array":t===null?"null":typeof t}}class Fs{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(t,e){const i=Number.isFinite(e)?Math.max(0,e):0,n=Math.max(0,t-i*1e3),s=Math.max(0,t-n);return{fromMs:n,toMs:t,ms:s,seconds:s/1e3}}static instants(t,e,i,n,s){if(!(n>0))return 1;const r=s>0?Fs.travelDegOver(t,e,i,i+n*1e3)/s/Fs.PIXELS_PER_INSTANT:0,a=Fs.flashesOver(t,n)*Fs.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(r,a));return c<2?1:Math.min(Fs.MAX_INSTANTS,c)}static travelDegOver(t,e,i,n){let s=0;for(const r of t){if(!r.track||r.track.length<2)continue;const a=Fs.directionAt(r,e,i),c=Fs.directionAt(r,e,n),l=Math.min(1,Math.max(-1,a.x*c.x+a.y*c.y+a.z*c.z));s=Math.max(s,Math.acos(l)*180/Math.PI)}return s}static flashesOver(t,e){let i=0;for(const n of t)for(const s of n.lights??[])s.pattern.kind==="flash"&&(i=Math.max(i,s.pattern.perMinute));return i/60*e}static directionAt(t,e,i){const n=Er(t,i),s=n.eastM,r=n.altitudeM-e,a=n.northM,c=Math.hypot(s,r,a);return c===0?{x:0,y:1,z:0}:{x:s/c,y:r/c,z:a/c}}}const fg=["en","fr","es","it"],BS={en:()=>we(()=>Promise.resolve().then(()=>YS),void 0,import.meta.url).then(o=>o.ufoMessages_en),fr:()=>we(()=>import("./UfoMessages_fr-Cs2GCHEt.js"),[],import.meta.url).then(o=>o.ufoMessages_fr),es:()=>we(()=>import("./UfoMessages_es-BRCWkzr3.js"),[],import.meta.url).then(o=>o.ufoMessages_es),it:()=>we(()=>import("./UfoMessages_it-B2hvjhgb.js"),[],import.meta.url).then(o=>o.ufoMessages_it)};function HS(o){return BS[o]()}const GS={en:()=>we(()=>Promise.resolve().then(()=>kO),void 0,import.meta.url).then(o=>o.sightingMessages_en),fr:()=>we(()=>import("./SightingMessages_fr-Dwkll3ZY.js"),[],import.meta.url).then(o=>o.sightingMessages_fr),es:()=>we(()=>import("./SightingMessages_es-DBRW6jG0.js"),[],import.meta.url).then(o=>o.sightingMessages_es),it:()=>we(()=>import("./SightingMessages_it-CS1pKPSh.js"),[],import.meta.url).then(o=>o.sightingMessages_it)};function VS(o){return GS[o]()}const WS={en:()=>we(()=>Promise.resolve().then(()=>UO),void 0,import.meta.url).then(o=>o.shareMessages_en),fr:()=>we(()=>import("./ShareMessages_fr-DyOB2E5o.js"),[],import.meta.url).then(o=>o.shareMessages_fr),es:()=>we(()=>import("./ShareMessages_es-BM5hHumO.js"),[],import.meta.url).then(o=>o.shareMessages_es),it:()=>we(()=>import("./ShareMessages_it-C9F8UHk_.js"),[],import.meta.url).then(o=>o.shareMessages_it)};function XS(o){return WS[o]()}function $S(o){switch(o){case"fr":return we(()=>import("./TagNames_fr-Dnqq6HQ5.js"),[],import.meta.url).then(t=>t.tagNames_fr);case"es":return we(()=>import("./TagNames_es-BfnMpc3D.js"),[],import.meta.url).then(t=>t.tagNames_es);case"it":return we(()=>import("./TagNames_it-n6E4EGYO.js"),[],import.meta.url).then(t=>t.tagNames_it);default:return Promise.resolve({})}}function Iy(o){switch(o){case"fr":return we(()=>import("./SceneNames_fr-DixomaFq.js"),[],import.meta.url).then(t=>t.sceneNames_fr);case"es":return we(()=>import("./SceneNames_es-CPCIUfgZ.js"),[],import.meta.url).then(t=>t.sceneNames_es);case"it":return we(()=>import("./SceneNames_it-BTNeU7-M.js"),[],import.meta.url).then(t=>t.sceneNames_it);default:return Promise.resolve(void 0)}}const Dy={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:cl.EN},YS=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Dy},Symbol.toStringTag,{value:"Module"})),Cy=Math.PI/180,qS=180/Math.PI,KS=256,Oy=19,ZS=1.25;function Py(o,t){return 156543.03392*Math.cos(o*Cy)/2**t}function Ly(o,t){return Py(o,t)*KS}function JS(o,t){let e=0;for(;e<Oy&&Ly(o,e+1)>=t;)e++;return e}function Ny(o,t){return Ly(o,t)}function jS(o,t){const e=t*ZS;let i=0;for(;i<Oy&&Py(o,i)>e;)i++;return i}function ad(o){const t=o*Cy;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}function ky(o,t,e){const i=2**e;return{x:(o+180)/360*i,y:ad(t)*i}}function Uy(o,t,e){const i=ad(o.north),n=ad(o.south);return{x:(t-o.west)/(o.east-o.west),y:(ad(e)-i)/(n-i)}}function QS(o,t,e){const{x:i,y:n}=ky(o,t,e);return{x:Math.floor(i),y:Math.floor(n),z:e}}function tE(o){const t=2**o.z,e=o.x/t*360-180,i=(o.x+1)/t*360-180,n=rv(o.y,t);return{south:rv(o.y+1,t),north:n,west:e,east:i}}function rv(o,t){const e=o/t;return Math.atan(Math.sinh(Math.PI*(1-2*e)))*qS}function Fy(o,t,e,i){const n=QS(o,t,e),s=Math.floor(i/2),r=[];for(let l=-s;l<=s;l++)for(let h=-s;h<=s;h++)r.push({x:n.x+h,y:n.y+l,z:e});const a=r.map(tE),c={south:Math.min(...a.map(l=>l.south)),north:Math.max(...a.map(l=>l.north)),west:Math.min(...a.map(l=>l.west)),east:Math.max(...a.map(l=>l.east))};return{tiles:r,bounds:c}}const eE="#2ec4ff";class eo{constructor(t){this.ctx=t}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(t,e){let i,n=1/0;for(const s of this.targets){const r=Math.hypot(s.x-t,s.y-e);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(t){const{ctx:e}=this;e.save(),this.targets=[],e.clearRect(0,0,this.width,this.height),this.paintGround(t),this.paintNight(t.nightFraction),this.paintPath(t),this.paintTraces(t),t.position?(this.paintCone(t,t.position),this.paintDecor(t),this.paintMarkers(t),this.paintObserver(t,t.position)):(this.paintDecor(t),this.paintMarkers(t)),this.paintNorth(),this.paintFooter(t.bounds,t.attribution),e.restore()}toCanvas(t,e,i){const n=Uy(t,i,e);return{x:n.x*this.width,y:n.y*this.height}}paintGround(t){const{ctx:e}=this;e.fillStyle="#1d2321",e.fillRect(0,0,this.width,this.height);const i=t.imagery;if(!i)return;const n=this.toCanvas(t.bounds,i.bounds.north,i.bounds.west),s=this.toCanvas(t.bounds,i.bounds.south,i.bounds.east);e.drawImage(i.source,n.x,n.y,s.x-n.x,s.y-n.y)}paintNight(t=0){if(t<=0)return;const{ctx:e}=this;e.save(),e.fillStyle=`rgba(6, 12, 30, ${Math.min(t,1)*.78})`,e.fillRect(0,0,this.width,this.height),e.restore()}paintDecor(t){const{ctx:e}=this;for(const i of t.decor){const n=this.toCanvas(t.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}),e.beginPath(),e.rect(n.x-3.5,n.y-3.5,7,7),e.fillStyle="rgba(120, 220, 255, 0.85)",e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.7)",e.stroke(),i.headingDeg===void 0)continue;const s=(i.headingDeg-90)*Math.PI/180;e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(n.x+Math.cos(s)*10,n.y+Math.sin(s)*10),e.lineWidth=3,e.strokeStyle="rgba(0, 0, 0, 0.6)",e.stroke(),e.lineWidth=1.5,e.strokeStyle="rgba(120, 220, 255, 0.9)",e.stroke()}}paintPath(t){if(!t.path.moved)return;const{ctx:e}=this,i=t.path.points.map(n=>this.toCanvas(t.bounds,n.lat,n.lng));e.beginPath(),e.moveTo(i[0].x,i[0].y);for(const n of i.slice(1))e.lineTo(n.x,n.y);e.lineJoin="round",e.lineCap="round",e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=5,e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.9)",e.lineWidth=2,e.stroke()}paintTraces(t){const{ctx:e}=this;for(const i of t.traces??[]){const n=i.points.map(r=>this.toCanvas(t.bounds,r.lat,r.lng));if(n.length===0)continue;const s=i.color??eE;if(i.kind==="point")e.beginPath(),e.moveTo(n[0].x,n[0].y-6),e.lineTo(n[0].x+6,n[0].y),e.lineTo(n[0].x,n[0].y+6),e.lineTo(n[0].x-6,n[0].y),e.closePath(),e.fillStyle=s,e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.8)",e.stroke();else{e.beginPath(),e.moveTo(n[0].x,n[0].y);for(const r of n.slice(1))e.lineTo(r.x,r.y);i.kind==="polygon"&&e.closePath(),e.lineJoin="round",e.setLineDash([]),e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=4.5,e.stroke(),e.setLineDash([9,5]),e.strokeStyle=s,e.lineWidth=2.5,e.stroke(),e.setLineDash([])}if(i.label){e.font="11px sans-serif",e.textAlign="left",e.textBaseline="middle";let r=n[0];if(i.kind==="line"&&t.position){const a=this.toCanvas(t.bounds,t.position.lat,t.position.lng);r=n.reduce((c,l)=>Math.hypot(l.x-a.x,l.y-a.y)>Math.hypot(c.x-a.x,c.y-a.y)?l:c)}this.paintOutlinedText(i.label,r.x+9,r.y-9)}}}paintCone(t,e){const{headingDeg:i,coneHalfAngleDeg:n}=t;if(i===void 0||n===void 0)return;const{ctx:s}=this,r=this.toCanvas(t.bounds,e.lat,e.lng),a=Math.hypot(this.width,this.height),c=(i-90)*Math.PI/180,l=n*Math.PI/180;s.save(),s.beginPath(),s.moveTo(r.x,r.y),s.arc(r.x,r.y,a,c-l,c+l),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(t){const{ctx:e}=this;e.textAlign="center",e.textBaseline="middle",e.font="bold 10px sans-serif";for(const i of[...t.markers].sort((n,s)=>Number(n.current)-Number(s.current))){const n=this.toCanvas(t.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:eo.MARKER_RADIUS_PX}),e.beginPath(),e.arc(n.x,n.y,eo.MARKER_RADIUS_PX,0,Math.PI*2),e.fillStyle=i.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",e.fill(),e.lineWidth=2,e.strokeStyle="rgba(255, 255, 255, 0.9)",e.stroke(),e.fillStyle=i.current?"#1d2321":"#fff",e.fillText(i.label,n.x,n.y)}}paintObserver(t,e){const{ctx:i}=this,n=this.toCanvas(t.bounds,e.lat,e.lng);t.observerLabel&&this.targets.push({kind:"observer",label:t.observerLabel,lat:e.lat,lng:e.lng,x:n.x,y:n.y,radius:8});const s=t.markers.some(r=>{if(!r.current)return!1;const a=ae(r.lat,r.lng,e.lat,e.lng);return Math.hypot(a.x,a.z)<=eo.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?eo.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:t}=this,e=this.width-14,i=16;t.beginPath(),t.moveTo(e,i-9),t.lineTo(e-4.5,i+5),t.lineTo(e,i+2),t.lineTo(e+4.5,i+5),t.closePath(),t.fillStyle="rgba(255, 255, 255, 0.92)",t.strokeStyle="rgba(0, 0, 0, 0.6)",t.lineWidth=1,t.fill(),t.stroke(),t.font="bold 9px sans-serif",t.textAlign="center",t.textBaseline="top",t.strokeText("N",e,i+6),t.fillText("N",e,i+6)}paintFooter(t,e){const{ctx:i}=this;i.font="9px sans-serif",i.textBaseline="bottom";const n=e?this.wrap(e,this.width-20):[];let s=this.height-4;i.textAlign="right";for(const f of n.slice().reverse())this.paintOutlinedText(f,this.width-6,s),s-=11;const r=(t.south+t.north)/2,c=Math.abs(ae(r,t.east,r,t.west).x)/this.width,l=eo.SCALE_STEPS_M.find(f=>f/c<=this.width/3);if(l===void 0)return;const h=l/c,u=8,d=s-3;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.6)",i.beginPath(),i.moveTo(u,d),i.lineTo(u+h,d),i.stroke(),i.lineWidth=1.5,i.strokeStyle="rgba(255, 255, 255, 0.95)",i.stroke(),i.textAlign="left",this.paintOutlinedText(l>=1e3?`${l/1e3} km`:`${l} m`,u,d-3)}paintOutlinedText(t,e,i){const{ctx:n}=this;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.75)",n.strokeText(t,e,i),n.fillStyle="#fff",n.fillText(t,e,i)}wrap(t,e){const i=[];let n="";for(const s of t.split(" ")){const r=n?`${n} ${s}`:s;n&&this.ctx.measureText(r).width>e?(i.push(n),n=s):n=r}return n&&i.push(n),i}}class Qe{static MIN_ZOOM=.25;static MAX_ZOOM=64;static MIN_SPAN_M=400;static MARGIN=.6;static IMAGERY_PX=768;static fitted(t,e){return Qe.including(t.boundsAround(Qe.MIN_SPAN_M,Qe.MARGIN),e)}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(t,e,i){const n=Math.min(Qe.MAX_ZOOM,Math.max(Qe.MIN_ZOOM,this.zoom*i)),s=this.centerX+(t-.5)/this.zoom,r=this.centerY+(e-.5)/this.zoom;this.centerX=s-(t-.5)/n,this.centerY=r-(e-.5)/n,this.zoom=n}panBy(t,e){this.centerX-=t/this.zoom,this.centerY-=e/this.zoom}refit(t,e){if(!this.changed)return;const i=this.boundsWithin(t),n=Qe.mercatorY01(e.north),s=Qe.mercatorY01(e.south),r=Qe.mercatorY01(i.north),a=Qe.mercatorY01(i.south);this.zoom=(e.east-e.west)/(i.east-i.west),this.centerX=((i.west+i.east)/2-e.west)/(e.east-e.west),this.centerY=((r+a)/2-n)/(s-n)}keepInView(t,e,i){if(!this.changed)return!1;const n=this.boundsWithin(t),s=Qe.mercatorY01(n.north),r=Qe.mercatorY01(n.south),a=(e.lng-n.west)/(n.east-n.west),c=(Qe.mercatorY01(e.lat)-s)/(r-s);return a>=i&&a<=1-i&&c>=i&&c<=1-i?!1:(this.panBy(.5-a,.5-c),!0)}boundsWithin(t){if(!this.changed)return t;const e=.5/this.zoom,i=Qe.mercatorY01(t.north),n=Qe.mercatorY01(t.south),s=t.east-t.west;return{west:t.west+(this.centerX-e)*s,east:t.west+(this.centerX+e)*s,north:Qe.latitudeAt(i+(this.centerY-e)*(n-i)),south:Qe.latitudeAt(i+(this.centerY+e)*(n-i))}}static including(t,e,i=3){const n=(t.north+t.south)/2,s=(t.east+t.west)/2,r=ae(n,t.east,n,s).x;let a=r;for(const c of e){const{x:l,z:h}=ae(c.lat,c.lng,n,s),u=Math.max(Math.abs(l),Math.abs(h));u<=r*i&&(a=Math.max(a,u*1.15))}return a<=r?t:{north:fs(0,-a,n,s).lat,south:fs(0,a,n,s).lat,east:fs(a,0,n,s).lng,west:fs(-a,0,n,s).lng}}static expand(t,e){const i=t.east-t.west,n=t.north-t.south;return{west:t.west-i*e,east:t.east+i*e,south:t.south-n*e,north:t.north+n*e}}static pointAt(t,e,i){const n=Qe.mercatorY01(t.north),s=Qe.mercatorY01(t.south);return{lat:Qe.latitudeAt(n+i*(s-n)),lng:t.west+e*(t.east-t.west)}}static mercatorY01(t){const e=t*Math.PI/180;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}static latitudeAt(t){return Math.atan(Math.sinh(Math.PI*(1-2*t)))*180/Math.PI}}const Ms=256,av=3,iE=32768;class nE{fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(t,e){const i=(t.south+t.north)/2,n=(t.west+t.east)/2,s=Math.abs(ae(i,t.east,i,t.west).x),r=Math.abs(ae(t.north,n,t.south,n).z),a=JS(i,Math.max(s,r)),{tiles:c}=Fy(n,i,a,av),l=av*Ms,h=new Float32Array(l*l),u=c[0];await Promise.all(c.map(f=>this.decodeTileInto(f,u,h,l)));const d=new Float32Array(e.width*e.height);for(let f=0;f<e.height;f++){const p=t.north+(t.south-t.north)*(f/(e.height-1));for(let g=0;g<e.width;g++){const m=t.west+(t.east-t.west)*(g/(e.width-1));d[f*e.width+g]=this.sampleAt(p,m,a,u,h,l)}}return{heights:d,width:e.width,height:e.height,bounds:t}}async decodeTileInto(t,e,i,n){const s=this.tileUrlTemplate.replace("{z}",String(t.z)).replace("{x}",String(t.x)).replace("{y}",String(t.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()),c=document.createElement("canvas");c.width=Ms,c.height=Ms;const l=c.getContext("2d");if(!l)throw new Error("2D canvas context unavailable");l.drawImage(a,0,0);const{data:h}=l.getImageData(0,0,Ms,Ms),u=(t.x-e.x)*Ms,d=(t.y-e.y)*Ms;for(let f=0;f<Ms;f++)for(let p=0;p<Ms;p++){const g=(f*Ms+p)*4,m=h[g]*256+h[g+1]+h[g+2]/256-iE,v=u+p,y=d+f;i[y*n+v]=m}}sampleAt(t,e,i,n,s,r){const{x:a,y:c}=ky(e,t,i),l=(a-n.x)*Ms,h=(c-n.y)*Ms,u=Math.max(0,Math.min(r-1,Math.floor(l))),d=Math.max(0,Math.min(r-1,Math.floor(h))),f=Math.min(r-1,u+1),p=Math.min(r-1,d+1),g=l-u,m=h-d,v=s[d*r+u],y=s[d*r+f],x=s[p*r+u],M=s[p*r+f],b=v+(y-v)*g,S=x+(M-x)*g;return b+(S-b)*m}}class Df{constructor(t,e,i,n){this.width=t,this.height=e,this.samples=i,this.values=n}at(t,e,i=0){return this.values[(e*this.width+t)*this.samples+i]}static parse(t){const e=new DataView(t);if(t.byteLength<8||e.getUint16(0)!==18761||e.getUint16(2,!0)!==42)throw new Error("Not a little-endian TIFF");const i=e.getUint32(4,!0),n=e.getUint16(i,!0),s=new Map;for(let v=0;v<n;v++){const y=i+2+v*12;s.set(e.getUint16(y,!0),{type:e.getUint16(y+2,!0),count:e.getUint32(y+4,!0),value:e.getUint32(y+8,!0)})}const r=(v,y)=>{const x=s.get(v);if(x===void 0){if(y===void 0)throw new Error(`TIFF without tag ${v}`);return y}return x.type===3?x.value&65535:x.value},a=v=>{const y=s.get(v);if(y===void 0)throw new Error(`TIFF without tag ${v}`);const x=y.type===3?2:4,M=[];if(y.count*x<=4){const b=new DataView(new ArrayBuffer(4));b.setUint32(0,y.value,!0);for(let S=0;S<y.count;S++)M.push(x===2?b.getUint16(S*2,!0):b.getUint32(0,!0))}else for(let b=0;b<y.count;b++)M.push(x===2?e.getUint16(y.value+b*2,!0):e.getUint32(y.value+b*4,!0));return M};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(s.has(322))throw new Error("Tiled TIFF");const c=r(256),l=r(257),h=r(277,1),u=a(258)[0],d=r(339,1)===3;if(!(d&&u===32||!d&&u===8))throw new Error(`Unsupported TIFF samples: ${u} bits`);const f=a(273),p=a(279),g=new Uint8Array(c*l*h*(u/8));let m=0;for(let v=0;v<f.length&&m<g.length;v++){const y=Math.min(p[v],g.length-m);g.set(new Uint8Array(t,f[v],y),m),m+=y}if(m<g.length)throw new Error("Truncated TIFF");return new Df(c,l,h,d?new Float32Array(g.buffer):g)}}class aa extends Error{constructor(t,e){super(e),this.reason=t,this.name="SurroundingsUnavailableError"}}class sE{constructor(t,e,i,n,s){this.heights=t,this.plants=e,this.buildings=i,this.size=n,this.metresPerPixel=s}structureAt(t,e){const i=Math.floor(t/this.metresPerPixel+this.size/2),n=Math.floor(this.size/2-e/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(t,e,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 c=this.structureAt(t+a*this.metresPerPixel,e+r*this.metresPerPixel);c!==void 0&&(n===void 0||c>n)&&(n=c)}return n}}class Re{static covers(t,e){return t>=41.2&&t<=51.3&&e>=-5.4&&e<=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(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??Re.WMS,this.wfs=t.wfsEndpoint??Re.WFS}static radius(t){return Math.min(t,Re.MAX_RADIUS_M)}static lidarRadius(t){return Math.min(t,Re.MAX_LIDAR_RADIUS_M)}async lidar(t,e){const i=Re.lidarRadius(e),n=Math.ceil(2*i/Re.METRES_PER_PIXEL),[s,r]=await Promise.all([this.raster(t,i,n,Re.HEIGHT_LAYER),this.raster(t,i,n,Re.CLASS_LAYER)]);if(s.samples!==1||r.samples<3)throw new aa("unreachable","The survey answered in a layout this does not read");const a=s.values;if(a.every(u=>u===Re.NO_DATA))throw new aa("no-coverage","No LiDAR HD survey here yet");const c=new Uint8Array(n*n),l=new Uint8Array(n*n);for(let u=0;u<n*n;u++){const d=r.values[u*r.samples],f=r.values[u*r.samples+1],p=r.values[u*r.samples+2];c[u]=f>d&&f>p?1:0,l[u]=d>120&&f<90&&p<90?1:0}const h=2*i/n;return{size:n,metresPerPixel:h,heights:a,vegetation:c,building:l,structures:new sE(a,c,l,n,h)}}async laserDate(t){return Re.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",t))}async photoDate(t){return Re.latest(await this.dated("ORTHOIMAGERY.ORTHOPHOTOS.GRAPHE-MOSAIQUAGE:graphe_bdortho","geom","date_vol",t))}static latest(t){return t.map(i=>/^\d{4}-\d{2}-\d{2}/.exec(String(i??""))?.[0]).filter(i=>i!==void 0).sort().at(-1)}async dated(t,e,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(t,`BBOX(${e},${r},'EPSG:4326')`,i,20)).map(a=>a.properties[i])}catch{return[]}}async photo(t,e){const i=Re.radius(e),n=Math.min(Re.MAX_PHOTO_PIXELS,Math.ceil(2*i/Re.METRES_PER_PIXEL)),s=await this.raster(t,i,n,Re.PHOTO_LAYER);if(s.samples<3)throw new aa("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(t,e,i){const n=Re.radius(e),s=n/Re.METRES_PER_DEGREE,r=n/(Re.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),c=`BBOX(geometrie,${[t.lng-r,t.lat-s,t.lng+r,t.lat+s].map(v=>v.toFixed(6)).join(",")},'EPSG:4326')`,[l,h,u,d,f,p]=await Promise.all([this.features("construction_lineaire",`${c} AND nature='Pont'`,"nature,geometrie"),this.features("troncon_de_route",`${c} 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",`${c} AND position_par_rapport_au_sol>'0'`,"position_par_rapport_au_sol,geometrie").catch(()=>[]),this.features("ligne_electrique",c,"voltage,geometrie"),i?this.features("batiment",c,Re.BUILDING_PROPERTIES,5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",c,"toponyme,categorie,geometrie",100).catch(()=>[]):Promise.resolve([])]),g=i?await this.wholeWorship(p,f,[t.lng-r,t.lat-s,t.lng+r,t.lat+s]):[],m=[...f,...g];return{bridges:l,elevatedRoads:h,elevatedRailways:u,lines:d,buildings:m,zones:p,mapDate:Re.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(t,e,i){const[n,s,r,a]=i,c=Re.MAX_WHOLE_M/Re.METRES_PER_DEGREE;let l;for(const u of t){if(u.properties.categorie!=="Religieux")continue;const[d,f,p,g]=Re.extent(u);if(d>=n&&f>=s&&p<=r&&g<=a)continue;const m=[Math.max(d,n-c),Math.max(f,s-c),Math.min(p,r+c),Math.min(g,a+c)];l=l?[Math.min(l[0],m[0]),Math.min(l[1],m[1]),Math.max(l[2],m[2]),Math.max(l[3],m[3])]:m}if(!l)return[];const h=new Set(e.map(u=>u.properties.cleabs));try{return(await this.features("batiment",`BBOX(geometrie,${l.map(d=>d.toFixed(6)).join(",")},'EPSG:4326')`,Re.BUILDING_PROPERTIES,1e3)).filter(d=>!h.has(d.properties.cleabs))}catch{return[]}}static extent(t){let e=1/0,i=1/0,n=-1/0,s=-1/0;const r=a=>{Array.isArray(a)&&typeof a[0]=="number"?(e=Math.min(e,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(t.geometry.coordinates),[e,i,n,s]}async elevatedRoadLines(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(s=>s.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${e} AND position_par_rapport_au_sol>'0'`,"geometrie",300),n=[];for(const s of i){const{type:r,coordinates:a}=s.geometry,c=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const l of c)n.push(l.map(h=>({lat:h[1],lng:h[0]})))}return n}async waterSurfaces(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("surface_hydrographique",`${e} AND position_par_rapport_au_sol='0' AND persistance='Permanent'`,"cleabs,nature,geometrie",500)}async roads(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_route",`${e} 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(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_voie_ferree",`${e} 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(t,e,i,n){const s=e/Re.METRES_PER_DEGREE,r=e/(Re.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:n,STYLES:"",CRS:"EPSG:4326",BBOX:[t.lat-s,t.lng-r,t.lat+s,t.lng+r].map(l=>l.toFixed(6)).join(","),WIDTH:String(i),HEIGHT:String(i),FORMAT:"image/geotiff"});let c;try{c=await this.fetchImpl(`${this.wms}?${a}`)}catch(l){throw new aa("unreachable",l instanceof Error?l.message:String(l))}if(!c.ok)throw new aa("unreachable",`The survey answered ${c.status}`);try{return Df.parse(await c.arrayBuffer())}catch(l){throw new aa("unreachable",l instanceof Error?l.message:String(l))}}async features(t,e,i,n=200){const s=new URLSearchParams({SERVICE:"WFS",VERSION:"2.0.0",REQUEST:"GetFeature",TYPENAMES:t.includes(":")?t:`BDTOPO_V3:${t}`,SRSNAME:"EPSG:4326",OUTPUTFORMAT:"application/json",COUNT:String(n),CQL_FILTER:e,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${s}`)}catch(c){throw new aa("unreachable",c instanceof Error?c.message:String(c))}if(!r.ok)throw new aa("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class ba{static NEAR_M=15;static ALIGNED_DEG=30;static LONG_ENOUGH_M=15;static SAMPLE_M=5;static follows(t,e){if(t.length<2||e.length<2)return!1;const i=e[0],n=e.map(a=>ae(a.lat,a.lng,i.lat,i.lng)),s=t.map(a=>ae(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<s.length-1;a++){const c=s[a],l=s[a+1],h=Math.hypot(l.x-c.x,l.z-c.z);if(h<1e-6)continue;const u=Math.max(1,Math.ceil(h/ba.SAMPLE_M)),d=Math.atan2(l.x-c.x,-(l.z-c.z));for(let f=0;f<=u;f++){const p=f/u,g=ba.nearest(n,c.x+(l.x-c.x)*p,c.z+(l.z-c.z)*p);g.distanceM>ba.NEAR_M||ba.angleBetween(d,g.heading)<=ba.ALIGNED_DEG&&(r+=h/u)}}return r>=ba.LONG_ENOUGH_M}static nearest(t,e,i){let n={distanceM:1/0,heading:0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,l=a.z-r.z,h=c*c+l*l,u=h<1e-9?0:Math.max(0,Math.min(1,((e-r.x)*c+(i-r.z)*l)/h)),d=Math.hypot(e-(r.x+c*u),i-(r.z+l*u));d<n.distanceM&&(n={distanceM:d,heading:Math.atan2(c,-l)})}return n}static angleBetween(t,e){const i=Math.abs((t-e)*180/Math.PI%180);return Math.min(i,180-i)}}class xe{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(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??xe.WMS,this.timeoutMs=t.timeoutMs??xe.DEFAULT_TIMEOUT_MS,this.maxWindowM=t.maxWindowM??xe.MAX_WINDOW_M,this.geoplatform=new Re({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:t.wfsEndpoint})}async getElevationGrid(t,e,i){const n={lat:(t.south+t.north)/2,lng:(t.west+t.east)/2};if(!Re.covers(n.lat,n.lng))throw new Error("The IGN's relief covers France only");const s=Math.abs(ae(n.lat,t.east,n.lat,t.west).x),r=Math.abs(ae(t.north,n.lng,t.south,n.lng).z);e=this.finer(e,s,r);const a={x:s/Math.max(1,e.width-1),y:r/Math.max(1,e.height-1)},c={x:Math.min(a.x,this.maxWindowM),y:Math.min(a.y,this.maxWindowM)},l={south:t.south-c.y/xe.METRES_PER_DEGREE,north:t.north+c.y/xe.METRES_PER_DEGREE,west:t.west-c.x/(xe.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180)),east:t.east+c.x/(xe.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180))},h=g=>Math.min(xe.MAX_PIXELS,Math.max(xe.MIN_PIXELS,Math.ceil(g/xe.METRES_PER_PIXEL))),u={width:h(s+2*c.x),height:h(r+2*c.y)},d={x:(s+2*c.x)/u.width,y:(r+2*c.y)/u.height};let f=new Error("No layer of the IGN's relief answered");const p=Math.max(d.x,d.y)>xe.COARSE_METRES_PER_PIXEL;for(const g of p?[...xe.LAYERS].reverse():xe.LAYERS)try{const m=await this.heights(l,u,g);g===xe.LAYERS[0]&&await this.layBridgeDecks(m,l,u,i?.route);const v=this.sample(m,e,t,l,d,a);if(v)return{heights:v,width:e.width,height:e.height,bounds:t};f=new Error(`${g} does not cover this place`)}catch(m){f=m}throw f}finer(t,e,i){if(t.width<xe.MESH_FROM_VERTICES||t.height<xe.MESH_FROM_VERTICES)return t;const n=(s,r)=>{const a=Math.ceil(s/xe.FINE_SPACING_M),c=Math.max(r-1,Math.min(xe.MAX_SEGMENTS,a));return c%2===0?c:c+1};return{width:n(e,t.width)+1,height:n(i,t.height)+1}}async raster(t,e,i){const n=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:i,STYLES:"",CRS:"EPSG:4326",BBOX:[t.south,t.west,t.north,t.east].map(r=>r.toFixed(6)).join(","),WIDTH:String(e.width),HEIGHT:String(e.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 Df.parse(await s.arrayBuffer())}async heights(t,e,i){const n=await this.raster(t,e,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(t,e,i,n){if(!(!n||n.length<2)&&!(!(t.values instanceof Float32Array)||!t.values.some(s=>s>xe.NO_DATA_BELOW)))try{const s=(await this.geoplatform.elevatedRoadLines({west:e.west,south:e.south,east:e.east,north:e.north})).filter(a=>ba.follows(n,a));if(s.length===0)return;const r=Float32Array.from(t.values);await this.layClassifiedDecks(t,e,i,s),this.layRouteDecks(t,r,e,s)}catch{}}async layClassifiedDecks(t,e,i,n){try{const s=await this.raster(e,i,xe.CLASS_LAYER);if(s.samples<3||s.width!==t.width||s.height!==t.height)return;const r=(m,[v,y,x])=>s.values[m*s.samples]===v&&s.values[m*s.samples+1]===y&&s.values[m*s.samples+2]===x,a=t.width,c=t.height,l=new Uint8Array(a*c);let h=!1;for(let m=0;m<l.length;m++)r(m,xe.DECK)&&(l[m]=1,h=!0);if(!h)return;const u=xe.DECK_END_PIXELS,d=[];for(let m=0;m<l.length;m++){if(l[m]!==1)continue;const v=m%a,y=(m-v)/a;for(let x=-u;x<=u;x++)for(let M=-u;M<=u;M++){const b=v+M,S=y+x;if(b<0||S<0||b>=a||S>=c)continue;const E=S*a+b;l[E]===0&&r(E,xe.NO_CLASS)&&d.push(E)}}for(const m of d)l[m]=1;const f=this.paint(n,e,a,c),p=this.touching(l,f,a,c);if(p.every(m=>m===0))return;const g=await this.heights(e,i,xe.SURFACE_LAYER);if(g.width!==a||g.height!==c)return;for(let m=0;m<p.length;m++){if(p[m]===0)continue;const v=g.values[m];Number.isFinite(v)&&v>xe.NO_DATA_BELOW&&v>t.values[m]&&(t.values[m]=v)}}catch{}}layRouteDecks(t,e,i,n){const{width:s,height:r}=t,a=(i.north+i.south)/2,c=(i.east-i.west)*xe.METRES_PER_DEGREE*Math.cos(a*Math.PI/180),l=(i.north-i.south)*xe.METRES_PER_DEGREE,h=c/s,u=l/r,d=v=>({x:(v.lng-i.west)/(i.east-i.west)*c,y:(i.north-v.lat)/(i.north-i.south)*l}),f=(v,y)=>{const x=Math.floor(v/h),M=Math.floor(y/u);if(x<0||M<0||x>=s||M>=r)return;const b=e[M*s+x];return Number.isFinite(b)&&b>xe.NO_DATA_BELOW?b:void 0},p=xe.DECK_HALF_WIDTH_M,g=xe.DECK_APPROACH_M,m=(v,y)=>{const x=Math.hypot(v.x-y.x,v.y-y.y)||1,M={x:(v.x-y.x)/x,y:(v.y-y.y)/x},b=[0,g/2,g].map(S=>f(v.x+M.x*S,v.y+M.y*S)).filter(S=>S!==void 0);return b.length>0?Math.max(...b):void 0};for(const v of xe.chains(n.map(y=>y.map(d)))){const y=[0];for(let I=1;I<v.length;I++)y.push(y[I-1]+Math.hypot(v[I].x-v[I-1].x,v[I].y-v[I-1].y));const x=y[y.length-1];if(x<1||x>xe.DECK_STRAIGHT_MAX_M)continue;const M=m(v[0],v[1]),b=m(v[v.length-1],v[v.length-2]);if(M===void 0||b===void 0)continue;const S=p+g,E=Math.max(0,Math.floor((Math.min(...v.map(I=>I.x))-S)/h)),w=Math.min(s-1,Math.ceil((Math.max(...v.map(I=>I.x))+S)/h)),_=Math.max(0,Math.floor((Math.min(...v.map(I=>I.y))-S)/u)),D=Math.min(r-1,Math.ceil((Math.max(...v.map(I=>I.y))+S)/u));for(let I=_;I<=D;I++)for(let O=E;O<=w;O++){const L=xe.nearestAlong(v,y,{x:(O+.5)*h,y:(I+.5)*u});if(L.distance>p||L.s<-g||L.s>x+g)continue;const N=M+(b-M)*Math.min(1,Math.max(0,L.s/x)),P=I*s+O;e[P]>=N||(t.values[P]=N)}}}static chains(t){const e=t.filter(s=>s.length>=2).map(s=>[...s]),i=[],n=(s,r)=>Math.hypot(s.x-r.x,s.y-r.y)<=1;for(;e.length>0;){let s=e.shift(),r=!0;for(;r;){r=!1;for(let a=0;a<e.length;a++){const c=e[a],l=s[0],h=s[s.length-1];if(n(h,c[0]))s=[...s,...c.slice(1)];else if(n(h,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else if(n(l,c[c.length-1]))s=[...c.slice(0,-1),...s];else if(n(l,c[0]))s=[...[...c].reverse().slice(0,-1),...s];else continue;e.splice(a,1),r=!0;break}}i.push(s)}return i}static nearestAlong(t,e,i){let n={s:0,distance:1/0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,l=a.y-r.y,h=c*c+l*l;if(h<1e-9)continue;let u=((i.x-r.x)*c+(i.y-r.y)*l)/h;s>0&&(u=Math.max(0,u)),s<t.length-2&&(u=Math.min(1,u));const d=Math.hypot(i.x-(r.x+c*u),i.y-(r.y+l*u));d<n.distance&&(n={s:e[s]+u*Math.sqrt(h),distance:d})}return n}paint(t,e,i,n){const s=new Uint8Array(i*n),r=c=>(c-e.west)/(e.east-e.west)*i,a=c=>(e.north-c)/(e.north-e.south)*n;for(const c of t)for(let l=0;l<c.length-1;l++){const h=r(c[l].lng),u=a(c[l].lat),d=r(c[l+1].lng),f=a(c[l+1].lat),p=Math.max(1,Math.ceil(Math.hypot(d-h,f-u)*2));for(let g=0;g<=p;g++){const m=Math.floor(h+(d-h)*g/p),v=Math.floor(u+(f-u)*g/p);for(let y=-1;y<=1;y++)for(let x=-1;x<=1;x++){const M=m+x,b=v+y;M>=0&&b>=0&&M<i&&b<n&&(s[b*i+M]=1)}}}return s}touching(t,e,i,n){const s=new Uint8Array(t.length),r=new Uint8Array(t.length);for(let a=0;a<t.length;a++){if(t[a]===0||r[a]===1)continue;const c=[],l=[a];r[a]=1;let h=!1;for(;l.length>0;){const u=l.pop();c.push(u),e[u]===1&&(h=!0);const d=u%i,f=(u-d)/i;for(let p=-1;p<=1;p++)for(let g=-1;g<=1;g++){const m=d+g,v=f+p;if(m<0||v<0||m>=i||v>=n)continue;const y=v*i+m;t[y]===1&&r[y]===0&&(r[y]=1,l.push(y))}}if(h)for(const u of c)s[u]=1}return s}sample(t,e,i,n,s,r){const{width:a,height:c}=e,l=new Float32Array(a*c),h=new Uint8Array(a*c),u=Math.min(r.x,this.maxWindowM)/s.x,d=Math.min(r.y,this.maxWindowM)/s.y;let f=0;for(let p=0;p<c;p++){const g=i.north+(i.south-i.north)*(c===1?.5:p/(c-1)),m=(n.north-g)/(n.north-n.south)*t.height-.5;for(let v=0;v<a;v++){const x=(i.west+(i.east-i.west)*(a===1?.5:v/(a-1))-n.west)/(n.east-n.west)*t.width-.5,M=u>1||d>1?this.tent(t,x,m,Math.max(1,u),Math.max(1,d)):this.bilinear(t,x,m),b=p*a+v;M===void 0?f++:(l[b]=M,h[b]=1)}}if(!(f===a*c||f/(a*c)>xe.MAX_HOLE_SHARE))return this.fill(l,h,a,c),l}tent(t,e,i,n,s){let r=0,a=0,c=0;const l=Math.max(0,Math.ceil(i-s)),h=Math.min(t.height-1,Math.floor(i+s)),u=Math.max(0,Math.ceil(e-n)),d=Math.min(t.width-1,Math.floor(e+n));for(let f=l;f<=h;f++){const p=1-Math.abs(f-i)/s;if(!(p<=0))for(let g=u;g<=d;g++){const m=p*(1-Math.abs(g-e)/n);if(m<=0)continue;c+=m;const v=t.at(g,f);!Number.isFinite(v)||v<xe.NO_DATA_BELOW||(r+=m*v,a+=m)}}return c>0&&a>=c*.5?r/a:void 0}bilinear(t,e,i){const n=Math.max(0,Math.min(t.width-1,Math.floor(e))),s=Math.max(0,Math.min(t.height-1,Math.floor(i))),r=Math.min(t.width-1,n+1),a=Math.min(t.height-1,s+1),c=Math.max(0,Math.min(1,e-n)),l=Math.max(0,Math.min(1,i-s)),h=t.at(n,s),u=t.at(r,s),d=t.at(n,a),f=t.at(r,a);for(const m of[h,u,d,f])if(!Number.isFinite(m)||m<xe.NO_DATA_BELOW)return;const p=h+(u-h)*c,g=d+(f-d)*c;return p+(g-p)*l}fill(t,e,i,n){let s=e.reduce((r,a)=>r+(a?0:1),0);for(;s>0;){const r=[];for(let a=0;a<n;a++)for(let c=0;c<i;c++){const l=a*i+c;if(e[l])continue;let h=0,u=0;for(let d=-1;d<=1;d++)for(let f=-1;f<=1;f++){const p=a+d,g=c+f;p<0||g<0||p>=n||g>=i||!e[p*i+g]||(h+=t[p*i+g],u++)}u>0&&r.push([l,h/u])}if(r.length===0)return;for(const[a,c]of r)t[a]=c,e[a]=1;s-=r.length}}}class rE{providers;constructor(...t){this.providers=t}async getElevationGrid(t,e,i){let n=new Error("No source of relief to ask");for(const s of this.providers)try{return await s.getElevationGrid(t,e,i)}catch(r){n=r}throw n}}const od=256,aE=5;async function zy(o,t,e,i){const n=(o.south+o.north)/2,s=(o.west+o.east)/2,r=Math.abs(ae(n,o.east,n,o.west).x),a=Math.abs(ae(o.north,s,o.south,s).z),c=Math.max(r,a),{zoom:l,gridSize:h}=oE(n,c,Math.max(t.width,t.height)),{tiles:u,bounds:d}=Fy(s,n,l,h),f=h*od,p=document.createElement("canvas");p.width=f,p.height=f;const g=p.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");const m=u[0];await Promise.all(u.map(async M=>{const b=e(M),S=await i(b);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${b}`);const E=await createImageBitmap(await S.blob());g.drawImage(E,(M.x-m.x)*od,(M.y-m.y)*od)}));const v=Math.min(Math.max(t.width,t.height),f);if(v===f)return{source:p,width:f,height:f,bounds:d};const y=document.createElement("canvas");y.width=v,y.height=v;const x=y.getContext("2d");if(!x)throw new Error("2D canvas context unavailable");return x.drawImage(p,0,0,f,f,0,0,v,v),{source:y,width:v,height:v,bounds:d}}function oE(o,t,e){let i=jS(o,t/Math.max(1,e)),n=ov(o,i,t);for(;n>aE&&i>0;)i--,n=ov(o,i,t);return{zoom:i,gridSize:n,mPerPixel:Ny(o,i)/od}}function ov(o,t,e){const i=Math.ceil(e/2/Ny(o,t));return Math.max(3,2*i+1)}class By{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(t,e){return zy(t,e,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class Zn{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(t,e=Zn.ENDPOINTS){const i=/\((-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\)/.exec(t);if(!i)return[...e];const[n,s,r,a]=i.slice(1).map(Number),c=(n+r)/2,l=(s+a)/2,h=Zn.FRANCE;return c>=h.south&&c<=h.north&&l>=h.west&&l<=h.east?[Zn.FRANCE_ENDPOINT,...e.filter(d=>d!==Zn.FRANCE_ENDPOINT)]:[...e]}fetchImpl;endpoints;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.endpoints=t.endpoints}static queue=Promise.resolve();static HANG_MS=4e4;static RETRY_MS=4e3;query(t){return this.queued(()=>this.ask(t))}queued(t){const e=Zn.queue.then(t,t);return Zn.queue=e.catch(()=>{}),e}async ask(t){let e;for(const i of this.endpoints??Zn.endpointsFor(t))for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(Zn.HANG_MS)});if(s.ok)return await s.json();if(e=new Error(`${new URL(i).host} refused (${s.status})`),s.status!==429&&s.status!==504)break}catch(s){e=new Error(`${new URL(i).host} unreachable (${String(s)})`);break}await new Promise(s=>setTimeout(s,Zn.RETRY_MS))}throw e??new Error("No Overpass instance answered")}}class wa{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(t={}){this.client=new Zn(t)}async getRoads(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];way["highway"~"^(${wa.DRIVABLE.join("|")})$"](${e});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(t){const e=[];for(const i of t.elements??[]){const n=i.geometry,s=i.tags;!s||!n||n.length<2||e.push({id:`osm-${i.id??e.length}`,name:s.name,surface:wa.surfaceOf(s),widthM:wa.widthOf(s),...wa.paintOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return e}static paintOf(t){const e=t.highway??"",i=t.junction==="roundabout"||t.junction==="circular",n=t.oneway,s=n==="yes"||n==="1"||n==="true"||n===void 0&&(e==="motorway"||i),r=n==="-1"||n==="reverse",a=Number.parseInt(t.lanes??"",10),c=Number.parseInt(t.maxspeed??"",10),l=i?"roundabout":e==="motorway"?"motorway":e.endsWith("_link")?"slip":(e==="trunk"||e==="primary")&&(s||r)?"dual":e?"road":void 0;return{...l?{kind:l}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...n!==void 0||e==="motorway"||i?{direction:r?"backward":s?"forward":"both"}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{}}}static widthOf(t){const e=Number.parseFloat(t.width??t.est_width??"");if(Number.isFinite(e)&&e>0)return e;const i=Number.parseInt(t.lanes??"",10);return Number.isFinite(i)&&i>0?i*3.5:wa.WIDTH_M[t.highway]??wa.DEFAULT_WIDTH_M}static surfaceOf(t){const e=t.surface;return e==="dirt"||e==="earth"||e==="mud"?"dirt":e==="gravel"||e==="fine_gravel"||e==="compacted"||e==="ground"||e==="sand"||e==="unpaved"?"gravel":e?"paved":t.highway==="track"?"gravel":"paved"}}const jf="https://ufoathome.org/roads/index.json";class Cc{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Cc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Roads © OpenStreetMap contributors"}get contemporary(){return this.contemporaryRead??this.fallback?.contemporary??!0}async getRoads(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRoads(t);return this.attributionRead=this.fallback.attribution,this.contemporaryRead=this.fallback.contemporary,i}async held(t){let e;try{e=await this.load()}catch{return}const i=e.find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2402
- `);let e=Cc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Cc.shared.set(t,e),e.then(i=>{i.length===0&&Cc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.144.0")}`,e=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(e&&e!==jf?[e,jf]:[jf]).map(i=>i+t)}}class _a{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(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRoads(t){return(await this.platform.roads(t)).flatMap((i,n)=>_a.wayOf(i,n))}static wayOf(t,e){if(t.geometry.type!=="LineString")return[];const i=t.geometry.coordinates.map(([d,f])=>({lat:f,lng:d}));if(i.length<2)return[];const n=String(t.properties.nature??""),s=_a.BY_NATURE[n]??_a.DEFAULT,r=Number(t.properties.largeur_de_chaussee),a=Number(t.properties.nombre_de_voies),c=Number(t.properties.vitesse_moyenne_vl),l=_a.DIRECTIONS[String(t.properties.sens_de_circulation??"")],h=_a.KINDS[n],u=[t.properties.cpx_toponyme_route_nommee,t.properties.nom_voie_ban_gauche,t.properties.nom_voie_ban_droite].find(d=>typeof d=="string"&&d.length>0);return[{id:String(t.properties.cleabs??`ign-${e}`),...u?{name:u}:{},surface:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.widthM,...t.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...l?{direction:l}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{},points:i}]}}class cE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(t){if(_a.covers(t))try{const e=await this.regional.getRoads(t);if(e.length>0)return e}catch{}return this.worldwide.getRoads(t)}}class Eh{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getWater(t){return(await this.platform.waterSurfaces(t)).flatMap((i,n)=>Eh.surfacesOf(i,n))}static surfacesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="Polygon"?[n]:i==="MultiPolygon"?n:[],r=String(t.properties.cleabs??`ign-water-${e}`);return s.flatMap((a,c)=>{const l=a.map(h=>Eh.open(h.map(u=>({lat:u[1],lng:u[0]})))).filter(h=>h.length>=3);return l.length>0?[{id:s.length>1?`${r}-${c}`:r,rings:l}]:[]})}static open(t){const e=t[0],i=t[t.length-1];return t.length>1&&e.lat===i.lat&&e.lng===i.lng?t.slice(0,-1):t}}class io{attribution="Water © OpenStreetMap contributors";client;constructor(t={}){this.client=new Zn(t)}async getWater(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];(way["natural"="water"](${e});way["waterway"="riverbank"](${e});)->.w;(relation["natural"="water"](${e});relation["waterway"="riverbank"](${e});)->.r;.w out geom;.r out body;way(r.r)(${e});out geom;`;return io.surfacesFrom(await this.client.query(i))}static surfacesFrom(t){const e=t.elements??[],i=new Map;for(const r of e)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 e){if(r.type!=="relation")continue;const a=l=>(r.members??[]).filter(h=>h.type==="way"&&h.role===l&&h.ref!==void 0&&i.has(h.ref)).map(h=>(s.add(h.ref),i.get(h.ref))),c=io.rings(a("inner"));for(const[l,h]of io.rings(a("outer")).entries()){const u=c.filter(d=>io.contains(h,d[0]));n.push({id:`osm-r${r.id}-${l}`,rings:[h,...u]})}}for(const r of e)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 io.rings([i.get(r.id)??[]]))n.push({id:`osm-w${r.id}`,rings:[a]});return n}static rings(t){const e=(s,r)=>s.lat===r.lat&&s.lng===r.lng,i=t.filter(s=>s.length>=2).map(s=>[...s]),n=[];for(;i.length>0;){let s=i.pop(),r=!0;for(;!e(s[0],s[s.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const c=i[a],l=s[s.length-1];if(e(l,c[0]))s=[...s,...c.slice(1)];else if(e(l,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}s.length>=4&&e(s[0],s[s.length-1])&&n.push(s.slice(0,-1))}return n}static contains(t,e){let i=!1;for(let n=0,s=t.length-1;n<t.length;s=n++){const r=t[n],a=t[s];r.lat>e.lat!=a.lat>e.lat&&e.lng<(a.lng-r.lng)*(e.lat-r.lat)/(a.lat-r.lat)+r.lng&&(i=!i)}return i}}class lE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(t){if(Eh.covers(t))try{const e=await this.regional.getWater(t);if(e.length>0)return e}catch{}return this.worldwide.getWater(t)}}const Qf="https://ufoathome.org/water/index.json";class Oc{attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Oc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Water © OpenStreetMap contributors"}async getWater(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getWater(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2403
- `);let e=Oc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Oc.shared.set(t,e),e.then(i=>{i.length===0&&Oc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.144.0")}`,e=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(e&&e!==Qf?[e,Qf]:[Qf]).map(i=>i+t)}}class Xn{constructor(t){this.water=t}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(t){const e=Xn.key(t);let i=Xn.asked.get(e);return i===void 0&&(i=this.recalled(e,t),Xn.asked.set(e,i),i.catch(()=>Xn.asked.delete(e))),structuredClone(await i)}static forget(){Xn.asked.clear()}static key(t){return`v${Xn.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}async recalled(t,e){const i=await Xn.openCache(),n=Xn.request(t);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:c}=await r.json();if(Date.now()-a<Xn.MAX_AGE_MS&&Array.isArray(c))return c;await i.delete(n)}}catch{}const s=await this.water.getWater(e);return i&&Xn.store(i,n,s),s}static async store(t,e,i){try{const n={savedAt:Date.now(),surfaces:i};await t.put(e,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await t.keys();for(const r of s.slice(0,Math.max(0,s.length-Xn.MAX_STORED)))await t.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Xn.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__water__/${encodeURIComponent(t)}`)}}class Ta{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(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRailways(t){return(await this.platform.railways(t)).flatMap((i,n)=>Ta.linesOf(i,n))}static linesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=Ta.BY_NATURE[String(t.properties.nature??"")];if(!r)return[];const a=String(t.properties.cleabs??`ign-rail-${e}`),c=Number(t.properties.nombre_de_voies),l=Number(t.properties.position_par_rapport_au_sol),h=t.properties.cpx_toponyme,u=Ta.GAUGE_MM[String(t.properties.largeur??"")]??1435,d=Ta.electrificationOf(r.kind,u,t.properties.electrifie);return s.flatMap((f,p)=>{const g=f.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>Ta.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.length>1?`${a}-${p}`:a,...typeof h=="string"&&h.length>0?{name:h}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:u,tracks:Number.isInteger(c)&&c>0?c:1,...d?{electrification:d}:{},level:Number.isFinite(l)?l:0,points:g}]})}static electrificationOf(t,e,i){if(i===!1)return"none";if(i===!0){if(t==="subway")return"third_rail";if(!(t==="funicular"||e<1435))return"overhead"}}}class pn{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(t={}){this.client=new Zn(t)}async named(t,e){if(t.length===0)return[...t];const i=`${e.south},${e.west},${e.north},${e.east}`,n=`[out:json][timeout:120];way["railway"~"^(${pn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${pn.ROUTES})$"];out body;`;return pn.apply(t,await this.client.query(n),e)}static apply(t,e,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=pn.ways(e,n);return s.length===0?[...t]:t.map(r=>{const a=r.points.map(v=>ae(v.lat,v.lng,n.lat,n.lng)),c=new Map,l=new Map,h=new Map;let u=0;const d=s.filter(v=>v.service===!!r.service);for(const v of pn.samples(a)){u++;const y=pn.waysAt(d,v);if(y.length===0)continue;const[x]=y;x.name&&c.set(x.name,(c.get(x.name)??0)+1),x.voltageV&&l.set(x.voltageV,(l.get(x.voltageV)??0)+1);for(const M of new Set(y.flatMap(b=>b.services)))h.set(M,(h.get(M)??0)+1)}const f=v=>[...v.entries()].sort((y,x)=>x[1]-y[1])[0]?.[0],p=r.name??f(c),g=r.voltageV??(r.electrification==="none"?void 0:f(l)),m=[...h.entries()].filter(([,v])=>v*4>=u).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...p?{name:p}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}static serviceOf(t){const e=t.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return e||[t.network,t.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(t){const e=new Map;for(const i of t.elements??[]){if(i.type!=="relation"||!i.tags)continue;const n=pn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=e.get(s.ref)??new Set;r.add(n),e.set(s.ref,r)}}return e}static voltageOf(t){const e=Number.parseInt((t.voltage??"").split(";")[0],10);return Number.isFinite(e)&&e>0?e:void 0}static ways(t,e){const i=pn.servicesByWay(t),n=[];for(const s of t.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=pn.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(c=>ae(c.lat,c.lon,e.lat,e.lng))})}return n}static samples(t){const e=[];for(let i=0;i<t.length-1;i++){const n=Math.hypot(t[i+1].x-t[i].x,t[i+1].z-t[i].z);if(n<1e-6)continue;const s=(t[i+1].x-t[i].x)/n,r=(t[i+1].z-t[i].z)/n;for(let a=pn.SAMPLE_M/2;a<n;a+=pn.SAMPLE_M)e.push({x:t[i].x+s*a,z:t[i].z+r*a,dx:s,dz:r})}return e}static waysAt(t,e){const i=Math.cos(pn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of t){let r;for(let a=0;a<s.path.length-1;a++){const c=s.path[a],l=s.path[a+1],h=l.x-c.x,u=l.z-c.z,d=Math.hypot(h,u);if(d<1e-6||Math.abs((h*e.dx+u*e.dz)/d)<i)continue;const f=Math.max(0,Math.min(1,((e.x-c.x)*h+(e.z-c.z)*u)/(d*d))),p=Math.hypot(e.x-(c.x+h*f),e.z-(c.z+u*f));p<=pn.NEAR_M&&(r===void 0||p<r)&&(r=p)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Pc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(t={}){this.client=new Zn(t)}async getRailways(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Pc.KINDS.join("|")})$"](${e})->.w;.w out tags geom;rel(bw.w)["route"~"^(${pn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(t){const e=[],i=pn.servicesByWay(t);for(const n of t.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(),c=pn.voltageOf(r),l=Pc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),u=Number.parseInt(r.tracks??"",10),d=Pc.electrificationOf(r.electrified),f=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;e.push({id:`osm-rail-${n.id??e.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...c?{voltageV:c}:{},kind:l,...r.service||r.usage==="industrial"?{service:!0}:{},...f?{highSpeed:!0}:{},gaugeMm:Number.isFinite(h)&&h>300?h:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(u)&&u>0?u:1,...d?{electrification:d}:{},level:Pc.levelOf(r),points:s.map(p=>({lat:p.lat,lng:p.lon}))})}return e}static kindOf(t){switch(t.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(t){if(t!==void 0){if(t==="no")return"none";if(t==="contact_line"||t==="yes")return"overhead";if(t==="rail"||t==="4th_rail"||t==="ground-level_power_supply")return"third_rail"}}static levelOf(t){const e=Number.parseInt(t.layer??"",10);return t.tunnel&&t.tunnel!=="no"?Number.isFinite(e)&&e<0?e:-1:t.covered==="yes"&&t.location==="underground"?-1:t.bridge&&t.bridge!=="no"?Number.isFinite(e)&&e>0?e:1:0}}class hE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(t){if(!Ta.covers(t))return this.worldwide.getRailways(t);let e;try{if(e=await this.regional.getRailways(t),e.length>0)return e}catch{}try{return await this.worldwide.getRailways(t)}catch(i){if(e)return e;throw i}}}class Xi{constructor(t,e=Date.now){this.railways=t,this.now=e}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(t){const e=Xi.key(t);let i=Xi.asked.get(e)??Xi.containing(t);if(i===void 0){const n=this.recalled(e,t);i={bounds:t,answer:n},Xi.asked.set(e,i),n.catch(()=>Xi.asked.delete(e))}return structuredClone(await i.answer)}static forget(){Xi.asked.clear(),Xi.failedAt=-1/0}static key(t){return`v${Xi.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}static containing(t){for(const e of Xi.asked.values()){const i=e.bounds;if(i.north>=t.north&&i.south<=t.south&&i.east>=t.east&&i.west<=t.west)return e}}async recalled(t,e){const i=await Xi.openCache(),n=Xi.request(t);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:c,lines:l}=await a.json();if(Array.isArray(l)){if(this.now()-c<Xi.MAX_AGE_MS)return l;s=l}}}catch{}if(this.now()-Xi.failedAt<Xi.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(e)}catch(a){if(Xi.failedAt=this.now(),s)return s;throw a}return i&&Xi.store(i,n,{savedAt:this.now(),lines:r}),r}static async store(t,e,i){try{await t.delete(e),await t.put(e,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const n=await t.keys();for(const s of n.slice(0,Math.max(0,n.length-Xi.MAX_STORED)))await t.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Xi.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__railways__/${encodeURIComponent(t)}`)}}const t0="https://ufoathome.org/railways/index.json";class Lc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Lc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRailways(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2404
- `);let e=Lc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Lc.shared.set(t,e),e.then(i=>{i.length===0&&Lc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.144.0")}`,e=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(e&&e!==t0?[e,t0]:[t0]).map(i=>i+t)}}function Hy(){return{elevation:uE(),imagery:Gy(),roads:dE(),water:fE(),railways:pE()}}function uE(){return new rE(new xe,new nE)}function Gy(){return new By}function dE(){return new Cc({fallback:new cE(new _a,new wa)})}function fE(){return new Oc({fallback:new Xn(new lE(new Eh,new io))})}function pE(){return new Lc({fallback:new Xi(new hE(new Ta,new Pc))})}const mE=new Set,Ar="show-observer-map",_r="hide-milestones",bo="minified";class Le extends HTMLElement{static get observedAttributes(){return["src",Ar,_r,bo]}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 Qe;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=Rf.create();issues=[];issueCheck=0;sightingAudio=new NS;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>Le.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Dy;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const t=this.controlsRow,e=t.classList.contains("more-open"),i=()=>t.scrollWidth>t.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,t.classList.remove("narrow","more-open","nomoments","compact","tiny"),t.clientWidth>0&&i()){t.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;t.classList.add(s)}e&&t.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(t){this.controlsRow.classList.toggle("more-open",!t),this.updateMoreButton()}updateMoreButton(){const t=this.controlsRow.classList.contains("more-open");Le.setIcon(this.moreButton,t?qt.UNFOLDED:qt.FOLDED);const e=t?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=e,this.moreButton.setAttribute("aria-label",e),this.moreButton.setAttribute("aria-expanded",String(t))}addControl(t){this.controlsRight.insertBefore(t,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=t=>{t.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=t=>{const e=this.canvasPointFromEvent(t),i=e&&this.shapeAt(e.x,e.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=`${t.clientX-s.left+12}px`,this.tooltip.style.top=`${t.clientY-s.top+12}px`};handleObserverMapPointerMove=t=>{if(this.dragObserverMap(t))return;const e=this.observerMapTargetFrom(t);if(!e){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(t,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(t,e.label)};showObserverMapTooltip(t,e){this.tooltip.textContent=e,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-i.left+12}px`,this.tooltip.style.top=`${t.clientY-i.top+12}px`}handleObserverMapClick=t=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const e=this.observerMapTargetFrom(t);if(!e){this.observerPlacing&&this.placeObserverFrom(t);return}if(e.kind==="milestone"&&e.t!==void 0){this.player.seek(e.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:e.lat,lng:e.lng,kind:e.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(t){const e=this.observerMapCanvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return this.observerMapRenderer.hitTest((t.clientX-e.left)/e.width*this.observerMapCanvas.width,(t.clientY-e.top)/e.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=t=>{t.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,moved:!1})};handleObserverMapPointerUp=t=>{const e=this.observerMapDrag;!e||e.pointerId!==t.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),e.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(t.pointerId)&&this.observerMapCanvas.releasePointerCapture(t.pointerId)))};dragObserverMap(t){const e=this.observerMapDrag;if(!e||e.pointerId!==t.pointerId)return!1;if(!e.moved){if(Math.hypot(t.clientX-e.startX,t.clientY-e.startY)<Le.OBSERVER_MAP_DRAG_PX)return!1;e.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(t.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((t.clientX-e.lastX)/i.width,(t.clientY-e.lastY)/i.height),this.observerMapViewChanged()),e.lastX=t.clientX,e.lastY=t.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=t=>{t.preventDefault();const e=this.observerMapCanvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=t.deltaMode===0?t.deltaY:t.deltaY*40;this.zoomObserverMap((t.clientX-e.left)/e.width,(t.clientY-e.top)/e.height,Math.exp(-i*.002))};zoomObserverMap(t,e,i){this.observerMapView.zoomAt(t,e,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=Qe.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=Qe.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Le.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(t){const e=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!e||i.width===0||i.height===0)return;const n=Qe.pointAt(e,(t.clientX-i.left)/i.width,(t.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 t=document.createElement("template");t.innerHTML=`<style>${TS}</style>${_S}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new ol(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 eo(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 e=this.shadow.getElementById("mini-bar"),i=e.querySelector(".mini-track"),n=a=>{const c=i.getBoundingClientRect(),l=this.player.seekableDuration;if(c.width<=0||l<=0)return;const h=Math.min(Math.max((a.clientX-c.left)/c.width,0),1)*l;this.player.seek(h),this.miniScrubTime.textContent=this.formatElapsedAt(h),this.miniScrubTime.style.left=this.miniDot.style.left};let s=!1;e.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),e.setPointerCapture(a.pointerId),e.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),e.addEventListener("pointermove",a=>{e.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{e.classList.contains("scrubbing")&&(e.classList.remove("scrubbing"),e.hasPointerCapture(a.pointerId)&&e.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&this.play())};e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r),e.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 t=this.getAttribute("src");t&&this.loadFromSrc(t)}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(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===Ar&&this.applyObserverMapDefault(),t===_r&&this.setMilestonesShown(!this.hasAttribute(_r)),t===bo){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&e===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(bo)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(Wy)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const t=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",t),t&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(t){this.sightingData=await Na.recording(t)}get sightingData(){return kS(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=FS(t),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(t,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(t){this.titleOverride=t,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const t=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=t,this.playerTitleBox.hidden=t===""}get recordingIssues(){return this.issues}async reportIssues(t,e){const i=++this.issueCheck;let n=[];try{const{default:s}=await we(async()=>{const{default:r}=await import("./sightingSchema-t3YCF0eV.js");return{default:r}},[],import.meta.url);n=new Ls(s).issues(t)}catch{}i===this.issueCheck&&(this.issues=[...n,...e.loadIssues],cl.warn(this.issues,e.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(gE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const t=this.issues.length;this.issuesBox.hidden=t===0,this.shadow.getElementById("issues-count").textContent=String(t);const e=this.messages.recordingIssues.replace("{count}",String(t));this.issuesButton.title=e,this.issuesButton.setAttribute("aria-label",e),this.shadow.getElementById("issues-title").textContent=e,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=cl.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(t){this.soundPreview=t,this.sightingAudio.resume(),this.sightingAudio.setSound(t)}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(t){this.player.seek(t)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(t){t!==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(t){if(t!==this.clockHeld){if(this.clockHeld=t,t){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(t){this.toolbar.classList.toggle("hidden",!t),t?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(t){this.currentSighting.event.durationSeconds=t,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(t){const e=new Set(t);e.size===this.highlightedSourceIds.size&&[...e].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=e,this.refresh())}hasVisibleShapeAt(t,e){return this.shapeAt(t,e)!==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(t){const e=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of e)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 t=this.currentSighting.references;!this.referenceOpacityTouched&&t.length>0&&(this.referenceOpacityInput.value=String(t[0].opacity));for(const e of[...this.referenceViews.keys()])t.some(i=>i.id===e)||this.referenceViews.delete(e);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(t){let e=this.referenceViews.get(t.id);return e||(e={shown:!0,opacity:t.opacity},this.referenceViews.set(t.id,e)),e}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=t=>{const e=t.composedPath();e.includes(this.referencesMenu)||e.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=t=>{t.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const t=this.referencesButton.getBoundingClientRect(),e=this.referencesMenu,i=4;e.style.bottom=`${Math.max(i,window.innerHeight-t.top+i)}px`,e.style.top="auto";const n=e.getBoundingClientRect().width;e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const t=this.currentSighting.references.map(e=>{const i=this.viewOfReference(e),n=this.said.read(e.title)??e.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 c=document.createElement("span");c.textContent=n,c.title=n,r.append(a,c);const l=document.createElement("input");return l.type="range",l.min="0",l.max="1",l.step="0.05",l.value=String(i.opacity),l.title=this.messages.referenceOpacity,l.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),l.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,l.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),l.addEventListener("input",()=>{i.opacity=Number(l.value),this.dispatchReferenceView()}),s.append(r,l),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...t)}updateReferencesButton(){const t=this.currentSighting.references.length>0,e=this.severalReferences,i=e?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState||e,this.referencesButton.setAttribute("aria-pressed",String(i)),e?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Le.setIcon(this.referencesButton,i?qt.PICTURES_ON:qt.PICTURES_OFF);const n=e?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)),Le.setIcon(this.tracesButton,this.tracesShownState?qt.TRACES_ON:qt.TRACES_OFF);const t=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=t,this.tracesButton.setAttribute("aria-label",t)}dispatchReferenceView(){const t=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(e=>[e.id,{...this.viewOfReference(e)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:t}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?ih(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...e.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/t,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(t,e.map(i=>i.t)),this.refreshMomentsPicker(e)}refreshMomentsPicker(t){const e=this.milestonesShown&&t.length>0;this.momentsBox.hidden=!e,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...t.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(t){const i=(t?this.said.read(t.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=t!==void 0&&Number(n.dataset.t)===t.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=t=>{if(!this.momentsMenu.hidden){if(t instanceof KeyboardEvent){t.key==="Escape"&&this.closeMomentsMenu();return}t.composedPath().some(e=>e===this.momentsMenu||e===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(t,e){const n=[0,...this.milestonesShown&&t>0?[...new Set(e.filter(r=>r>0&&r<t))].sort((r,a)=>r-a):[],Math.max(t,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 c=document.createElement("i");c.className="seek-hover";const l=document.createElement("i");l.className="seek-played",a.append(c,l),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:l,hover:c})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(t,e){const i=t.end-t.start,n=i>0?(e-t.start)/i:e>=t.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintMiniProgress(t){const e=this.player.seekableDuration,i=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(t)}miniDot;miniScrubTime;paintSeekProgress(t){for(const i of this.seekSegmentList)i.played.style.width=Le.fillOf(i,t);const e=this.player.seekableDuration;this.seekDot.style.left=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`}hoverSeek(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((f,p)=>{f.hover.style.width=Le.fillOf(f,s),f.element.classList.toggle("hovered",s>=f.start&&(s<f.end||p===r))});const a=this.milestonesShown?this.sighting.milestones:[],c=a.length>0?Zf(a,s):void 0,l=c?this.said.read(c.label)??"":"",h=c?this.said.read(c.note):void 0,u=h?`${l} — ${h}`:l;this.seekPreviewTitle.textContent=u,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const d=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*e.width-d/2,0),Math.max(e.width-d,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const t of this.seekSegmentList)t.hover.style.width="0",t.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(t){const e=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=e===void 0,e?.(t,this.seekPreviewCanvas)}paintChrome(t){const e=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(!e||typeof e.setTransform!="function"||n===0||s===0){t(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),c=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==c&&(this.chromeCanvas.height=c),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,a,c),this.chromeDirty=!1,i&&(e.setTransform(a/this.canvas.width,0,0,c/this.canvas.height,0,0),this.chromeRenderer??=new ol(e),this.chromeDirty=!0,t(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(t){if(t.pointerType!=="mouse"){this.scrubbingPointer=t.pointerId;try{this.seekInput.setPointerCapture(t.pointerId)}catch{}this.seekToPointer(t)}}touchScrub(t){t.pointerId===this.scrubbingPointer&&this.seekToPointer(t)}endTouchScrub(t){t.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(t))}seekToPointer(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(t){const e=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(e<=0||i<=0)return;const n=Le.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-t)>n||(!s||Math.abs(a-t)<Math.abs(s.t-t))&&(s={t:a,name:r.title})}return s}snapSeekToMark(t){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(t)?.t??t):t}nameMarkUnder(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=(t.clientX-e.left)/e.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(t){const e=this.milestonesShown&&this.sighting.milestones.length>0?Zf(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,this.showCurrentMoment(e),!e)return;const i=document.createElement("b");i.textContent=this.said.read(e.label)??"";const n=this.said.read(e.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(t){const e=this.exposureTimes(t),i=1/e.length;return e.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(t=this.currentTime){const e=Fs.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Le.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Le.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Le.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Le.EXPOSURE_STEP_PX),s=Math.min(Le.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(e.fromMs+e.ms*a/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,a]of i){const c=n.get(r);if(!c)continue;const l=c.bounds.x+c.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=c.bounds.y+c.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(l,h))}return s}shapeAt(t,e,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,t,e,i);if(s)return s}}shapesAt(t){const e=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}return e}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const t=Bi.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===t)return;this.canvas.width=t,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${t} / ${this.canvas.height}`)}canvasPointFromEvent(t){const e=this.canvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return{x:(t.clientX-e.left)/e.width*this.canvas.width,y:(t.clientY-e.top)/e.height*this.canvas.height}}onFrame(t,e){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:mE;this.canvasRenderer.setStarPoints(Bi.starPointsOf(this.sighting.instrument));const n=(ze(this.sighting,t)?.rollDeg??0)+this.gaitAt(t).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(t),r=this.frameShift;if(this.paintsShapes)for(const c of s)for(const[,l]of c.shapes){const h=c.share,u=h===1?l:{...l,transparency:1-(1-l.transparency)*h};this.canvasRenderer.paintShape(this.shifted(u,r))}for(const[c,l]of s[0].shapes)!this.selectionShown||!i.has(c)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...l,selected:!0}):this.canvasRenderer.paintMemberOutline(l):this.canvasRenderer.paintSelectionOnly(this.shifted(l,r)));const a=this.selectionShown&&i.size>1?hs.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds)):void 0;this.chromeDraw=c=>{a&&c.paintGroupHandles(a),this.overlayPainter?.(c)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(c=>[...c.shapes.values()].filter(l=>l.transparency<1).map(l=>this.shifted(l,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.paintSeekProgress(t),this.minified&&this.paintMiniProgress(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(wy(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:t}}))}shifted(t,e){return e.x===0&&e.y===0?t:{...t,bounds:{...t.bounds,x:t.bounds.x+e.x,y:t.bounds.y+e.y}}}createPlayer(){const t=new RS(this.currentSighting.timeline,(e,i)=>this.onFrame(e,i));return t.loop=this.loopEnabled,t.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},t}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=t=>{t.key.toLowerCase()!=="f"||t.altKey||t.ctrlKey||t.metaKey||!this.enableClickToPlay||t.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(t.preventDefault(),this.toggleFullscreen())};handleSeekKey=t=>{if(t.altKey||t.ctrlKey||t.metaKey)return;const e=t.key==="ArrowLeft"?-1:t.key==="ArrowRight"?1:0;if(e){t.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+e*Le.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.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 t=this.playbackFlash;t.innerHTML=this.player.playbackState==="playing"?qt.PLAY:qt.PAUSE,t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}static icons=new WeakMap;static setIcon(t,e){Le.icons.get(t)!==e&&(Le.icons.set(t,e),t.innerHTML=e)}set captionHeld(t){this.stageElement.classList.toggle("caption-held",t)}set controlsHeld(t){this.stageElement.classList.toggle("controls-held",t)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(t){this.quietControlsValue=t,this.stageElement.classList.toggle("quiet",t)}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},Le.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!t),t!==this.wasPlaying&&t&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=t,this.updateStartState(),Le.setIcon(this.playPauseButton,t?qt.PAUSE:qt.PLAY);const e=this.player.seekableDuration>0;this.playPauseButton.disabled=!e;const i=e?t?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 t=this.playbackBeforeClick;t&&(this.currentTime=t.time,t.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(t=>{console.error("<rr0-ufo>: requestFullscreen() failed —",t)})}enterSimulatedFullscreen(){const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=t.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const e=t.style;e.setProperty("position","fixed"),e.setProperty("inset","0"),e.setProperty("margin","0"),e.setProperty("max-width","none"),e.setProperty("max-height","none"),e.setProperty("aspect-ratio","auto"),e.setProperty("z-index","2147483647"),e.setProperty("background","#000"),e.setProperty("width","100vw"),e.setProperty("width","100dvw"),e.setProperty("height","100vh"),e.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 t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?t.setAttribute("style",this.styleBeforeSimulatedFullscreen):t.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const t=this.observerMapPanel.hidden;this.observerMapAsked=t,this.setObserverMapOpen(t),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:t}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const t=this.getAttribute(Ar),e=t===null?this.sighting.observerMap??this.observerPath?.travels===!0:t!=="false";this.setObserverMapOpen(e&&this.observerPath!==void 0)}setObserverMapOpen(t){this.observerMapPanel.hidden=!t,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(t)),this.updateObserverMapButton(),t&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const t=!this.observerMapPanel.hidden;Le.setIcon(this.observerMapButton,t?qt.MAP_ON:qt.MAP_OFF);const e=t?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e);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 t=this.observerPath!==void 0;if(this.observerPath=$c.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!t&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const e=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=Qe.fitted(this.observerPath,e);(!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(t,e){const i=Math.abs(t.east-t.west)/20;return Math.abs(t.north-e.north)<i&&Math.abs(t.south-e.south)<i&&Math.abs(t.west-e.west)<i&&Math.abs(t.east-e.east)<i}async loadObserverMapImagery(){const t=this.observerMapViewBounds;if(!t||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(t)))return;const e=this.observerMapView.changed,i=e?Qe.expand(t,Le.OBSERVER_MAP_IMAGERY_AHEAD):t,n=Qe.IMAGERY_PX*(e?1+2*Le.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=t.east-t.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:Gy();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(t){const e=this.observerMapImageryBounds;if(!e)return!0;const i=this.observerMapImagery?.bounds??e,n=this.observerMapView.changed?Qe.expand(t,Le.OBSERVER_MAP_IMAGERY_LOOKAHEAD):t,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=t.east-t.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(t){t!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=t,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(t){this.mapSceneBounds=t.map(e=>({x:e.x*this.canvas.width,y:e.y*this.canvas.height,width:e.width*this.canvas.width,height:e.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const t=this.observerMapBoxPx;if(!t)return;const e=[...this.mapShapeBounds,...this.mapSceneBounds],i=(l,h,u)=>{for(const d of e)if(!(d.x+d.width<l-u||d.x>h+u)&&!(d.y>t.bottom+u||d.y+d.height<t.top-u))return!0;return!1},n=[this.canvas.width-t.width,this.canvas.width],s=[0,t.width],r=Le.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&c&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(c||!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 t=this.observerMapPanel.clientWidth;if(t===0)return;const e=Math.round(t*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==e&&(this.observerMapCanvas.width=e,this.observerMapCanvas.height=e)}measureObserverMapBox(){const t=this.observerMapPanel.getBoundingClientRect(),e=this.canvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=this.canvas.width/e.width,n=this.canvas.height/e.height;this.observerMapBoxPx={width:t.width*i,top:(t.top-e.top)*n,bottom:(t.bottom-e.top)*n}}paintObserverMap(t){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const e=ze(this.currentSighting,t);e?.lat!==void 0&&e.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:e.lat,lng:e.lng},Le.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?Zf(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?ih(this.currentSighting.milestones):[]){const a=ze(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:e?.lat!==void 0&&e.lng!==void 0?{lat:e.lat,lng:e.lng}:void 0,headingDeg:e?.headingDeg===void 0?void 0:e.headingDeg+this.lookYawDeg,coneHalfAngleDeg:e?yr.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(Bi.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(t),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(t){this.milestonesShown=t,this.milestoneMarks.hidden=!t,this.momentsBox.hidden=!t||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,ih(this.sighting.milestones).map(e=>e.t)),this.milestonesButton.setAttribute("aria-pressed",String(t)),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,Le.setIcon(this.milestonesButton,this.milestonesShown?qt.MILESTONES_ON:qt.MILESTONES_OFF);const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=ze(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Er(i,t),{lat:s,lng:r}=fs(n.eastM,-n.northM,e.lat,e.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(t){const e=t===void 0?void 0:Math.max(0,Math.min(1,-t/12));e!==this.observerMapNightFraction&&(this.observerMapNightFraction=e,this.paintObserverMap(this.currentTime))}setLookOffset(t,e){t===this.lookYawDeg&&e===this.lookPitchDeg||(this.lookYawDeg=t,this.lookPitchDeg=e,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const t=this.gaitAt(this.currentTime),e=this.lookYawDeg+t.yawDeg,i=this.lookPitchDeg+t.pitchDeg;if(e===0&&i===0)return{x:0,y:0};const n=ze(this.currentSighting,this.currentTime),s=yr.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(e),y:s.angleDegToRadiusPx(i)}}gaitAt(t){return Xe.bodyAt(this.currentSighting,t,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(t){t!==this.mutedState&&(this.mutedState=t,!t&&this.volumeState===0&&(this.volumeState=Le.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(t){this.setVolume(t)}setVolume(t){this.volumeState=Math.min(Math.max(t,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 t=!this.hasSound;this.miniMuteButton.hidden=t,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Le.setIcon(this.miniMuteButton,this.mutedState?qt.MUTED:qt.VOLUME);const e=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=e,this.miniMuteButton.setAttribute("aria-label",e),this.muteButton.disabled=t,this.volumeInput.hidden=t,t){Le.setIcon(this.muteButton,qt.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Le.setIcon(this.muteButton,this.mutedState?qt.MUTED:qt.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 t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Le.setIcon(this.fullscreenButton,t?qt.EXIT_FULLSCREEN:qt.ENTER_FULLSCREEN),this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Es(ka.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=dg(ka.preferencesFor(this),fg);if(t===this.messagesLanguage||t==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=t;const e=await HS(t);this.messagesLanguage===t&&this.applyMessages(e)}messagesLanguage;updateTimeLabelTitles(){const t=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,e=this.canSwitchTimeDisplay?` — ${t}`:"";this.timeStartLabel.title=this.messages.currentPosition+e,this.timeEndLabel.title=this.messages.duration+e,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(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const t=this.currentSighting.event,e=by(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?Dp(t.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(t){if(this.realDurationMs===void 0)return oa(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?lv(cv(this.realStartMs+i)):oa(i)}formatElapsedAt(t){const e=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?oa(t):oa(e>0&&t<=e?t/e*this.realDurationMs:t)}formatRemaining(t){const e=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return oa(Math.max(0,e-t));const i=e>0&&t<=e?t/e*this.realDurationMs:t;return oa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?oa(this.currentSighting.timeline.duration):this.canShowClockTime?lv(cv(this.realStartMs+this.realDurationMs)):oa(this.realDurationMs)}}function cv(o){const t=new Date(o);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function lv(o){if(o.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return o.second?`${t(o.hour)}:${t(o.minute??0)}:${t(o.second)}`:`${t(o.hour)}:${t(o.minute??0)}`}function oa(o){const t=Math.round(o/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Pp="rr0-ufo";function Vy(){customElements.get(Pp)||customElements.define(Pp,Le)}const gE="recordingissues",Wy="minifiedreset";/**
2401
+ `)}`)}}class Ls{constructor(t){this.format=t}issues(t){const e=[];return this.object(t,this.format,"",e),e}object(t,e,i,n){if(!Ls.isObject(t)){n.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:Ls.typeOf(t)});return}for(const[s,r]of Object.entries(t)){const a=i?`${i}.${s}`:s,c=e[s];c?this.field(r,c,a,n):n.push({kind:"unknown-key",path:a})}}field(t,e,i,n){if(Ls.isStated(t)){this.field(t.value,e,i,n);return}if(!(e.loose||t===void 0||t===null))switch(e.type){case"enum":(typeof t!="string"||!e.values?.includes(t))&&n.push({kind:"not-in-list",path:i,expected:(e.values??[]).map(s=>`"${s}"`).join(", "),found:JSON.stringify(t)});return;case"object":e.fields?this.object(t,e.fields,i,n):Ls.isObject(t)||n.push({kind:"wrong-type",path:i,expected:"object",found:Ls.typeOf(t)});return;case"array":Array.isArray(t)?e.fields&&t.forEach((s,r)=>{const a=Ls.isStated(s)?s.value:s;this.object(a,e.fields,`${i}.${r}`,n)}):n.push({kind:"wrong-type",path:i,expected:"array",found:Ls.typeOf(t)});return;default:typeof t!==e.type&&n.push({kind:"wrong-type",path:i,expected:e.type,found:Ls.typeOf(t)})}}static isObject(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}static isStated(t){return Ls.isObject(t)&&"value"in t&&Object.keys(t).every(e=>e==="value"||e==="basis"||e==="rationale")}static typeOf(t){return Array.isArray(t)?"array":t===null?"null":typeof t}}class Fs{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(t,e){const i=Number.isFinite(e)?Math.max(0,e):0,n=Math.max(0,t-i*1e3),s=Math.max(0,t-n);return{fromMs:n,toMs:t,ms:s,seconds:s/1e3}}static instants(t,e,i,n,s){if(!(n>0))return 1;const r=s>0?Fs.travelDegOver(t,e,i,i+n*1e3)/s/Fs.PIXELS_PER_INSTANT:0,a=Fs.flashesOver(t,n)*Fs.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(r,a));return c<2?1:Math.min(Fs.MAX_INSTANTS,c)}static travelDegOver(t,e,i,n){let s=0;for(const r of t){if(!r.track||r.track.length<2)continue;const a=Fs.directionAt(r,e,i),c=Fs.directionAt(r,e,n),l=Math.min(1,Math.max(-1,a.x*c.x+a.y*c.y+a.z*c.z));s=Math.max(s,Math.acos(l)*180/Math.PI)}return s}static flashesOver(t,e){let i=0;for(const n of t)for(const s of n.lights??[])s.pattern.kind==="flash"&&(i=Math.max(i,s.pattern.perMinute));return i/60*e}static directionAt(t,e,i){const n=Er(t,i),s=n.eastM,r=n.altitudeM-e,a=n.northM,c=Math.hypot(s,r,a);return c===0?{x:0,y:1,z:0}:{x:s/c,y:r/c,z:a/c}}}const fg=["en","fr","es","it"],BS={en:()=>we(()=>Promise.resolve().then(()=>YS),void 0,import.meta.url).then(o=>o.ufoMessages_en),fr:()=>we(()=>import("./UfoMessages_fr-Cs2GCHEt.js"),[],import.meta.url).then(o=>o.ufoMessages_fr),es:()=>we(()=>import("./UfoMessages_es-BRCWkzr3.js"),[],import.meta.url).then(o=>o.ufoMessages_es),it:()=>we(()=>import("./UfoMessages_it-B2hvjhgb.js"),[],import.meta.url).then(o=>o.ufoMessages_it)};function HS(o){return BS[o]()}const GS={en:()=>we(()=>Promise.resolve().then(()=>kO),void 0,import.meta.url).then(o=>o.sightingMessages_en),fr:()=>we(()=>import("./SightingMessages_fr-1Wf0tZCS.js"),[],import.meta.url).then(o=>o.sightingMessages_fr),es:()=>we(()=>import("./SightingMessages_es-CLihvSau.js"),[],import.meta.url).then(o=>o.sightingMessages_es),it:()=>we(()=>import("./SightingMessages_it-BBpNT9oj.js"),[],import.meta.url).then(o=>o.sightingMessages_it)};function VS(o){return GS[o]()}const WS={en:()=>we(()=>Promise.resolve().then(()=>UO),void 0,import.meta.url).then(o=>o.shareMessages_en),fr:()=>we(()=>import("./ShareMessages_fr-DyOB2E5o.js"),[],import.meta.url).then(o=>o.shareMessages_fr),es:()=>we(()=>import("./ShareMessages_es-BM5hHumO.js"),[],import.meta.url).then(o=>o.shareMessages_es),it:()=>we(()=>import("./ShareMessages_it-C9F8UHk_.js"),[],import.meta.url).then(o=>o.shareMessages_it)};function XS(o){return WS[o]()}function $S(o){switch(o){case"fr":return we(()=>import("./TagNames_fr-Dnqq6HQ5.js"),[],import.meta.url).then(t=>t.tagNames_fr);case"es":return we(()=>import("./TagNames_es-BfnMpc3D.js"),[],import.meta.url).then(t=>t.tagNames_es);case"it":return we(()=>import("./TagNames_it-n6E4EGYO.js"),[],import.meta.url).then(t=>t.tagNames_it);default:return Promise.resolve({})}}function Iy(o){switch(o){case"fr":return we(()=>import("./SceneNames_fr-DixomaFq.js"),[],import.meta.url).then(t=>t.sceneNames_fr);case"es":return we(()=>import("./SceneNames_es-CPCIUfgZ.js"),[],import.meta.url).then(t=>t.sceneNames_es);case"it":return we(()=>import("./SceneNames_it-BTNeU7-M.js"),[],import.meta.url).then(t=>t.sceneNames_it);default:return Promise.resolve(void 0)}}const Dy={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:cl.EN},YS=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Dy},Symbol.toStringTag,{value:"Module"})),Cy=Math.PI/180,qS=180/Math.PI,KS=256,Oy=19,ZS=1.25;function Py(o,t){return 156543.03392*Math.cos(o*Cy)/2**t}function Ly(o,t){return Py(o,t)*KS}function JS(o,t){let e=0;for(;e<Oy&&Ly(o,e+1)>=t;)e++;return e}function Ny(o,t){return Ly(o,t)}function jS(o,t){const e=t*ZS;let i=0;for(;i<Oy&&Py(o,i)>e;)i++;return i}function ad(o){const t=o*Cy;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}function ky(o,t,e){const i=2**e;return{x:(o+180)/360*i,y:ad(t)*i}}function Uy(o,t,e){const i=ad(o.north),n=ad(o.south);return{x:(t-o.west)/(o.east-o.west),y:(ad(e)-i)/(n-i)}}function QS(o,t,e){const{x:i,y:n}=ky(o,t,e);return{x:Math.floor(i),y:Math.floor(n),z:e}}function tE(o){const t=2**o.z,e=o.x/t*360-180,i=(o.x+1)/t*360-180,n=rv(o.y,t);return{south:rv(o.y+1,t),north:n,west:e,east:i}}function rv(o,t){const e=o/t;return Math.atan(Math.sinh(Math.PI*(1-2*e)))*qS}function Fy(o,t,e,i){const n=QS(o,t,e),s=Math.floor(i/2),r=[];for(let l=-s;l<=s;l++)for(let h=-s;h<=s;h++)r.push({x:n.x+h,y:n.y+l,z:e});const a=r.map(tE),c={south:Math.min(...a.map(l=>l.south)),north:Math.max(...a.map(l=>l.north)),west:Math.min(...a.map(l=>l.west)),east:Math.max(...a.map(l=>l.east))};return{tiles:r,bounds:c}}const eE="#2ec4ff";class eo{constructor(t){this.ctx=t}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(t,e){let i,n=1/0;for(const s of this.targets){const r=Math.hypot(s.x-t,s.y-e);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(t){const{ctx:e}=this;e.save(),this.targets=[],e.clearRect(0,0,this.width,this.height),this.paintGround(t),this.paintNight(t.nightFraction),this.paintPath(t),this.paintTraces(t),t.position?(this.paintCone(t,t.position),this.paintDecor(t),this.paintMarkers(t),this.paintObserver(t,t.position)):(this.paintDecor(t),this.paintMarkers(t)),this.paintNorth(),this.paintFooter(t.bounds,t.attribution),e.restore()}toCanvas(t,e,i){const n=Uy(t,i,e);return{x:n.x*this.width,y:n.y*this.height}}paintGround(t){const{ctx:e}=this;e.fillStyle="#1d2321",e.fillRect(0,0,this.width,this.height);const i=t.imagery;if(!i)return;const n=this.toCanvas(t.bounds,i.bounds.north,i.bounds.west),s=this.toCanvas(t.bounds,i.bounds.south,i.bounds.east);e.drawImage(i.source,n.x,n.y,s.x-n.x,s.y-n.y)}paintNight(t=0){if(t<=0)return;const{ctx:e}=this;e.save(),e.fillStyle=`rgba(6, 12, 30, ${Math.min(t,1)*.78})`,e.fillRect(0,0,this.width,this.height),e.restore()}paintDecor(t){const{ctx:e}=this;for(const i of t.decor){const n=this.toCanvas(t.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}),e.beginPath(),e.rect(n.x-3.5,n.y-3.5,7,7),e.fillStyle="rgba(120, 220, 255, 0.85)",e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.7)",e.stroke(),i.headingDeg===void 0)continue;const s=(i.headingDeg-90)*Math.PI/180;e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(n.x+Math.cos(s)*10,n.y+Math.sin(s)*10),e.lineWidth=3,e.strokeStyle="rgba(0, 0, 0, 0.6)",e.stroke(),e.lineWidth=1.5,e.strokeStyle="rgba(120, 220, 255, 0.9)",e.stroke()}}paintPath(t){if(!t.path.moved)return;const{ctx:e}=this,i=t.path.points.map(n=>this.toCanvas(t.bounds,n.lat,n.lng));e.beginPath(),e.moveTo(i[0].x,i[0].y);for(const n of i.slice(1))e.lineTo(n.x,n.y);e.lineJoin="round",e.lineCap="round",e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=5,e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.9)",e.lineWidth=2,e.stroke()}paintTraces(t){const{ctx:e}=this;for(const i of t.traces??[]){const n=i.points.map(r=>this.toCanvas(t.bounds,r.lat,r.lng));if(n.length===0)continue;const s=i.color??eE;if(i.kind==="point")e.beginPath(),e.moveTo(n[0].x,n[0].y-6),e.lineTo(n[0].x+6,n[0].y),e.lineTo(n[0].x,n[0].y+6),e.lineTo(n[0].x-6,n[0].y),e.closePath(),e.fillStyle=s,e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.8)",e.stroke();else{e.beginPath(),e.moveTo(n[0].x,n[0].y);for(const r of n.slice(1))e.lineTo(r.x,r.y);i.kind==="polygon"&&e.closePath(),e.lineJoin="round",e.setLineDash([]),e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=4.5,e.stroke(),e.setLineDash([9,5]),e.strokeStyle=s,e.lineWidth=2.5,e.stroke(),e.setLineDash([])}if(i.label){e.font="11px sans-serif",e.textAlign="left",e.textBaseline="middle";let r=n[0];if(i.kind==="line"&&t.position){const a=this.toCanvas(t.bounds,t.position.lat,t.position.lng);r=n.reduce((c,l)=>Math.hypot(l.x-a.x,l.y-a.y)>Math.hypot(c.x-a.x,c.y-a.y)?l:c)}this.paintOutlinedText(i.label,r.x+9,r.y-9)}}}paintCone(t,e){const{headingDeg:i,coneHalfAngleDeg:n}=t;if(i===void 0||n===void 0)return;const{ctx:s}=this,r=this.toCanvas(t.bounds,e.lat,e.lng),a=Math.hypot(this.width,this.height),c=(i-90)*Math.PI/180,l=n*Math.PI/180;s.save(),s.beginPath(),s.moveTo(r.x,r.y),s.arc(r.x,r.y,a,c-l,c+l),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(t){const{ctx:e}=this;e.textAlign="center",e.textBaseline="middle",e.font="bold 10px sans-serif";for(const i of[...t.markers].sort((n,s)=>Number(n.current)-Number(s.current))){const n=this.toCanvas(t.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:eo.MARKER_RADIUS_PX}),e.beginPath(),e.arc(n.x,n.y,eo.MARKER_RADIUS_PX,0,Math.PI*2),e.fillStyle=i.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",e.fill(),e.lineWidth=2,e.strokeStyle="rgba(255, 255, 255, 0.9)",e.stroke(),e.fillStyle=i.current?"#1d2321":"#fff",e.fillText(i.label,n.x,n.y)}}paintObserver(t,e){const{ctx:i}=this,n=this.toCanvas(t.bounds,e.lat,e.lng);t.observerLabel&&this.targets.push({kind:"observer",label:t.observerLabel,lat:e.lat,lng:e.lng,x:n.x,y:n.y,radius:8});const s=t.markers.some(r=>{if(!r.current)return!1;const a=ae(r.lat,r.lng,e.lat,e.lng);return Math.hypot(a.x,a.z)<=eo.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?eo.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:t}=this,e=this.width-14,i=16;t.beginPath(),t.moveTo(e,i-9),t.lineTo(e-4.5,i+5),t.lineTo(e,i+2),t.lineTo(e+4.5,i+5),t.closePath(),t.fillStyle="rgba(255, 255, 255, 0.92)",t.strokeStyle="rgba(0, 0, 0, 0.6)",t.lineWidth=1,t.fill(),t.stroke(),t.font="bold 9px sans-serif",t.textAlign="center",t.textBaseline="top",t.strokeText("N",e,i+6),t.fillText("N",e,i+6)}paintFooter(t,e){const{ctx:i}=this;i.font="9px sans-serif",i.textBaseline="bottom";const n=e?this.wrap(e,this.width-20):[];let s=this.height-4;i.textAlign="right";for(const f of n.slice().reverse())this.paintOutlinedText(f,this.width-6,s),s-=11;const r=(t.south+t.north)/2,c=Math.abs(ae(r,t.east,r,t.west).x)/this.width,l=eo.SCALE_STEPS_M.find(f=>f/c<=this.width/3);if(l===void 0)return;const h=l/c,u=8,d=s-3;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.6)",i.beginPath(),i.moveTo(u,d),i.lineTo(u+h,d),i.stroke(),i.lineWidth=1.5,i.strokeStyle="rgba(255, 255, 255, 0.95)",i.stroke(),i.textAlign="left",this.paintOutlinedText(l>=1e3?`${l/1e3} km`:`${l} m`,u,d-3)}paintOutlinedText(t,e,i){const{ctx:n}=this;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.75)",n.strokeText(t,e,i),n.fillStyle="#fff",n.fillText(t,e,i)}wrap(t,e){const i=[];let n="";for(const s of t.split(" ")){const r=n?`${n} ${s}`:s;n&&this.ctx.measureText(r).width>e?(i.push(n),n=s):n=r}return n&&i.push(n),i}}class Qe{static MIN_ZOOM=.25;static MAX_ZOOM=64;static MIN_SPAN_M=400;static MARGIN=.6;static IMAGERY_PX=768;static fitted(t,e){return Qe.including(t.boundsAround(Qe.MIN_SPAN_M,Qe.MARGIN),e)}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(t,e,i){const n=Math.min(Qe.MAX_ZOOM,Math.max(Qe.MIN_ZOOM,this.zoom*i)),s=this.centerX+(t-.5)/this.zoom,r=this.centerY+(e-.5)/this.zoom;this.centerX=s-(t-.5)/n,this.centerY=r-(e-.5)/n,this.zoom=n}panBy(t,e){this.centerX-=t/this.zoom,this.centerY-=e/this.zoom}refit(t,e){if(!this.changed)return;const i=this.boundsWithin(t),n=Qe.mercatorY01(e.north),s=Qe.mercatorY01(e.south),r=Qe.mercatorY01(i.north),a=Qe.mercatorY01(i.south);this.zoom=(e.east-e.west)/(i.east-i.west),this.centerX=((i.west+i.east)/2-e.west)/(e.east-e.west),this.centerY=((r+a)/2-n)/(s-n)}keepInView(t,e,i){if(!this.changed)return!1;const n=this.boundsWithin(t),s=Qe.mercatorY01(n.north),r=Qe.mercatorY01(n.south),a=(e.lng-n.west)/(n.east-n.west),c=(Qe.mercatorY01(e.lat)-s)/(r-s);return a>=i&&a<=1-i&&c>=i&&c<=1-i?!1:(this.panBy(.5-a,.5-c),!0)}boundsWithin(t){if(!this.changed)return t;const e=.5/this.zoom,i=Qe.mercatorY01(t.north),n=Qe.mercatorY01(t.south),s=t.east-t.west;return{west:t.west+(this.centerX-e)*s,east:t.west+(this.centerX+e)*s,north:Qe.latitudeAt(i+(this.centerY-e)*(n-i)),south:Qe.latitudeAt(i+(this.centerY+e)*(n-i))}}static including(t,e,i=3){const n=(t.north+t.south)/2,s=(t.east+t.west)/2,r=ae(n,t.east,n,s).x;let a=r;for(const c of e){const{x:l,z:h}=ae(c.lat,c.lng,n,s),u=Math.max(Math.abs(l),Math.abs(h));u<=r*i&&(a=Math.max(a,u*1.15))}return a<=r?t:{north:fs(0,-a,n,s).lat,south:fs(0,a,n,s).lat,east:fs(a,0,n,s).lng,west:fs(-a,0,n,s).lng}}static expand(t,e){const i=t.east-t.west,n=t.north-t.south;return{west:t.west-i*e,east:t.east+i*e,south:t.south-n*e,north:t.north+n*e}}static pointAt(t,e,i){const n=Qe.mercatorY01(t.north),s=Qe.mercatorY01(t.south);return{lat:Qe.latitudeAt(n+i*(s-n)),lng:t.west+e*(t.east-t.west)}}static mercatorY01(t){const e=t*Math.PI/180;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}static latitudeAt(t){return Math.atan(Math.sinh(Math.PI*(1-2*t)))*180/Math.PI}}const Ms=256,av=3,iE=32768;class nE{fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(t,e){const i=(t.south+t.north)/2,n=(t.west+t.east)/2,s=Math.abs(ae(i,t.east,i,t.west).x),r=Math.abs(ae(t.north,n,t.south,n).z),a=JS(i,Math.max(s,r)),{tiles:c}=Fy(n,i,a,av),l=av*Ms,h=new Float32Array(l*l),u=c[0];await Promise.all(c.map(f=>this.decodeTileInto(f,u,h,l)));const d=new Float32Array(e.width*e.height);for(let f=0;f<e.height;f++){const p=t.north+(t.south-t.north)*(f/(e.height-1));for(let g=0;g<e.width;g++){const m=t.west+(t.east-t.west)*(g/(e.width-1));d[f*e.width+g]=this.sampleAt(p,m,a,u,h,l)}}return{heights:d,width:e.width,height:e.height,bounds:t}}async decodeTileInto(t,e,i,n){const s=this.tileUrlTemplate.replace("{z}",String(t.z)).replace("{x}",String(t.x)).replace("{y}",String(t.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()),c=document.createElement("canvas");c.width=Ms,c.height=Ms;const l=c.getContext("2d");if(!l)throw new Error("2D canvas context unavailable");l.drawImage(a,0,0);const{data:h}=l.getImageData(0,0,Ms,Ms),u=(t.x-e.x)*Ms,d=(t.y-e.y)*Ms;for(let f=0;f<Ms;f++)for(let p=0;p<Ms;p++){const g=(f*Ms+p)*4,m=h[g]*256+h[g+1]+h[g+2]/256-iE,v=u+p,y=d+f;i[y*n+v]=m}}sampleAt(t,e,i,n,s,r){const{x:a,y:c}=ky(e,t,i),l=(a-n.x)*Ms,h=(c-n.y)*Ms,u=Math.max(0,Math.min(r-1,Math.floor(l))),d=Math.max(0,Math.min(r-1,Math.floor(h))),f=Math.min(r-1,u+1),p=Math.min(r-1,d+1),g=l-u,m=h-d,v=s[d*r+u],y=s[d*r+f],x=s[p*r+u],M=s[p*r+f],b=v+(y-v)*g,S=x+(M-x)*g;return b+(S-b)*m}}class Df{constructor(t,e,i,n){this.width=t,this.height=e,this.samples=i,this.values=n}at(t,e,i=0){return this.values[(e*this.width+t)*this.samples+i]}static parse(t){const e=new DataView(t);if(t.byteLength<8||e.getUint16(0)!==18761||e.getUint16(2,!0)!==42)throw new Error("Not a little-endian TIFF");const i=e.getUint32(4,!0),n=e.getUint16(i,!0),s=new Map;for(let v=0;v<n;v++){const y=i+2+v*12;s.set(e.getUint16(y,!0),{type:e.getUint16(y+2,!0),count:e.getUint32(y+4,!0),value:e.getUint32(y+8,!0)})}const r=(v,y)=>{const x=s.get(v);if(x===void 0){if(y===void 0)throw new Error(`TIFF without tag ${v}`);return y}return x.type===3?x.value&65535:x.value},a=v=>{const y=s.get(v);if(y===void 0)throw new Error(`TIFF without tag ${v}`);const x=y.type===3?2:4,M=[];if(y.count*x<=4){const b=new DataView(new ArrayBuffer(4));b.setUint32(0,y.value,!0);for(let S=0;S<y.count;S++)M.push(x===2?b.getUint16(S*2,!0):b.getUint32(0,!0))}else for(let b=0;b<y.count;b++)M.push(x===2?e.getUint16(y.value+b*2,!0):e.getUint32(y.value+b*4,!0));return M};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(s.has(322))throw new Error("Tiled TIFF");const c=r(256),l=r(257),h=r(277,1),u=a(258)[0],d=r(339,1)===3;if(!(d&&u===32||!d&&u===8))throw new Error(`Unsupported TIFF samples: ${u} bits`);const f=a(273),p=a(279),g=new Uint8Array(c*l*h*(u/8));let m=0;for(let v=0;v<f.length&&m<g.length;v++){const y=Math.min(p[v],g.length-m);g.set(new Uint8Array(t,f[v],y),m),m+=y}if(m<g.length)throw new Error("Truncated TIFF");return new Df(c,l,h,d?new Float32Array(g.buffer):g)}}class aa extends Error{constructor(t,e){super(e),this.reason=t,this.name="SurroundingsUnavailableError"}}class sE{constructor(t,e,i,n,s){this.heights=t,this.plants=e,this.buildings=i,this.size=n,this.metresPerPixel=s}structureAt(t,e){const i=Math.floor(t/this.metresPerPixel+this.size/2),n=Math.floor(this.size/2-e/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(t,e,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 c=this.structureAt(t+a*this.metresPerPixel,e+r*this.metresPerPixel);c!==void 0&&(n===void 0||c>n)&&(n=c)}return n}}class Re{static covers(t,e){return t>=41.2&&t<=51.3&&e>=-5.4&&e<=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(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??Re.WMS,this.wfs=t.wfsEndpoint??Re.WFS}static radius(t){return Math.min(t,Re.MAX_RADIUS_M)}static lidarRadius(t){return Math.min(t,Re.MAX_LIDAR_RADIUS_M)}async lidar(t,e){const i=Re.lidarRadius(e),n=Math.ceil(2*i/Re.METRES_PER_PIXEL),[s,r]=await Promise.all([this.raster(t,i,n,Re.HEIGHT_LAYER),this.raster(t,i,n,Re.CLASS_LAYER)]);if(s.samples!==1||r.samples<3)throw new aa("unreachable","The survey answered in a layout this does not read");const a=s.values;if(a.every(u=>u===Re.NO_DATA))throw new aa("no-coverage","No LiDAR HD survey here yet");const c=new Uint8Array(n*n),l=new Uint8Array(n*n);for(let u=0;u<n*n;u++){const d=r.values[u*r.samples],f=r.values[u*r.samples+1],p=r.values[u*r.samples+2];c[u]=f>d&&f>p?1:0,l[u]=d>120&&f<90&&p<90?1:0}const h=2*i/n;return{size:n,metresPerPixel:h,heights:a,vegetation:c,building:l,structures:new sE(a,c,l,n,h)}}async laserDate(t){return Re.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",t))}async photoDate(t){return Re.latest(await this.dated("ORTHOIMAGERY.ORTHOPHOTOS.GRAPHE-MOSAIQUAGE:graphe_bdortho","geom","date_vol",t))}static latest(t){return t.map(i=>/^\d{4}-\d{2}-\d{2}/.exec(String(i??""))?.[0]).filter(i=>i!==void 0).sort().at(-1)}async dated(t,e,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(t,`BBOX(${e},${r},'EPSG:4326')`,i,20)).map(a=>a.properties[i])}catch{return[]}}async photo(t,e){const i=Re.radius(e),n=Math.min(Re.MAX_PHOTO_PIXELS,Math.ceil(2*i/Re.METRES_PER_PIXEL)),s=await this.raster(t,i,n,Re.PHOTO_LAYER);if(s.samples<3)throw new aa("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(t,e,i){const n=Re.radius(e),s=n/Re.METRES_PER_DEGREE,r=n/(Re.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),c=`BBOX(geometrie,${[t.lng-r,t.lat-s,t.lng+r,t.lat+s].map(v=>v.toFixed(6)).join(",")},'EPSG:4326')`,[l,h,u,d,f,p]=await Promise.all([this.features("construction_lineaire",`${c} AND nature='Pont'`,"nature,geometrie"),this.features("troncon_de_route",`${c} 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",`${c} AND position_par_rapport_au_sol>'0'`,"position_par_rapport_au_sol,geometrie").catch(()=>[]),this.features("ligne_electrique",c,"voltage,geometrie"),i?this.features("batiment",c,Re.BUILDING_PROPERTIES,5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",c,"toponyme,categorie,geometrie",100).catch(()=>[]):Promise.resolve([])]),g=i?await this.wholeWorship(p,f,[t.lng-r,t.lat-s,t.lng+r,t.lat+s]):[],m=[...f,...g];return{bridges:l,elevatedRoads:h,elevatedRailways:u,lines:d,buildings:m,zones:p,mapDate:Re.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(t,e,i){const[n,s,r,a]=i,c=Re.MAX_WHOLE_M/Re.METRES_PER_DEGREE;let l;for(const u of t){if(u.properties.categorie!=="Religieux")continue;const[d,f,p,g]=Re.extent(u);if(d>=n&&f>=s&&p<=r&&g<=a)continue;const m=[Math.max(d,n-c),Math.max(f,s-c),Math.min(p,r+c),Math.min(g,a+c)];l=l?[Math.min(l[0],m[0]),Math.min(l[1],m[1]),Math.max(l[2],m[2]),Math.max(l[3],m[3])]:m}if(!l)return[];const h=new Set(e.map(u=>u.properties.cleabs));try{return(await this.features("batiment",`BBOX(geometrie,${l.map(d=>d.toFixed(6)).join(",")},'EPSG:4326')`,Re.BUILDING_PROPERTIES,1e3)).filter(d=>!h.has(d.properties.cleabs))}catch{return[]}}static extent(t){let e=1/0,i=1/0,n=-1/0,s=-1/0;const r=a=>{Array.isArray(a)&&typeof a[0]=="number"?(e=Math.min(e,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(t.geometry.coordinates),[e,i,n,s]}async elevatedRoadLines(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(s=>s.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${e} AND position_par_rapport_au_sol>'0'`,"geometrie",300),n=[];for(const s of i){const{type:r,coordinates:a}=s.geometry,c=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const l of c)n.push(l.map(h=>({lat:h[1],lng:h[0]})))}return n}async waterSurfaces(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("surface_hydrographique",`${e} AND position_par_rapport_au_sol='0' AND persistance='Permanent'`,"cleabs,nature,geometrie",500)}async roads(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_route",`${e} 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(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_voie_ferree",`${e} 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(t,e,i,n){const s=e/Re.METRES_PER_DEGREE,r=e/(Re.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:n,STYLES:"",CRS:"EPSG:4326",BBOX:[t.lat-s,t.lng-r,t.lat+s,t.lng+r].map(l=>l.toFixed(6)).join(","),WIDTH:String(i),HEIGHT:String(i),FORMAT:"image/geotiff"});let c;try{c=await this.fetchImpl(`${this.wms}?${a}`)}catch(l){throw new aa("unreachable",l instanceof Error?l.message:String(l))}if(!c.ok)throw new aa("unreachable",`The survey answered ${c.status}`);try{return Df.parse(await c.arrayBuffer())}catch(l){throw new aa("unreachable",l instanceof Error?l.message:String(l))}}async features(t,e,i,n=200){const s=new URLSearchParams({SERVICE:"WFS",VERSION:"2.0.0",REQUEST:"GetFeature",TYPENAMES:t.includes(":")?t:`BDTOPO_V3:${t}`,SRSNAME:"EPSG:4326",OUTPUTFORMAT:"application/json",COUNT:String(n),CQL_FILTER:e,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${s}`)}catch(c){throw new aa("unreachable",c instanceof Error?c.message:String(c))}if(!r.ok)throw new aa("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class ba{static NEAR_M=15;static ALIGNED_DEG=30;static LONG_ENOUGH_M=15;static SAMPLE_M=5;static follows(t,e){if(t.length<2||e.length<2)return!1;const i=e[0],n=e.map(a=>ae(a.lat,a.lng,i.lat,i.lng)),s=t.map(a=>ae(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<s.length-1;a++){const c=s[a],l=s[a+1],h=Math.hypot(l.x-c.x,l.z-c.z);if(h<1e-6)continue;const u=Math.max(1,Math.ceil(h/ba.SAMPLE_M)),d=Math.atan2(l.x-c.x,-(l.z-c.z));for(let f=0;f<=u;f++){const p=f/u,g=ba.nearest(n,c.x+(l.x-c.x)*p,c.z+(l.z-c.z)*p);g.distanceM>ba.NEAR_M||ba.angleBetween(d,g.heading)<=ba.ALIGNED_DEG&&(r+=h/u)}}return r>=ba.LONG_ENOUGH_M}static nearest(t,e,i){let n={distanceM:1/0,heading:0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,l=a.z-r.z,h=c*c+l*l,u=h<1e-9?0:Math.max(0,Math.min(1,((e-r.x)*c+(i-r.z)*l)/h)),d=Math.hypot(e-(r.x+c*u),i-(r.z+l*u));d<n.distanceM&&(n={distanceM:d,heading:Math.atan2(c,-l)})}return n}static angleBetween(t,e){const i=Math.abs((t-e)*180/Math.PI%180);return Math.min(i,180-i)}}class xe{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(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??xe.WMS,this.timeoutMs=t.timeoutMs??xe.DEFAULT_TIMEOUT_MS,this.maxWindowM=t.maxWindowM??xe.MAX_WINDOW_M,this.geoplatform=new Re({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:t.wfsEndpoint})}async getElevationGrid(t,e,i){const n={lat:(t.south+t.north)/2,lng:(t.west+t.east)/2};if(!Re.covers(n.lat,n.lng))throw new Error("The IGN's relief covers France only");const s=Math.abs(ae(n.lat,t.east,n.lat,t.west).x),r=Math.abs(ae(t.north,n.lng,t.south,n.lng).z);e=this.finer(e,s,r);const a={x:s/Math.max(1,e.width-1),y:r/Math.max(1,e.height-1)},c={x:Math.min(a.x,this.maxWindowM),y:Math.min(a.y,this.maxWindowM)},l={south:t.south-c.y/xe.METRES_PER_DEGREE,north:t.north+c.y/xe.METRES_PER_DEGREE,west:t.west-c.x/(xe.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180)),east:t.east+c.x/(xe.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180))},h=g=>Math.min(xe.MAX_PIXELS,Math.max(xe.MIN_PIXELS,Math.ceil(g/xe.METRES_PER_PIXEL))),u={width:h(s+2*c.x),height:h(r+2*c.y)},d={x:(s+2*c.x)/u.width,y:(r+2*c.y)/u.height};let f=new Error("No layer of the IGN's relief answered");const p=Math.max(d.x,d.y)>xe.COARSE_METRES_PER_PIXEL;for(const g of p?[...xe.LAYERS].reverse():xe.LAYERS)try{const m=await this.heights(l,u,g);g===xe.LAYERS[0]&&await this.layBridgeDecks(m,l,u,i?.route);const v=this.sample(m,e,t,l,d,a);if(v)return{heights:v,width:e.width,height:e.height,bounds:t};f=new Error(`${g} does not cover this place`)}catch(m){f=m}throw f}finer(t,e,i){if(t.width<xe.MESH_FROM_VERTICES||t.height<xe.MESH_FROM_VERTICES)return t;const n=(s,r)=>{const a=Math.ceil(s/xe.FINE_SPACING_M),c=Math.max(r-1,Math.min(xe.MAX_SEGMENTS,a));return c%2===0?c:c+1};return{width:n(e,t.width)+1,height:n(i,t.height)+1}}async raster(t,e,i){const n=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:i,STYLES:"",CRS:"EPSG:4326",BBOX:[t.south,t.west,t.north,t.east].map(r=>r.toFixed(6)).join(","),WIDTH:String(e.width),HEIGHT:String(e.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 Df.parse(await s.arrayBuffer())}async heights(t,e,i){const n=await this.raster(t,e,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(t,e,i,n){if(!(!n||n.length<2)&&!(!(t.values instanceof Float32Array)||!t.values.some(s=>s>xe.NO_DATA_BELOW)))try{const s=(await this.geoplatform.elevatedRoadLines({west:e.west,south:e.south,east:e.east,north:e.north})).filter(a=>ba.follows(n,a));if(s.length===0)return;const r=Float32Array.from(t.values);await this.layClassifiedDecks(t,e,i,s),this.layRouteDecks(t,r,e,s)}catch{}}async layClassifiedDecks(t,e,i,n){try{const s=await this.raster(e,i,xe.CLASS_LAYER);if(s.samples<3||s.width!==t.width||s.height!==t.height)return;const r=(m,[v,y,x])=>s.values[m*s.samples]===v&&s.values[m*s.samples+1]===y&&s.values[m*s.samples+2]===x,a=t.width,c=t.height,l=new Uint8Array(a*c);let h=!1;for(let m=0;m<l.length;m++)r(m,xe.DECK)&&(l[m]=1,h=!0);if(!h)return;const u=xe.DECK_END_PIXELS,d=[];for(let m=0;m<l.length;m++){if(l[m]!==1)continue;const v=m%a,y=(m-v)/a;for(let x=-u;x<=u;x++)for(let M=-u;M<=u;M++){const b=v+M,S=y+x;if(b<0||S<0||b>=a||S>=c)continue;const E=S*a+b;l[E]===0&&r(E,xe.NO_CLASS)&&d.push(E)}}for(const m of d)l[m]=1;const f=this.paint(n,e,a,c),p=this.touching(l,f,a,c);if(p.every(m=>m===0))return;const g=await this.heights(e,i,xe.SURFACE_LAYER);if(g.width!==a||g.height!==c)return;for(let m=0;m<p.length;m++){if(p[m]===0)continue;const v=g.values[m];Number.isFinite(v)&&v>xe.NO_DATA_BELOW&&v>t.values[m]&&(t.values[m]=v)}}catch{}}layRouteDecks(t,e,i,n){const{width:s,height:r}=t,a=(i.north+i.south)/2,c=(i.east-i.west)*xe.METRES_PER_DEGREE*Math.cos(a*Math.PI/180),l=(i.north-i.south)*xe.METRES_PER_DEGREE,h=c/s,u=l/r,d=v=>({x:(v.lng-i.west)/(i.east-i.west)*c,y:(i.north-v.lat)/(i.north-i.south)*l}),f=(v,y)=>{const x=Math.floor(v/h),M=Math.floor(y/u);if(x<0||M<0||x>=s||M>=r)return;const b=e[M*s+x];return Number.isFinite(b)&&b>xe.NO_DATA_BELOW?b:void 0},p=xe.DECK_HALF_WIDTH_M,g=xe.DECK_APPROACH_M,m=(v,y)=>{const x=Math.hypot(v.x-y.x,v.y-y.y)||1,M={x:(v.x-y.x)/x,y:(v.y-y.y)/x},b=[0,g/2,g].map(S=>f(v.x+M.x*S,v.y+M.y*S)).filter(S=>S!==void 0);return b.length>0?Math.max(...b):void 0};for(const v of xe.chains(n.map(y=>y.map(d)))){const y=[0];for(let I=1;I<v.length;I++)y.push(y[I-1]+Math.hypot(v[I].x-v[I-1].x,v[I].y-v[I-1].y));const x=y[y.length-1];if(x<1||x>xe.DECK_STRAIGHT_MAX_M)continue;const M=m(v[0],v[1]),b=m(v[v.length-1],v[v.length-2]);if(M===void 0||b===void 0)continue;const S=p+g,E=Math.max(0,Math.floor((Math.min(...v.map(I=>I.x))-S)/h)),w=Math.min(s-1,Math.ceil((Math.max(...v.map(I=>I.x))+S)/h)),_=Math.max(0,Math.floor((Math.min(...v.map(I=>I.y))-S)/u)),D=Math.min(r-1,Math.ceil((Math.max(...v.map(I=>I.y))+S)/u));for(let I=_;I<=D;I++)for(let O=E;O<=w;O++){const L=xe.nearestAlong(v,y,{x:(O+.5)*h,y:(I+.5)*u});if(L.distance>p||L.s<-g||L.s>x+g)continue;const N=M+(b-M)*Math.min(1,Math.max(0,L.s/x)),P=I*s+O;e[P]>=N||(t.values[P]=N)}}}static chains(t){const e=t.filter(s=>s.length>=2).map(s=>[...s]),i=[],n=(s,r)=>Math.hypot(s.x-r.x,s.y-r.y)<=1;for(;e.length>0;){let s=e.shift(),r=!0;for(;r;){r=!1;for(let a=0;a<e.length;a++){const c=e[a],l=s[0],h=s[s.length-1];if(n(h,c[0]))s=[...s,...c.slice(1)];else if(n(h,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else if(n(l,c[c.length-1]))s=[...c.slice(0,-1),...s];else if(n(l,c[0]))s=[...[...c].reverse().slice(0,-1),...s];else continue;e.splice(a,1),r=!0;break}}i.push(s)}return i}static nearestAlong(t,e,i){let n={s:0,distance:1/0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,l=a.y-r.y,h=c*c+l*l;if(h<1e-9)continue;let u=((i.x-r.x)*c+(i.y-r.y)*l)/h;s>0&&(u=Math.max(0,u)),s<t.length-2&&(u=Math.min(1,u));const d=Math.hypot(i.x-(r.x+c*u),i.y-(r.y+l*u));d<n.distance&&(n={s:e[s]+u*Math.sqrt(h),distance:d})}return n}paint(t,e,i,n){const s=new Uint8Array(i*n),r=c=>(c-e.west)/(e.east-e.west)*i,a=c=>(e.north-c)/(e.north-e.south)*n;for(const c of t)for(let l=0;l<c.length-1;l++){const h=r(c[l].lng),u=a(c[l].lat),d=r(c[l+1].lng),f=a(c[l+1].lat),p=Math.max(1,Math.ceil(Math.hypot(d-h,f-u)*2));for(let g=0;g<=p;g++){const m=Math.floor(h+(d-h)*g/p),v=Math.floor(u+(f-u)*g/p);for(let y=-1;y<=1;y++)for(let x=-1;x<=1;x++){const M=m+x,b=v+y;M>=0&&b>=0&&M<i&&b<n&&(s[b*i+M]=1)}}}return s}touching(t,e,i,n){const s=new Uint8Array(t.length),r=new Uint8Array(t.length);for(let a=0;a<t.length;a++){if(t[a]===0||r[a]===1)continue;const c=[],l=[a];r[a]=1;let h=!1;for(;l.length>0;){const u=l.pop();c.push(u),e[u]===1&&(h=!0);const d=u%i,f=(u-d)/i;for(let p=-1;p<=1;p++)for(let g=-1;g<=1;g++){const m=d+g,v=f+p;if(m<0||v<0||m>=i||v>=n)continue;const y=v*i+m;t[y]===1&&r[y]===0&&(r[y]=1,l.push(y))}}if(h)for(const u of c)s[u]=1}return s}sample(t,e,i,n,s,r){const{width:a,height:c}=e,l=new Float32Array(a*c),h=new Uint8Array(a*c),u=Math.min(r.x,this.maxWindowM)/s.x,d=Math.min(r.y,this.maxWindowM)/s.y;let f=0;for(let p=0;p<c;p++){const g=i.north+(i.south-i.north)*(c===1?.5:p/(c-1)),m=(n.north-g)/(n.north-n.south)*t.height-.5;for(let v=0;v<a;v++){const x=(i.west+(i.east-i.west)*(a===1?.5:v/(a-1))-n.west)/(n.east-n.west)*t.width-.5,M=u>1||d>1?this.tent(t,x,m,Math.max(1,u),Math.max(1,d)):this.bilinear(t,x,m),b=p*a+v;M===void 0?f++:(l[b]=M,h[b]=1)}}if(!(f===a*c||f/(a*c)>xe.MAX_HOLE_SHARE))return this.fill(l,h,a,c),l}tent(t,e,i,n,s){let r=0,a=0,c=0;const l=Math.max(0,Math.ceil(i-s)),h=Math.min(t.height-1,Math.floor(i+s)),u=Math.max(0,Math.ceil(e-n)),d=Math.min(t.width-1,Math.floor(e+n));for(let f=l;f<=h;f++){const p=1-Math.abs(f-i)/s;if(!(p<=0))for(let g=u;g<=d;g++){const m=p*(1-Math.abs(g-e)/n);if(m<=0)continue;c+=m;const v=t.at(g,f);!Number.isFinite(v)||v<xe.NO_DATA_BELOW||(r+=m*v,a+=m)}}return c>0&&a>=c*.5?r/a:void 0}bilinear(t,e,i){const n=Math.max(0,Math.min(t.width-1,Math.floor(e))),s=Math.max(0,Math.min(t.height-1,Math.floor(i))),r=Math.min(t.width-1,n+1),a=Math.min(t.height-1,s+1),c=Math.max(0,Math.min(1,e-n)),l=Math.max(0,Math.min(1,i-s)),h=t.at(n,s),u=t.at(r,s),d=t.at(n,a),f=t.at(r,a);for(const m of[h,u,d,f])if(!Number.isFinite(m)||m<xe.NO_DATA_BELOW)return;const p=h+(u-h)*c,g=d+(f-d)*c;return p+(g-p)*l}fill(t,e,i,n){let s=e.reduce((r,a)=>r+(a?0:1),0);for(;s>0;){const r=[];for(let a=0;a<n;a++)for(let c=0;c<i;c++){const l=a*i+c;if(e[l])continue;let h=0,u=0;for(let d=-1;d<=1;d++)for(let f=-1;f<=1;f++){const p=a+d,g=c+f;p<0||g<0||p>=n||g>=i||!e[p*i+g]||(h+=t[p*i+g],u++)}u>0&&r.push([l,h/u])}if(r.length===0)return;for(const[a,c]of r)t[a]=c,e[a]=1;s-=r.length}}}class rE{providers;constructor(...t){this.providers=t}async getElevationGrid(t,e,i){let n=new Error("No source of relief to ask");for(const s of this.providers)try{return await s.getElevationGrid(t,e,i)}catch(r){n=r}throw n}}const od=256,aE=5;async function zy(o,t,e,i){const n=(o.south+o.north)/2,s=(o.west+o.east)/2,r=Math.abs(ae(n,o.east,n,o.west).x),a=Math.abs(ae(o.north,s,o.south,s).z),c=Math.max(r,a),{zoom:l,gridSize:h}=oE(n,c,Math.max(t.width,t.height)),{tiles:u,bounds:d}=Fy(s,n,l,h),f=h*od,p=document.createElement("canvas");p.width=f,p.height=f;const g=p.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");const m=u[0];await Promise.all(u.map(async M=>{const b=e(M),S=await i(b);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${b}`);const E=await createImageBitmap(await S.blob());g.drawImage(E,(M.x-m.x)*od,(M.y-m.y)*od)}));const v=Math.min(Math.max(t.width,t.height),f);if(v===f)return{source:p,width:f,height:f,bounds:d};const y=document.createElement("canvas");y.width=v,y.height=v;const x=y.getContext("2d");if(!x)throw new Error("2D canvas context unavailable");return x.drawImage(p,0,0,f,f,0,0,v,v),{source:y,width:v,height:v,bounds:d}}function oE(o,t,e){let i=jS(o,t/Math.max(1,e)),n=ov(o,i,t);for(;n>aE&&i>0;)i--,n=ov(o,i,t);return{zoom:i,gridSize:n,mPerPixel:Ny(o,i)/od}}function ov(o,t,e){const i=Math.ceil(e/2/Ny(o,t));return Math.max(3,2*i+1)}class By{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(t,e){return zy(t,e,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class Zn{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(t,e=Zn.ENDPOINTS){const i=/\((-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\)/.exec(t);if(!i)return[...e];const[n,s,r,a]=i.slice(1).map(Number),c=(n+r)/2,l=(s+a)/2,h=Zn.FRANCE;return c>=h.south&&c<=h.north&&l>=h.west&&l<=h.east?[Zn.FRANCE_ENDPOINT,...e.filter(d=>d!==Zn.FRANCE_ENDPOINT)]:[...e]}fetchImpl;endpoints;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.endpoints=t.endpoints}static queue=Promise.resolve();static HANG_MS=4e4;static RETRY_MS=4e3;query(t){return this.queued(()=>this.ask(t))}queued(t){const e=Zn.queue.then(t,t);return Zn.queue=e.catch(()=>{}),e}async ask(t){let e;for(const i of this.endpoints??Zn.endpointsFor(t))for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(Zn.HANG_MS)});if(s.ok)return await s.json();if(e=new Error(`${new URL(i).host} refused (${s.status})`),s.status!==429&&s.status!==504)break}catch(s){e=new Error(`${new URL(i).host} unreachable (${String(s)})`);break}await new Promise(s=>setTimeout(s,Zn.RETRY_MS))}throw e??new Error("No Overpass instance answered")}}class wa{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(t={}){this.client=new Zn(t)}async getRoads(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];way["highway"~"^(${wa.DRIVABLE.join("|")})$"](${e});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(t){const e=[];for(const i of t.elements??[]){const n=i.geometry,s=i.tags;!s||!n||n.length<2||e.push({id:`osm-${i.id??e.length}`,name:s.name,surface:wa.surfaceOf(s),widthM:wa.widthOf(s),...wa.paintOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return e}static paintOf(t){const e=t.highway??"",i=t.junction==="roundabout"||t.junction==="circular",n=t.oneway,s=n==="yes"||n==="1"||n==="true"||n===void 0&&(e==="motorway"||i),r=n==="-1"||n==="reverse",a=Number.parseInt(t.lanes??"",10),c=Number.parseInt(t.maxspeed??"",10),l=i?"roundabout":e==="motorway"?"motorway":e.endsWith("_link")?"slip":(e==="trunk"||e==="primary")&&(s||r)?"dual":e?"road":void 0;return{...l?{kind:l}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...n!==void 0||e==="motorway"||i?{direction:r?"backward":s?"forward":"both"}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{}}}static widthOf(t){const e=Number.parseFloat(t.width??t.est_width??"");if(Number.isFinite(e)&&e>0)return e;const i=Number.parseInt(t.lanes??"",10);return Number.isFinite(i)&&i>0?i*3.5:wa.WIDTH_M[t.highway]??wa.DEFAULT_WIDTH_M}static surfaceOf(t){const e=t.surface;return e==="dirt"||e==="earth"||e==="mud"?"dirt":e==="gravel"||e==="fine_gravel"||e==="compacted"||e==="ground"||e==="sand"||e==="unpaved"?"gravel":e?"paved":t.highway==="track"?"gravel":"paved"}}const jf="https://ufoathome.org/roads/index.json";class Cc{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Cc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Roads © OpenStreetMap contributors"}get contemporary(){return this.contemporaryRead??this.fallback?.contemporary??!0}async getRoads(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRoads(t);return this.attributionRead=this.fallback.attribution,this.contemporaryRead=this.fallback.contemporary,i}async held(t){let e;try{e=await this.load()}catch{return}const i=e.find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2402
+ `);let e=Cc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Cc.shared.set(t,e),e.then(i=>{i.length===0&&Cc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.145.0")}`,e=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(e&&e!==jf?[e,jf]:[jf]).map(i=>i+t)}}class _a{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(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRoads(t){return(await this.platform.roads(t)).flatMap((i,n)=>_a.wayOf(i,n))}static wayOf(t,e){if(t.geometry.type!=="LineString")return[];const i=t.geometry.coordinates.map(([d,f])=>({lat:f,lng:d}));if(i.length<2)return[];const n=String(t.properties.nature??""),s=_a.BY_NATURE[n]??_a.DEFAULT,r=Number(t.properties.largeur_de_chaussee),a=Number(t.properties.nombre_de_voies),c=Number(t.properties.vitesse_moyenne_vl),l=_a.DIRECTIONS[String(t.properties.sens_de_circulation??"")],h=_a.KINDS[n],u=[t.properties.cpx_toponyme_route_nommee,t.properties.nom_voie_ban_gauche,t.properties.nom_voie_ban_droite].find(d=>typeof d=="string"&&d.length>0);return[{id:String(t.properties.cleabs??`ign-${e}`),...u?{name:u}:{},surface:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.widthM,...t.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...l?{direction:l}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{},points:i}]}}class cE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(t){if(_a.covers(t))try{const e=await this.regional.getRoads(t);if(e.length>0)return e}catch{}return this.worldwide.getRoads(t)}}class Eh{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getWater(t){return(await this.platform.waterSurfaces(t)).flatMap((i,n)=>Eh.surfacesOf(i,n))}static surfacesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="Polygon"?[n]:i==="MultiPolygon"?n:[],r=String(t.properties.cleabs??`ign-water-${e}`);return s.flatMap((a,c)=>{const l=a.map(h=>Eh.open(h.map(u=>({lat:u[1],lng:u[0]})))).filter(h=>h.length>=3);return l.length>0?[{id:s.length>1?`${r}-${c}`:r,rings:l}]:[]})}static open(t){const e=t[0],i=t[t.length-1];return t.length>1&&e.lat===i.lat&&e.lng===i.lng?t.slice(0,-1):t}}class io{attribution="Water © OpenStreetMap contributors";client;constructor(t={}){this.client=new Zn(t)}async getWater(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];(way["natural"="water"](${e});way["waterway"="riverbank"](${e});)->.w;(relation["natural"="water"](${e});relation["waterway"="riverbank"](${e});)->.r;.w out geom;.r out body;way(r.r)(${e});out geom;`;return io.surfacesFrom(await this.client.query(i))}static surfacesFrom(t){const e=t.elements??[],i=new Map;for(const r of e)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 e){if(r.type!=="relation")continue;const a=l=>(r.members??[]).filter(h=>h.type==="way"&&h.role===l&&h.ref!==void 0&&i.has(h.ref)).map(h=>(s.add(h.ref),i.get(h.ref))),c=io.rings(a("inner"));for(const[l,h]of io.rings(a("outer")).entries()){const u=c.filter(d=>io.contains(h,d[0]));n.push({id:`osm-r${r.id}-${l}`,rings:[h,...u]})}}for(const r of e)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 io.rings([i.get(r.id)??[]]))n.push({id:`osm-w${r.id}`,rings:[a]});return n}static rings(t){const e=(s,r)=>s.lat===r.lat&&s.lng===r.lng,i=t.filter(s=>s.length>=2).map(s=>[...s]),n=[];for(;i.length>0;){let s=i.pop(),r=!0;for(;!e(s[0],s[s.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const c=i[a],l=s[s.length-1];if(e(l,c[0]))s=[...s,...c.slice(1)];else if(e(l,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}s.length>=4&&e(s[0],s[s.length-1])&&n.push(s.slice(0,-1))}return n}static contains(t,e){let i=!1;for(let n=0,s=t.length-1;n<t.length;s=n++){const r=t[n],a=t[s];r.lat>e.lat!=a.lat>e.lat&&e.lng<(a.lng-r.lng)*(e.lat-r.lat)/(a.lat-r.lat)+r.lng&&(i=!i)}return i}}class lE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(t){if(Eh.covers(t))try{const e=await this.regional.getWater(t);if(e.length>0)return e}catch{}return this.worldwide.getWater(t)}}const Qf="https://ufoathome.org/water/index.json";class Oc{attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Oc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Water © OpenStreetMap contributors"}async getWater(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getWater(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2403
+ `);let e=Oc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Oc.shared.set(t,e),e.then(i=>{i.length===0&&Oc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.145.0")}`,e=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(e&&e!==Qf?[e,Qf]:[Qf]).map(i=>i+t)}}class Xn{constructor(t){this.water=t}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(t){const e=Xn.key(t);let i=Xn.asked.get(e);return i===void 0&&(i=this.recalled(e,t),Xn.asked.set(e,i),i.catch(()=>Xn.asked.delete(e))),structuredClone(await i)}static forget(){Xn.asked.clear()}static key(t){return`v${Xn.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}async recalled(t,e){const i=await Xn.openCache(),n=Xn.request(t);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:c}=await r.json();if(Date.now()-a<Xn.MAX_AGE_MS&&Array.isArray(c))return c;await i.delete(n)}}catch{}const s=await this.water.getWater(e);return i&&Xn.store(i,n,s),s}static async store(t,e,i){try{const n={savedAt:Date.now(),surfaces:i};await t.put(e,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await t.keys();for(const r of s.slice(0,Math.max(0,s.length-Xn.MAX_STORED)))await t.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Xn.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__water__/${encodeURIComponent(t)}`)}}class Ta{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(t={}){this.platform=new Re(t)}static covers(t){return Re.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRailways(t){return(await this.platform.railways(t)).flatMap((i,n)=>Ta.linesOf(i,n))}static linesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=Ta.BY_NATURE[String(t.properties.nature??"")];if(!r)return[];const a=String(t.properties.cleabs??`ign-rail-${e}`),c=Number(t.properties.nombre_de_voies),l=Number(t.properties.position_par_rapport_au_sol),h=t.properties.cpx_toponyme,u=Ta.GAUGE_MM[String(t.properties.largeur??"")]??1435,d=Ta.electrificationOf(r.kind,u,t.properties.electrifie);return s.flatMap((f,p)=>{const g=f.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>Ta.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.length>1?`${a}-${p}`:a,...typeof h=="string"&&h.length>0?{name:h}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:u,tracks:Number.isInteger(c)&&c>0?c:1,...d?{electrification:d}:{},level:Number.isFinite(l)?l:0,points:g}]})}static electrificationOf(t,e,i){if(i===!1)return"none";if(i===!0){if(t==="subway")return"third_rail";if(!(t==="funicular"||e<1435))return"overhead"}}}class pn{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(t={}){this.client=new Zn(t)}async named(t,e){if(t.length===0)return[...t];const i=`${e.south},${e.west},${e.north},${e.east}`,n=`[out:json][timeout:120];way["railway"~"^(${pn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${pn.ROUTES})$"];out body;`;return pn.apply(t,await this.client.query(n),e)}static apply(t,e,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=pn.ways(e,n);return s.length===0?[...t]:t.map(r=>{const a=r.points.map(v=>ae(v.lat,v.lng,n.lat,n.lng)),c=new Map,l=new Map,h=new Map;let u=0;const d=s.filter(v=>v.service===!!r.service);for(const v of pn.samples(a)){u++;const y=pn.waysAt(d,v);if(y.length===0)continue;const[x]=y;x.name&&c.set(x.name,(c.get(x.name)??0)+1),x.voltageV&&l.set(x.voltageV,(l.get(x.voltageV)??0)+1);for(const M of new Set(y.flatMap(b=>b.services)))h.set(M,(h.get(M)??0)+1)}const f=v=>[...v.entries()].sort((y,x)=>x[1]-y[1])[0]?.[0],p=r.name??f(c),g=r.voltageV??(r.electrification==="none"?void 0:f(l)),m=[...h.entries()].filter(([,v])=>v*4>=u).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...p?{name:p}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}static serviceOf(t){const e=t.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return e||[t.network,t.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(t){const e=new Map;for(const i of t.elements??[]){if(i.type!=="relation"||!i.tags)continue;const n=pn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=e.get(s.ref)??new Set;r.add(n),e.set(s.ref,r)}}return e}static voltageOf(t){const e=Number.parseInt((t.voltage??"").split(";")[0],10);return Number.isFinite(e)&&e>0?e:void 0}static ways(t,e){const i=pn.servicesByWay(t),n=[];for(const s of t.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=pn.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(c=>ae(c.lat,c.lon,e.lat,e.lng))})}return n}static samples(t){const e=[];for(let i=0;i<t.length-1;i++){const n=Math.hypot(t[i+1].x-t[i].x,t[i+1].z-t[i].z);if(n<1e-6)continue;const s=(t[i+1].x-t[i].x)/n,r=(t[i+1].z-t[i].z)/n;for(let a=pn.SAMPLE_M/2;a<n;a+=pn.SAMPLE_M)e.push({x:t[i].x+s*a,z:t[i].z+r*a,dx:s,dz:r})}return e}static waysAt(t,e){const i=Math.cos(pn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of t){let r;for(let a=0;a<s.path.length-1;a++){const c=s.path[a],l=s.path[a+1],h=l.x-c.x,u=l.z-c.z,d=Math.hypot(h,u);if(d<1e-6||Math.abs((h*e.dx+u*e.dz)/d)<i)continue;const f=Math.max(0,Math.min(1,((e.x-c.x)*h+(e.z-c.z)*u)/(d*d))),p=Math.hypot(e.x-(c.x+h*f),e.z-(c.z+u*f));p<=pn.NEAR_M&&(r===void 0||p<r)&&(r=p)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Pc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(t={}){this.client=new Zn(t)}async getRailways(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Pc.KINDS.join("|")})$"](${e})->.w;.w out tags geom;rel(bw.w)["route"~"^(${pn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(t){const e=[],i=pn.servicesByWay(t);for(const n of t.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(),c=pn.voltageOf(r),l=Pc.kindOf(r),h=Number.parseInt((r.gauge??"").split(";")[0],10),u=Number.parseInt(r.tracks??"",10),d=Pc.electrificationOf(r.electrified),f=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;e.push({id:`osm-rail-${n.id??e.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...c?{voltageV:c}:{},kind:l,...r.service||r.usage==="industrial"?{service:!0}:{},...f?{highSpeed:!0}:{},gaugeMm:Number.isFinite(h)&&h>300?h:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(u)&&u>0?u:1,...d?{electrification:d}:{},level:Pc.levelOf(r),points:s.map(p=>({lat:p.lat,lng:p.lon}))})}return e}static kindOf(t){switch(t.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(t){if(t!==void 0){if(t==="no")return"none";if(t==="contact_line"||t==="yes")return"overhead";if(t==="rail"||t==="4th_rail"||t==="ground-level_power_supply")return"third_rail"}}static levelOf(t){const e=Number.parseInt(t.layer??"",10);return t.tunnel&&t.tunnel!=="no"?Number.isFinite(e)&&e<0?e:-1:t.covered==="yes"&&t.location==="underground"?-1:t.bridge&&t.bridge!=="no"?Number.isFinite(e)&&e>0?e:1:0}}class hE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(t){if(!Ta.covers(t))return this.worldwide.getRailways(t);let e;try{if(e=await this.regional.getRailways(t),e.length>0)return e}catch{}try{return await this.worldwide.getRailways(t)}catch(i){if(e)return e;throw i}}}class Xi{constructor(t,e=Date.now){this.railways=t,this.now=e}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(t){const e=Xi.key(t);let i=Xi.asked.get(e)??Xi.containing(t);if(i===void 0){const n=this.recalled(e,t);i={bounds:t,answer:n},Xi.asked.set(e,i),n.catch(()=>Xi.asked.delete(e))}return structuredClone(await i.answer)}static forget(){Xi.asked.clear(),Xi.failedAt=-1/0}static key(t){return`v${Xi.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}static containing(t){for(const e of Xi.asked.values()){const i=e.bounds;if(i.north>=t.north&&i.south<=t.south&&i.east>=t.east&&i.west<=t.west)return e}}async recalled(t,e){const i=await Xi.openCache(),n=Xi.request(t);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:c,lines:l}=await a.json();if(Array.isArray(l)){if(this.now()-c<Xi.MAX_AGE_MS)return l;s=l}}}catch{}if(this.now()-Xi.failedAt<Xi.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(e)}catch(a){if(Xi.failedAt=this.now(),s)return s;throw a}return i&&Xi.store(i,n,{savedAt:this.now(),lines:r}),r}static async store(t,e,i){try{await t.delete(e),await t.put(e,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const n=await t.keys();for(const s of n.slice(0,Math.max(0,n.length-Xi.MAX_STORED)))await t.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Xi.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__railways__/${encodeURIComponent(t)}`)}}const t0="https://ufoathome.org/railways/index.json";class Lc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Lc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRailways(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.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 t=this.indexUrls.join(`
2404
+ `);let e=Lc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Lc.shared.set(t,e),e.then(i=>{i.length===0&&Lc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.145.0")}`,e=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(e&&e!==t0?[e,t0]:[t0]).map(i=>i+t)}}function Hy(){return{elevation:uE(),imagery:Gy(),roads:dE(),water:fE(),railways:pE()}}function uE(){return new rE(new xe,new nE)}function Gy(){return new By}function dE(){return new Cc({fallback:new cE(new _a,new wa)})}function fE(){return new Oc({fallback:new Xn(new lE(new Eh,new io))})}function pE(){return new Lc({fallback:new Xi(new hE(new Ta,new Pc))})}const mE=new Set,Ar="show-observer-map",_r="hide-milestones",bo="minified";class Le extends HTMLElement{static get observedAttributes(){return["src",Ar,_r,bo]}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 Qe;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=Rf.create();issues=[];issueCheck=0;sightingAudio=new NS;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>Le.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Dy;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const t=this.controlsRow,e=t.classList.contains("more-open"),i=()=>t.scrollWidth>t.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,t.classList.remove("narrow","more-open","nomoments","compact","tiny"),t.clientWidth>0&&i()){t.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;t.classList.add(s)}e&&t.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(t){this.controlsRow.classList.toggle("more-open",!t),this.updateMoreButton()}updateMoreButton(){const t=this.controlsRow.classList.contains("more-open");Le.setIcon(this.moreButton,t?qt.UNFOLDED:qt.FOLDED);const e=t?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=e,this.moreButton.setAttribute("aria-label",e),this.moreButton.setAttribute("aria-expanded",String(t))}addControl(t){this.controlsRight.insertBefore(t,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=t=>{t.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=t=>{const e=this.canvasPointFromEvent(t),i=e&&this.shapeAt(e.x,e.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=`${t.clientX-s.left+12}px`,this.tooltip.style.top=`${t.clientY-s.top+12}px`};handleObserverMapPointerMove=t=>{if(this.dragObserverMap(t))return;const e=this.observerMapTargetFrom(t);if(!e){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(t,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(t,e.label)};showObserverMapTooltip(t,e){this.tooltip.textContent=e,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-i.left+12}px`,this.tooltip.style.top=`${t.clientY-i.top+12}px`}handleObserverMapClick=t=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const e=this.observerMapTargetFrom(t);if(!e){this.observerPlacing&&this.placeObserverFrom(t);return}if(e.kind==="milestone"&&e.t!==void 0){this.player.seek(e.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:e.lat,lng:e.lng,kind:e.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(t){const e=this.observerMapCanvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return this.observerMapRenderer.hitTest((t.clientX-e.left)/e.width*this.observerMapCanvas.width,(t.clientY-e.top)/e.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=t=>{t.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,moved:!1})};handleObserverMapPointerUp=t=>{const e=this.observerMapDrag;!e||e.pointerId!==t.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),e.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(t.pointerId)&&this.observerMapCanvas.releasePointerCapture(t.pointerId)))};dragObserverMap(t){const e=this.observerMapDrag;if(!e||e.pointerId!==t.pointerId)return!1;if(!e.moved){if(Math.hypot(t.clientX-e.startX,t.clientY-e.startY)<Le.OBSERVER_MAP_DRAG_PX)return!1;e.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(t.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((t.clientX-e.lastX)/i.width,(t.clientY-e.lastY)/i.height),this.observerMapViewChanged()),e.lastX=t.clientX,e.lastY=t.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=t=>{t.preventDefault();const e=this.observerMapCanvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=t.deltaMode===0?t.deltaY:t.deltaY*40;this.zoomObserverMap((t.clientX-e.left)/e.width,(t.clientY-e.top)/e.height,Math.exp(-i*.002))};zoomObserverMap(t,e,i){this.observerMapView.zoomAt(t,e,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=Qe.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=Qe.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Le.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(t){const e=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!e||i.width===0||i.height===0)return;const n=Qe.pointAt(e,(t.clientX-i.left)/i.width,(t.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 t=document.createElement("template");t.innerHTML=`<style>${TS}</style>${_S}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new ol(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 eo(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 e=this.shadow.getElementById("mini-bar"),i=e.querySelector(".mini-track"),n=a=>{const c=i.getBoundingClientRect(),l=this.player.seekableDuration;if(c.width<=0||l<=0)return;const h=Math.min(Math.max((a.clientX-c.left)/c.width,0),1)*l;this.player.seek(h),this.miniScrubTime.textContent=this.formatElapsedAt(h),this.miniScrubTime.style.left=this.miniDot.style.left};let s=!1;e.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),e.setPointerCapture(a.pointerId),e.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),e.addEventListener("pointermove",a=>{e.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{e.classList.contains("scrubbing")&&(e.classList.remove("scrubbing"),e.hasPointerCapture(a.pointerId)&&e.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&this.play())};e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r),e.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 t=this.getAttribute("src");t&&this.loadFromSrc(t)}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(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===Ar&&this.applyObserverMapDefault(),t===_r&&this.setMilestonesShown(!this.hasAttribute(_r)),t===bo){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&e===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(bo)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(Wy)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const t=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",t),t&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(t){this.sightingData=await Na.recording(t)}get sightingData(){return kS(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=FS(t),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(t,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(t){this.titleOverride=t,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const t=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=t,this.playerTitleBox.hidden=t===""}get recordingIssues(){return this.issues}async reportIssues(t,e){const i=++this.issueCheck;let n=[];try{const{default:s}=await we(async()=>{const{default:r}=await import("./sightingSchema-t3YCF0eV.js");return{default:r}},[],import.meta.url);n=new Ls(s).issues(t)}catch{}i===this.issueCheck&&(this.issues=[...n,...e.loadIssues],cl.warn(this.issues,e.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(gE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const t=this.issues.length;this.issuesBox.hidden=t===0,this.shadow.getElementById("issues-count").textContent=String(t);const e=this.messages.recordingIssues.replace("{count}",String(t));this.issuesButton.title=e,this.issuesButton.setAttribute("aria-label",e),this.shadow.getElementById("issues-title").textContent=e,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=cl.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(t){this.soundPreview=t,this.sightingAudio.resume(),this.sightingAudio.setSound(t)}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(t){this.player.seek(t)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(t){t!==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(t){if(t!==this.clockHeld){if(this.clockHeld=t,t){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(t){this.toolbar.classList.toggle("hidden",!t),t?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(t){this.currentSighting.event.durationSeconds=t,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(t){const e=new Set(t);e.size===this.highlightedSourceIds.size&&[...e].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=e,this.refresh())}hasVisibleShapeAt(t,e){return this.shapeAt(t,e)!==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(t){const e=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of e)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 t=this.currentSighting.references;!this.referenceOpacityTouched&&t.length>0&&(this.referenceOpacityInput.value=String(t[0].opacity));for(const e of[...this.referenceViews.keys()])t.some(i=>i.id===e)||this.referenceViews.delete(e);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(t){let e=this.referenceViews.get(t.id);return e||(e={shown:!0,opacity:t.opacity},this.referenceViews.set(t.id,e)),e}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=t=>{const e=t.composedPath();e.includes(this.referencesMenu)||e.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=t=>{t.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const t=this.referencesButton.getBoundingClientRect(),e=this.referencesMenu,i=4;e.style.bottom=`${Math.max(i,window.innerHeight-t.top+i)}px`,e.style.top="auto";const n=e.getBoundingClientRect().width;e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const t=this.currentSighting.references.map(e=>{const i=this.viewOfReference(e),n=this.said.read(e.title)??e.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 c=document.createElement("span");c.textContent=n,c.title=n,r.append(a,c);const l=document.createElement("input");return l.type="range",l.min="0",l.max="1",l.step="0.05",l.value=String(i.opacity),l.title=this.messages.referenceOpacity,l.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),l.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,l.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),l.addEventListener("input",()=>{i.opacity=Number(l.value),this.dispatchReferenceView()}),s.append(r,l),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...t)}updateReferencesButton(){const t=this.currentSighting.references.length>0,e=this.severalReferences,i=e?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState||e,this.referencesButton.setAttribute("aria-pressed",String(i)),e?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Le.setIcon(this.referencesButton,i?qt.PICTURES_ON:qt.PICTURES_OFF);const n=e?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)),Le.setIcon(this.tracesButton,this.tracesShownState?qt.TRACES_ON:qt.TRACES_OFF);const t=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=t,this.tracesButton.setAttribute("aria-label",t)}dispatchReferenceView(){const t=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(e=>[e.id,{...this.viewOfReference(e)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:t}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?ih(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...e.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/t,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(t,e.map(i=>i.t)),this.refreshMomentsPicker(e)}refreshMomentsPicker(t){const e=this.milestonesShown&&t.length>0;this.momentsBox.hidden=!e,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...t.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(t){const i=(t?this.said.read(t.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=t!==void 0&&Number(n.dataset.t)===t.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=t=>{if(!this.momentsMenu.hidden){if(t instanceof KeyboardEvent){t.key==="Escape"&&this.closeMomentsMenu();return}t.composedPath().some(e=>e===this.momentsMenu||e===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(t,e){const n=[0,...this.milestonesShown&&t>0?[...new Set(e.filter(r=>r>0&&r<t))].sort((r,a)=>r-a):[],Math.max(t,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 c=document.createElement("i");c.className="seek-hover";const l=document.createElement("i");l.className="seek-played",a.append(c,l),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:l,hover:c})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(t,e){const i=t.end-t.start,n=i>0?(e-t.start)/i:e>=t.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintMiniProgress(t){const e=this.player.seekableDuration,i=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(t)}miniDot;miniScrubTime;paintSeekProgress(t){for(const i of this.seekSegmentList)i.played.style.width=Le.fillOf(i,t);const e=this.player.seekableDuration;this.seekDot.style.left=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`}hoverSeek(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((f,p)=>{f.hover.style.width=Le.fillOf(f,s),f.element.classList.toggle("hovered",s>=f.start&&(s<f.end||p===r))});const a=this.milestonesShown?this.sighting.milestones:[],c=a.length>0?Zf(a,s):void 0,l=c?this.said.read(c.label)??"":"",h=c?this.said.read(c.note):void 0,u=h?`${l} — ${h}`:l;this.seekPreviewTitle.textContent=u,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const d=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*e.width-d/2,0),Math.max(e.width-d,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const t of this.seekSegmentList)t.hover.style.width="0",t.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(t){const e=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=e===void 0,e?.(t,this.seekPreviewCanvas)}paintChrome(t){const e=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(!e||typeof e.setTransform!="function"||n===0||s===0){t(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),c=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==c&&(this.chromeCanvas.height=c),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,a,c),this.chromeDirty=!1,i&&(e.setTransform(a/this.canvas.width,0,0,c/this.canvas.height,0,0),this.chromeRenderer??=new ol(e),this.chromeDirty=!0,t(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(t){if(t.pointerType!=="mouse"){this.scrubbingPointer=t.pointerId;try{this.seekInput.setPointerCapture(t.pointerId)}catch{}this.seekToPointer(t)}}touchScrub(t){t.pointerId===this.scrubbingPointer&&this.seekToPointer(t)}endTouchScrub(t){t.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(t))}seekToPointer(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(t){const e=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(e<=0||i<=0)return;const n=Le.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-t)>n||(!s||Math.abs(a-t)<Math.abs(s.t-t))&&(s={t:a,name:r.title})}return s}snapSeekToMark(t){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(t)?.t??t):t}nameMarkUnder(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=(t.clientX-e.left)/e.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(t){const e=this.milestonesShown&&this.sighting.milestones.length>0?Zf(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,this.showCurrentMoment(e),!e)return;const i=document.createElement("b");i.textContent=this.said.read(e.label)??"";const n=this.said.read(e.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(t){const e=this.exposureTimes(t),i=1/e.length;return e.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(t=this.currentTime){const e=Fs.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Le.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Le.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Le.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Le.EXPOSURE_STEP_PX),s=Math.min(Le.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(e.fromMs+e.ms*a/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,a]of i){const c=n.get(r);if(!c)continue;const l=c.bounds.x+c.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=c.bounds.y+c.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(l,h))}return s}shapeAt(t,e,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,t,e,i);if(s)return s}}shapesAt(t){const e=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}return e}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const t=Bi.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===t)return;this.canvas.width=t,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${t} / ${this.canvas.height}`)}canvasPointFromEvent(t){const e=this.canvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return{x:(t.clientX-e.left)/e.width*this.canvas.width,y:(t.clientY-e.top)/e.height*this.canvas.height}}onFrame(t,e){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:mE;this.canvasRenderer.setStarPoints(Bi.starPointsOf(this.sighting.instrument));const n=(ze(this.sighting,t)?.rollDeg??0)+this.gaitAt(t).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(t),r=this.frameShift;if(this.paintsShapes)for(const c of s)for(const[,l]of c.shapes){const h=c.share,u=h===1?l:{...l,transparency:1-(1-l.transparency)*h};this.canvasRenderer.paintShape(this.shifted(u,r))}for(const[c,l]of s[0].shapes)!this.selectionShown||!i.has(c)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...l,selected:!0}):this.canvasRenderer.paintMemberOutline(l):this.canvasRenderer.paintSelectionOnly(this.shifted(l,r)));const a=this.selectionShown&&i.size>1?hs.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds)):void 0;this.chromeDraw=c=>{a&&c.paintGroupHandles(a),this.overlayPainter?.(c)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(c=>[...c.shapes.values()].filter(l=>l.transparency<1).map(l=>this.shifted(l,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.paintSeekProgress(t),this.minified&&this.paintMiniProgress(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(wy(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:t}}))}shifted(t,e){return e.x===0&&e.y===0?t:{...t,bounds:{...t.bounds,x:t.bounds.x+e.x,y:t.bounds.y+e.y}}}createPlayer(){const t=new RS(this.currentSighting.timeline,(e,i)=>this.onFrame(e,i));return t.loop=this.loopEnabled,t.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},t}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=t=>{t.key.toLowerCase()!=="f"||t.altKey||t.ctrlKey||t.metaKey||!this.enableClickToPlay||t.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(t.preventDefault(),this.toggleFullscreen())};handleSeekKey=t=>{if(t.altKey||t.ctrlKey||t.metaKey)return;const e=t.key==="ArrowLeft"?-1:t.key==="ArrowRight"?1:0;if(e){t.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+e*Le.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.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 t=this.playbackFlash;t.innerHTML=this.player.playbackState==="playing"?qt.PLAY:qt.PAUSE,t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}static icons=new WeakMap;static setIcon(t,e){Le.icons.get(t)!==e&&(Le.icons.set(t,e),t.innerHTML=e)}set captionHeld(t){this.stageElement.classList.toggle("caption-held",t)}set controlsHeld(t){this.stageElement.classList.toggle("controls-held",t)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(t){this.quietControlsValue=t,this.stageElement.classList.toggle("quiet",t)}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},Le.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!t),t!==this.wasPlaying&&t&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=t,this.updateStartState(),Le.setIcon(this.playPauseButton,t?qt.PAUSE:qt.PLAY);const e=this.player.seekableDuration>0;this.playPauseButton.disabled=!e;const i=e?t?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 t=this.playbackBeforeClick;t&&(this.currentTime=t.time,t.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(t=>{console.error("<rr0-ufo>: requestFullscreen() failed —",t)})}enterSimulatedFullscreen(){const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=t.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const e=t.style;e.setProperty("position","fixed"),e.setProperty("inset","0"),e.setProperty("margin","0"),e.setProperty("max-width","none"),e.setProperty("max-height","none"),e.setProperty("aspect-ratio","auto"),e.setProperty("z-index","2147483647"),e.setProperty("background","#000"),e.setProperty("width","100vw"),e.setProperty("width","100dvw"),e.setProperty("height","100vh"),e.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 t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?t.setAttribute("style",this.styleBeforeSimulatedFullscreen):t.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const t=this.observerMapPanel.hidden;this.observerMapAsked=t,this.setObserverMapOpen(t),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:t}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const t=this.getAttribute(Ar),e=t===null?this.sighting.observerMap??this.observerPath?.travels===!0:t!=="false";this.setObserverMapOpen(e&&this.observerPath!==void 0)}setObserverMapOpen(t){this.observerMapPanel.hidden=!t,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(t)),this.updateObserverMapButton(),t&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const t=!this.observerMapPanel.hidden;Le.setIcon(this.observerMapButton,t?qt.MAP_ON:qt.MAP_OFF);const e=t?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e);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 t=this.observerPath!==void 0;if(this.observerPath=$c.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!t&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const e=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=Qe.fitted(this.observerPath,e);(!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(t,e){const i=Math.abs(t.east-t.west)/20;return Math.abs(t.north-e.north)<i&&Math.abs(t.south-e.south)<i&&Math.abs(t.west-e.west)<i&&Math.abs(t.east-e.east)<i}async loadObserverMapImagery(){const t=this.observerMapViewBounds;if(!t||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(t)))return;const e=this.observerMapView.changed,i=e?Qe.expand(t,Le.OBSERVER_MAP_IMAGERY_AHEAD):t,n=Qe.IMAGERY_PX*(e?1+2*Le.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=t.east-t.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:Gy();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(t){const e=this.observerMapImageryBounds;if(!e)return!0;const i=this.observerMapImagery?.bounds??e,n=this.observerMapView.changed?Qe.expand(t,Le.OBSERVER_MAP_IMAGERY_LOOKAHEAD):t,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=t.east-t.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(t){t!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=t,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(t){this.mapSceneBounds=t.map(e=>({x:e.x*this.canvas.width,y:e.y*this.canvas.height,width:e.width*this.canvas.width,height:e.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const t=this.observerMapBoxPx;if(!t)return;const e=[...this.mapShapeBounds,...this.mapSceneBounds],i=(l,h,u)=>{for(const d of e)if(!(d.x+d.width<l-u||d.x>h+u)&&!(d.y>t.bottom+u||d.y+d.height<t.top-u))return!0;return!1},n=[this.canvas.width-t.width,this.canvas.width],s=[0,t.width],r=Le.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&c&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(c||!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 t=this.observerMapPanel.clientWidth;if(t===0)return;const e=Math.round(t*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==e&&(this.observerMapCanvas.width=e,this.observerMapCanvas.height=e)}measureObserverMapBox(){const t=this.observerMapPanel.getBoundingClientRect(),e=this.canvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=this.canvas.width/e.width,n=this.canvas.height/e.height;this.observerMapBoxPx={width:t.width*i,top:(t.top-e.top)*n,bottom:(t.bottom-e.top)*n}}paintObserverMap(t){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const e=ze(this.currentSighting,t);e?.lat!==void 0&&e.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:e.lat,lng:e.lng},Le.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?Zf(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?ih(this.currentSighting.milestones):[]){const a=ze(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:e?.lat!==void 0&&e.lng!==void 0?{lat:e.lat,lng:e.lng}:void 0,headingDeg:e?.headingDeg===void 0?void 0:e.headingDeg+this.lookYawDeg,coneHalfAngleDeg:e?yr.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(Bi.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(t),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(t){this.milestonesShown=t,this.milestoneMarks.hidden=!t,this.momentsBox.hidden=!t||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,ih(this.sighting.milestones).map(e=>e.t)),this.milestonesButton.setAttribute("aria-pressed",String(t)),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,Le.setIcon(this.milestonesButton,this.milestonesShown?qt.MILESTONES_ON:qt.MILESTONES_OFF);const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=ze(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Er(i,t),{lat:s,lng:r}=fs(n.eastM,-n.northM,e.lat,e.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(t){const e=t===void 0?void 0:Math.max(0,Math.min(1,-t/12));e!==this.observerMapNightFraction&&(this.observerMapNightFraction=e,this.paintObserverMap(this.currentTime))}setLookOffset(t,e){t===this.lookYawDeg&&e===this.lookPitchDeg||(this.lookYawDeg=t,this.lookPitchDeg=e,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const t=this.gaitAt(this.currentTime),e=this.lookYawDeg+t.yawDeg,i=this.lookPitchDeg+t.pitchDeg;if(e===0&&i===0)return{x:0,y:0};const n=ze(this.currentSighting,this.currentTime),s=yr.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(e),y:s.angleDegToRadiusPx(i)}}gaitAt(t){return Xe.bodyAt(this.currentSighting,t,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(t){t!==this.mutedState&&(this.mutedState=t,!t&&this.volumeState===0&&(this.volumeState=Le.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(t){this.setVolume(t)}setVolume(t){this.volumeState=Math.min(Math.max(t,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 t=!this.hasSound;this.miniMuteButton.hidden=t,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Le.setIcon(this.miniMuteButton,this.mutedState?qt.MUTED:qt.VOLUME);const e=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=e,this.miniMuteButton.setAttribute("aria-label",e),this.muteButton.disabled=t,this.volumeInput.hidden=t,t){Le.setIcon(this.muteButton,qt.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Le.setIcon(this.muteButton,this.mutedState?qt.MUTED:qt.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 t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Le.setIcon(this.fullscreenButton,t?qt.EXIT_FULLSCREEN:qt.ENTER_FULLSCREEN),this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Es(ka.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=dg(ka.preferencesFor(this),fg);if(t===this.messagesLanguage||t==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=t;const e=await HS(t);this.messagesLanguage===t&&this.applyMessages(e)}messagesLanguage;updateTimeLabelTitles(){const t=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,e=this.canSwitchTimeDisplay?` — ${t}`:"";this.timeStartLabel.title=this.messages.currentPosition+e,this.timeEndLabel.title=this.messages.duration+e,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(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const t=this.currentSighting.event,e=by(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?Dp(t.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(t){if(this.realDurationMs===void 0)return oa(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?lv(cv(this.realStartMs+i)):oa(i)}formatElapsedAt(t){const e=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?oa(t):oa(e>0&&t<=e?t/e*this.realDurationMs:t)}formatRemaining(t){const e=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return oa(Math.max(0,e-t));const i=e>0&&t<=e?t/e*this.realDurationMs:t;return oa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?oa(this.currentSighting.timeline.duration):this.canShowClockTime?lv(cv(this.realStartMs+this.realDurationMs)):oa(this.realDurationMs)}}function cv(o){const t=new Date(o);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function lv(o){if(o.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return o.second?`${t(o.hour)}:${t(o.minute??0)}:${t(o.second)}`:`${t(o.hour)}:${t(o.minute??0)}`}function oa(o){const t=Math.round(o/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Pp="rr0-ufo";function Vy(){customElements.get(Pp)||customElements.define(Pp,Le)}const gE="recordingissues",Wy="minifiedreset";/**
2405
2405
  * @license
2406
2406
  * Copyright 2010-2026 Three.js Authors
2407
2407
  * SPDX-License-Identifier: MIT
@@ -8632,7 +8632,7 @@ uniform float uWindowLuminance;
8632
8632
  varying float vLitRank;
8633
8633
  ${c.fragmentShader.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
8634
8634
  totalEmissiveRadiance *= step(vLitRank, uLitShare) * uWindowLuminance * ${yt.WINDOW_VARIETY_GLSL};`)}`},r.customProgramCacheKey=()=>"facade-lit-windows";const a=new bt(s,r);return a.castShadow=!0,a.receiveShadow=!0,e.add(a),e}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 t=n=>`vec3(${n.map(s=>s.toFixed(4)).join(", ")})`,e=el.ofTemperature(yt.ROOM_LIGHT_K),i=el.ofTemperature(yt.COLD_ROOM_LIGHT_K);return`(mix(0.35, 2.0, fract(vLitRank * 97.13) * fract(vLitRank * 97.13)) * mix(${t(e)}, ${t(i)}, step(0.86, fract(vLitRank * 53.71))))`}static setWindowLuminance(t){yt.windowLuminance.value=yt.WINDOW_LUMINANCE_CD_M2*t}static setLitWindowShare(t){yt.litWindowShare.value=Math.max(0,Math.min(1,t))}static build(t,e){const i=yt.hasFacade(t)?yt.buildFacade(t):t.kind==="building"?l2(t.floors??zd,t.windows,t.observerSide,t.occupiedFloor,t.observerFacing):t.kind==="tree"?u2():t.kind==="shrub"?h2():t.kind==="bridge"?NC(t):t.kind==="wire"?kC(t):t.kind==="wall"?$i.build(t):t.kind==="crop"?f2():t.kind==="terrace"?WC():t.kind==="mound"?p2():t.kind==="streetlight"?m2(e,t.lamp?.mount,t.lamp):t.kind==="trafficlight"?ge.trafficLight(se.isPedestrian(t.lights)):t.kind==="crossing"?ge.crossing(yt.sizeOf(t).widthM,yt.sizeOf(t).lengthM):t.kind==="roadsign"?ge.roadSign(t.sign):t.kind==="vehicle"?g2(e,t.windows,t.observerSide,t.observerFacing):t.kind==="aircraft"?w2():t.kind==="entity"?x2():ng();t.color&&this.paint(i,t.color);const n=this.scaleFor(t),s=new Oe;return t.kind==="building"&&t.roof&&this.addRoof(s,t),i.name=yt.BODY_NAME,i.scale.copy(n),s.add(i),t.headingDeg!==void 0&&(s.rotation.y=-t.headingDeg*q0),this.addLights(s,t.lights),yt.fitLights(s,t,t.sizeM??{}),s}static scaleFor(t){const e=t.sizeM;if(!e||yt.hasFacade(t)||t.kind==="bridge"||t.kind==="wire"||t.kind==="terrace"||t.kind==="wall"||t.kind==="crossing")return new R(1,1,1);const i=this.naturalSize(t.kind,t.floors);return new R(e.widthM===void 0?1:j0(e.widthM,i.widthM),e.heightM===void 0?1:j0(t.kind==="building"?this.wallHeightOf(t,e.heightM):e.heightM,i.heightM),e.lengthM===void 0?1:j0(e.lengthM,i.lengthM))}static naturalSize(t,e){const i=t==="building"?Math.max(1,(e??zd)+1):0;if(t==="bridge")return ui.NATURAL_SIZE;if(t==="wire")return To.NATURAL_SIZE;if(t==="terrace"||t==="wall")return{widthM:1,lengthM:1,heightM:1};if(t==="crossing")return{widthM:6,lengthM:2.5,heightM:ge.CROSSING_LIFT_M};const n=`${t}:${i}`,s=v2.get(n);if(s)return s;const r=t==="building"?l2(i-1,void 0,void 0,void 0):t==="tree"?u2():t==="shrub"?h2():t==="crop"?f2():t==="mound"?p2():t==="streetlight"?m2(!1):t==="trafficlight"?ge.trafficLight(!1):t==="roadsign"?ge.roadSign(void 0):t==="vehicle"?g2(!1,void 0,void 0):t==="aircraft"?w2():t==="entity"?x2():ng(),a=new hn().setFromObject(r),c={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),v2.set(n,c),c}static usesModel(t){return Bd(t)!==void 0&&!(t.observerSide!==void 0&&al(t.kind))}static applyModel(t,e,i,n={}){const s=this.bodyOf(t),r=new Oe;r.name=yt.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*q0,i.updateMatrixWorld(!0);const a=new hn().setFromObject(i),c={lengthM:a.max.z-a.min.z,heightM:a.max.y-a.min.y,widthM:a.max.x-a.min.x},l=e.kind==="tree"&&e.sizeM?.heightM!==void 0?{heightM:e.sizeM.heightM}:e.sizeM,h=M2(l,c)??M2(n.depictedSizeM,c)??1;i.scale.multiplyScalar(h);const u=a.getCenter(new R).multiplyScalar(h);i.position.x-=u.x,i.position.z-=u.z,i.position.y-=e.kind==="aircraft"?u.y:a.min.y*h,i.traverse(d=>{d instanceof bt&&(d.castShadow=!0,d.receiveShadow=!0)}),r.add(i),e.kind==="tree"&&r.add(yt.trunkShadow(c.heightM*h)),s.parent?(s.parent.add(r),s.removeFromParent()):t.add(r),this.dispose(s),yt.fitLights(t,e,{widthM:c.widthM*h,heightM:c.heightM*h,lengthM:c.lengthM*h})}static fitLights(t,e,i){const n=Hd.byId(Bc.rigOf(e)||void 0)?.referenceSizeM;if(!n||!e.lights)return;const s=(h,u)=>h===void 0||u===0?1:h/u,r=s(i.widthM,n.widthM),a=s(i.heightM,n.heightM),c=s(i.lengthM,n.lengthM),l=new Map(e.lights.map(h=>[h.id,h.offsetM]));t.traverse(h=>{const u=h.userData.lightId,d=u===void 0?void 0:l.get(u);d&&h.position.set(d.x*r,d.y*a,d.z*c)})}static trunkShadow(t){yt.trunkProxy??={geometry:new Cn(1,1.15,1,8),material:new es({colorWrite:!1,depthWrite:!1})};const e=new bt(yt.trunkProxy.geometry,yt.trunkProxy.material),i=Math.min(.3,Math.max(.12,t*.035)),n=t*.45;return e.scale.set(i,n,i),e.position.y=n/2,e.castShadow=!0,e.receiveShadow=!1,e.userData.sharedModel=!0,e.name="trunk-shadow",e}static trunkProxy;static sizeOf(t){const e=this.naturalSize(t.kind,t.floors);return{widthM:t.sizeM?.widthM??e.widthM,lengthM:t.sizeM?.lengthM??e.lengthM,heightM:t.sizeM?.heightM??e.heightM}}static addLights(t,e){for(const i of e??[]){const n=_C(i.color),s=se.figureOf(i),r=s?ge.pedestrianFigure(s,1.8*(i.radiusM??K0)):new Gi(i.radiusM??K0,8,6),a=Ue(t,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 c=a.material;Xx.apply(c),c.transparent=!0,c.depthWrite=!1,c.fog=!1}}static setLights(t,e,i,n,s=0,r=1,a=xC,c=[1,1,1],l){if(!e||e.length===0)return;const h=new Map(e.map(d=>[d.id,d]));let u;l&&e.some(d=>d.beamDeg!==void 0)&&(t.updateWorldMatrix(!0,!1),u=t.worldToLocal(yt.eyeScratch.copy(l)));for(const d of t.children){if(!(d instanceof bt))continue;const f=d.userData.lightId;if(!f)continue;const p=h.get(f);if(!p)continue;const g=s>0?_y(p,i,i+s):oS(p,i)?1:0,m=u&&p.beamDeg!==void 0?yt.beamShare(p.beamDeg,d.position,u):1;d.visible=g>0&&m>0;const v=p.radiusM??K0,y=Math.max(1,n*a/v),x=v*y,M=r/(Math.PI*x*x),b=d.material,S=d.userData.lightColor;if(S){const E=g*m*bC*(p.intensity??1)*M,w=[S[0]*E*c[0],S[1]*E*c[1],S[2]*E*c[2]],_=Math.min(1,o2/Math.max(w[0],w[1],w[2],1e-30));b.color.setRGB(w[0]*_,w[1]*_,w[2]*_)}d.scale.setScalar(y)}}static eyeScratch=new R;static beamShare(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=i.z-e.z,a=Math.hypot(n,s,r);if(a===0)return 1;const c=-r/a;if(c<=0)return 0;const l=Math.log(.5)/Math.log(Math.cos(t*Math.PI/180));return Math.pow(c,l)}static setLit(t,e,i,n=1,s){const[r,a,c]=e==="streetlight"?[wC*yt.lampShare(s),SC,yt.lampHue(s)]:[EC,AC,vb],l=i?r*n/(Math.PI*a*a):0,h=Math.min(1,o2/Math.max(c[0]*l,c[1]*l,c[2]*l,1e-30)),u=[c[0]*l*h,c[1]*l*h,c[2]*l*h];t.traverse(d=>{const f=d.userData;!(d instanceof bt)||!f.emissive||f.lightId||(d.material instanceof Rs?d.material.emissive.setRGB(...u):d.material.color.setRGB(...u))})}static REFERENCE_LUMENS=1e4;static lampShare(t){return t?.lumens?t.lumens/yt.REFERENCE_LUMENS:1}static lampHue(t){return t?.colorTemperatureK?el.ofTemperature(t.colorTemperatureK):RC}static dispose(t){t.traverse(e=>{if(!(e instanceof bt))return;if(e.userData.sharedModel){for(const n of e.userData.tintedMaterials??[])n.dispose();return}e.geometry.dispose();const i=e.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const tp="https://ufoathome.org/models/index.json";class mh{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??qC()}async entries(t){const e=await this.load();return t?e.filter(i=>[i.kind].flat().includes(t)):e}async entry(t){return(await this.load()).find(e=>e.id===t)}load(){if(this.loading)return this.loading;if(!this.sharing)return this.loading=this.fetchFirstAvailable();const t=this.indexUrls.join(`
8635
- `);let e=mh.shared.get(t);return e||(e=this.fetchFirstAvailable(),mh.shared.set(t,e),e.then(i=>{i.length===0&&mh.shared.delete(t)})),this.loading=e}async fetchFirstAvailable(){for(const t of this.indexUrls){const e=await this.fetchIndex(t);if(e)return e}return[]}async fetchIndex(t){try{const e=await this.fetchImpl(t);if(!e.ok)return;const i=await e.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,t).href})):void 0}catch{return}}}function qC(){const o=`?v=${encodeURIComponent("0.144.0")}`,t=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(t&&t!==tp?[t,tp]:[tp]).map(e=>e+o)}const KC=[{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 mh}];async function ep(o){const{GLTFLoader:t}=await we(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-BGUT3v5v.js");return{GLTFLoader:i}},[],import.meta.url),e=new t;return new Promise((i,n)=>{e.load(o,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${o}: ${s instanceof Error?s.message:String(s)}`)))})}const Eb=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class us{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(t,e){this.mesh=new bt(new Gn(2,2),new Se({uniforms:{uColor:{value:new st(0,0,0)},uRadius:{value:1}},vertexShader:us.VERTEX,fragmentShader:us.FRAGMENT,transparent:!0,depthWrite:!1,blending:nn,toneMapped:!1})),this.mesh.name=t,this.mesh.frustumCulled=!1,this.mesh.renderOrder=e,this.mesh.visible=!1}shine(t,e,i){this.mesh.visible=!0,this.mesh.position.set(t.x,t.y,t.z),this.mesh.material.uniforms.uRadius.value=e,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(t,e,i,n){const s=Math.max(t,n*us.MIN_ANGLE_RAD),r=us.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(us.MAX_SHARE,e/r)}}static conserving(t){return Math.sqrt(t/(us.MAX_SHARE*us.FILL*Math.PI))}static VERTEX=`
8635
+ `);let e=mh.shared.get(t);return e||(e=this.fetchFirstAvailable(),mh.shared.set(t,e),e.then(i=>{i.length===0&&mh.shared.delete(t)})),this.loading=e}async fetchFirstAvailable(){for(const t of this.indexUrls){const e=await this.fetchIndex(t);if(e)return e}return[]}async fetchIndex(t){try{const e=await this.fetchImpl(t);if(!e.ok)return;const i=await e.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,t).href})):void 0}catch{return}}}function qC(){const o=`?v=${encodeURIComponent("0.145.0")}`,t=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(t&&t!==tp?[t,tp]:[tp]).map(e=>e+o)}const KC=[{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 mh}];async function ep(o){const{GLTFLoader:t}=await we(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-BGUT3v5v.js");return{GLTFLoader:i}},[],import.meta.url),e=new t;return new Promise((i,n)=>{e.load(o,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${o}: ${s instanceof Error?s.message:String(s)}`)))})}const Eb=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class us{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(t,e){this.mesh=new bt(new Gn(2,2),new Se({uniforms:{uColor:{value:new st(0,0,0)},uRadius:{value:1}},vertexShader:us.VERTEX,fragmentShader:us.FRAGMENT,transparent:!0,depthWrite:!1,blending:nn,toneMapped:!1})),this.mesh.name=t,this.mesh.frustumCulled=!1,this.mesh.renderOrder=e,this.mesh.visible=!1}shine(t,e,i){this.mesh.visible=!0,this.mesh.position.set(t.x,t.y,t.z),this.mesh.material.uniforms.uRadius.value=e,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(t,e,i,n){const s=Math.max(t,n*us.MIN_ANGLE_RAD),r=us.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(us.MAX_SHARE,e/r)}}static conserving(t){return Math.sqrt(t/(us.MAX_SHARE*us.FILL*Math.PI))}static VERTEX=`
8636
8636
  uniform float uRadius;
8637
8637
  varying vec2 vOffset;
8638
8638
  void main() {
@@ -9332,7 +9332,7 @@ void main() {
9332
9332
  `);let s=ar.cache.get(n);return s||(s=Promise.all(i.map(r=>ar.load(r.url))).then(r=>r.reduce((a,c)=>ar.concat(a,c))),ar.cache.set(n,s)),s}static parse(t){const e=t.byteLength/(4*Float32Array.BYTES_PER_ELEMENT),i=e*Float32Array.BYTES_PER_ELEMENT;return{count:e,ra:new Float32Array(t,0*i,e),dec:new Float32Array(t,1*i,e),mag:new Float32Array(t,2*i,e),ci:new Float32Array(t,3*i,e)}}static concat(t,e){const i=(n,s)=>{const r=new Float32Array(n.length+s.length);return r.set(n,0),r.set(s,n.length),r};return{count:t.count+e.count,ra:i(t.ra,e.ra),dec:i(t.dec,e.dec),mag:i(t.mag,e.mag),ci:i(t.ci,e.ci)}}}class We{constructor(t){if(this.heights=t,t.length!==We.WIDTH*We.HEIGHT)throw new Error(`a lunar relief has ${We.WIDTH*We.HEIGHT} samples, not ${t.length}`)}static SAMPLES_PER_DEGREE=16;static WIDTH=360*We.SAMPLES_PER_DEGREE;static HEIGHT=180*We.SAMPLES_PER_DEGREE;static UNIT_KM=.1;static REFERENCE_RADIUS_KM=1737.4;static BAND_FROM_DEG=74;static BAND_TO_DEG=106;heightKm(t,e){const i=We.SAMPLES_PER_DEGREE,n=(e%360+360)%360*i-.5,s=(90-t)*i-.5,r=Math.floor(n),a=Math.floor(s),c=n-r,l=s-a,h=(f,p)=>{const g=(f%We.WIDTH+We.WIDTH)%We.WIDTH,m=Math.min(We.HEIGHT-1,Math.max(0,p));return this.heights[m*We.WIDTH+g]},u=h(r,a)*(1-c)+h(r+1,a)*c,d=h(r,a+1)*(1-c)+h(r+1,a+1)*c;return(u*(1-l)+d*l)*We.UNIT_KM}static inBand(t,e){const i=Math.PI/180,n=Math.acos(Math.cos(t*i)*Math.cos(e*i))*180/Math.PI;return n>=We.BAND_FROM_DEG&&n<=We.BAND_TO_DEG}static withBump(t,e,i,n=.4){const s=new Int8Array(We.WIDTH*We.HEIGHT),r=We.SAMPLES_PER_DEGREE,a=Math.ceil(n*r),c=Math.floor(e*r),l=Math.floor((90-t)*r);for(let h=-a;h<=a;h++)for(let u=-a;u<=a;u++)Math.hypot(u,h)<=a&&(s[(l+h)*We.WIDTH+(c+u+We.WIDTH)%We.WIDTH]=Math.round(i/We.UNIT_KM));return new We(s)}static smooth(){return new We(new Int8Array(We.WIDTH*We.HEIGHT))}}class ws{static SAMPLES=5760;static SEARCH_FROM_DEG=87;static SEARCH_TO_DEG=90.2;static SEARCH_STEP_DEG=.0625;static profile(t,e,i,n=ws.SAMPLES){const{s,u:r,w:a,distanceKm:c}=ws.frame(t,e),l=Math.PI/180,h=new Float32Array(n),u=We.REFERENCE_RADIUS_KM;for(let d=0;d<n;d++){const f=d/n*2*Math.PI,p=Math.cos(f),g=Math.sin(f),m=p*r[0]+g*a[0],v=p*r[1]+g*a[1],y=p*r[2]+g*a[2];let x=0;for(let M=ws.SEARCH_FROM_DEG;M<=ws.SEARCH_TO_DEG;M+=ws.SEARCH_STEP_DEG){const b=Math.cos(M*l),S=Math.sin(M*l),E=b*s[0]+S*m,w=b*s[1]+S*v,_=b*s[2]+S*y,D=Math.asin(Math.max(-1,Math.min(1,_)))/l,I=Math.atan2(w,E)/l,O=u+i.heightKm(D,I),L=Math.atan2(O*S,c-O*b);L>x&&(x=L)}h[d]=x/l}return{radiusDeg:h,meanRadiusDeg:Math.asin(u/c)/l}}static frame(t,e){const i=new Qr(e.lat,e.lng,e.elevationM),n=ta(t),s=Vm(t,i,!1),r=new Ce(s.x-n.x,s.y-n.y,s.z-n.z,n.t),a=Math.hypot(r.x,r.y,r.z)*ws.AU_KM,c=ws.bodyFixed(t),l=c(r),h=Math.hypot(l[0],l[1],l[2]),u=[l[0]/h,l[1]/h,l[2]/h],d=_D(t,i),f=Jg(d),p=Zr(d,new Ce(-r.x,-r.y,-r.z,n.t)),g=Math.asin(p.z/Math.hypot(p.x,p.y,p.z)),m=Math.atan2(-p.y,p.x),v=new Ce(-Math.sin(g)*Math.cos(m),Math.sin(g)*Math.sin(m),Math.cos(g),n.t),y=new Ce(-Math.sin(m),-Math.cos(m),0,n.t);return{s:u,u:c(Zr(f,v)),w:c(Zr(f,y)),distanceKm:a}}static surfacePoint(t,e,i,n){const{s,u:r,w:a}=ws.frame(t,e),c=Math.PI/180,l=[0,1,2].map(u=>Math.cos(i*c)*r[u]+Math.sin(i*c)*a[u]),h=[0,1,2].map(u=>Math.cos(n*c)*s[u]+Math.sin(n*c)*l[u]);return{latDeg:Math.asin(h[2])/c,lonDeg:Math.atan2(h[1],h[0])/c}}static radiusAt(t,e){const i=t.radiusDeg.length,n=(e/360*i%i+i)%i,s=Math.floor(n),r=n-s;return t.radiusDeg[s]*(1-r)+t.radiusDeg[(s+1)%i]*r}static uncoveredFraction(t,e,i){const n=t.radiusDeg.length,s=i.upDeg*i.upDeg+i.rightDeg*i.rightDeg;let r=0;for(let a=0;a<n;a++){const c=a/n*2*Math.PI,l=Math.cos(c),h=Math.sin(c),u=l*i.upDeg+h*i.rightDeg,d=u*u-s+e*e;if(d<=0)continue;const f=Math.sqrt(d),p=u+f;if(p<=0)continue;const g=Math.max(0,u-f),m=Math.max(g,t.radiusDeg[a]);p>m&&(r+=.5*(p*p-m*m))}return Math.min(1,Math.max(0,r*(2*Math.PI/n)/(Math.PI*e*e)))}static AU_KM=1495978707e-1;static bodyFixed(t){const e=GD(ut.Moon,t),i=Math.PI/180,n=e.ra*15*i,s=e.dec*i,r=e.spin*i,a=(l,[h,u,d])=>[Math.cos(l)*h+Math.sin(l)*u,-Math.sin(l)*h+Math.cos(l)*u,d],c=(l,[h,u,d])=>[h,Math.cos(l)*u+Math.sin(l)*d,-Math.sin(l)*u+Math.cos(l)*d];return l=>a(r,c(Math.PI/2-s,a(Math.PI/2+n,[l.x,l.y,l.z])))}static subObserverPoint(t,e){const i=new Qr(e.lat,e.lng,e.elevationM),n=ta(t),s=Vm(t,i,!1),r=ws.bodyFixed(t)(new Ce(s.x-n.x,s.y-n.y,s.z-n.z,n.t)),a=Math.hypot(r[0],r[1],r[2]);return{latDeg:Math.asin(r[2]/a)*180/Math.PI,lonDeg:Math.atan2(r[1],r[0])*180/Math.PI}}}class gh{static cache=new Map;static load(t){let e=gh.cache.get(t);return e||(e=gh.fetchRelief(t).catch(()=>{}),gh.cache.set(t,e)),e}static async fetchRelief(t){const e=await fetch(t);if(!e.ok)return;let i=new Uint8Array(await e.arrayBuffer());if(i[0]===31&&i[1]===139){if(typeof DecompressionStream>"u")return;const n=new Blob([i]).stream().pipeThrough(new DecompressionStream("gzip"));i=new Uint8Array(await new Response(n).arrayBuffer())}return new We(new Int8Array(i.buffer,i.byteOffset,i.length))}}class yf{static ID="color-vision";static MATRICES={protan:[.152286,1.052583,-.204868,.114503,.786281,.099216,-.003882,-.048116,1.051998],deutan:[.367322,.860646,-.227968,.280085,.672501,.047413,-.01182,.04294,.968881],tritan:[1.255528,-.076749,-.178779,-.078411,.930809,.147602,.004733,.691367,.3039]};id=yf.ID;label="Colour vision";hint="How colours look to someone whose cones differ, from Machado et al. 2009. Only recolours: it does not change brightness or what the eye can resolve.";sources=["Machado, Oliveira, Fernandes, A Physiologically-based Model for Simulation of Color Vision Deficiency, IEEE TVCG 15(6), 2009"];settings=[{id:"type",label:"Type",kind:"choice",default:"normal",choices:[{id:"normal",label:"Typical"},{id:"protan",label:"Protan (red-weak or red-blind)"},{id:"deutan",label:"Deutan (green-weak or green-blind)"},{id:"tritan",label:"Tritan (blue-weak or blue-blind)"}]},{id:"severity",label:"Severity",kind:"number",default:100,min:0,max:100,step:5,unit:"%"}];perceive(t){const e=yf.MATRICES[String(t.type)];if(!e)return is.NONE;const i=Number(t.severity??100),n=Math.max(0,Math.min(100,Number.isFinite(i)?i:100))/100;return{colorMatrix:e.map((r,a)=>is.IDENTITY[a]+(r-is.IDENTITY[a])*n),contrastGain:1}}}class r1{static ID="fatigue";id=r1.ID;label="Fatigue";hint="Stated only: sleep loss has not been shown to change what a healthy eye receives, so the picture is unchanged. It bears on attention and memory, not on vision.";sources=["Studies of contrast sensitivity during prolonged sleep deprivation (60 hours, naval officers): no significant change"];settings=[{id:"hoursAwake",label:"Awake for",kind:"number",default:0,min:0,max:72,step:1,unit:"h"}];perceive(t){return is.NONE}}class so{static ID="intoxication";static MEASURED_LEVEL=.08;static MEASURED_LOSS_DB=.9;static MAX_EFFECT_LEVEL=.1;static MAX_LEVEL=.5;id=so.ID;label="Alcohol";hint="Lowers contrast sensitivity by about 0.9 dB at 0.08 % blood alcohol (one controlled study, results vary), drawn up to 0.1 % at most: a higher level is recorded but shown as 0.1 %, since nothing was measured past it. Double vision, narrowed field and other drugs are not modelled: no source quantifies them.";sources=["Frontiers in Neuroscience, 2022, doi:10.3389/fnins.2022.873671 (contrast sensitivity at about 0.08 % blood alcohol)"];settings=[{id:"bloodAlcohol",label:"Blood alcohol",kind:"number",default:0,min:0,max:so.MAX_LEVEL,step:.01,unit:"%",also:{unit:"g/L",factor:10,digits:1}}];perceive(t){const e=Number(t.bloodAlcohol??0),i=Math.max(0,Math.min(so.MAX_EFFECT_LEVEL,Number.isFinite(e)?e:0));if(i===0)return is.NONE;const n=i/so.MEASURED_LEVEL*so.MEASURED_LOSS_DB;return{colorMatrix:is.IDENTITY,contrastGain:10**(-n/20)}}}class vh{static ALL=[new yf,new so,new r1];static byId(t){return vh.ALL.find(e=>e.id===t)}static perceptionOf(t){return vh.ALL.reduce((e,i)=>is.combine(e,i.perceive(t?.[i.id]??{})),is.NONE)}static compact(t){const e={};for(const i of vh.ALL){const n=t[i.id]??{},s=Object.fromEntries(i.settings.filter(r=>n[r.id]!==void 0&&n[r.id]!==r.default).map(r=>[r.id,n[r.id]]));Object.keys(s).length>0&&(e[i.id]=s)}return Object.keys(e).length>0?e:void 0}}class xf{constructor(t){this.names=t}body(t,e){return this.names?.bodies[t]??e}star(t){return this.names?.stars[t.name]??t.name}comet(t){return this.names?.comets[t.id]??t.name}nova(t){return this.names?.novae[t.id]??t.name}satelliteClass(t){return this.names?.satelliteClasses[t.id]??t.name}shower(t){return this.names?.showers[t.id]??t.name}lightRig(t){return this.names?.lightRigs[t.id]??t.name}instrument(t){return this.names?.instruments[t.id]??t.name}decorKind(t,e){return this.names?.decorKinds[t]??e}point(t){return Po.point(t,this.names?.compassPoints)}towards(t){return Po.towards(t,this.names)}}class zs{static ENGLISH={kinds:{rail:"Railway",light_rail:"Light rail",tram:"Tramway",subway:"Metro",funicular:"Funicular"},highSpeed:"High-speed line",service:"Siding",singleTrack:"single track",tracks:"{count} tracks",overhead:"overhead wire {height} m above the rail",overheadVoltage:"overhead wire at {voltage}, {height} m above the rail",thirdRail:"third rail",thirdRailVoltage:"third rail at {voltage}",notElectrified:"not electrified",gauge:"{mm} mm gauge",metreGauge:"metre gauge",distance:"{distance} away"};static STANDARD_GAUGE_MM=1435;static METRE_GAUGE_MM=1e3;static kind(t,e){return t.highSpeed?e.highSpeed:t.service?e.service:e.kinds[t.kind]}static name(t,e){const i=t.name??zs.kind(t,e);return t.services?.length?`${i} — ${t.services.join(", ")}`:i}static voltage(t,e){return t>=1e3?`${(t/1e3).toLocaleString(e,{maximumFractionDigits:1})} kV`:`${t.toLocaleString(e)} V`}static detail(t,e,i,n){const{line:s}=t,r=[];s.name&&r.push(zs.kind(s,e).toLocaleLowerCase(n)),r.push(s.tracks>1?e.tracks.replace("{count}",String(s.tracks)):e.singleTrack);const a=s.voltageV?zs.voltage(s.voltageV,n):void 0;if(t.contactM!==void 0){const c=t.contactM.toLocaleString(n,{minimumFractionDigits:2,maximumFractionDigits:2});r.push((a?e.overheadVoltage.replace("{voltage}",a):e.overhead).replace("{height}",c))}else s.electrification==="third_rail"?r.push(a?e.thirdRailVoltage.replace("{voltage}",a):e.thirdRail):s.electrification==="none"&&r.push(e.notElectrified);return s.gaugeMm===zs.METRE_GAUGE_MM?r.push(e.metreGauge):s.gaugeMm!==zs.STANDARD_GAUGE_MM&&r.push(e.gauge.replace("{mm}",s.gaugeMm.toLocaleString(n))),r.push(e.distance.replace("{distance}",i(t.distanceM))),s.services?.length?`${zs.name(s,e)}; ${r.join(", ")}`:`${zs.name(s,e)} — ${r.join(", ")}`}}class a1{constructor(t,e){this.element=t,this.onChange=e,t.addEventListener("error",()=>{this.url=void 0,this.release()})}shown=!1;url;get up(){return this.shown}show(t,e,i=!0){const n=a1.resolve(t,e);if(this.url=n,!n||!i){this.release();return}this.element.src=n,this.element.hidden=!1;const s=this.shown;this.shown=!0,s||this.onChange()}release(){this.shown&&(this.shown=!1,this.element.hidden=!0,this.element.removeAttribute("src"),this.onChange())}restore(){this.url&&this.show(this.url)}static resolve(t,e){if(!(typeof t!="string"||t.trim()===""))try{const i=new URL(t.trim(),e??location.href);return i.protocol==="https:"||i.protocol==="http:"?i.href:void 0}catch{return}}}const rO={halo22:"22° halo — a ring round the Sun, from light bent through hexagonal ice crystals in high cirrus; its inner edge is red, at 21.7°",halo46:"46° halo — a rarer, fainter ring: light entering a crystal by a side face and leaving by an end face",oddRadius:"{angle}° halo — an odd-radius ring, rare and faint, made by ice crystals with pyramid ends",parhelion:"Parhelion (sundog) — a bright coloured spot beside the Sun at its own height, from flat plates falling level; red toward the Sun",parhelion120:"120° parhelion — a faint white spot 120° from the Sun, from light reflected inside flat plates",upperTangentArc:"Upper tangent arc — a bright arc resting on top of the 22° halo, from columns lying level",lowerTangentArc:"Lower tangent arc — an arc touching the bottom of the 22° halo, from columns lying level",circumzenithal:"Circumzenithal arc — a vivid band of colour near the zenith, from light entering the top face of flat plates (only with the Sun under 32°)",circumhorizontal:"Circumhorizontal arc — a band of colour low in the sky, from light entering the side face of flat plates (only with the Sun over 58°)",parhelicCircle:"Parhelic circle — a white circle round the whole sky at the Sun's own height, from reflections on the vertical faces of flat plates",pillar:"Light pillar — a shaft of light standing above the Sun, from reflections off slightly tilted flat plates",subsun:"Subsun — a mirror image of the Sun below the horizon, from reflections off the flat faces of plates"},aO=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,oO=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,cO=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,lO=20,hO=1;class uO{context;buffers=new Map;ambientSource;ambientGain;ambientKey="none";ambientToken=0;ambientVolume=0;windSource;windGain;windActive=!1;windToken=0;windVolume=0;paused=!0;requested={type:"none",intensity:0,windSpeed:0};level=1;master;output(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("WeatherAudio: Web Audio unavailable, weather sounds disabled:",t);return}}Io.unlock(this.context)}setAmbient(t,e,i){if(this.requested={type:t,intensity:e,windSpeed:i},!this.context)return;this.paused&&(t="none",e=0,i=0);const n=t==="rain"||t==="hail"?t:"none";if(this.ambientVolume=n==="hail"?Math.min(1,e*1.3+.2):n==="rain"?e:0,n!==this.ambientKey){this.ambientKey=n;const r=++this.ambientToken;this.stopSource(this.ambientSource,this.ambientGain),this.ambientSource=void 0,this.ambientGain=void 0,n!=="none"&&this.startLoop(aO,this.ambientVolume).then(a=>this.applyIfCurrent(a,r,()=>this.ambientToken,c=>{this.ambientSource=c?.source,this.ambientGain=c?.gain,c&&(c.gain.gain.value=this.ambientVolume)}))}else this.ambientGain&&(this.ambientGain.gain.value=this.ambientVolume);this.windVolume=Math.min(i/lO,1);const s=i>hO;if(s!==this.windActive){this.windActive=s;const r=++this.windToken;this.stopSource(this.windSource,this.windGain),this.windSource=void 0,this.windGain=void 0,s&&this.startLoop(oO,this.windVolume).then(a=>this.applyIfCurrent(a,r,()=>this.windToken,c=>{this.windSource=c?.source,this.windGain=c?.gain,c&&(c.gain.gain.value=this.windVolume)}))}else this.windGain&&(this.windGain.gain.value=this.windVolume)}setPaused(t){if(t===this.paused)return;this.paused=t;const{type:e,intensity:i,windSpeed:n}=this.requested;this.setAmbient(e,i,n)}playThunder(){!this.context||this.paused||this.playOneShot(cO,.9)}dispose(){this.ambientToken++,this.windToken++,this.stopSource(this.ambientSource,this.ambientGain),this.stopSource(this.windSource,this.windGain),this.ambientSource=void 0,this.ambientGain=void 0,this.windSource=void 0,this.windGain=void 0,this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear()}applyIfCurrent(t,e,i,n){if(e!==i()){t?.source.stop();return}n(t)}async startLoop(t,e){const i=this.context;if(i)try{const n=await this.getBuffer(t),s=i.createBufferSource();s.buffer=n,s.loop=!0;const r=i.createGain();return r.gain.value=e,s.connect(r).connect(this.output(i)),s.start(),{source:s,gain:r}}catch(n){console.warn("Weather ambient sound failed to load, staying silent:",n);return}}async playOneShot(t,e){const i=this.context;if(i)try{const n=await this.getBuffer(t),s=i.createBufferSource();s.buffer=n;const r=i.createGain();r.gain.value=e,s.connect(r).connect(this.output(i)),s.start()}catch(n){console.warn("Thunder sound failed to load:",n)}}async getBuffer(t){const e=this.context;if(!e)throw new Error("WeatherAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(t);return i||(i=fetch(t).then(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${t}`);return n.arrayBuffer()}).then(n=>e.decodeAudioData(n)),this.buffers.set(t,i)),i}stopSource(t,e){try{t?.stop()}catch{}t?.disconnect(),e?.disconnect()}}class Wr{constructor(t){this.elements=t;const{eccentricity:e,perihelionAu:i}=t,[n,s]=this.perifocalAxes(),r=Math.sqrt(Wr.SUN_GM_AU3_PER_DAY2*(1+e)/i);this.perihelionPosition=this.scale(n,i),this.perihelionVelocity=this.scale(s,r),this.inverseSemiMajorAxis=(1-e)/i}static SUN_GM_AU3_PER_DAY2=.0002959122082855911;static MAX_ITERATIONS=200;perihelionPosition;perihelionVelocity;inverseSemiMajorAxis;positionAt(t){const e=t-this.elements.perihelionJd,i=this.universalAnomaly(e),n=this.inverseSemiMajorAxis*i*i,s=this.elements.perihelionAu,r=1-i*i/s*Wr.stumpffC(n),a=e-i*i*i/Math.sqrt(Wr.SUN_GM_AU3_PER_DAY2)*Wr.stumpffS(n);return{x:r*this.perihelionPosition.x+a*this.perihelionVelocity.x,y:r*this.perihelionPosition.y+a*this.perihelionVelocity.y,z:r*this.perihelionPosition.z+a*this.perihelionVelocity.z}}heliocentricDistanceAt(t){const e=this.positionAt(t);return Math.hypot(e.x,e.y,e.z)}universalAnomaly(t){if(t===0)return 0;const e=Math.sign(t),i=Math.sqrt(Wr.SUN_GM_AU3_PER_DAY2)*Math.abs(t),n=a=>{const c=this.inverseSemiMajorAxis*a*a,l=this.elements.perihelionAu;return(1-this.inverseSemiMajorAxis*l)*a*a*a*Wr.stumpffS(c)+l*a};let s=Math.max(1,i/this.elements.perihelionAu);for(;n(s)<i;)s*=2;let r=0;for(let a=0;a<Wr.MAX_ITERATIONS&&s-r>1e-13*Math.max(1,s);a++){const c=(r+s)/2;n(c)<i?r=c:s=c}return e*(r+s)/2}perifocalAxes(){const t=this.elements.ascendingNodeDeg*Math.PI/180,e=this.elements.argumentOfPerihelionDeg*Math.PI/180,i=this.elements.inclinationDeg*Math.PI/180,n=Math.cos(t),s=Math.sin(t),r=Math.cos(e),a=Math.sin(e),c=Math.cos(i),l=Math.sin(i);return[{x:n*r-s*a*c,y:s*r+n*a*c,z:a*l},{x:-n*a-s*r*c,y:-s*a+n*r*c,z:r*l}]}scale(t,e){return{x:t.x*e,y:t.y*e,z:t.z*e}}static stumpffC(t){if(Math.abs(t)<1e-6)return 1/2-t/24+t*t/720;if(t>0)return(1-Math.cos(Math.sqrt(t)))/t;const e=Math.sqrt(-t);return(Math.cosh(e)-1)/-t}static stumpffS(t){if(Math.abs(t)<1e-6)return 1/6-t/120+t*t/5040;if(t>0){const i=Math.sqrt(t);return(i-Math.sin(i))/(i*i*i)}const e=Math.sqrt(-t);return(Math.sinh(e)-e)/(e*e*e)}}const Db=[{id:"halley-1910",designation:"1P/Halley",name:"Halley's Comet",orbit:{eccentricity:.9672960498922706,perihelionAu:.5872100477652511,inclinationDeg:162.218798367122,ascendingNodeDeg:58.56208298700436,argumentOfPerihelionDeg:111.7366940639061,perihelionJd:2.4187816784171113e6},peakMagnitude:0,peakOn:"1910-05-20",absoluteMagnitude:4.72,activityExponent:4,tailLengthDeg:100,tailLengthAu:.1638,note:"Passed 0.15 au from Earth on 20 May 1910, and the Earth crossed the outer tail the day before — the apparition that produced a genuine public panic."},{id:"brooks-1911",designation:"C/1911 O1",name:"Comet Brooks",orbit:{eccentricity:.9876404970138669,perihelionAu:.4898172916113738,inclinationDeg:33.34043866978714,ascendingNodeDeg:293.7022074981857,argumentOfPerihelionDeg:153.5578007321686,perihelionJd:2.4193378856140426e6},peakMagnitude:2,peakOn:"1911-10-25",absoluteMagnitude:5.59,activityExponent:4},{id:"skjellerup-maristany-1927",designation:"C/1927 X1",name:"Comet Skjellerup-Maristany",orbit:{eccentricity:.999839726885059,perihelionAu:.1761569619628186,inclinationDeg:85.1125991950808,ascendingNodeDeg:78.24360172472711,argumentOfPerihelionDeg:47.15877857390136,perihelionJd:2.4252326808989984e6},peakMagnitude:-6,peakOn:"1927-12-15",absoluteMagnitude:1.19,activityExponent:4,note:"One of the few comets of the century seen in full daylight."},{id:"de-kock-paraskevopoulos-1941",designation:"C/1941 B2",name:"Comet de Kock-Paraskevopoulos",orbit:{eccentricity:.9991026715181549,perihelionAu:.7900329662827822,inclinationDeg:168.2039226531089,ascendingNodeDeg:43.10609347214336,argumentOfPerihelionDeg:268.6990344196369,perihelionJd:2430022157765061e-9},peakMagnitude:2,peakOn:"1941-02-05",absoluteMagnitude:5.01,activityExponent:4},{id:"southern-1947",designation:"C/1947 X1",name:"the Southern Comet",orbit:{eccentricity:.9998424430916737,perihelionAu:.1100045955093761,inclinationDeg:138.5113919632757,ascendingNodeDeg:337.3114969669252,argumentOfPerihelionDeg:196.1820121395961,perihelionJd:2.4325220864727003e6},peakMagnitude:-3,peakOn:"1947-12-08",absoluteMagnitude:3.01,activityExponent:4,note:"A bright southern-hemisphere comet of December 1947, the month the American sighting wave of that year was still being argued over."},{id:"eclipse-1948",designation:"C/1948 V1",name:"the Eclipse Comet",orbit:{eccentricity:.9999130678247334,perihelionAu:.1354437057263306,inclinationDeg:23.11668597152911,ascendingNodeDeg:211.0454985994762,argumentOfPerihelionDeg:107.2474157073104,perihelionJd:2.4328519265329437e6},peakMagnitude:-2,peakOn:"1948-11-01",absoluteMagnitude:4.79,activityExponent:4,note:"Found during the total solar eclipse of 1 November 1948, which is how a comet that bright had gone unnoticed: it had been hidden in the Sun's glare."},{id:"arend-roland-1957",designation:"C/1956 R1",name:"Comet Arend-Roland",orbit:{eccentricity:1.0002570255357,perihelionAu:.3160532361485914,inclinationDeg:119.9440863251822,ascendingNodeDeg:215.8548157717755,argumentOfPerihelionDeg:308.775920364167,perihelionJd:2.4359365327396123e6},peakMagnitude:.5,peakOn:"1957-04-25",absoluteMagnitude:3.96,activityExponent:4,note:"Showed a spike pointing back TOWARD the Sun in late April 1957 — a real anti-tail, and much reported at the time."},{id:"mrkos-1957",designation:"C/1957 P1",name:"Comet Mrkos",orbit:{eccentricity:.9993521583504134,perihelionAu:.3549238508212375,inclinationDeg:93.9433042053929,ascendingNodeDeg:68.32441518619923,argumentOfPerihelionDeg:40.31823675802871,perihelionJd:243605193752228e-8},peakMagnitude:1,peakOn:"1957-08-05",absoluteMagnitude:5.07,activityExponent:4,note:"The second bright naked-eye comet of 1957, four months after Arend-Roland."},{id:"seki-lines-1962",designation:"C/1962 C1",name:"Comet Seki-Lines",orbit:{eccentricity:1.000003791331562,perihelionAu:.03139689112215131,inclinationDeg:65.01487186102287,ascendingNodeDeg:304.6776602796538,argumentOfPerihelionDeg:11.47295326312573,perihelionJd:2437756163010178e-9},peakMagnitude:-2.5,peakOn:"1962-04-01",absoluteMagnitude:9.3,activityExponent:4},{id:"ikeya-seki-1965",designation:"C/1965 S1",name:"Comet Ikeya-Seki",orbit:{eccentricity:.9999141178248997,perihelionAu:.007785966366889336,inclinationDeg:141.8642315267051,ascendingNodeDeg:346.9951764632611,argumentOfPerihelionDeg:69.04909813996062,perihelionJd:2.4390546837018197e6},peakMagnitude:-10,peakOn:"1965-10-21",alsoRecordedMagnitude:2,alsoRecordedOn:"1965-10-30",absoluteMagnitude:5.26,activityExponent:4.002,tailLengthDeg:25,tailLengthAu:.5048,note:"A sungrazer that passed 450 000 km above the Sun's surface and was seen beside it in broad daylight — the brightest comet of the twentieth century. It then stood in the dawn sky for a fortnight with a tail some 25 degrees long, which is the second magnitude recorded here."},{id:"bennett-1970",designation:"C/1969 Y1",name:"Comet Bennett",orbit:{eccentricity:.9962979048768408,perihelionAu:.5376209981502136,inclinationDeg:90.03975717147327,ascendingNodeDeg:224.6576652531314,argumentOfPerihelionDeg:354.1494209173161,perihelionJd:2.4406655455270996e6},peakMagnitude:0,peakOn:"1970-03-26",absoluteMagnitude:3.36,activityExponent:4},{id:"white-ortiz-bolelli-1970",designation:"C/1970 K1",name:"Comet White-Ortiz-Bolelli",orbit:{eccentricity:.9999488875801225,perihelionAu:.00884411465256722,inclinationDeg:138.9520738221631,ascendingNodeDeg:336.8194095816687,argumentOfPerihelionDeg:61.10224765396615,perihelionJd:2.4407209807728203e6},peakMagnitude:1,peakOn:"1970-05-22",absoluteMagnitude:4.35,activityExponent:4},{id:"kohoutek-1973",designation:"C/1973 E1",name:"Comet Kohoutek",orbit:{eccentricity:1.000007152175185,perihelionAu:.1424250377812859,inclinationDeg:14.30414984159355,ascendingNodeDeg:258.4893339663974,argumentOfPerihelionDeg:37.79772760699667,perihelionJd:2442044930687027e-9},peakMagnitude:0,peakOn:"1974-01-05",absoluteMagnitude:4.89,activityExponent:4,note:"Announced in advance as the comet of the century and remembered for disappointing: it was an ordinary naked-eye object, not the spectacle the press had promised."},{id:"west-1976",designation:"C/1975 V1",name:"Comet West",orbit:{eccentricity:1.000017859625611,perihelionAu:.1966006188461085,inclinationDeg:43.07319920579427,ascendingNodeDeg:118.9189245655447,argumentOfPerihelionDeg:358.4315101259072,perihelionJd:2442833721841768e-9},peakMagnitude:-3,peakOn:"1976-02-25",absoluteMagnitude:4.41,activityExponent:4,tailLengthDeg:30,tailLengthAu:.4325,note:"Broke into four pieces at perihelion. Barely reported at the time — the press had been burned by Kohoutek two years earlier."},{id:"iras-araki-alcock-1983",designation:"C/1983 H1",name:"Comet IRAS-Araki-Alcock",orbit:{eccentricity:.9898409731606003,perihelionAu:.9913412593828502,inclinationDeg:73.25000846947029,ascendingNodeDeg:49.10235754476374,argumentOfPerihelionDeg:192.8506176754439,perihelionJd:2.4454757545235856e6},peakMagnitude:1.7,peakOn:"1983-05-11",absoluteMagnitude:9.04,activityExponent:4,note:"Passed 0.031 au from Earth on 11 May 1983, one of the closest cometary approaches on record: it crossed a quarter of the sky in a night, which no other comet in this list did."},{id:"halley-1986",designation:"1P/Halley",name:"Halley's Comet",orbit:{eccentricity:.9672792271749998,perihelionAu:.5871034488173393,inclinationDeg:162.2422242700916,ascendingNodeDeg:58.85993640671803,argumentOfPerihelionDeg:111.8655480539208,perihelionJd:2.4464709589610207e6},peakMagnitude:2.1,peakOn:"1986-03-10",absoluteMagnitude:2.71,activityExponent:4,note:"The worst-placed return in two thousand years — famous, expected, and for most observers a faint smudge."},{id:"hyakutake-1996",designation:"C/1996 B2",name:"Comet Hyakutake",orbit:{eccentricity:.9997295133739305,perihelionAu:.2302272039470452,inclinationDeg:124.923592343765,ascendingNodeDeg:188.0454295899424,argumentOfPerihelionDeg:130.1724036582639,perihelionJd:2.4502048946148166e6},peakMagnitude:0,peakOn:"1996-03-25",absoluteMagnitude:4.75,activityExponent:4,tailLengthDeg:80,tailLengthAu:1,note:"Passed 0.10 au from Earth in March 1996, five weeks BEFORE perihelion, with a tail measured at some 80 degrees — the longest of the modern era."},{id:"hale-bopp-1997",designation:"C/1995 O1",name:"Comet Hale-Bopp",orbit:{eccentricity:.9951314746156615,perihelionAu:.9141695067003724,inclinationDeg:89.43017155012492,ascendingNodeDeg:282.470602866853,argumentOfPerihelionDeg:130.5872524854533,perihelionJd:2450539633099368e-9},peakMagnitude:-.8,peakOn:"1997-04-01",absoluteMagnitude:-1.06,activityExponent:4,tailLengthDeg:20,tailLengthAu:.9938,note:"Visible to the naked eye for about eighteen months, longer than any comet on record."},{id:"mcnaught-2007",designation:"C/2006 P1",name:"Comet McNaught",orbit:{eccentricity:1.00001811603225,perihelionAu:.1707325614080681,inclinationDeg:77.83726446452654,ascendingNodeDeg:267.4149080498975,argumentOfPerihelionDeg:155.9756130642756,perihelionJd:2454113298753579e-9},peakMagnitude:-5.5,peakOn:"2007-01-13",absoluteMagnitude:2.53,activityExponent:4,tailLengthDeg:35,tailLengthAu:.5009,note:"The brightest comet since Ikeya-Seki, seen in daylight beside the Sun in January 2007."},{id:"lovejoy-2011",designation:"C/2011 W3",name:"Comet Lovejoy",orbit:{eccentricity:.999915056276912,perihelionAu:.005553783989325053,inclinationDeg:134.3558712062691,ascendingNodeDeg:326.3693517957772,argumentOfPerihelionDeg:53.50991655176601,perihelionJd:2455911511809431e-9},peakMagnitude:-3,peakOn:"2011-12-16",alsoRecordedMagnitude:1.5,alsoRecordedOn:"2011-12-22",absoluteMagnitude:3.51,activityExponent:1.194,note:"A sungrazer that was expected to be destroyed at perihelion and came out the other side, to stand in the southern dawn sky for the rest of December — which is the second magnitude recorded here."},{id:"panstarrs-2013",designation:"C/2011 L4",name:"Comet PANSTARRS",orbit:{eccentricity:1.000032542889696,perihelionAu:.301544229714915,inclinationDeg:84.2081978367921,ascendingNodeDeg:65.66588626213694,argumentOfPerihelionDeg:333.6516444379993,perihelionJd:2456361669960698e-9},peakMagnitude:1,peakOn:"2013-03-10",absoluteMagnitude:5.98,activityExponent:4},{id:"neowise-2020",designation:"C/2020 F3",name:"Comet NEOWISE",orbit:{eccentricity:.9991782081129224,perihelionAu:.2946512466331692,inclinationDeg:128.9375043020912,ascendingNodeDeg:61.01042991771634,argumentOfPerihelionDeg:37.2786526292898,perihelionJd:2.4590341788972816e6},peakMagnitude:.9,peakOn:"2020-07-08",absoluteMagnitude:5.79,activityExponent:4,tailLengthDeg:10,tailLengthAu:.1808,note:"The first comet since Hale-Bopp that ordinary observers in the northern hemisphere saw without being told where to look."},{id:"tsuchinshan-atlas-2024",designation:"C/2023 A3",name:"Comet Tsuchinshan-ATLAS",orbit:{eccentricity:1.000020192843226,perihelionAu:.3914228969475176,inclinationDeg:139.1105462619479,ascendingNodeDeg:21.55945689078845,argumentOfPerihelionDeg:308.4913086299446,perihelionJd:2460581242087108e-9},peakMagnitude:0,peakOn:"2024-10-14",absoluteMagnitude:3.97,activityExponent:4,tailLengthDeg:20,tailLengthAu:.1902,note:"Briefly reported far brighter around 9 October 2024, when it stood almost between the observer and the Sun and forward-scattered the light through its own dust — a geometry this catalog's brightness model does not attempt, so what is stored is the ordinary evening-sky peak a few days later."}];class dO{static WINDOW_DAYS=200;static TWILIGHT_ELONGATION_DEG=15;static LIGHT_SPEED_AU_PER_DAY=173.144632674;static orbits=new Map;static aroundDate(t){const e=this.julianDayOf(t);return Db.filter(i=>Math.abs(e-i.orbit.perihelionJd)<=this.WINDOW_DAYS)}static brightestAt(t,e){return this.aroundDate(t).map(i=>this.appearanceOf(i,t,e)).sort((i,n)=>i.magnitude-n.magnitude)[0]}static appearanceOf(t,e,i){const n=Je(e),s=this.earthPositionAt(n),r=this.apparentPositionOf(t,2451545+n.tt,s),a=this.subtract(r,s),c=this.length(r),l=this.length(a),h=this.tailEndAt(t,r,s,c,n,e,i),u=this.horizontalOf(a,n,e,i);return{apparition:t,position:u,...h,heliocentricDistanceAu:c,earthDistanceAu:l,elongationDeg:this.angleBetween(a,this.subtract({x:0,y:0,z:0},s)),magnitude:this.magnitudeAt(t,c,l)}}static magnitudeAt(t,e,i){const n=t.absoluteMagnitude+5*Math.log10(i)+2.5*t.activityExponent*Math.log10(e);return Math.max(n,t.peakMagnitude)}static tailEndAt(t,e,i,n,s,r,a){if(t.tailLengthAu===void 0)return{};const c=1+t.tailLengthAu/n,l=this.subtract({x:e.x*c,y:e.y*c,z:e.z*c},i),h=this.subtract(e,i);return{tailEnd:this.horizontalOf(l,s,r,a),tailLengthDeg:this.angleBetween(h,l)}}static apparentPositionOf(t,e,i){const n=this.orbitOf(t);let s=n.positionAt(e);for(let r=0;r<2;r++){const a=this.length(this.subtract(s,i))/this.LIGHT_SPEED_AU_PER_DAY;s=n.positionAt(e-a)}return s}static horizontalOf(t,e,i,n){const s=Zr(wD(),new Ce(t.x,t.y,t.z,e)),r=Zr(db(e),s),a=Vm(e,new Qr(n.lat,n.lng,n.elevationM),!0),c=new Ce(r.x-a.x,r.y-a.y,r.z-a.z,e),l=Wf(c);return t1(l.ra,l.dec,i,n)}static earthPositionAt(t){return Zr(bD(),Fa(ut.Earth,t))}static julianDayOf(t){return 2451545+Je(t).tt}static orbitOf(t){const e=this.orbits.get(t.id);if(e)return e;const i=new Wr(t.orbit);return this.orbits.set(t.id,i),i}static subtract(t,e){return{x:t.x-e.x,y:t.y-e.y,z:t.z-e.z}}static length(t){return Math.hypot(t.x,t.y,t.z)}static angleBetween(t,e){const i=(t.x*e.x+t.y*e.y+t.z*e.z)/(this.length(t)*this.length(e)||1);return Math.acos(Math.min(1,Math.max(-1,i)))*180/Math.PI}}const xp=[{id:"sn-1006",kind:"supernova",designation:"SN 1006",name:"Supernova of 1006",raHours:15.03947,decDeg:-42.09694,peakMagnitude:-7.5,peakJd:2088620,startJd:2088620,lightCurve:[[0,-7.5],[29,-5.9],[60,-4.9],[106,-3.2],[166,-1.9],[258,-1],[350,.5],[364,.7],[411,1.2],[456,1.8],[484,2.5],[785.5,7]],source:"Winkler, Gupta & Long 2003 (peak); decline borrowed from SN 1572",note:"The brightest stellar event in recorded history, seen in daylight, low in the southern sky from Europe and the Near East. The decline is modelled, not recorded, and falls below the naked eye after about two years where the chronicles speak of three."},{id:"sn-1054",kind:"supernova",designation:"SN 1054",name:"Supernova of 1054",raHours:5.5755,decDeg:22.0175,peakMagnitude:-6,peakJd:2106216,startJd:2106216,lightCurve:[[0,-6],[23,-4],[642,6]],source:"Chinese chronicles (Song huiyao), via Stephenson & Green 2002",note:"The explosion that left the Crab Nebula. Its magnitude is an estimate; the two durations are recorded."},{id:"sn-1181",kind:"supernova",designation:"SN 1181",name:"Supernova of 1181",raHours:.88645,decDeg:67.50067,peakMagnitude:0,peakJd:2152636,startJd:2152636,lightCurve:[[0,0],[185,6]],source:"Chinese and Japanese chronicles, via Stephenson & Green 2002",note:"Circumpolar from Europe and China, so never set. Its peak magnitude is uncertain by at least a magnitude."},{id:"sn-1572",kind:"supernova",designation:"SN 1572",name:"Tycho's Supernova",raHours:.42264,decDeg:64.14083,peakMagnitude:-4,peakJd:2295551,startJd:2295546,lightCurve:[[0,-3],[5,-4],[34,-2.4],[65,-1.4],[111,.3],[171,1.6],[263,2.5],[355,4],[369,4.2],[416,4.7],[461,5.3],[489,6]],source:"Tycho Brahe and contemporaries, reduced by Ruiz-Lapuente 2004",note:"Circumpolar from northern Europe. Tycho showed it had no parallax, so it was not in the air: a new star, beyond the Moon."},{id:"sn-1604",kind:"supernova",designation:"SN 1604",name:"Kepler's Supernova",raHours:17.51125,decDeg:-21.48733,peakMagnitude:-2.95,peakJd:2307210,startJd:2307191,lightCurve:[[0,.23],[3,-1.3],[6,-2.08],[9,-2.17],[19,-2.95],[27,-2.95],[32,-1.95],[36,-1.52],[86,.9],[96,.45],[103,1],[114,1.2],[118,1.55],[133,1.95],[137,2.3],[170,2.25],[185,2.25],[194,2.4],[197,2.9],[308,4.45],[324,4.45],[339,4.95],[364,4.7]],source:"Kepler, Fabricius, Maestlin and the Korean court astronomers, reduced by Ruiz-Lapuente 2017",note:"The last supernova in our Galaxy seen with the naked eye. It went behind the Sun from mid-November 1604 to January 1605, which is the gap in its record."},{id:"t-crb-1866",kind:"nova",designation:"T CrB",name:"Nova Coronae Borealis 1866",raHours:15.99171,decDeg:25.92017,peakMagnitude:2,peakJd:2402734,startJd:2402734,lightCurve:[[0,2],[1.5,3],[2.5,3.11],[6.5,5.18],[8.5,5.75],[10.5,6.85],[11.5,6.8],[12.5,7.5],[16,8.18],[32,9.27],[38,9.2],[40,8.95],[44,9.4],[48,9.07],[54,9.4],[58,9.21],[79,9.44],[107,9.26],[111,9.01],[115,8.21],[119,7.96],[159,7.51],[179,7.57],[183,7.97],[191,7.66],[199,8.2],[207,8.31],[211,8.83],[215,8.65],[223,8.97],[297,8.9],[345,9.25],[377,9.07],[425,9.3],[537,9.3]],source:"Recorded peak (Birmingham); curve borrowed from its 1946 eruption",note:"The first eruption of the recurrent nova T CrB to be seen. The decline is its 1946 one."},{id:"t-aur-1891",kind:"nova",designation:"T Aur",name:"Nova Aurigae 1891",raHours:5.53309,decDeg:30.44583,peakMagnitude:4.49,peakJd:2412083,startJd:2412079,lightCurve:[[0,5.28],[4,4.49],[24,4.58],[40,4.97],[52,4.95],[56,4.5],[60,4.9],[68,4.88],[72,5.25],[76,4.93],[84,5.44],[88,7.23],[96,8.85],[100,10.44]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"gk-per-1901",kind:"nova",designation:"GK Per",name:"Nova Persei 1901",raHours:3.52,decDeg:43.90431,peakMagnitude:.19,peakJd:24154395e-1,startJd:24154377e-1,lightCurve:[[0,2.7],[.8,.86],[1.8,.19],[2.3,.2],[5.8,1.78],[11.8,2.54],[12.8,2.98],[17.8,3.62],[18.8,3.35],[19.8,3.77],[20.8,3.59],[22.8,3.95],[24.8,3.82],[25.6,4.99],[25.9,4.89],[26.6,3.69],[27.6,3.94],[27.9,4.61],[28.6,5.28],[28.9,4.46],[29.9,3.8],[30.9,4.27],[31.6,5.21],[31.9,5.22],[32.9,3.88],[33.9,4.19],[34.6,4.85],[35.6,4.8],[36.6,4.23],[37.6,4.44],[38.9,4.15],[39.7,5.19],[40.6,5.39],[40.9,5.35],[41.9,4.01],[42.6,4.5],[42.9,4.49],[43.6,5.53],[44,5.23],[44.6,5.61],[44.9,5.5],[45.9,4.17],[46.9,4.69],[47.6,5.5],[48.6,5.59],[49.6,5.14],[49.9,4.48],[50.6,4.45],[50.9,4.55],[51.6,5.47],[52.6,5.74],[53.7,5.66],[55.7,4.41],[56.7,5.43],[58.7,5.81],[58.9,5.58],[59.7,5.64],[59.9,4.76],[60.9,4.26],[61.9,5.62],[62.7,5.85],[62.9,5.53],[63.7,5.8],[64.9,4.28],[65.6,5.33],[66.7,5.87],[66.9,5.56],[68.7,5.7],[68.9,5.3],[69.7,4.47],[70.7,5.65],[72.9,5.98],[73.9,5.71],[74.7,4.98],[74.9,4.46],[75.7,4.87],[76.9,6.05],[77.6,5.76],[78,6],[78.7,5.95],[80.7,4.98],[81.9,5.85],[82.7,6.02],[84.7,5.41],[84.9,5.08],[85.7,5.17],[85.9,5.6],[87,6.1],[88.8,6.2],[89.7,4.96],[89.9,4.93],[90.7,5.9],[91.9,6.32],[92.7,5.86],[93.1,6.24],[93.7,5.38],[93.9,6.2],[96.1,6.12],[97.1,6.37],[97.6,5.12],[98,5.85],[99.3,6.35],[101.3,6.12],[101.7,5.25],[102.3,4.95],[102.7,6.12],[103.2,5.83],[104.7,6.37],[105,6.13],[106,6.22],[106.7,4.88],[107.7,6.3],[108.1,6.4],[109,6],[109.7,5.16],[110,5.82],[112.1,5.89],[113.1,5.5],[115.7,5.8],[116,6.11],[118.7,5.68],[119,6.23],[119.7,5.85],[120,6.12],[121,4.62],[121.8,5.9],[123,5.48],[125,6.05],[126,5.89],[130.9,6.11],[146.1,6.02],[155.6,6.26],[180.4,6.09],[190.4,6.39],[245.5,6.87],[266.2,6.77],[301.1,7.16],[321.5,7.07],[346.5,7.87],[375.7,7.86],[385.8,8.09],[389.8,8.55],[406.1,8.33],[416.5,8.59],[445.9,8.62],[472.1,9.24],[565.9,9.74],[571,9.4],[589.8,9.76]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"Discovered on 21 February 1901 by Thomas Anderson in Edinburgh, and the brightest nova of the century until V603 Aql."},{id:"dn-gem-1912",kind:"nova",designation:"DN Gem",name:"Nova Geminorum 1912",raHours:6.9151,decDeg:32.14108,peakMagnitude:3.58,peakJd:241947675e-2,startJd:241947275e-2,lightCurve:[[0,11.7],[1,4.5],[4,3.58],[5,4.45],[5.5,5.32],[6,5.53],[6.5,5.11],[8,5.43],[8.5,5.16],[11,5.53],[11.5,5.13],[12,5.18],[13.75,4.5],[15.75,5.3],[18.75,6],[19.75,5.55],[26.75,6],[28.75,5.9],[31.75,6.6],[32.75,6.2],[33.75,6.5],[36.75,6.55],[39.75,6.2],[40.75,6.75],[41.75,7],[44.75,6.75],[52.75,6.75],[54.75,7.23],[58.25,7.5],[62.25,7.3],[64.25,7.47],[66.25,8.1],[70.25,7.5],[72.25,8.1],[78.25,7.55],[80.25,8.2],[86.25,7.2],[90.25,7.3],[92.25,7.8],[152.25,7.2],[160.25,7.4],[166.25,8.2],[168.25,8.2],[170.25,7.3],[180.25,7.4],[182.25,8],[186.25,7.5],[190.25,7.6],[192.25,8],[211.25,7.75],[227.25,8],[275.25,7.78],[315.25,8.6],[331.25,7.79],[339.25,8.27],[363.25,8.61],[443.25,8.93],[451.25,9.2],[535.25,10.3],[567.25,9.9],[615.25,10.8],[631.25,10.63],[647.25,10.88],[679.25,10.8],[695.25,11.07],[727.25,11]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v603-aql-1918",kind:"nova",designation:"V603 Aql",name:"Nova Aquilae 1918",raHours:18.81518,decDeg:.58414,peakMagnitude:-.5,peakJd:242175475e-2,startJd:242174875e-2,lightCurve:[[0,11.3],[2,10.5],[4,6.6],[4.5,1.04],[6,-.5],[6.5,.18],[10,1.1],[10.5,.95],[12.75,1.89],[21.75,3.07],[23.75,3.76],[29.75,3.16],[34.75,3.5],[36.75,3.86],[44.75,3.79],[48.75,4.43],[52.75,3.84],[56.75,3.95],[57.75,4.04],[58.75,4.49],[59.75,4.42],[60.75,4.69],[62.75,4.6],[63.75,4.11],[64.75,3.97],[68.75,4.18],[70.75,4.65],[71.75,4.51],[73.75,4.73],[75.75,4.44],[79.75,4.85],[83.75,4.43],[89.75,4.88],[92.75,4.86],[94.75,4.58],[96.75,4.92],[99.75,5.05],[163.25,5.45],[167.25,5.7],[179.25,5.48],[191.25,5.8],[203.25,5.5],[247.25,5.9],[251.25,6.25],[257.25,5.5],[265.25,6.13],[281.25,6.33],[345.25,6.3],[385.25,6.73],[393.25,6.43],[425.25,6.71],[433.25,6.56],[461.25,7.27],[525.25,7.6],[541.25,7.47],[637.25,8.3],[669.25,8.17],[717.25,8.55],[749.25,8.4],[765.25,8.68],[885.25,8.75],[949.25,9.4],[1013.25,9.19],[1141.25,9.57],[1269.25,9.48],[1333.25,9.95],[1653.25,9.94],[1781.25,10.28],[1909.25,10.34],[2037.25,10.1],[2101.25,10.46],[2165.25,10.51],[2357.25,10.3],[2549.25,10.77],[2741.25,10.46],[2869.25,10.83],[3125.25,10.71],[3317.25,11.22],[3381.25,10.91],[3637.25,11.42],[3829.25,10.96],[3893.25,11.65],[3957.25,11.63],[4085.25,11.14],[4213.25,11.48],[4277.25,10.7],[4341.25,11.42],[4405.25,11.47],[4469.25,11.06],[4533.25,11.08],[4597.25,11.7],[4725.25,11.45],[4789.25,10.94]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"The brightest nova of the modern era, at magnitude -0.5 on 9-10 June 1918: as bright as Vega, in a summer evening sky, in wartime."},{id:"v476-cyg-1920",kind:"nova",designation:"V476 Cyg",name:"Nova Cygni 1920",raHours:19.97347,decDeg:53.61858,peakMagnitude:1.94,peakJd:242256025e-2,startJd:242255925e-2,lightCurve:[[0,2.7],[1,1.94],[3,2.07],[4.5,2.95],[8.25,4],[31.75,6.41],[35.75,7.23],[37.75,7.08],[41.75,7.33],[43.75,7.92],[45.75,8.2],[51.75,8.59],[63.75,8.82],[65.75,9.25],[71.75,8.93],[85.75,9.43],[87.75,9.05],[95.75,9.2],[97.75,8.67],[99.75,9.07],[112.75,8.78],[120.75,9.03],[128.75,8.67],[144.75,8.94],[152.75,8.73],[168.75,8.79],[176.75,9.28],[192.75,9],[216.75,9.6],[232.75,9.27],[240.75,9.5],[288.75,9.4],[296.75,9.6],[304.75,9.3],[320.75,9.73],[328.75,9.5],[336.75,9.8],[428.75,9.61],[476.75,10.01],[492.75,9.76],[508.75,9.87],[524.75,9.65],[556.75,9.87],[572.75,9.65],[620.75,10.22],[668.75,10.44],[684.75,10.23],[716.75,10.33],[756.75,10.66],[884.75,10.59],[948.75,10.96],[1108.75,10.96]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"rr-pic-1925",kind:"nova",designation:"RR Pic",name:"Nova Pictoris 1925",raHours:6.59335,decDeg:-62.64008,peakMagnitude:.95,peakJd:24243085e-1,startJd:24242995e-1,lightCurve:[[0,2.43],[5,2.35],[6,2.1],[7,2.4],[9,.95],[13,1.8],[14,1.7],[16,2.15],[18,2.2],[19,1.9],[23,3.1],[27,3.05],[31.5,3.58],[43.5,3.08],[47.5,3.15],[57.5,2.3],[59.5,1.65],[63.5,3.03],[65.5,2.84],[67.5,3.16],[69.5,2.4],[71.5,2.04],[73.5,2.05],[75.5,2.55],[79.5,3],[83.5,3.15],[116.5,3.54],[120.5,3.78],[124.5,3.67],[136.5,4.18],[148.5,4.34],[154.5,4.17],[194.5,4.43],[226.5,4.93],[234.5,4.8],[242.5,5.4],[250.5,5.5],[266.5,5.15],[298.5,5.6],[362.5,5.4],[414.5,5.7],[430.5,5.5],[494.5,6.2],[718.5,6.52],[830.5,6.3],[862.5,6.6],[878.5,6.4],[910.5,6.77],[958.5,6.67],[1062.5,7.07],[1318.5,7.35],[1590.5,8.12],[1718.5,8.25],[2486.5,8.59],[2614.5,8.47],[2742.5,8.7],[3382.5,8.6],[3766.5,8.97],[4022.5,8.79],[4150.5,9.22],[6710.5,10.29],[7414.5,11.03],[8438.5,10.96]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"A slow nova, and a southern one: more than two months within two magnitudes of its peak."},{id:"dq-her-1934",kind:"nova",designation:"DQ Her",name:"Nova Herculis 1934",raHours:18.12507,decDeg:45.85906,peakMagnitude:1.56,peakJd:24277935e-1,startJd:242778675e-2,lightCurve:[[0,3.4],[1.5,2.4],[3,2.67],[5.75,2.01],[6.75,1.56],[7.75,1.59],[11.75,2.97],[12.75,2.31],[14.75,3.07],[15.75,2.56],[16.75,2.51],[19.75,2.68],[23.75,2.53],[24.75,2.27],[26.75,2.58],[30.75,2.24],[31.75,2.63],[32.75,2.66],[34.75,2.11],[39.75,2.71],[41.75,2.31],[43.75,2.37],[46.75,3.64],[47.75,3.21],[50.75,3.23],[52.75,2.66],[55.75,2.56],[58.75,2.97],[60.75,2.77],[61.75,3.36],[63.75,3.43],[64.75,2.89],[65.75,3.22],[68.75,3.52],[69.75,2.95],[70.75,3.06],[71.75,2.7],[76.75,3.65],[79.75,3.74],[81.75,3.21],[83.75,3.75],[87.75,3.69],[92.75,4.04],[94.75,4.8],[97.75,4.24],[98.75,4.52],[100.75,4.08],[101.75,4.43],[105.75,4.58],[106.75,4.33],[107.75,4.73],[108.75,6.57],[109.75,8.08],[110.75,8.15],[111.75,8.56],[113.75,8.45],[114.75,9.15],[115.75,9.15],[116.75,9.59],[117.75,9.43],[118.75,9.8],[122.75,10.5],[123.75,10.28],[124.75,10.93],[127.75,10.83],[129.75,11.87],[131.75,12.42],[135.75,12.5],[137.75,12.9],[138.75,12.77],[139.75,13],[143.75,12],[144.75,12.33],[146.75,12.35],[147.75,11.64],[148.75,11.83],[150.75,10.9],[151.75,10.78],[152.75,11.17],[154.75,10.32],[155.75,10.4],[165.25,9.24],[185.25,7.74],[225.25,6.8],[273.25,6.72],[321.25,6.97],[333.25,6.79],[353.25,7],[357.25,6.82],[377.25,6.88],[401.25,7.29],[409.25,6.8],[413.25,6.8],[419.25,7.1],[435.25,7.09],[451.25,7.4],[475.25,7],[555.25,7.48],[823.25,7.83],[855.25,8.18],[1135.25,8.43],[1823.25,9.98],[1887.25,9.71],[2015.25,10.55],[2335.25,10.95]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"Lost about ten magnitudes in a few weeks from April 1935, when dust condensed around it, then came back to naked-eye brightness."},{id:"cp-lac-1936",kind:"nova",designation:"CP Lac",name:"Nova Lacertae 1936",raHours:22.26142,decDeg:55.61703,peakMagnitude:2.02,peakJd:242834025e-2,startJd:242833825e-2,lightCurve:[[0,4.03],[.5,2.9],[1,2.45],[2,2.02],[2.5,2.61],[4,3],[4.5,3.35],[5,3.3],[9.25,4.59],[14.25,5.45],[22.25,6.03],[23.25,6.3],[26.25,6.23],[38.25,6.74],[41.25,6.61],[50.25,7.35],[53.25,7.27],[57.25,7.7],[58.25,7.54],[60.25,7.55],[61.25,7.79],[71.25,7.6],[74.25,7.81],[76.25,8.3],[77.25,7.79],[86.25,8.21],[87.25,8],[88.25,8.25],[92.25,8.17],[94.25,8.47],[102.25,8.27],[103.25,8.7],[104.25,8.4],[110.25,8.66],[116.75,8.55],[122.75,8.83],[126.75,8.7],[140.75,9.06],[154.75,9.01],[164.75,9.36],[170.75,9.18],[174.75,9.48],[186.75,9.42],[188.75,9.73],[192.75,9.53],[200.75,9.74],[202.75,9.5],[204.75,9.77],[208.75,9.6],[214.75,9.75],[216.75,10.05],[222.75,9.7],[232.75,10.03],[236.75,9.82],[250.75,10.1],[254.75,9.9],[260.75,10.1],[264.75,9.8],[266.75,10.15],[268.75,10],[274.75,10.2],[276.75,9.9],[292.75,10.6],[294.75,10.6],[298.75,10.1],[318.75,10.35],[320.75,10.6],[322.75,10.3],[328.75,10.65],[332.75,10.3],[338.75,10.7],[348.75,10.53],[350.75,10.7],[354.75,10.37],[358.75,10.58],[365.75,10.43],[373.75,10.85],[421.75,10.94]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"cp-pup-1942",kind:"nova",designation:"CP Pup",name:"Nova Puppis 1942",raHours:8.19613,decDeg:-35.35139,peakMagnitude:.73,peakJd:243067675e-2,startJd:243067275e-2,lightCurve:[[0,.95],[4,.73],[4.5,1.3],[5.5,1.47],[6,2.01],[7.75,2.88],[8.75,2.97],[10.75,3.5],[11.75,4.02],[13.75,4.4],[14.75,3.8],[17.75,5],[18.75,4.93],[19.75,5.48],[23.75,5.5],[25.75,5.65],[26.75,5.99],[33.25,6.28],[45.25,6.6],[57.25,6.41],[81.25,6.85],[89.25,6.5],[97.25,6.67],[101.25,7],[113.25,6.66],[125.25,7.1],[135.25,6.96],[231.25,7.86],[279.25,7.8],[327.25,8.33],[407.25,8.18],[423.25,8.59],[471.25,8.53],[503.25,8.99],[551.25,8.97],[567.25,8.7],[583.25,9.47],[615.25,8.95],[655.25,9.5],[751.25,9.55],[815.25,10.09],[847.25,10.02],[879.25,10.48],[911.25,10.34],[1023.25,10.79],[1279.25,10.9]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"One of the fastest bright novae: two magnitudes gone in four days."},{id:"t-crb-1946",kind:"nova",designation:"T CrB",name:"Nova Coronae Borealis 1946",raHours:15.99171,decDeg:25.92017,peakMagnitude:2.5,peakJd:2431860,startJd:2431860,lightCurve:[[0,2.5],[1.5,3.5],[2.5,3.61],[6.5,5.68],[8.5,6.25],[10.5,7.35],[11.5,7.3],[12.5,8],[16,8.68],[32,9.77],[38,9.7],[40,9.45],[44,9.9],[48,9.57],[54,9.9],[58,9.71],[79,9.94],[107,9.76],[111,9.51],[115,8.71],[119,8.46],[159,8.01],[179,8.07],[183,8.47],[191,8.16],[199,8.7],[207,8.81],[211,9.33],[215,9.15],[223,9.47],[297,9.4],[345,9.75],[377,9.57],[425,9.8],[537,9.8]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"A recurrent nova. It erupted in 1866 and in 1946, and a third eruption was expected from 2024 on."},{id:"v446-her-1960",kind:"nova",designation:"V446 Her",name:"Nova Herculis 1960",raHours:18.956,decDeg:13.24147,peakMagnitude:4.83,peakJd:24370038e-1,startJd:24370033e-1,lightCurve:[[0,5.2],[.5,4.83],[2,4.9],[2.5,5.4],[3,5.05],[3.5,5.57],[4,5.25],[5,5.5],[6.5,5.4],[7.2,5.78],[8.2,5.6],[9.2,5.98],[10.2,5.92],[11.2,6.21],[16.2,6.1],[17.2,6.23],[18.2,7.2],[19.2,6.51],[20.2,6.78],[26.2,6.97],[27.2,7.24],[28.2,7.13],[29.2,7.45],[31.2,7.2],[40.7,7.57],[44.7,8.25],[46.7,7.84],[56.7,8.15],[60.7,8.9],[70.7,8.7],[72.7,8.14],[76.7,8.71],[80.7,8.47],[82.7,8.87],[86.7,8.57],[90.7,8.93],[107.7,9.11],[111.7,8.94],[115.7,9.27],[139.7,9.38],[151.7,9.91],[155.7,9.72],[173.7,10.51],[221.7,10.95]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v533-her-1963",kind:"nova",designation:"V533 Her",name:"Nova Herculis 1963",raHours:18.23902,decDeg:41.85614,peakMagnitude:3,peakJd:24380605e-1,startJd:24380565e-1,lightCurve:[[0,8],[4,3],[4.5,3],[8,4],[13,3.95],[15,4.6],[21,4.53],[24,5.05],[27,5.15],[32,4.76],[34,4.98],[35,5.39],[37,5.43],[41,6.04],[49,6.02],[56.5,6.34],[60.5,6.11],[74.5,6.72],[102.5,6.99],[137.5,7.81],[197.5,8.31],[217.5,8.8],[225.5,8.57],[233.5,9.03],[237.5,8.78],[277.5,9.44],[301.5,9.46],[315.5,9.86],[323.5,9.73],[339.5,10.05],[355.5,10.74],[363.5,10.32],[371.5,10.6],[387.5,10.69],[427.5,10.38],[435.5,10.84],[443.5,10.74],[451.5,11.33],[459.5,10.98],[467.5,11.17],[507.5,11.16],[539.5,11.66],[603.5,11.7],[619.5,12.05],[651.5,12.03],[659.5,11.74],[667.5,10.9]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"hr-del-1967",kind:"nova",designation:"HR Del",name:"Nova Delphini 1967",raHours:20.70565,decDeg:19.16092,peakMagnitude:3.58,peakJd:2439838,startJd:2439646,lightCurve:[[0,11.9],[6,11.8],[12,8.8],[16,8.3],[20,6.7],[30,5.8],[36,5.51],[66,5.55],[78,5.35],[86,4.89],[96,5],[108,4.75],[136,5.13],[152,4.83],[182,4.93],[186,4.59],[192,3.58],[202,5],[220,5.46],[226,5.14],[230,5.45],[232,5.14],[236,5],[242,5.08],[244,4.59],[246,4.45],[254,5.3],[256,4.75],[260,5.69],[268,4.8],[274,4.94],[276,5.45],[280,5.2],[282,5.51],[286,5.58],[292,4.95],[294,5.16],[298,4.94],[311,5.09],[335,4.4],[367,5.76],[407,6.16],[423,6.55],[603,7.43],[907,8.32],[1451,9.41],[2347,10.75]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"An exceptionally slow nova: rose over months and stayed near magnitude 4 to 5 for most of 1967 and 1968."},{id:"lv-vul-1968",kind:"nova",designation:"LV Vul",name:"Nova Vulpeculae 1968",raHours:19.80012,decDeg:27.1715,peakMagnitude:4.5,peakJd:243996425e-2,startJd:243996325e-2,lightCurve:[[0,5],[1,4.5],[2,5],[2.5,4.86],[3,5.1],[3.5,4.88],[4,5.1],[5,4.9],[7,5.4],[8,5.23],[10.5,5.42],[12,5.82],[13,5.4],[13.5,5.74],[14,5.7],[14.5,6.08],[15,5.75],[15.5,5.86],[16,5.6],[17,5.8],[18,5.6],[20.5,6.34],[21,6.2],[22.5,6.84],[23,6.57],[24,6.98],[24.5,6.3],[25,7.1],[26,6.65],[34.25,7.48],[35.25,7.23],[39.25,7.32],[44.25,7.76],[45.25,7.49],[46.25,7.78],[50.25,7.84],[51.25,8.1],[53.25,7.9],[54.25,8.13],[56.25,8],[57.75,8.24],[67.75,8.52],[75.75,8.38],[83.75,8.69],[89.75,8.59],[125.75,9.32],[127.75,9.33],[129.75,8.98],[131.75,9.29],[135.75,9.43],[212.75,9.9],[220.75,10.16],[228.75,10.03],[236.75,10.3],[244.75,10.16],[264.75,10.54],[280.75,10.45],[296.75,10.79],[328.75,10.78]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"fh-ser-1970",kind:"nova",designation:"FH Ser",name:"Nova Serpentis 1970",raHours:18.51307,decDeg:2.61444,peakMagnitude:4.5,peakJd:244063425e-2,startJd:244063125e-2,lightCurve:[[0,7],[2,5],[3,4.5],[3.5,5],[4.5,4.6],[5.5,5],[6.5,4.68],[12.25,4.66],[16.25,5.3],[17.25,5.72],[18.25,5.3],[19.25,5.2],[23.25,5.84],[24.25,5.68],[27.25,5.9],[30.25,5.47],[32.25,5.9],[34.25,5.7],[43.25,6.28],[45.25,6.1],[50.25,6.62],[52.25,6.47],[57.25,6.63],[60.25,7.08],[61.25,6.87],[62.25,7.2],[63.25,6.85],[64.25,7.68],[65.25,7.3],[66.25,8.3],[67.25,7.93],[69.25,9.15],[71.25,9.2],[72.25,9.63],[74.25,9.9],[76.25,9.7],[77.25,10.25],[78.25,10.1],[79.25,10.4],[80.25,10.23],[81.25,10.57],[83.25,10.64],[85.25,10.35],[86.25,11.2],[87.25,10.1],[89.25,11.2],[96.25,11.35],[100.25,11.95],[102.25,11.1],[104.25,11.65],[106.25,11.5],[108.25,12.07],[114.75,11.32],[118.75,11.28],[122.75,10.93],[130.75,10.85],[134.75,10.52],[154.75,10.65],[162.75,10.12],[174.75,9.98],[178.75,10.34],[186.75,9.98],[214.75,10.25],[224.75,10.02],[240.75,10.2],[264.75,10],[272.75,10.2],[280.75,10.05],[288.75,10.4],[296.75,10],[348.75,10.7],[396.75,10.3],[444.75,10.73],[460.75,10.59],[540.75,10.94],[556.75,10.82]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v1500-cyg-1975",kind:"nova",designation:"V1500 Cyg",name:"Nova Cygni 1975",raHours:21.19349,decDeg:48.15056,peakMagnitude:1.88,peakJd:244265525e-2,startJd:244265425e-2,lightCurve:[[0,2.44],[1,1.88],[1.5,1.88],[2.5,2.41],[3,3.38],[4,4.28],[8.25,5.81],[11.25,6.46],[22.25,7.35],[33.25,7.73],[34.25,7.97],[37.25,7.86],[40.25,8.3],[43.25,8.19],[48.25,8.6],[49.25,8.46],[66.25,9.04],[70.25,8.93],[75.25,9.23],[76.25,9.03],[80.25,9.39],[81.25,9.19],[83.25,9.35],[84.25,9.13],[86.25,9.39],[89.25,9.32],[90.25,9.54],[93.25,9.37],[105.75,9.86],[193.75,10.43],[201.75,10.7],[209.75,10.47],[257.75,10.94],[265.75,10.81]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"One of the fastest novae on record: discovered on 29 August 1975, at its peak of magnitude 1.9 within two days, and two magnitudes down again two days later."},{id:"v842-cen-1986",kind:"nova",designation:"V842 Cen",name:"Nova Centauri 1986",raHours:14.59794,decDeg:-57.6265,peakMagnitude:4.9,peakJd:244675975e-2,startJd:244675725e-2,lightCurve:[[0,5.6],[2.5,4.9],[3.5,5.1],[15.5,5.1],[17.5,5.75],[18.5,5.4],[20.5,5.5],[22.5,5.95],[30.5,6.15],[31.5,6.3],[32,7.5],[34.5,7.2],[38.5,7.5],[39,7],[41.5,7.15],[42.5,6.7],[44.5,7.23],[45.5,6.6],[53,9.3]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"sn-1987a",kind:"supernova",designation:"SN 1987A",name:"Supernova 1987A",raHours:5.59111,decDeg:-69.26975,peakMagnitude:2.98,peakJd:24469425e-1,startJd:24468495e-1,lightCurve:[[0,6.36],[1,6.11],[2,4.63],[4,4.45],[32,3.97],[56,3.15],[93,2.98],[105,3.35],[118,4.11],[134,4.43],[504,8.15],[617,10.27]],source:"V photometry compiled by the Open Supernova Catalog (Sternberg catalogue, IAU circulars, CTIO)",note:"In the Large Magellanic Cloud, 160 000 light years away: the nearest supernova since Kepler's, and invisible north of about 20° N."},{id:"v1974-cyg-1992",kind:"nova",designation:"V1974 Cyg",name:"Nova Cygni 1992",raHours:20.50879,decDeg:52.63078,peakMagnitude:4.27,peakJd:24486753e-1,startJd:24486718e-1,lightCurve:[[0,7.2],[1,5.23],[2,4.62],[3.5,4.27],[4.5,4.59],[6,4.5],[7,4.78],[7.5,4.52],[8,4.82],[10.7,5.25],[11.7,5.66],[16.7,5.85],[21.7,6.47],[22.7,6.3],[27.7,6.46],[29.7,6.83],[34.7,6.9],[35.7,7.25],[36.7,7],[37.7,7.16],[39.7,7.03],[43.7,7.41],[45.7,7.26],[50.7,7.45],[57.7,7.78],[58.7,8.13],[61.7,7.92],[64.7,8.19],[65.7,7.99],[71.7,8.22],[76.7,8.01],[128.2,8.72],[176.2,8.89],[192.2,9.15],[216.2,9.28],[232.2,9.07],[236.2,9.3],[390.2,10.99]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v382-vel-1999",kind:"nova",designation:"V382 Vel",name:"Nova Velorum 1999",raHours:10.74678,decDeg:-52.42533,peakMagnitude:2.88,peakJd:245132225e-2,startJd:245132075e-2,lightCurve:[[0,2.99],[1.5,2.88],[2.5,3.46],[4.5,3.98],[5,4.32],[5.5,4.23],[7.5,4.85],[21.75,6.67],[30.25,7.2],[40.25,7.41],[93.25,7.95],[97.25,8.25],[101.25,8],[113.25,7.96],[129.25,8.5],[155.25,8.47],[163.25,9.1],[179.25,9],[187.25,8.7],[195.25,9.15],[211.25,9.23],[235.25,9.8],[243.25,9.71],[299.25,10.42],[383.25,10.52],[415.25,10.81]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v1494-aql-1999",kind:"nova",designation:"V1494 Aql",name:"Nova Aquilae 1999",raHours:19.38482,decDeg:4.9555,peakMagnitude:4.11,peakJd:245151575e-2,startJd:245151425e-2,lightCurve:[[0,5.15],[.5,4.86],[1,4.27],[1.5,4.11],[2.5,4.35],[5,5.48],[10.5,6.26],[14.25,6.28],[20.25,7.43],[24.25,7.25],[25.25,7.63],[27.25,7.7],[29.25,7.42],[33.25,8.08],[35.25,8.03],[36.25,7.6],[37.25,7.6],[46.25,8.5],[54.25,8.28],[56.25,8.63],[58.25,8.4],[61.25,9.53],[62.25,9],[64.25,9.13],[69.25,8.58],[70.25,8.9],[72.25,8.88],[75.25,8.57],[77.25,9],[79.25,8.8],[81.25,9.7],[83.25,9.6],[85.25,9.8],[86.75,9.5],[88.75,9.54],[90.75,8.9],[92.75,8.85],[96.75,9.63],[102.75,9.7],[104.75,8.98],[106.75,8.73],[116.75,9.63],[118.75,9.6],[120.75,9.07],[122.75,9.26],[124.75,9.8],[128.75,9.36],[134.75,9.75],[147.75,9.92],[155.75,9.81],[259.75,10.96]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"v4743-sgr-2002",kind:"nova",designation:"V4743 Sgr",name:"Nova Sagittarii 2002",raHours:19.01926,decDeg:-22.00167,peakMagnitude:5,peakJd:245253775e-2,startJd:245253675e-2,lightCurve:[[0,5.2],[1,5],[2,5.89],[2.5,5.91],[3.5,6.43],[5,6.45],[5.5,6.86],[6,6.59],[7,6.77],[7.5,7.31],[8.5,6.99],[9,7.09],[10.5,7.86],[11,7.58],[11.5,7.89],[15.75,8.33],[17.75,8.18],[18.75,8.58],[19.75,8.44],[22.75,8.83],[23.75,8.6],[24.75,8.85],[27.75,8.83],[30.75,9.4],[31.75,9.09],[36.25,9.08],[38.25,9.34],[62.25,9.75],[66.25,10.1],[70.25,9.7],[74.25,10],[171.25,10.9]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010"},{id:"rs-oph-2006",kind:"nova",designation:"RS Oph",name:"Nova Ophiuchi 2006",raHours:17.83699,decDeg:-6.70792,peakMagnitude:4.8,peakJd:2453779,startJd:2453779,lightCurve:[[0,4.8],[1.25,4.97],[2.75,5.78],[3.25,5.7],[3.75,6.24],[4.25,6.05],[4.75,6.38],[5.25,6.3],[8.5,7.25],[14.5,7.95],[24.5,8.55],[29.5,9.08],[48,9.87],[80,10.28],[107,11.54],[119,11.54],[139,11.98],[147,11.83],[163,12.03],[171,11.97],[175,11.65],[183,11.84],[195,11.64],[203,11.8],[207,12.13],[219,11.45],[277,11.68],[325,11],[341,11.53],[357,11.62],[373,11.3],[405,11.5],[421,11.17],[469,10.96],[501,11.22],[549,10.75],[581,11.08],[597,10.98]],source:"AAVSO, binned by Strope, Schaefer & Henden 2010",note:"A recurrent nova, erupting every twenty years or so (1898, 1907, 1933, 1945, 1958, 1967, 1985, 2006, 2021)."},{id:"v1280-sco-2007",kind:"nova",designation:"V1280 Sco",name:"Nova Scorpii 2007",raHours:16.96145,decDeg:-32.34325,peakMagnitude:3.8,peakJd:2454149,startJd:2454136,lightCurve:[[0,9.7],[13,3.8],[34,5.8],[103,15]],source:"AAVSO (discovery, peak, dust minimum); t2 from Das et al. 2008",note:"Faded from sight quickly when dust formed around it, three weeks after its peak."},{id:"v339-del-2013",kind:"nova",designation:"V339 Del",name:"Nova Delphini 2013",raHours:20.39186,decDeg:20.76772,peakMagnitude:4.4,peakJd:24565214e-1,startJd:24565214e-1,lightCurve:[[0,4.4],[11,6.4],[20,7.4]],source:"Gehrz et al. 2015 (peak, t2, t3)",note:"High in the summer evening sky of the northern hemisphere, and widely photographed."},{id:"v1369-cen-2013",kind:"nova",designation:"V1369 Cen",name:"Nova Centauri 2013",raHours:13.9126,decDeg:-59.15114,peakMagnitude:3.48,peakJd:245663965e-2,startJd:24566285e-1,lightCurve:[[0,5.33],[1.57,4.08],[2.75,3.73],[4.57,4.16],[5.96,4.15],[10.26,3.77],[11.15,3.48],[12.14,3.74],[14.17,4.78],[15.46,4.97],[23.16,4.22],[26.25,4.32],[27.31,4.82],[29.56,5.11],[32.66,4.71],[33.84,4.86],[36.05,4.46],[37.15,4.99],[41.42,4.59],[42.37,4.93],[43.37,4.82],[44.54,5.09],[49.95,5.38],[51.99,5.82],[54.21,5.77]],source:"AAVSO, binned by day, as plotted by Izzo 2017 (arXiv:1704.07214, figure 1)",note:"Discovered on 2 December 2013 by John Seach at magnitude 5.5, it flared several times, reaching about 3.3 around 14 December: the brightest nova of the century so far, and a southern one."},{id:"rs-oph-2021",kind:"nova",designation:"RS Oph",name:"Nova Ophiuchi 2021",raHours:17.83699,decDeg:-6.70792,peakMagnitude:4.6,peakJd:2459436,startJd:2459435,lightCurve:[[0,5],[1,4.6],[2.25,4.77],[3.75,5.58],[4.25,5.5],[4.75,6.04],[5.25,5.85],[5.75,6.18],[6.25,6.1],[9.5,7.05],[15.5,7.75],[25.5,8.35],[30.5,8.88],[49,9.67],[81,10.08],[108,11.34],[120,11.34],[140,11.78],[148,11.63],[164,11.83],[172,11.77],[176,11.45],[184,11.64],[196,11.44],[204,11.6],[208,11.93],[220,11.25],[278,11.48],[326,10.8],[342,11.33],[358,11.42],[374,11.1],[406,11.3],[422,10.97],[470,10.76],[502,11.02],[550,10.55],[582,10.88],[598,10.78]],source:"Recorded discovery and peak (8 and 9 August 2021); curve borrowed from its 2006 eruption",note:"RS Oph's latest eruption, discovered on 8 August 2021. The decline is its 2006 one."}];class ty{static UNIX_EPOCH_JD=24405875e-1;static aroundDate(t){const e=this.julianDayOf(t);return xp.filter(i=>this.magnitudeAt(i,e)!==void 0)}static appearancesAt(t,e){const i=this.julianDayOf(t),n=[];for(const s of xp){const r=this.magnitudeAt(s,i);r!==void 0&&n.push({outburst:s,position:Bs.ofJ2000(s.raHours,s.decDeg,t,e),magnitude:r})}return n.sort((s,r)=>s.magnitude-r.magnitude)}static brightestAt(t,e){return this.appearancesAt(t,e)[0]}static byId(t){return xp.find(e=>e.id===t)}static magnitudeAt(t,e){const i=t.lightCurve,n=e-t.startJd;if(i.length===0||n<i[0][0]||n>i[i.length-1][0])return;let s=1;for(;s<i.length-1&&i[s][0]<n;)s++;const[r,a]=i[s-1]??i[0],[c,l]=i[s]??i[0];if(c===r)return a;const h=Math.min(1,Math.max(0,(n-r)/(c-r)));return a+h*(l-a)}static julianDayOf(t){return t.getTime()/864e5+this.UNIX_EPOCH_JD}}const fO=[{id:"quadrantids",code:"QUA",name:"Quadrantids",radiantRaHours:15.33,radiantDecDeg:49.7,start:{month:12,day:28},peak:{month:1,day:3},end:{month:1,day:12},peakZhr:110,velocityKmS:41,populationIndex:2.1},{id:"lyrids",code:"LYR",name:"April Lyrids",radiantRaHours:18.13,radiantDecDeg:33.3,start:{month:4,day:16},peak:{month:4,day:22},end:{month:4,day:25},peakZhr:18,velocityKmS:49,populationIndex:2.1},{id:"eta-aquariids",code:"ETA",name:"eta Aquariids",radiantRaHours:22.53,radiantDecDeg:-1,start:{month:4,day:19},peak:{month:5,day:6},end:{month:5,day:28},peakZhr:50,velocityKmS:66,populationIndex:2.4},{id:"alpha-capricornids",code:"CAP",name:"alpha Capricornids",radiantRaHours:20.47,radiantDecDeg:-9.2,start:{month:7,day:3},peak:{month:7,day:30},end:{month:8,day:15},peakZhr:5,velocityKmS:23,populationIndex:2.5},{id:"southern-delta-aquariids",code:"SDA",name:"Southern delta Aquariids",radiantRaHours:22.67,radiantDecDeg:-16.4,start:{month:7,day:12},peak:{month:7,day:30},end:{month:8,day:23},peakZhr:25,velocityKmS:41,populationIndex:3.2},{id:"perseids",code:"PER",name:"Perseids",radiantRaHours:3.22,radiantDecDeg:58,start:{month:7,day:17},peak:{month:8,day:12},end:{month:8,day:24},peakZhr:100,velocityKmS:59,populationIndex:2.2},{id:"southern-taurids",code:"STA",name:"Southern Taurids",radiantRaHours:3.47,radiantDecDeg:13,start:{month:9,day:10},peak:{month:10,day:10},end:{month:11,day:20},peakZhr:5,velocityKmS:27,populationIndex:2.3},{id:"draconids",code:"DRA",name:"October Draconids",radiantRaHours:17.47,radiantDecDeg:54,start:{month:10,day:6},peak:{month:10,day:8},end:{month:10,day:10},peakZhr:10,velocityKmS:20,populationIndex:2.6},{id:"orionids",code:"ORI",name:"Orionids",radiantRaHours:6.35,radiantDecDeg:15.6,start:{month:10,day:2},peak:{month:10,day:21},end:{month:11,day:7},peakZhr:20,velocityKmS:66,populationIndex:2.5},{id:"northern-taurids",code:"NTA",name:"Northern Taurids",radiantRaHours:3.87,radiantDecDeg:22,start:{month:10,day:20},peak:{month:11,day:12},end:{month:12,day:10},peakZhr:5,velocityKmS:29,populationIndex:2.3},{id:"leonids",code:"LEO",name:"Leonids",radiantRaHours:10.13,radiantDecDeg:21.6,start:{month:11,day:6},peak:{month:11,day:17},end:{month:11,day:30},peakZhr:15,velocityKmS:71,populationIndex:2.5},{id:"geminids",code:"GEM",name:"Geminids",radiantRaHours:7.47,radiantDecDeg:32.3,start:{month:12,day:4},peak:{month:12,day:14},end:{month:12,day:17},peakZhr:150,velocityKmS:35,populationIndex:2.6},{id:"ursids",code:"URS",name:"Ursids",radiantRaHours:14.47,radiantDecDeg:75.3,start:{month:12,day:17},peak:{month:12,day:22},end:{month:12,day:26},peakZhr:10,velocityKmS:33,populationIndex:3}],bf=6.5;class bp{static activeAt(t){return fO.flatMap(e=>{const i=this.nearness(e,t);return i<=0?[]:[{shower:e,zhr:e.peakZhr*i,nearness:i}]})}static nearness(t,e){const i=this.dayOfYear(e),n=this.dayOfYear(this.asDate(t.start)),s=this.dayOfYear(this.asDate(t.peak)),r=this.dayOfYear(this.asDate(t.end)),a=this.wrappedDelta(i,s),c=this.wrappedDelta(s,n),l=this.wrappedDelta(r,s);return a<0?a<-c?0:1+a/c:a>0?a>l?0:1-a/l:1}static observedRatePerHour(t,e,i,n=bf){if(e<=0)return 0;const s=bf-n;return t*Math.sin(e*Math.PI/180)/Math.pow(i,s)}static radiantPosition(t,e,i){return Bs.ofJ2000(t.radiantRaHours,t.radiantDecDeg,e,i)}static dayOfYear(t){const e=Date.UTC(t.getUTCFullYear(),0,1);return Math.floor((Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate())-e)/864e5)+1}static asDate(t){return new Date(Date.UTC(2001,t.month-1,t.day))}static wrappedDelta(t,e){const i=t-e;return i>182?i-365:i<-182?i+365:i}}class Ci{static QUIET_RATE_PER_HOUR=2;static APEX_RATE_PER_HOUR=8;static POPULATION_INDEX=3;static apexPosition(t,e){const i=Je(t),n=new Bf(0,QI(t).elon-90,1),s=Zr(TD(i),Qg(n,i)),r=Wf(s);return t1(r.ra,r.dec,t,e)}static observedRatePerHour(t,e=bf){const i=Ci.APEX_RATE_PER_HOUR*Math.max(0,Math.sin(t*Math.PI/180)),n=bf-e;return(Ci.QUIET_RATE_PER_HOUR+i)/Math.pow(Ci.POPULATION_INDEX,n)}static schedule(t){const e=new Xf(t.seed^1542469173);return Hs.schedule(t).map(i=>{const n=Ci.toCartesian({altitudeDeg:Math.asin(e.next())*180/Math.PI,azimuthDeg:e.between(0,360)}),s=i.fromRadiantDeg*Math.PI/180,r=Ci.turnAround(n,e.between(0,360)),a={x:n.x*Math.cos(s)+r.x*Math.sin(s),y:n.y*Math.cos(s)+r.y*Math.sin(s),z:n.z*Math.cos(s)+r.z*Math.sin(s)};return{...i,radiant:Ci.toHorizontal(a),bearingDeg:Ci.bearingFrom(a,n)}})}static turnAround(t,e){const[i,n]=Ci.basisAround(t),s=e*Math.PI/180;return{x:i.x*Math.cos(s)+n.x*Math.sin(s),y:i.y*Math.cos(s)+n.y*Math.sin(s),z:i.z*Math.cos(s)+n.z*Math.sin(s)}}static bearingFrom(t,e){const[i,n]=Ci.basisAround(t),s=t.x*e.x+t.y*e.y+t.z*e.z,r=Ci.normalise({x:e.x-t.x*s,y:e.y-t.y*s,z:e.z-t.z*s});return(Math.atan2(r.x*n.x+r.y*n.y+r.z*n.z,r.x*i.x+r.y*i.y+r.z*i.z)*180/Math.PI%360+360)%360}static basisAround(t){const e=Math.abs(t.y)<.9?{x:0,y:1,z:0}:{x:1,y:0,z:0},i=Ci.normalise(Ci.cross(t,e));return[i,Ci.normalise(Ci.cross(t,i))]}static toHorizontal(t){const e=Math.hypot(t.x,t.y,t.z)||1;return{altitudeDeg:Math.asin(Math.min(1,Math.max(-1,t.y/e)))*180/Math.PI,azimuthDeg:(Math.atan2(t.x,-t.z)*180/Math.PI%360+360)%360}}static appearanceOf(t){const e=Ci.toCartesian(t.radiant??{altitudeDeg:90,azimuthDeg:0}),i=Ci.turnAround(e,t.bearingDeg),n=t.fromRadiantDeg*Math.PI/180;return Ci.toHorizontal({x:e.x*Math.cos(n)+i.x*Math.sin(n),y:e.y*Math.cos(n)+i.y*Math.sin(n),z:e.z*Math.cos(n)+i.z*Math.sin(n)})}static toCartesian(t){const e=t.altitudeDeg*Math.PI/180,i=t.azimuthDeg*Math.PI/180,n=Math.cos(e);return{x:n*Math.sin(i),y:Math.sin(e),z:-n*Math.cos(i)}}static cross(t,e){return{x:t.y*e.z-t.z*e.y,y:t.z*e.x-t.x*e.z,z:t.x*e.y-t.y*e.x}}static normalise(t){const e=Math.hypot(t.x,t.y,t.z)||1;return{x:t.x/e,y:t.y/e,z:t.z/e}}static TYPICAL_VELOCITY_KM_S=40}const ey="https://ufoathome.org/tle/index.json";class Sn{static MAX_ELEMENT_AGE_DAYS=7;static DAY_MS=864e5;fetchImpl;indexUrls;index;files=new Map;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Sn.defaultIndexUrls()}static defaultIndexUrls(){const t=[];return typeof location<"u"&&/^https?:$/.test(location.protocol)&&t.push(new URL("/tle/index.json",location.href).href),t.includes(ey)||t.push(ey),t}static FIRST_SNAPSHOT="2021-02-22";async covers(t){const e=Date.parse(`${Sn.FIRST_SNAPSHOT}T00:00:00Z`)-Sn.MAX_ELEMENT_AGE_DAYS*Sn.DAY_MS;if(t.getTime()<e)return!1;const i=await this.loadIndex();return i?Object.values(i.index.kinds).some(n=>t.getTime()>=Date.parse(n.from)-Sn.MAX_ELEMENT_AGE_DAYS*Sn.DAY_MS&&t.getTime()<=Date.parse(n.to)+Sn.MAX_ELEMENT_AGE_DAYS*Sn.DAY_MS):!1}async at(t){const e=await this.loadIndex();if(!e)return;const{index:i,base:n}=e,s=[],r=[];for(const a of Object.keys(i.kinds)){const c=await this.kindAt(a,t,i,n);s.push(...c),r.push(this.coverageOf(a,t,i,c.length>0))}return{objects:s,coverage:r,credit:i.credit,creditUrl:i.source}}async kindAt(t,e,i,n){const s=e.getTime(),r=i.binDays*Sn.DAY_MS,a=Math.floor(s/r),c=s-a*r<r/2?a-1:a+1,l=new Set(i.kinds[t].bins),h=[a,c].map(g=>new Date(g*r).toISOString().slice(0,10)).filter(g=>l.has(g));if(h.length===0)return[];const[u,...d]=await Promise.all([this.json(new URL(`objects-${t}.json`,n).href),...h.map(g=>this.binary(new URL(`${t}/${g}.bin`,n).href))]),f=new Map;for(const g of d)for(const m of Sn.decode(g,i.recordBytes)){const v=f.get(m.norad);(!v||Math.abs(m.epochMs-s)<Math.abs(v.epochMs-s))&&f.set(m.norad,m)}const p=[];for(const g of f.values()){const m=Math.abs(g.epochMs-s)/Sn.DAY_MS;if(m>Sn.MAX_ELEMENT_AGE_DAYS)continue;const v=u[g.norad]??{name:String(g.norad)};v.launch&&Date.parse(`${v.launch}T00:00:00Z`)>s||p.push({norad:g.norad,name:v.name,kind:t,launch:v.launch,stdMag:v.stdMag,elements:g,ageDays:m})}return p}coverageOf(t,e,i,n){const{from:s,to:r}=i.kinds[t],a=e.getTime(),c=Sn.MAX_ELEMENT_AGE_DAYS*Sn.DAY_MS,l=n?"covered":a<Date.parse(s)-c?"before":a>Date.parse(r)+c?"after":"gap";return{kind:t,status:l,from:s,to:r}}static decode(t,e){const i=new DataView(t),n=[];for(let s=0;s+e<=t.byteLength;s+=e)n.push({norad:i.getUint32(s,!0),epochMs:i.getFloat64(s+4,!0),bstar:i.getFloat32(s+12,!0),inclinationDeg:i.getFloat32(s+16,!0),raanDeg:i.getFloat32(s+20,!0),eccentricity:i.getFloat32(s+24,!0),argOfPerigeeDeg:i.getFloat32(s+28,!0),meanAnomalyDeg:i.getFloat32(s+32,!0),meanMotion:i.getFloat64(s+36,!0)});return n}loadIndex(){return this.index??=(async()=>{for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;return{index:await e.json(),base:t}}catch{}})(),this.index}json(t){return this.cached(t,async e=>e.json())}binary(t){return this.cached(t,async e=>e.arrayBuffer())}cached(t,e){let i=this.files.get(t);return i||(i=this.fetchImpl(t).then(n=>{if(!n.ok)throw new Error(`${t}: ${n.status}`);return e(n)}),i.catch(()=>this.files.delete(t)),this.files.set(t,i)),i}}class pO{lowerM;upperM;add(t,e){if(!(t<=0)){if(e.behindM!==void 0){const i=Ze.sizeMAt(e.behindM,t);this.lowerM=this.lowerM===void 0?i:Math.max(this.lowerM,i)}if(e.inFrontM!==void 0){const i=Ze.sizeMAt(e.inFrontM,t);this.upperM=this.upperM===void 0?i:Math.min(this.upperM,i)}}}get sizeRange(){return{minM:this.lowerM,maxM:this.upperM}}get empty(){return this.lowerM===void 0&&this.upperM===void 0}get contradictory(){return this.lowerM!==void 0&&this.upperM!==void 0&&this.lowerM>this.upperM}distanceRangeAt(t){return t<=0?{}:{minM:this.lowerM===void 0?void 0:Ze.distanceMAt(this.lowerM,t),maxM:this.upperM===void 0?void 0:Ze.distanceMAt(this.upperM,t)}}clear(){this.lowerM=void 0,this.upperM=void 0}}class No{static DEG_PER_SECOND=360/86164.0905;static degOver(t){return Math.max(0,t)*No.DEG_PER_SECOND}static instants(t,e){if(!(e>0))return 1;const i=No.degOver(t)/e;return i<1?1:Math.min(No.MAX_INSTANTS,Math.max(2,Math.ceil(i)))}static MAX_INSTANTS=64}class fn{static EYE={apertureMm:7,exposureSeconds:.1,resolutionArcsec:60};static WAVELENGTH_M=55e-8;static ARCSEC_PER_RADIAN=180*3600/Math.PI;static UNKNOWN_CAMERA_FOCAL_MM=50;static UNKNOWN_CAMERA_DETAIL_UM=20;static get skyDriftArcsecPerSecond(){return No.DEG_PER_SECOND*3600}static graspOf(t,e={}){if(t.visualAid)return fn.visualAidGrasp(t,e.focalLengthMm);const i=e.exposureSeconds??t.exposureSeconds,n=e.fNumber??t.fNumber;if(i===void 0||n===void 0||!(i>0)||!(n>0))return fn.EYE;const s=e.focalLengthMm??t.frame?.focalLengthMm??fn.UNKNOWN_CAMERA_FOCAL_MM,r=s/n,a=fn.resolutionArcsec(t,s,r);return{apertureMm:r,exposureSeconds:Math.min(i,fn.trailLimitedSeconds(a)),resolutionArcsec:a}}static visualAidGrasp(t,e){const i=t.visualAid,n=fn.EYE,s=e??t.frame?.focalLengthMm,r=i.magnification??(s!==void 0&&i.eyepieceFocalMm?s/i.eyepieceFocalMm:1),a=Math.min(i.apertureMm,n.apertureMm*r);return{apertureMm:Math.max(a,n.apertureMm),exposureSeconds:n.exposureSeconds,resolutionArcsec:n.resolutionArcsec/Math.max(1,Math.min(r,i.apertureMm/n.apertureMm))}}static resolutionArcsec(t,e,i){const s=(t.detailUm??fn.UNKNOWN_CAMERA_DETAIL_UM)/1e3/e*fn.ARCSEC_PER_RADIAN,r=1.22*fn.WAVELENGTH_M/(i/1e3)*fn.ARCSEC_PER_RADIAN;return Math.max(s,r)}static trailLimitedSeconds(t){return t/fn.skyDriftArcsecPerSecond}static gainOverEye(t,e={}){const i=fn.graspOf(t,e),n=fn.EYE,s=(i.apertureMm/n.apertureMm)**2,r=i.exposureSeconds/n.exposureSeconds,a=(n.resolutionArcsec/i.resolutionArcsec)**2;return 1.25*Math.log10(s*r*a)}static gainFor(t,e){const i=e.fieldOfViewDeg===void 0?void 0:Bi.focalLengthMmFor(t,e.fieldOfViewDeg);return fn.gainOverEye(t,{fNumber:e.fNumber,focalLengthMm:i,exposureSeconds:e.exposureSeconds})}}const iy=111320,Xl=Math.PI/180,mO=1.02,gO=1;class Mh{static of(t,e){const i=Mh.sightings(t,e);if(i.length<2)return;const n=Mh.baseline(i);if(!n)return;const{near:s,far:r,closedM:a}=n,c=Math.tan(r.widthDeg/2*Xl)===0?0:Math.tan(s.widthDeg/2*Xl)/Math.tan(r.widthDeg/2*Xl);if(c<mO)return;const l=a/(c-1),h=Ze.sizeMAt(l,s.widthDeg),u=i.map(d=>({t:d.t,m:Ze.distanceMAt(h,d.widthDeg)}));return{widthM:h,distanceM:u,nearestM:Math.min(...u.map(d=>d.m)),fromT:r.t,toT:s.t,closedM:a}}static sightings(t,e){return t.timeline.allKeyframes.flatMap(i=>{const n=i.shapes.find(a=>a.sourceId===e)?.shape,s=n?.angular?.widthDeg,r=ze(t,i.t);return s===void 0||s<=0||r?.lat===void 0||r.lng===void 0?[]:[{t:i.t,widthDeg:s,lat:r.lat,lng:r.lng,sightAzimuthDeg:n?.aim?.azimuthDeg??r.headingDeg}]}).sort((i,n)=>i.t-n.t)}static baseline(t){let e;for(const i of t)for(const n of t){if(i.t>=n.t)continue;const s=Mh.closedAlongSight(i,n),[r,a,c]=s>=0?[n,i,s]:[i,n,-s];c<gO||r.widthDeg<=a.widthDeg||(!e||c>e.closedM)&&(e={near:r,far:a,closedM:c})}return e}static closedAlongSight(t,e){const i=(e.lat-t.lat)*iy,n=(e.lng-t.lng)*iy*Math.cos(t.lat*Xl),s=(t.sightAzimuthDeg??0)*Xl;return i*Math.cos(s)+n*Math.sin(s)}}class Ln{static CONVENTIONAL_M=5;static NEAREST_M=.2;static MARGIN=1.1;static resolve(t){if(t.statedM!==void 0&&t.statedM>0)return{distanceM:Ln.atLeastNearest(t.statedM),basis:"stated"};if(t.hypothesisM!==void 0&&t.hypothesisM>0)return{distanceM:Ln.atLeastNearest(t.hypothesisM),basis:"hypothesis"};if(t.derivedM!==void 0&&t.derivedM>0)return{distanceM:Ln.atLeastNearest(t.derivedM),basis:"derived"};const e=Ln.largest(t.range?.minM,t.crossing?.behindM),i=Ln.smallest(t.range?.maxM,t.crossing?.inFrontM),n=e===void 0?void 0:e*Ln.MARGIN,s=i===void 0?void 0:i/Ln.MARGIN;return n!==void 0&&s!==void 0?{distanceM:Ln.atLeastNearest(n<=s?Math.sqrt(n*s):n),basis:"bounded"}:n!==void 0?{distanceM:Ln.atLeastNearest(n),basis:"bounded"}:s!==void 0&&s<Ln.CONVENTIONAL_M?{distanceM:Ln.atLeastNearest(s),basis:"bounded"}:{distanceM:Ln.CONVENTIONAL_M,basis:"conventional"}}static atLeastNearest(t){return Math.max(Ln.NEAREST_M,t)}static largest(...t){const e=t.filter(i=>i!==void 0&&i>0);return e.length===0?void 0:Math.max(...e)}static smallest(...t){const e=t.filter(i=>i!==void 0&&i>0);return e.length===0?void 0:Math.min(...e)}}const wp=Math.PI/180;class Wt{constructor(t,e,i){this.body=t,this.ground=e,this.eyeAt=i;const n=[...t.track].sort((s,r)=>s.t-r.t);this.keys=this.place(n,i);for(const s of n)Wt.collect(this.motionKeys,s.t,s.motions),Wt.collect(this.lightKeys,s.t,s.lights)}static EYE_HEIGHT_M=1.6;static MAX_RANGE_M=3e4;static DEFAULT_SIZE={widthM:1,lengthM:1,heightM:1};static DEFAULT_APPEARANCE={color:"#c8c8c8",albedo:.5,luminanceCdM2:0,transparency:0,haloScale:1};keys;motionKeys=new Map;lightKeys=new Map;static collect(t,e,i){for(const[n,s]of Object.entries(i??{})){const r=t.get(n)??[];r.push({t:e,value:s}),t.set(n,r)}}motionsAt(t){return Wt.channelsAt(this.motionKeys,t,0)}lightsAt(t){return this.lightKeys.size>0?Wt.channelsAt(this.lightKeys,t,void 0):void 0}static channelsAt(t,e,i){const n={};for(const[s,r]of t){let a=r.length-1;for(;a>=0&&r[a].t>e;)a--;if(a<0){i!==void 0&&(n[s]=i);continue}const c=r[a],l=r[Math.min(a+1,r.length-1)],h=l===c||l.t===c.t?0:Math.min(1,(e-c.t)/(l.t-c.t));n[s]=Wt.lerp(c.value,l.value,h)}return n}static eyeOf(t,e,i){const n=ze(t,0),s=ze(t,e),a=n?.lat!==void 0&&n.lng!==void 0&&s?.lat!==void 0&&s.lng!==void 0?ae(s.lat,s.lng,n.lat,n.lng):void 0,c=a?a.x:0,l=a?-a.z:0;return{eastM:c,northM:l,upM:i.heightAt(c,l)+Wt.EYE_HEIGHT_M+(s?.elevationM??0),headingDeg:s?.headingDeg}}static lineOfSightMeetsGround(t,e,i,n){const s=Wt.directionOf(e,i),r=l=>t.upM+s.upM*l-n.heightAt(t.eastM+s.eastM*l,t.northM+s.northM*l);let a=0,c=0;for(;c<Wt.MAX_RANGE_M;){if(c=a+Math.max(.5,a*.01),r(c)<=0){for(let l=0;l<30;l++){const h=(a+c)/2;r(h)<=0?c=h:a=h}return c}a=c}}static directionOf(t,e){const i=t*wp,n=e*wp;return{eastM:Math.sin(i)*Math.cos(n),northM:Math.cos(i)*Math.cos(n),upM:Math.sin(n)}}at(t){const e=this.keys;if(e.length===0||t<e[0].t)return;let i=0,n=e.length-1;for(;i<n;){const g=i+n+1>>1;e[g].t>t?n=g-1:i=g}const s=i,r=e[s];if(!r.present)return;const a=e[Math.min(s+1,e.length-1)],c=a===r||a.t===r.t?0:Math.min(1,(t-r.t)/(a.t-r.t)),l=this.body.withObserver&&r.carried&&a.carried?this.eyeAt(t):void 0,h=l?l.eastM+Wt.lerp(r.carried.eastM,a.carried.eastM,c):Wt.lerp(r.eastM,a.eastM,c),u=l?l.northM+Wt.lerp(r.carried.northM,a.carried.northM,c):Wt.lerp(r.northM,a.northM,c),d={widthM:Wt.lerp(r.sizeM.widthM,a.sizeM.widthM,c),lengthM:Wt.lerp(r.sizeM.lengthM,a.sizeM.lengthM,c),heightM:Wt.lerp(r.sizeM.heightM,a.sizeM.heightM,c)},f={headingDeg:Wt.lerpAngle(r.attitude.headingDeg,a.attitude.headingDeg,c),pitchDeg:Wt.lerp(r.attitude.pitchDeg,a.attitude.pitchDeg,c),rollDeg:Wt.lerp(r.attitude.rollDeg,a.attitude.rollDeg,c)};let p;if(l)p=l.upM+Wt.lerp(r.carried.upM,a.carried.upM,c);else if("aboveGroundM"in r.vertical&&"aboveGroundM"in a.vertical){const g=Wt.lerp(r.vertical.aboveGroundM,a.vertical.aboveGroundM,c);p=this.groundUnderFootprint(h,u,d,f.headingDeg)+g+d.heightM/2}else p=Wt.lerp(this.centreUpOf(r),this.centreUpOf(a),c);return{id:this.body.id,model:this.body.model,explains:this.body.explains??[],outlineNode:this.body.outlineNode,eastM:h,northM:u,upM:p,sizeM:d,attitude:f,appearance:{color:Wt.lerpColor(r.appearance.color,a.appearance.color,c),albedo:Wt.lerp(r.appearance.albedo,a.appearance.albedo,c),luminanceCdM2:Wt.lerp(r.appearance.luminanceCdM2,a.appearance.luminanceCdM2,c),transparency:Wt.lerp(r.appearance.transparency,a.appearance.transparency,c),haloScale:Wt.lerp(r.appearance.haloScale,a.appearance.haloScale,c)},flame:Wt.flameBetween(r.flame,a.flame,c),motions:this.motionsAt(t),lights:this.lightsAt(t),throwsFlame:this.body.track.some(g=>g.flame!==void 0&&g.flame.luminanceCdM2>0)}}static flameBetween(t,e,i){if(!t||t.luminanceCdM2<=0)return i>=1&&e&&e.luminanceCdM2>0?e:void 0;const n=t,s=e??t,r={...i<1?n:s,lengthM:Wt.lerp(n.lengthM,s.lengthM,i),widthM:Wt.lerp(n.widthM,s.widthM,i),luminanceCdM2:Wt.lerp(n.luminanceCdM2,s.luminanceCdM2,i)};return r.luminanceCdM2>0?r:void 0}centreUpOf(t){return"upM"in t.vertical?t.vertical.upM:this.groundUnderFootprint(t.eastM,t.northM,t.sizeM,t.attitude.headingDeg)+t.vertical.aboveGroundM+t.sizeM.heightM/2}groundUnderFootprint(t,e,i,n){const s=n*wp,r={eastM:Math.cos(s),northM:-Math.sin(s)},a={eastM:Math.sin(s),northM:Math.cos(s)};let c=this.ground.heightAt(t,e);for(const[l,h]of[[-1,-1],[1,-1],[-1,1],[1,1]]){const u=l*i.widthM/2,d=h*i.lengthM/2;c=Math.max(c,this.ground.heightAt(t+r.eastM*u+a.eastM*d,e+r.northM*u+a.northM*d))}return c}place(t,e){const i=[];let n;for(const s of t){const r=s.sizeM??n?.sizeM??Wt.DEFAULT_SIZE,a={headingDeg:s.attitude?.headingDeg??n?.attitude.headingDeg??0,pitchDeg:s.attitude?.pitchDeg??n?.attitude.pitchDeg??0,rollDeg:s.attitude?.rollDeg??n?.attitude.rollDeg??0},c={color:s.appearance?.color??n?.appearance.color??Wt.DEFAULT_APPEARANCE.color,albedo:s.appearance?.albedo??n?.appearance.albedo??Wt.DEFAULT_APPEARANCE.albedo,luminanceCdM2:s.appearance?.luminanceCdM2??n?.appearance.luminanceCdM2??Wt.DEFAULT_APPEARANCE.luminanceCdM2,transparency:s.appearance?.transparency??n?.appearance.transparency??Wt.DEFAULT_APPEARANCE.transparency,haloScale:s.appearance?.haloScale??n?.appearance.haloScale??Wt.DEFAULT_APPEARANCE.haloScale},l=this.positionOf(s,r,e)??(n&&{eastM:n.eastM,northM:n.northM,vertical:this.verticalOf(s,r)??n.vertical});if(!l)continue;const h=s.flame??n?.flame,u=s.present??n?.present??!0;if(n={t:s.t,...l,sizeM:r,attitude:a,appearance:c,flame:h,present:u},this.body.withObserver&&s.azimuthDeg!==void 0&&s.distanceM!==void 0){const d=Wt.directionOf(s.azimuthDeg,s.altitudeDeg??0);n.carried={eastM:d.eastM*s.distanceM,northM:d.northM*s.distanceM,upM:d.upM*s.distanceM}}i.push(n)}return i}verticalOf(t,e){if(t.onGround)return{aboveGroundM:0};if(t.altitudeAboveGroundM!==void 0)return{aboveGroundM:t.altitudeAboveGroundM};if(t.altitudeM!==void 0)return{upM:t.altitudeM+e.heightM/2}}positionOf(t,e,i){if(t.eastM!==void 0&&t.northM!==void 0)return{eastM:t.eastM,northM:t.northM,vertical:this.verticalOf(t,e)??{aboveGroundM:0}};if(t.azimuthDeg===void 0||t.altitudeDeg===void 0)return;const n=i(t.t);if(!n)return;const s=t.distanceM??(t.onGround?Wt.lineOfSightMeetsGround(n,t.azimuthDeg,t.altitudeDeg,this.ground):void 0);if(s===void 0)return;const r=Wt.directionOf(t.azimuthDeg,t.altitudeDeg),a=n.eastM+r.eastM*s,c=n.northM+r.northM*s;return{eastM:a,northM:c,vertical:this.verticalOf(t,e)??{upM:n.upM+r.upM*s}}}static lerp(t,e,i){return t+(e-t)*i}static lerpColor(t,e,i){const n=Wt.rgbOf(t),s=Wt.rgbOf(e);return!n||!s?i<1?t:e:"#"+n.map((r,a)=>Math.round(Wt.lerp(r,s[a],i)).toString(16).padStart(2,"0")).join("")}static rgbOf(t){const e=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t);if(!e)return;const i=e[1].length===3?e[1].replace(/./g,"$&$&"):e[1];return[0,2,4].map(n=>parseInt(i.slice(n,n+2),16))}static lerpAngle(t,e,i){const n=((e-t)%360+540)%360-180;return((t+n*i)%360+360)%360}}class Nn{static MJU_7={massKg:.37,burnedKg:.26,dragAreaM2:1.2*.0508*.2032,ejectionMS:30,burnS:4.5,luminousIntensityCd:2e4,flameSizeM:1.5,color:"#ffd9a0"};static SAMPLE_MS=100;static STEP_S=.002;static G=9.81;static expand(t){const e=t?.flares;return!t||!e||e.length===0?t:{...t,bodies:[...t.bodies,...e.flatMap(i=>Nn.bodiesOf(i))]}}static bodiesOf(t){const e={...Nn.MJU_7,...t.flare},i=[],n=t.aircraft;if(n.model||n.sound){const s=t.releases.map(h=>h.t),r=Math.min(n.t,...s)-12e4,a=Math.max(n.t,...s)+12e4,c=n.model?{color:"#30333a",albedo:.15}:{transparency:1},l=h=>{const u=Nn.aircraftAt(n,h);return{t:h,eastM:u.x,northM:u.y,altitudeM:u.z,attitude:{headingDeg:n.headingDeg},sizeM:n.sizeM??{widthM:1,lengthM:1,heightM:1},appearance:c}};i.push({id:`${t.id}-aircraft`,title:t.title,model:n.model??{id:"sphere"},track:[l(r),l(a)],sound:n.sound})}return n.glow&&i.push(Nn.glowBody(t,n.glow)),t.releases.forEach((s,r)=>i.push(Nn.flareBody(t,e,s,r))),i}static aircraftAt(t,e){const i=t.headingDeg*Math.PI/180,n=(e-t.t)/1e3*t.speedMS;return{x:t.eastM+Math.sin(i)*n,y:t.northM+Math.cos(i)*n,z:t.altitudeM}}static burnShare(t,e){if(e<0||e>=t.burnS)return 0;if(e<.2)return e/.2;const i=t.burnS*.75;return e<=i?1:(t.burnS-e)/(t.burnS-i)}static trajectory(t,e,i,n=Nn.SAMPLE_MS){const s=t.aircraft,r=s.headingDeg*Math.PI/180,c={...Nn.aircraftAt(s,i),vx:Math.sin(r)*s.speedMS,vy:Math.cos(r)*s.speedMS,vz:-e.ejectionMS},l=(t.wind?.towardDeg??0)*Math.PI/180,h=t.wind?.speedMS??0,u=Math.sin(l)*h,d=Math.cos(l)*h,f=s.originElevationM??1e3,p=[{t:i,x:c.x,y:c.y,z:c.z}],g=Nn.STEP_S,m=Math.round(n/1e3/g),v=Math.ceil(e.burnS/g);for(let y=1;y<=v;y++){const x=y*g,M=e.massKg-e.burnedKg*Math.min(1,x/e.burnS),b=1.225*Math.exp(-(c.z+f)/8500),S=c.vx-u,E=c.vy-d,w=c.vz,_=Math.hypot(S,E,w),D=.5*b*e.dragAreaM2*_/M;c.vx=(c.vx+D*g*u)/(1+D*g),c.vy=(c.vy+D*g*d)/(1+D*g),c.vz=(c.vz-Nn.G*g)/(1+D*g),c.x+=c.vx*g,c.y+=c.vy*g,c.z+=c.vz*g,(y%m===0||y===v)&&p.push({t:i+Math.round(x*1e3),x:c.x,y:c.y,z:c.z})}return p}static glowBody(t,e){const i=e.sizeM/2,n=e.luminousIntensityCd/(Math.PI*i*i),s=[{t:e.fromT,lit:!0}];if(e.onS&&e.offS)for(let l=e.fromT,h=!0;l<e.untilT;h=!h)l+=(h?e.onS:e.offS)*1e3,l<e.untilT&&s.push({t:l,lit:!h});const r=(l,h)=>{const u=Nn.aircraftAt(t.aircraft,l);return{t:l,eastM:u.x,northM:u.y,altitudeM:u.z,appearance:{color:e.color,luminanceCdM2:h?n:0}}},a=[];s.forEach(({t:l,lit:h},u)=>{u>0&&a.push(r(l-1,!h)),a.push(r(l,h))}),a[0]={...a[0],sizeM:{widthM:e.sizeM,lengthM:e.sizeM,heightM:e.sizeM},present:!0};const c=s[s.length-1];return a.push(r(e.untilT,c.lit),{t:e.untilT+1,present:!1}),{id:`${t.id}-glow`,title:t.title,explains:e.explains,model:{id:"sphere"},track:a}}static flareBody(t,e,i,n){const s=e.flameSizeM,r=s/2,a=e.luminousIntensityCd/(Math.PI*r*r),c=Nn.trajectory(t,e,i.t),l=c.map((h,u)=>({t:h.t,eastM:h.x,northM:h.y,altitudeM:h.z,...u===0?{sizeM:{widthM:s,lengthM:s,heightM:s},present:!0}:{},appearance:{color:e.color,luminanceCdM2:a*Nn.burnShare(e,(h.t-i.t)/1e3),...u===0?{haloScale:1}:{}}}));return l.push({t:c[c.length-1].t+1,present:!1}),{id:`${t.id}-flare-${n+1}`,title:t.title,explains:i.explains,model:{id:"sphere"},track:l}}}class mi{static COMMON={envelopeVolumeM3:.19,massKg:.065,fuelKg:.03,burnS:600,insideExcessK:150,dragAreaM2:.25,luminousIntensityCd:10,widthM:.6,heightM:1,color:"#ffa250"};static SAMPLE_MS=1e3;static STEP_S=.05;static COOLING_S=20;static G=9.81;static R_AIR=287.05;static LAPSE=.0065;static expand(t){const e=t?.lanterns;return!t||!e||e.length===0?t:{...t,bodies:[...t.bodies,...e.flatMap(i=>mi.bodiesOf(i))]}}static bodiesOf(t){return mi.releasesOf(t).map((e,i)=>mi.lanternBody(t,e,i))}static releasesOf(t){const e=[...t.releases??[]],i=t.group;if(!i||!(i.count>0))return e;const n=mi.randomFrom(i.seed??1),s=c=>c.min+(c.max-c.min)*n(),r=i.count>1?(i.untilT-i.fromT)/(i.count-1):0,a=i.radiusM??20;for(let c=0;c<i.count;c++){const l=i.fromT+r*c+(n()-.5)*r,h=a*Math.sqrt(n()),u=2*Math.PI*n();e.push({t:Math.round(Math.min(i.untilT,Math.max(i.fromT,l))),explains:i.explains,eastM:Math.round(h*Math.sin(u)*10)/10,northM:Math.round(h*Math.cos(u)*10)/10,burnedS:i.burnedS,lantern:{burnS:Math.round(s(i.burnS??{min:480,max:900})),insideExcessK:Math.round(s(i.insideExcessK??{min:125,max:175}))}})}return e}static randomFrom(t){let e=t>>>0;return()=>{e=e+1831565813>>>0;let i=e;return i=Math.imul(i^i>>>15,i|1),i^=i+Math.imul(i^i>>>7,i|61),((i^i>>>14)>>>0)/4294967296}}static typeOf(t,e){return{...mi.COMMON,...t.lantern,...e.lantern}}static heatShare(t,e){if(e<0||e>=t.burnS)return 0;const i=t.burnS*.75;return e<=i?1:(t.burnS-e)/(t.burnS-i)}static windAt(t,e){const i=mi.componentsOf(t.wind),n=t.windAloft;if(!n)return i;const s=mi.componentsOf(n),r=Math.max(0,Math.min(1,e/n.atM));return{x:i.x+(s.x-i.x)*r,y:i.y+(s.y-i.y)*r}}static trajectory(t,e,i=mi.SAMPLE_MS){const n=mi.typeOf(t,e),s=t.site,r=s.altitudeM??0,a=Math.max(0,e.burnedS??0),c=s.originElevationM??0,l=(t.airTemperatureC??10)+273.15,h={x:s.eastM+(e.eastM??0),y:s.northM+(e.northM??0),z:e.altitudeM??r,vx:0,vy:0,vz:0,excessK:n.insideExcessK*mi.heatShare(n,a)},u=mi.STEP_S,d=Math.max(1,Math.round(i/1e3/u)),f=Math.ceil(Math.max(0,n.burnS-a)/u),p=[{t:e.t,x:h.x,y:h.y,z:h.z,light:mi.heatShare(n,a)}];for(let g=1;g<=f;g++){const m=g*u,v=a+m,y=mi.heatShare(n,v);h.excessK+=(n.insideExcessK*y-h.excessK)*Math.min(1,u/mi.COOLING_S);const x=h.z-r,M=l-mi.LAPSE*Math.max(0,x),b=101325*Math.exp(-(h.z+c)/8400),S=b/(mi.R_AIR*M),E=b/(mi.R_AIR*(M+h.excessK)),w=n.massKg-n.fuelKg*Math.min(1,v/n.burnS),_=(S-E)*n.envelopeVolumeM3*mi.G,D=w+E*n.envelopeVolumeM3+.5*S*n.envelopeVolumeM3,I=mi.windAt(t,x),O=h.vx-I.x,L=h.vy-I.y,N=h.vz,P=.5*S*n.dragAreaM2*Math.hypot(O,L,N)/D;h.vx=(h.vx+P*u*I.x)/(1+P*u),h.vy=(h.vy+P*u*I.y)/(1+P*u),h.vz=(h.vz+(_-w*mi.G)/D*u)/(1+P*u),h.x+=h.vx*u,h.y+=h.vy*u,h.z=Math.max(r,h.z+h.vz*u);const z=h.z<=r&&m>10;if((g%d===0||g===f||z)&&p.push({t:e.t+Math.round(m*1e3),x:h.x,y:h.y,z:h.z,light:y}),z)break}return p}static componentsOf(t){if(!t)return{x:0,y:0};const e=t.towardDeg*Math.PI/180;return{x:Math.sin(e)*t.speedMS,y:Math.cos(e)*t.speedMS}}static lanternBody(t,e,i){const n=mi.typeOf(t,e),s=n.luminousIntensityCd/(Math.PI*n.widthM/2*n.heightM/2),r=mi.trajectory(t,e),a={widthM:n.widthM,lengthM:n.widthM,heightM:n.heightM},c=r.map((l,h)=>({t:l.t,eastM:l.x,northM:l.y,altitudeM:l.z,...h===0?{sizeM:a,present:!0}:{},appearance:{color:n.color,luminanceCdM2:s*l.light,...h===0?{albedo:.6,haloScale:1}:{}}}));return c.push({t:r[r.length-1].t+1,present:!1}),{id:`${t.id}-lantern-${i+1}`,title:t.title,explains:e.explains,model:{id:"sphere"},track:c}}}class o1{static FIRST_DAY="2022-01-01";static mayCover(t){return new Date(t).toISOString().slice(0,10)>=o1.FIRST_DAY}}class vO{constructor(t,e,i){this.citation=t,this.covers=e,this.load=i}loading;mayCover(t){return this.covers(t)}async between(t,e,i,n){try{return await(await this.provider()).between(t,e,i,n)}catch{return{status:"failed"}}}async describe(t,e){try{return await(await this.provider()).describe?.(t,e)}catch{return}}provider(){if(!this.loading){const t=this.load();this.loading=t,t.catch(()=>{this.loading===t&&(this.loading=void 0)})}return this.loading}}const MO="Aircraft positions: adsb.lol feeders and contributors, Open Database License 1.0 (https://www.adsb.lol/docs/open-data/historical/)",yO=[{id:"adsb-lol",name:"adsb.lol",credit:"adsb.lol feeders and contributors, ODbL 1.0",creditUrl:"https://www.adsb.lol/docs/open-data/historical/",create:()=>new vO(MO,o=>o1.mayCover(o),async()=>new(await we(async()=>{const{AdsbLolArchiveProvider:o}=await import("./AdsbLolArchiveProvider-SLZYD2p1.js");return{AdsbLolArchiveProvider:o}},[],import.meta.url)).AdsbLolArchiveProvider)}];class kn{static MAX_GAP_S=60;static FT_TO_M=.3048;static EARTH_RADIUS_KM=6371;static seenFrom(t,e,i){const n=kn.positionAt(t,i);if(!n)return;const s=Ae.seenFrom(e,n.geo);if(!(s.altitudeDeg<0))return{track:t,sky:s,altitudeFt:n.altitudeFt,groundSpeedKt:n.groundSpeedKt,trackDeg:n.trackDeg,angularRateDegPerS:kn.angularRate(t,e,i)}}static viewsAt(t,e,i){return t.flatMap(n=>kn.seenFrom(n,e,i)??[])}static groundDistanceKm(t,e){const i=Math.PI/180,n=Math.sin((e.lat-t.lat)*i/2)**2+Math.cos(t.lat*i)*Math.cos(e.lat*i)*Math.sin((e.lng-t.lng)*i/2)**2;return 2*kn.EARTH_RADIUS_KM*Math.asin(Math.min(1,Math.sqrt(n)))}static wrapLongitude(t){return((t+180)%360+360)%360-180}static positionAt(t,e){const i=t.points;if(i.length===0||e<i[0].t||e>i[i.length-1].t)return;let n=0;for(;n<i.length-1&&i[n+1].t<=e;)n++;const s=i[n],r=i[n+1]??s,a=r.t-s.t;if(a>kn.MAX_GAP_S*1e3)return;const c=a>0?(e-s.t)/a:0,l=s.altitudeFt+(r.altitudeFt-s.altitudeFt)*c,h=(r.lng-s.lng+540)%360-180;return{geo:{lat:s.lat+(r.lat-s.lat)*c,lng:kn.wrapLongitude(s.lng+h*c),heightM:l*kn.FT_TO_M},altitudeFt:l,groundSpeedKt:s.groundSpeedKt,trackDeg:s.trackDeg}}static angularRate(t,e,i){const n=kn.positionAt(t,i-500),s=kn.positionAt(t,i+500);if(!n||!s)return;const r=kn.unit(Ae.seenFrom(e,n.geo)),a=kn.unit(Ae.seenFrom(e,s.geo)),c=Math.min(1,Math.max(-1,r[0]*a[0]+r[1]*a[1]+r[2]*a[2]));return Math.acos(c)*180/Math.PI}static unit(t){const e=t.altitudeDeg*Math.PI/180,i=t.azimuthDeg*Math.PI/180;return[Math.cos(e)*Math.sin(i),Math.cos(e)*Math.cos(i),Math.sin(e)]}}const ny="https://ufoathome.org/fireballs/index.json";class gr{static FIRST_MONTH="2018-12";static STRIKING_MAGNITUDE=-1;static COLOR="#eef2ff";static TRAIN_S=.3;fetchImpl;indexUrls;index;months=new Map;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??gr.defaultIndexUrls()}static defaultIndexUrls(){const t=[];return typeof location<"u"&&/^https?:$/.test(location.protocol)&&t.push(new URL("/fireballs/index.json",location.href).href),t.includes(ny)||t.push(ny),t}static mayCover(t){return new Date(t).toISOString().slice(0,7)>=gr.FIRST_MONTH}async credit(){return(await this.loadIndex())?.index.credit}async between(t,e){if(!gr.mayCover(e))return;const i=await this.loadIndex();if(!i)return;const n=new Set([new Date(t).toISOString().slice(0,7),new Date(e).toISOString().slice(0,7)]);return[...n].some(r=>r>=i.index.from&&r<=i.index.to)?(await Promise.all([...n].filter(r=>i.index.months.includes(r)).map(r=>this.monthOf(r,i.base)))).flat().filter(r=>r.t>=t&&r.t<=e):void 0}static seenFrom(t,e){const i=gr.peakFraction(t),n={lat:t.from[0]+(t.to[0]-t.from[0])*i,lng:t.from[1]+(t.to[1]-t.from[1])*i,heightM:t.peakHeightKm*1e3},s=Ae.seenFrom(e,n);if(!(s.altitudeDeg<0))return{record:t,peak:s,magnitude:t.peakMagnitude+5*Math.log10(s.distanceKm/Ae.STANDARD_DISTANCE_KM)}}static asReentry(t,e){const i=t.t-e,n=i+Math.max(t.durationS,.1)*1e3;return{id:`gmn-${t.id}`,track:[{t:i,lat:t.from[0],lng:t.from[1],altitudeKm:t.from[2]},{t:n,lat:t.to[0],lng:t.to[1],altitudeKm:t.to[2]}],fragments:[{absoluteMagnitude:t.peakMagnitude,color:gr.COLOR,trainS:gr.TRAIN_S}]}}static peakFraction(t){const e=t.from[2]-t.to[2];return Math.abs(e)<1e-6?.5:Math.min(1,Math.max(0,(t.from[2]-t.peakHeightKm)/e))}loadIndex(){return this.index??=(async()=>{for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(e.ok)return{index:await e.json(),base:t}}catch{}})(),this.index}monthOf(t,e){let i=this.months.get(t);return i||(i=this.fetchImpl(new URL(`${t}.json`,e).href).then(n=>n.ok?n.json():[]).catch(()=>[]),this.months.set(t,i)),i}}const Ac=Math.PI/180,$l=180/Math.PI;class gi{constructor(t,e){this.timeline=t,this.tolerance=e}static DIRECTION_TOLERANCE_DEG=1;static SIZE_TOLERANCE=1.5;static RINGS=12;static SEGMENTS=24;static lawsOf(t,e){return{direction(i,n,s){const r=t.law({kind:"heading",value:i.azimuthDeg},e),a=Math.abs(((n.azimuthDeg-i.azimuthDeg)%360+540)%360-180),c=t.law({kind:"elevation",value:i.altitudeDeg},e),l=Math.max(gi.DIRECTION_TOLERANCE_DEG,s);return a>(r.high??i.azimuthDeg)-i.azimuthDeg+l||n.altitudeDeg>(c.high??i.altitudeDeg)+l||n.altitudeDeg<(c.low??i.altitudeDeg)-l},size(i,n){const s=t.law({kind:"angularSize",value:i},e);return n<(s.low??i)/gi.SIZE_TOLERANCE||n>(s.high??i)*gi.SIZE_TOLERANCE}}}at(t,e,i,n){const s=[];for(const r of e){const a=gi.projectionOf(r,i,n?.(r));if(a)for(const c of r.explains){const l=this.timeline.getInterpolatedShapeAt(t,c);!l||l.transparency>=1||s.push({...gi.compare(c,r.id,{aim:l.aim,angular:l.angular},a,this.tolerance),title:l.title})}}return s}static compare(t,e,i,n,s){const r=[],a=i.aim?gi.separationDeg(i.aim,n.aim):void 0;if(a!==void 0){const u=Math.max(i.angular?.widthDeg??0,n.angular.widthDeg)/2;(s?s.direction(i.aim,n.aim,u):a>Math.max(gi.DIRECTION_TOLERANCE_DEG,u))&&r.push("direction")}const c=i.angular&&i.angular.widthDeg>0?n.angular.widthDeg/i.angular.widthDeg:void 0,l=i.angular&&i.angular.heightDeg>0?n.angular.heightDeg/i.angular.heightDeg:void 0,h=(u,d)=>s?s.size(d,d*u):!gi.withinSize(u);return c!==void 0&&h(c,i.angular.widthDeg)&&r.push("width"),l!==void 0&&h(l,i.angular.heightDeg)&&r.push("height"),{sourceId:t,bodyId:e,stated:i,predicted:n,separationDeg:a,widthRatio:c,heightRatio:l,disagreements:r}}static projectionOf(t,e,i){const n=i&&i.length>0?i:gi.outlineOf(t),s=i&&i.length>0?gi.centreOf(i):t,r=gi.normalized({eastM:s.eastM-e.eastM,northM:s.northM-e.northM,upM:s.upM-e.upM});if(!r)return;const a=gi.normalized({eastM:r.northM,northM:-r.eastM,upM:0})??{eastM:1,northM:0,upM:0},c=gi.cross(a,r);let l=1/0,h=-1/0,u=1/0,d=-1/0;for(const f of n){const p={eastM:f.eastM-e.eastM,northM:f.northM-e.northM,upM:f.upM-e.upM},g=gi.dot(p,r);if(g<=0)return;const m=Math.atan2(gi.dot(p,a),g),v=Math.atan2(gi.dot(p,c),g);l=Math.min(l,m),h=Math.max(h,m),u=Math.min(u,v),d=Math.max(d,v)}return{aim:{azimuthDeg:(Math.atan2(r.eastM,r.northM)*$l+360)%360,altitudeDeg:Math.asin(Math.max(-1,Math.min(1,r.upM)))*$l},angular:{widthDeg:(h-l)*$l,heightDeg:(d-u)*$l}}}static centreOf(t){const e=i=>(Math.min(...t.map(n=>n[i]))+Math.max(...t.map(n=>n[i])))/2;return{eastM:e("eastM"),northM:e("northM"),upM:e("upM")}}static separationDeg(t,e){const i=t.altitudeDeg*Ac,n=e.altitudeDeg*Ac,s=Math.sin(i)*Math.sin(n)+Math.cos(i)*Math.cos(n)*Math.cos((t.azimuthDeg-e.azimuthDeg)*Ac);return Math.acos(Math.max(-1,Math.min(1,s)))*$l}static withinSize(t){return t<=gi.SIZE_TOLERANCE&&t>=1/gi.SIZE_TOLERANCE}static outlineOf(t){const e=t.sizeM.widthM/2,i=t.sizeM.lengthM/2,n=t.sizeM.heightM/2,s=[],r=t.model.url===void 0?t.model.id:void 0;if(r!==void 0&&r!=="box"&&Eb.includes(r))for(let u=0;u<=gi.RINGS;u++){const d=u/gi.RINGS*Math.PI;for(let f=0;f<gi.SEGMENTS;f++){const p=f/gi.SEGMENTS*2*Math.PI;s.push([e*Math.sin(d)*Math.cos(p),i*Math.sin(d)*Math.sin(p),n*Math.cos(d)])}}else for(const u of[-e,e])for(const d of[-i,i])for(const f of[-n,n])s.push([u,d,f]);const c=t.attitude.headingDeg*Ac,l=t.attitude.pitchDeg*Ac,h=t.attitude.rollDeg*Ac;return s.map(([u,d,f])=>{const p=u*Math.cos(h)+f*Math.sin(h),g=-u*Math.sin(h)+f*Math.cos(h),m=d*Math.cos(l)-g*Math.sin(l),v=d*Math.sin(l)+g*Math.cos(l);return{eastM:t.eastM+p*Math.cos(c)+m*Math.sin(c),northM:t.northM-p*Math.sin(c)+m*Math.cos(c),upM:t.upM+v}})}static dot(t,e){return t.eastM*e.eastM+t.northM*e.northM+t.upM*e.upM}static cross(t,e){return{eastM:t.northM*e.upM-t.upM*e.northM,northM:t.upM*e.eastM-t.eastM*e.upM,upM:t.eastM*e.northM-t.northM*e.eastM}}static normalized(t){const e=Math.hypot(t.eastM,t.northM,t.upM);return e>1e-9?{eastM:t.eastM/e,northM:t.northM/e,upM:t.upM/e}:void 0}}Vy();const xO={sun:"Sun",moon:"Moon",Venus:"Venus",Mars:"Mars",Jupiter:"Jupiter",Saturn:"Saturn"},bO="{name} — mag {mag}, {alt}° above the horizon",wO="{name} — {size}, {distance} away",SO="{name} — satellite, mag {mag}, {height} km up",sy={ghost:"Ghost: {name}",halo:"Halo: {name}",double:"Double: {name}",unnamed:"a light",detail:"{name}. {cause}, {where}.",causes:{lens:"A reflection between two surfaces of the lens",sensor:"The sensor's reflection, sent back by its cover glass",filter:"The sensor's reflection, sent back by the filter",glass:"A reflection between the two faces of the glass in front of the lens",drops:"Light scattered by drops on the glass",condensation:"Light scattered by condensation on the glass",dirt:"Light scattered by dirt on the glass"},opposite:"across the centre of the picture from the light",sameSide:"on the same side of the centre as the light",around:"round the light",drop:{lens:"Drop on the lens",filter:"Drop on the filter",window:"Drop on the window",windscreen:"Drop on the windscreen"},dropDetail:"{name}. Like a small lens, it shows upside down and blurred what is on the other side of it, rather than what is behind it."},EO={name:"Rocket plume",detail:"{name} — {part}, {distance} away, {height} km up",ascent:"exhaust of the ascent",burn:"exhaust of an engine burn",vent:"vented propellant"},AO="satellites-change",_O="fireballs-change",TO="references-change",RO="aircraft-change",Cb="rr0-confrontation",IO="{name} — mag {mag}, {alt}° below the horizontal",Sp="Credits",ry="comet:",ay="nova:",Ep={building:"Building",tree:"Tree",shrub:"Shrub",bridge:"Bridge",wire:"Overhead line",crop:"Crop row",terrace:"Terrace (restanque)",mound:"Stone heap",wall:"Dry-stone wall",streetlight:"Streetlight",trafficlight:"Traffic light",crossing:"Pedestrian crossing",roadsign:"Road sign",vehicle:"Vehicle",observer:"Observer",aircraft:"Aircraft",entity:"Being"},DO=new URL(""+new URL("lunar-relief.bin-ByThqxUn.gz",import.meta.url).href,import.meta.url).href,CO=new URL(""+new URL("stars-mag7.5-B43R6Wvg.bin",import.meta.url).href,import.meta.url).href,OO=new URL(""+new URL("stars-mag7.5-9-BLV2tFmZ.bin",import.meta.url).href,import.meta.url).href,PO=-18,LO={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},Qu={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class be extends HTMLElement{creditsButton;set ownCredits(t){this.creditsButton.hidden=!t}static get observedAttributes(){return["src","star-catalog-src","deep-star-catalog-src","show-compass","max-pixel-ratio",Ar,_r,bo]}shadow;stageElement;frameElement;sceneCanvas;busyElement;busyNote;loaderNote;loaderNotVideo;ufoElement;sceneRenderer;hoverTooltip;ghostPath;holding=!1;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;distanceHypotheses=new Map;depths=new Map;directionScratch=new R;meteorScheduleFor;lightningScheduleFor;lightningFlashes=[];lastLightningT;lastTimeMs=0;interpretationShown;confrontationReadings=[];confrontationTolerance;confrontationSignature="";comparing=!1;inTheRound=!0;lastSkyKey;starCatalog;starCatalogRequest=0;static tleArchive=new Sn;satellitesFor;satelliteRequest=0;satelliteStatus="none";satellites;satellitePassesMemo;static fireballArchive=new gr;fireballs;static aircraftProviders=new Map;static SOUND_LOOKBACK_MS=3e5;static TRAIL_LOOKBACK_MS=36e5;static TRAIL_MAX_AIRCRAFT=60;static NO_CONTRAILS=[];static NO_BEAMS=[];static upperAirProviders=new Map;static NO_PRESENCE=new Map;aircraftSource=yO[0];static trafficRuntimeLoading;static trafficRuntime;static loadTrafficRuntime(){return be.trafficRuntimeLoading??=we(()=>import("./trafficRuntime-CfPqH9j0.js"),__vite__mapDeps([2,1]),import.meta.url).then(t=>be.trafficRuntime=t),be.trafficRuntimeLoading.catch(()=>{be.trafficRuntimeLoading=void 0}),be.trafficRuntimeLoading}traffic;lastSun;get sunAltitudeDeg(){return this.sceneRenderer.sunAltitudeDeg??this.lastSun?.altitudeDeg}decorMemo;seatedMemo;starCatalogDepth=0;weatherAudio=new uO;vehicleAudio=new bS;aircraftAudio;vehicleHearing=new Vd;decorAircraftHearing;bodyHearing;decorModelSounds=new Map;thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=t=>{if(this.sceneRenderer.setCompassHovered(!0),this.holding){this.hoverTooltip.hidden=!0;return}const e=this.ufoElement.canvasElement,i=e.getBoundingClientRect();if(i.width===0||i.height===0)return;const n=(t.clientX-i.left)/i.width*e.width,s=(t.clientY-i.top)/i.height*e.height;if(this.ufoElement.hasVisibleShapeAt(n,s)){this.hoverTooltip.hidden=!0;return}const r=(t.clientX-i.left)/i.width*2-1,a=-((t.clientY-i.top)/i.height*2-1),c=this.pickAt(r,a,!0,t.altKey);c?this.showHoverTooltip(t,t.altKey&&c.detail?c.detail():c.name):this.hoverTooltip.hidden=!0,this.showGhostPath(c?.path,i)};showGhostPath(t,e){if(!t){this.ghostPath.toggleAttribute("hidden",!0);return}const i=this.stageElement.getBoundingClientRect(),n=d=>({x:e.left-i.left+(d.x+1)/2*e.width,y:e.top-i.top+(1-d.y)/2*e.height}),s=n(t.from),r=n(t.to),a=n({x:0,y:0});this.ghostPath.setAttribute("viewBox",`0 0 ${i.width} ${i.height}`);const[c,l,h,u]=Array.from(this.ghostPath.children);for(const d of[c,l])d.setAttribute("x1",String(s.x)),d.setAttribute("y1",String(s.y)),d.setAttribute("x2",String(r.x)),d.setAttribute("y2",String(r.y));h.setAttribute("cx",String(a.x)),h.setAttribute("cy",String(a.y)),u.setAttribute("cx",String(r.x)),u.setAttribute("cy",String(r.y)),this.ghostPath.toggleAttribute("hidden",!1)}pickAt(t,e,i=!0,n=!1){const s=this.naming,r=s.names;if(n&&this.sceneRenderer.pickDropAt(t,e)){const E=r?.ghostTooltip??sy,w=E.drop[this.ufoElement.sighting.lens?.glass??"lens"];return{kind:"drop",name:w,detail:()=>E.dropDetail.replace("{name}",w)}}const a=this.sceneRenderer.pickBodyAt(t,e);if(a)return{kind:"sky",id:a,name:this.bodyName(a)};const c=this.interpretationShown?this.sceneRenderer.pickInterpretationBodyAt(t,e):void 0,l=c?this.interpretationShown?.bodies.find(E=>E.id===c):void 0,h=l?this.said.read(l.title)||(l.model.id==="figure"?s.decorKind("entity",Ep.entity):void 0):void 0;if(c!==void 0&&h)return{kind:"body",id:c,name:h};const u=this.ufoElement.sighting.skyEvents?.beams,d=u?.length?this.sceneRenderer.pickBeamAt(t,e):void 0,f=d?u?.find(E=>E.id===d.id):void 0;if(d&&f){const E=this.said.read(f.title)||"Laser";return{kind:"beam",id:f.id,name:E,detail:()=>`${E} (${f.wavelengthNm} nm, ${f.powerW.toLocaleString()} W), ${this.distanceText(d.distanceM)}`}}const p=i?this.ghostPick(t,e):void 0;if(p)return p;const g=this.pickDecorAt(t,e),m=g?this.ufoElement.sighting.decor.find(E=>E.id===g):void 0;if(m){const E=this.said.read(m.title)||s.decorKind(m.kind,Ep[m.kind]);return{kind:"decor",id:m.id,name:E,detail:()=>this.decorTooltip(m,E)}}const v=this.sceneRenderer.pickRailwayAt(t,e);if(v){const E=r?.railwayTooltip??zs.ENGLISH;return{kind:"railway",id:v.line.id,name:zs.name(v.line,E),detail:()=>zs.detail(v,E,w=>this.distanceText(w))}}const y=this.trafficTooltipAt(t,e);if(y)return{kind:"traffic",name:y};const x=this.plumePickAt(t,e);if(x)return x;const M=this.sceneRenderer.pickSatelliteAt(t,e);if(M)return{kind:"satellite",name:(r?.satelliteTooltip??SO).replace("{name}",M.name).replace("{mag}",M.magnitude.toLocaleString(void 0,{maximumFractionDigits:1})).replace("{height}",Math.round(M.heightKm).toLocaleString())};const b=this.sceneRenderer.pickOpticsAt(t,e);if(b){const E=(r?.opticsTooltips??rO)[b.id].replace("{angle}",String(Math.round(b.angleDeg??0)));return{kind:"optics",id:b.id,name:E.split(" — ")[0],detail:()=>E}}const S=this.sceneRenderer.pickStarAt(t,e);if(S){const E=S.star.mag,w=S.altitudeDeg;return{kind:"star",name:(w<0?r?.starTooltipBelow??IO:r?.starTooltip??bO).replace("{name}",s.star(S.star)).replace("{mag}",E.toLocaleString(void 0,{maximumFractionDigits:Math.abs(E)<1?2:1})).replace("{alt}",String(Math.round(Math.abs(w))))}}}ghostPick(t,e){const i=this.sceneRenderer.pickGhostAt(t,e);if(!i)return;const n=this.naming.names?.ghostTooltip??sy,s=this.ufoElement.canvasElement,r={x:8/Math.max(1,s.clientWidth),y:8/Math.max(1,s.clientHeight)},a=[];for(let g=-4;g<=4;g++)for(let m=-4;m<=4;m++)a.push([m,g]);a.sort((g,m)=>Math.hypot(...g)-Math.hypot(...m));let c,l;for(const[g,m]of a){const v=this.pickAt(i.source.x+g*r.x,i.source.y+m*r.y,!1);if(v?.kind==="star")l??=v;else if(v){c=v;break}}c??=this.shiningDecorNear(i.source.x,i.source.y,6*Math.max(r.x,r.y)),c??=l;const h=(c?.kind==="star"?c.name.split(" — ")[0]:c?.name)??n.unnamed,u=i.ghost,f=(di.scatters(u)?n.halo:u.cause==="glass"?n.double:n.ghost).replace("{name}",h),p=u.scale<0?n.opposite:u.scale===1?n.around:n.sameSide;return{kind:"ghost",id:c?.id,name:f,detail:()=>n.detail.replace("{name}",f).replace("{cause}",n.causes[u.cause??"lens"]).replace("{where}",p),path:{from:{x:t,y:e},to:i.source}}}shiningDecorNear(t,e,i){let n;for(const s of this.ufoElement.sighting.decor){if(!(s.kind==="streetlight"||s.kind==="trafficlight"||(s.lights?.length??0)>0||s.kind==="vehicle"&&s.lit))continue;const a=this.sceneRenderer.decorScreenBox(s.id);if(!a)continue;const c=Math.hypot(Math.max(a.minX-t,0,t-a.maxX),Math.max(a.minY-e,0,e-a.maxY));if(c>i||n&&c>=n.distance)continue;const l=this.said.read(s.title)||this.naming.decorKind(s.kind,Ep[s.kind]);n={distance:c,pick:{kind:"decor",id:s.id,name:l}}}return n?.pick}glassWettingOf(t){const e=JSON.stringify([t.lens,t.instrumentId,t.weatherTrack.allKeyframes.map(i=>[i.t,i.weather.precipitationType,i.weather.precipitationIntensity,i.weather.windDirectionDeg,i.weather.windSpeed])]);if(this.glassWetting?.sighting!==t||this.glassWetting.key!==e){const i=new _o(n=>{if(!di.records(t.instrument)||!di.falling(t.lens))return 0;const s=wl(t,n*1e3),r=ze(t,n*1e3);return(s.precipitationAmount??1)*di.impactRate(s,t.lens?.glass,r&&{headingDeg:r.headingDeg??0,pitchDeg:r.pitchDeg,windFromDeg:s.windDirectionDeg,windSpeedMS:s.windSpeed})});this.glassWetting={sighting:t,key:e,wetting:i}}return this.glassWetting.wetting}glassWetting;plumePickAt(t,e){const i=this.ufoElement.sighting.skyEvents?.launches,n=i?.length?this.sceneRenderer.pickPlumeAt(t,e):void 0,s=n?i?.find(l=>l.id===n.launchId):void 0;if(!n||!s)return;const r=this.naming.names?.plumeTooltip??EO,a=this.said.read(s.title)||s.vehicle?.mission||r.name,c=()=>n.release===void 0||n.release==="burn"?r.ascent:s.jets?.find((h,u)=>`jet:${h.id??u}`===n.release)?.kind==="vent"?r.vent:r.burn;return{kind:"plume",id:s.id,name:a,detail:()=>r.detail.replace("{name}",a).replace("{part}",c()).replace("{distance}",this.distanceText(n.centre.distanceKm*1e3)).replace("{height}",Math.round(n.heightKm??0).toLocaleString())}}distanceText(t){return t>=1e3?`${(t/1e3).toLocaleString(void 0,{maximumFractionDigits:1})} km`:`${t.toLocaleString(void 0,{maximumFractionDigits:t<10?1:0})} m`}decorTooltip(t,e){const i=l=>l.toLocaleString(void 0,{maximumFractionDigits:l<10?1:0}),n=yt.sizeOf(t),s=this.sceneRenderer.decorDistanceM(t.id),r=s===void 0?"":this.distanceText(s);return(this.naming.names?.decorTooltip??wO).replace("{name}",e).replace("{size}",`${i(n.widthM)} × ${i(n.lengthM)} × ${i(n.heightM)} m`).replace("{distance}",r)}bodyName(t){const e=t.startsWith(ry)?t.slice(ry.length):void 0,i=e?Db.find(r=>r.id===e):void 0;if(i)return this.naming.comet(i);const n=t.startsWith(ay)?ty.byId(t.slice(ay.length)):void 0;if(n)return this.naming.nova(n);const s=xO[t];return s===void 0?t:this.naming.body(t,s)}get naming(){return this.sceneNaming}sceneNaming=new xf;namesLanguage="en";async loadSceneNames(){const t=dg(ka.preferencesFor(this),fg);if(t===this.namesLanguage)return;this.namesLanguage=t;const e=await Iy(t);t===this.namesLanguage&&this.applySceneNaming(new xf(e))}setBusy(t,e=""){this.busyElement.hidden=!t,this.busyNote.textContent=t?e:"",this.busyElement.setAttribute("aria-label",e),this.busyElement.setAttribute("aria-busy",String(t))}renderLoaderText(t,e){let i=0;const n=(s,r)=>{s.setAttribute("aria-label",r),s.replaceChildren(),r.split(" ").forEach((a,c)=>{c>0&&s.append(" ");const l=document.createElement("span");l.className="scene-loader-word",l.setAttribute("aria-hidden","true");for(const h of a){const u=document.createElement("span");u.className="scene-loader-letter",u.style.setProperty("--i",String(i++)),u.textContent=h,l.append(u)}s.append(l),i++})};n(this.loaderNotVideo,t),i+=6,n(this.loaderNote,e)}applySceneNaming(t){this.sceneNaming=t;const e=t.names?.credits??Sp;this.creditsButton.title=e,this.creditsButton.setAttribute("aria-label",e),t.names&&this.renderLoaderText(t.names.notAVideo,t.names.isASimulation),this.sceneRenderer.setCompassPoints(t.names?.compassPoints)}showHoverTooltip(t,e){this.hoverTooltip.textContent=e,this.hoverTooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect(),n=t.clientX-i.left+12,s=n+this.hoverTooltip.offsetWidth-i.width;this.hoverTooltip.style.left=`${s>0?Math.max(0,n-s-4):n}px`,this.hoverTooltip.style.top=`${t.clientY-i.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.ghostPath.toggleAttribute("hidden",!0),this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash(t){clearTimeout(this.thunderTimeoutId),this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),Qi.thunderDelayMs(t))}handleFirstInteraction=()=>{this.weatherAudio.resume(),this.vehicleAudio.resume(),this.aircraftAudio?.resume(),!this.interacted&&(this.interacted=!0,this.setWeather(wl(this.ufoElement.sighting,this.lastTimeMs)))};interacted=!1;applyLevel(){const t=this.ufoElement.level;this.weatherAudio.setLevel(t),this.vehicleAudio.setLevel(t),this.aircraftAudio?.setLevel(t)}handlePageGesture=()=>{this.ufoElement.playbackState==="playing"&&this.handleFirstInteraction()};unlockIfAlreadyActivated(){this.interacted||navigator.userActivation?.hasBeenActive&&this.handleFirstInteraction()}static GESTURES=["pointerdown","pointerup","touchend","click","keydown"];handleTimeUpdate=t=>{this.lastTimeMs=t.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.playbackState==="playing"&&this.sceneRenderer.frame(performance.now()),this.ufoElement.repaintChrome()};syncAnimationsToPlayback(){const t=this.ufoElement.playbackState==="playing";this.sceneRenderer.setAnimationsRunning(t,t),this.weatherAudio.setPaused(!t),this.vehicleAudio.setPaused(!t),this.aircraftAudio?.setPaused(!t),t&&this.unlockIfAlreadyActivated(),t||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${AS}</style>${ES}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.frameElement=this.shadow.getElementById("frame"),this.sceneCanvas=this.shadow.getElementById("scene-canvas"),this.sceneRenderer=new Et(this.sceneCanvas),this.sceneRenderer.onReferencesSettled=()=>this.dispatchEvent(new CustomEvent(TO));const e=this.shadow.getElementById("scene-loader");this.loaderNote=this.shadow.getElementById("scene-loader-note"),this.loaderNotVideo=this.shadow.getElementById("scene-loader-not-video"),this.renderLoaderText("This is not a video","It is a real-time simulation."),this.busyElement=this.shadow.getElementById("scene-busy"),this.busyNote=this.shadow.getElementById("scene-busy-note"),this.loader=e,this.poster=new a1(this.shadow.getElementById("scene-poster"),()=>{this.loader.style.animationDelay=!this.poster.up&&this.holding?"0s":"",this.applyHold()}),this.sceneRenderer.onFirstFrameHold=s=>{this.holding=s,this.applyHold()},this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ghostPath=this.shadow.getElementById("ghost-path"),this.ufoElement=document.createElement(Pp),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.paintsShapes=!1,this.ufoElement.observerMapFrozenSource=s=>this.frozenMapOf(s),this.forwardPlayerAttributes(),this.ufoElement.addEventListener("lookat",s=>this.lookToward(s.detail)),this.ufoElement.style.setProperty("--ufo-canvas-background","transparent"),this.ufoElement.style.setProperty("--ufo-canvas-border","none"),this.ufoElement.fullscreenTarget=this.stageElement,this.shadow.getElementById("ufo-slot").replaceWith(this.ufoElement),this.ufoElement.creditShownExternally=!0,this.creditsButton=this.shadow.getElementById("credits-button");const i=this.shadow.getElementById("credits-panel"),n=this.shadow.getElementById("credits-list");i.addEventListener("beforetoggle",s=>{s.newState==="open"&&dn.fill(n,this)}),this.creditsButton.title=Sp,this.creditsButton.setAttribute("aria-label",Sp),this.sceneRenderer.onMapSubjectBounds=s=>this.ufoElement.setMapSubjectBounds(s),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.addEventListener("playrequest",()=>this.poster.release()),this.ufoElement.addEventListener(Wy,()=>this.poster.restore()),this.ufoElement.seekPreviewPainter=(s,r)=>this.seekPreviewOf(r).paint(s,r),this.ufoElement.addEventListener("mutedchange",()=>this.applyLevel()),this.ufoElement.ambientSound=s=>s.vehicle!==void 0||s.decor.some(r=>r.engine!==void 0)||s.weatherTrack.allKeyframes.some(r=>r.weather.precipitationType!=="none"||r.weather.windSpeed>1),this.ufoElement.addEventListener("referenceview",s=>this.applyReferenceView(s.detail)),this.ufoElement.addEventListener("traceview",s=>this.sceneRenderer.setTracesShown(s.detail.shown)),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave);for(const s of be.GESTURES)this.addEventListener(s,this.handleFirstInteraction,!0)}get said(){return this.saidTexts??=new Es(ka.preferencesFor(this))}saidTexts;traceLabelsFor;observerHeadlightsAt(t,e){const i=t.vehicle;return i?{setting:Uo.at(i.headlights??"auto",i.headlightKeyframes,e)??"auto",headingDeg:this.travelHeadingAt(t,e)}:void 0}travelHeadingAt(t,e){const i=ze(t,e);if(!i)return 0;for(const n of[400,-400]){const s=ze(t,e+n);if(!s||i.lat===void 0||i.lng===void 0||s.lat===void 0||s.lng===void 0)break;const r=ae(s.lat,s.lng,i.lat,i.lng);if(Math.hypot(r.x,r.z)<.8)continue;return(Math.atan2(r.x,-r.z)*180/Math.PI+(n<0?180:0)+360)%360}return i.headingDeg??0}routeCache;routeOf(t){const e=t.allKeyframes;if(this.routeCache?.track===t&&this.routeCache.count===e.length)return this.routeCache.route;const i=e.flatMap(s=>s.pose.lat!==void 0&&s.pose.lng!==void 0?[{lat:s.pose.lat,lng:s.pose.lng}]:[]),n=i.length>=2?i:void 0;return this.routeCache={track:t,count:e.length,route:n},n}traceLabels(t){const e=ka.preferencesFor(this).join();if(this.traceLabelsFor?.traces!==t||this.traceLabelsFor.language!==e){const i=new Map;for(const n of t){const s=this.said.read(n.title);s&&i.set(n.id,s)}this.traceLabelsFor={traces:t,language:e,labels:i}}return this.traceLabelsFor.labels}connectedCallback(){this.saidTexts=void 0,this.loadSceneNames(),this.sceneRenderer.restoreContext(),this.resizeToStage(),this.updateAstronomy(this.lastTimeMs),this.loadStars(),this.resizeObserver=new ResizeObserver(()=>this.resizeToStage()),this.resizeObserver.observe(this.frameElement),this.watchVisibility(),document.addEventListener("fullscreenchange",this.handleFullscreenChange);for(const e of be.GESTURES)document.addEventListener(e,this.handlePageGesture,!0);const t=this.getAttribute("src");t&&this.loadFromSrc(t)}watchVisibility(){this.visibilityObserver?.disconnect(),!(typeof IntersectionObserver>"u"||this.hasAttribute("always-live"))&&(this.visibilityObserver=new IntersectionObserver(t=>{if(t[t.length-1].isIntersecting){this.sceneRenderer.resume();return}this.ufoElement.pause(),this.sceneRenderer.suspend()},{rootMargin:"100px"}),this.visibilityObserver.observe(this))}visibilityObserver;disconnectedCallback(){this.visibilityObserver?.disconnect(),this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange);for(const t of be.GESTURES)document.removeEventListener(t,this.handlePageGesture,!0);this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose(),this.vehicleAudio.dispose(),this.aircraftAudio?.dispose(),this.seekPreview?.dispose(),this.seekPreview=void 0,queueMicrotask(()=>{this.isConnected||this.sceneRenderer.releaseContext()})}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),(t==="star-catalog-src"||t==="deep-star-catalog-src")&&i!==e&&this.isConnected&&this.loadStars(),t==="show-compass"&&i!==e&&this.sceneRenderer.setShowCompass(this.hasAttribute("show-compass")),t==="max-pixel-ratio"&&i!==e){const n=Number(i);this.sceneRenderer.setMaxPixelRatio(Number.isFinite(n)&&n>0?n:Math.min(window.devicePixelRatio||1,2))}(t===Ar||t===_r||t===bo)&&i!==e&&this.forwardPlayerAttributes(),t===bo&&this.stageElement.classList.toggle("minified",i!==null)}forwardPlayerAttributes(){for(const t of[Ar,_r,bo]){const e=this.getAttribute(t);e===null?this.ufoElement.removeAttribute(t):this.ufoElement.setAttribute(t,e)}}setCompassForced(t){this.sceneRenderer.setCompassForced(t)}lookToward(t){const e=ze(this.ufoElement.sighting,this.lastTimeMs);if(t.kind==="observer"||e?.lat===void 0||e.lng===void 0||e.headingDeg===void 0){this.setLookOffset(0,0);return}const{x:i,z:n}=ae(t.lat,t.lng,e.lat,e.lng);if(Math.hypot(i,n)<1)return this.setLookOffset(0,0);const s=(Math.atan2(i,-n)*180/Math.PI+360)%360;this.setLookOffset(((s-e.headingDeg)%360+540)%360-180,-e.pitchDeg)}setLookOffset(t,e){this.sceneRenderer.setLookOffset(t,e),this.ufoElement.setLookOffset(t,e),this.updateAstronomy(this.lastTimeMs)}setIndoorLook(t,e){this.sceneRenderer.setIndoorLook(t,e)}setCloudRendering(t){this.sceneRenderer.setCloudRendering(t)}setWeather(t){this.sceneRenderer.setWeather(t),this.weatherAudio.setAmbient(t.precipitationType,t.precipitationIntensity*(t.precipitationAmount??1),t.windSpeed)}pickCloudAt(t,e){return this.sceneRenderer.pickCloudAt(t,e)}cloudDirectionAt(t,e){return this.sceneRenderer.cloudDirectionAt(t,e)}pickDecorAt(t,e){return this.sceneRenderer.pickDecorAt(t,e)}decorScreenBox(t){return this.sceneRenderer.decorScreenBox(t)}decorDrawnOffset(t){return this.sceneRenderer.decorDrawnOffset(t)}decorGroundPointAt(t,e,i,n=0){return this.sceneRenderer.decorGroundPointAt(t,e,i,n)}decorMetresPerNdcY(t){return this.sceneRenderer.decorMetresPerNdcY(t)}decorGrabHeightAt(t,e,i){return this.sceneRenderer.decorGrabHeightAt(t,e,i)}bodyScreenBox(t){return this.sceneRenderer.bodyScreenBox(t)}pickPlacedBodyAt(t,e){return this.sceneRenderer.pickPlacedBodyAt(t,e)}resumeWeatherAudio(){this.weatherAudio.resume(),this.vehicleAudio.resume(),this.aircraftAudio?.resume()}async loadFromSrc(t){const e=Na.recording(t);this.holdForNewScene(e);const i=await e;this.documentUrl=new URL(t,location.href).href,this.showPoster(i.image,this.documentUrl,!this.ufoElement.playRequested),this.sightingData=i}loader;poster;showPoster(t,e,i=!0){this.poster.show(t,e,i)}applyHold(){const t=this.holding,e=this.poster.up;this.loader.hidden=!t||e,t&&(this.hoverTooltip.hidden=!0),this.ufoElement.captionHeld=t||e,this.ufoElement.controlsHeld=t||e,this.ufoElement.holdClock(t)}holdForNewScene(t){this.sceneRenderer.holdForNewScene(t)}get documentUrl(){return this.sceneRenderer.documentUrl}set documentUrl(t){this.sceneRenderer.documentUrl=t}get sightingData(){return this.ufoElement.sightingData}set sightingData(t){this.ufoElement.sightingData=t,this.upperAirHeardLive=void 0,this.seekPreview?.recordingChanged(t),this.interpretationShown=this.inTheRound?mi.expand(Nn.expand(this.ufoElement.sighting.interpretation)):void 0,this.syncAccountHidden(),this.applyFrameFormat(),this.lastTimeMs=0,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(0)}seekPreview;seekPreviewOf(t){const e=this.sceneCanvas.width>0&&this.sceneCanvas.height>0?this.sceneCanvas.width/this.sceneCanvas.height:1.7777777777777777,i=Math.round(t.width/e);return t.height!==i&&(t.height=i),this.seekPreview??=new gf(this,()=>document.createElement(wf))}showAt(t){this.ufoElement.currentTime=t,this.framesAtAsk=this.sceneRenderer.framesDrawn}framesAtAsk=0;snapshotTo(t){if(this.sceneRenderer.frame(performance.now()),this.sceneRenderer.framesDrawn===this.framesAtAsk)return!1;const e=t.getContext("2d");return e?(e.imageSmoothingQuality="high",e.drawImage(this.sceneCanvas,0,0,t.width,t.height),!0):!1}referenceAspect(t){return this.sceneRenderer.referenceAspect(t)}screenPointOf(t){return this.sceneRenderer.screenPointOf(t)}directionAt(t,e){return this.sceneRenderer.directionAt(t,e)}referenceFailure(t){return this.sceneRenderer.referenceFailure(t)}applyReferenceView(t){this.sceneRenderer.setReferencesShown(t.shown);for(const e of this.ufoElement.sighting.references){const i=t.views?.[e.id];this.sceneRenderer.setReferenceView(e.id,{opacity:i?i.shown?i.opacity:0:t.opacity})}}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}get currentRoadAttribution(){return this.sceneRenderer.currentRoadAttribution}get currentWaterAttribution(){return this.sceneRenderer.currentWaterAttribution}get currentRailwayAttribution(){return this.sceneRenderer.currentRailwayAttribution}setTerrainProviders(t){this.liveTerrainProviders=t,this.frozenKey=void 0,this.applyFrozen(this.ufoElement.sighting.frozen)}liveTerrainProviders;frozenKey="none";applyFrozen(t){const e=Wc.isEmpty(t)?"none":`${JSON.stringify(t)}
9333
9333
  ${this.documentUrl??""}
9334
9334
  ${ti.generation}`;if(e===this.frozenKey)return;const i=this.frozenKey!==void 0&&this.traffic?.set!==void 0;this.frozenKey=e,this.sceneRenderer.setTerrainProviders(Mf.providers(t,this.documentUrl,this.liveTerrainProviders??Hy())),this.ufoElement.observerMapFrozen=this.frozenMapOf(t),i&&(this.traffic=void 0,this.decorMemo=void 0)}frozenMapOf(t){const e=Wc.held(t,"map");if(!e)return;const i=`${ti.address(e.src,this.documentUrl)}
9335
- ${ti.generation}`;return this.frozenMap?.key!==i&&(this.frozenMap={key:i,imagery:Mf.map(e,this.documentUrl)}),this.frozenMap.imagery}frozenMap;setDecorModelProvider(t){this.sceneRenderer.setDecorModelProvider(t)}get decorModelCredits(){return[...new Map(this.sceneRenderer.currentDecorModelCredits.map(e=>[`${e.title}|${e.author??""}|${e.license}|${e.sourceUrl??""}`,e])).values()]}applyFrameFormat(){const t=this.ufoElement.sighting.instrument,e=Ze.CANVAS_HEIGHT_PX,i=Bi.frameWidthPx(t,e);this.frameElement.style.setProperty("--frame-aspect",`${i} / ${e}`)}resizeToStage(){const t=this.frameElement.getBoundingClientRect(),e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.sceneCanvas.width=e,this.sceneCanvas.height=i,this.sceneRenderer.resize(e,i)}async loadStars(){const t=[{magnitudeLimit:Mp,url:this.getAttribute("star-catalog-src")??CO},{magnitudeLimit:yp,url:this.getAttribute("deep-star-catalog-src")??OO}],e=this.instrumentReach(),i=++this.starCatalogRequest;this.starCatalogDepth=e>Mp?yp:Mp;const n=await ar.upTo(t,e);i===this.starCatalogRequest&&(this.starCatalog=n,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=yp||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const t=this.ufoElement.sighting,e=fn.gainFor(t.instrument,{fNumber:ze(t,0)?.fNumber,fieldOfViewDeg:In.fovOf(t,0),exposureSeconds:t.exposure});return md(PO,e)}updateAstronomy(t){this.ensureStarsDeepEnough(),this.applySceneAt(t);const e=Fs.windowEndingAt(t,this.exposureSeconds()),i=e.seconds,n=this.degreesPerPixelAt(t),s=No.instants(i,n),r=Math.max(s,this.ufoElement.exposureTimes(t).length,Fs.instants(this.decorWithTraffic(this.ufoElement.sighting),ze(this.ufoElement.sighting,t)?.elevationM??0,e.fromMs,i,n));if(r<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(r,a=>this.applySceneAt(e.fromMs+e.ms*a/(r-1),{sky:Math.floor(a*s/r)!==Math.floor((a-1)*s/r),stepMs:e.ms/r}))}exposureSeconds(){return this.ufoElement.sighting.exposure??0}degreesPerPixelAt(t){const e=this.sceneCanvas.height;return e<=0?0:In.fovOf(this.ufoElement.sighting,t)/e}roadGradeAt(t,e){return t.observerTrack.allKeyframes.length<2?0:Dc.at(t,e,this.sceneRenderer.bodyGround)}get roadGradeDeg(){return this.roadGradeAt(this.ufoElement.sighting,this.ufoElement.currentTime)}applySceneAt(t,e){const i=this.ufoElement.sighting;this.setWeather(wl(i,t)),this.sceneRenderer.setInstrument(i.instrument),this.sceneRenderer.setLightPollution(i.lightPollution),e||this.vehicleAudio.setVoices(this.vehicleHearing.at(i,t)),e||this.pushAircraftSound(i,t),this.updateMeteorShower(i,t),this.updateLightning(i,t,e!==void 0),this.sceneRenderer.setDecor(this.seatedDecor(this.decorWithTraffic(i),t)),this.sceneRenderer.setDecorPresence(this.traffic?.set?.presence??be.NO_PRESENCE),this.sceneRenderer.setDecorSunlight(this.trafficSunlight(t)),this.sceneRenderer.setContrails(this.traffic?.contrails??be.NO_CONTRAILS),this.sceneRenderer.setContrailSunlight(this.contrailSunlight(t));const n=ze(i,t);this.sceneRenderer.setReferences(i.references,n?.lat!==void 0&&n.lng!==void 0?{lat:n.lat,lng:n.lng}:void 0);const s=ze(i,0),r=_c(i,0),a=ja(i.event.time??{},n?.lng??Qu.lng,i.event.utcOffsetHours),c=i.weatherSource!==void 0&&a?wS(a):void 0,l=Object.fromEntries(yd(_c(i,t)).map(I=>[I.id,q1(t,i.weatherTrack,r,s,n,I.id,I.instances?.length?void 0:c)]));this.sceneRenderer.setCloudOffset(q1(t,i.weatherTrack,r,s,n,void 0,c),l),this.sceneRenderer.setObserverPose(n?{...n,pitchDeg:n.pitchDeg+this.roadGradeAt(i,t)}:Qu),this.sceneRenderer.setLensOptics(this.lensOpticsAt(t)),this.sceneRenderer.setInstrumentGain(fn.gainFor(i.instrument,{fNumber:n?.fNumber,fieldOfViewDeg:In.fovOf(i,t),exposureSeconds:i.exposure}),i.instrument.detailUm!==void 0,Gs.byId(n?.filter).opticalDensity),this.sceneRenderer.setMedium(i.instrument.medium,i.exposure,n?.fNumber??i.instrument.fNumber,i.iso),this.sceneRenderer.setLensGhosts(di.optics(i.instrument,n?.fNumber??i.instrument.fNumber,i.lens,this.glassWettingOf(i).stateAt(t/1e3))),this.sceneRenderer.setPerception(vh.perceptionOf(i.account?.observerPerception)),this.sceneRenderer.setGait(Xe.bodyAt(i,t,this.ufoElement.steadyBody)),this.sceneRenderer.updateDecorAnchoring(ze(i,0),n,t),this.placeBodiesAt(t,e===void 0),this.sceneRenderer.updateDecorLitState(t,e?.stepMs??0),this.applyFrozen(i.frozen),this.sceneRenderer.setObserverRoute(this.routeOf(i.observerTrack)),this.sceneRenderer.setObserverHeadlights(this.observerHeadlightsAt(i,t)),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng,()=>{this.placeBodiesAt(this.lastTimeMs,!0),this.sceneRenderer.render()}),this.sceneRenderer.setStatedRoads(i.roads),this.sceneRenderer.setTraces(i.traces,this.traceLabels(i.traces)),this.pushPhenomenaAt(t);const h=n?.lat??Qu.lat,u=n?.lng??Qu.lng,d=ja(i.event.time??{},u,i.event.utcOffsetHours),f={lat:h,lng:u,elevationM:n?.elevationM??0};this.pushSatellitesAt(d,t,f),this.ensureFireballs(d);const p=i.skyEvents,g=[...p?.reentries??[],...this.fireballs?.reentries??[]];this.sceneRenderer.setReentries(g.length===0?[]:Ae.viewsAt(g,t,{lat:h,lng:u,heightM:f.elevationM})),this.sceneRenderer.setBeams(p?.beams??be.NO_BEAMS);const m=p?.launches??[];if(this.sceneRenderer.setLaunchPlumes(m.length===0||!d?[]:It.viewsAt(m,t,{lat:h,lng:u,heightM:f.elevationM},It.sunDirectionAt(new Date(d.getTime()+t)))),e&&!e.sky)return;if(this.sceneRenderer.setSkyUnknown(!d),!d){this.sceneRenderer.setAstronomy(LO);return}const v=new Date(d.getTime()+t),y=Math.max(1,Math.round(.25*this.degreesPerPixelAt(t)/No.DEG_PER_SECOND*1e3)),x=Math.max(1e-8,this.degreesPerPixelAt(t)*.1),M=`${Math.floor(v.getTime()/y)}|${Math.round(h/x)}|${Math.round(u/x)}|${Math.round(f.elevationM)}|${this.starCatalog?this.starCatalogDepth:0}`;if(M===this.lastSkyKey){this.sceneRenderer.render();return}this.lastSkyKey=M;const b=Fu("Sun",v,f),S=Fu("Moon",v,f);let E=Ui.separationOf(b,S)<1?Ui.viewAt(v,f):void 0;if(E){const I=Ui.offsetOf(b,S,E.separationDeg);if(E.obscuration>be.LIMB_FROM_OBSCURATION){const O=this.limbFor(v,f);O&&(E={...E,obscuration:1-ws.uncoveredFraction(O,E.sunRadiusDeg,I),limb:O})}E={...E,horizonShare:Ui.horizonShare(E,I,b.altitudeDeg,b.azimuthDeg,mr.distanceKm(v,f))}}const w={...b,magnitude:Y0("Sun",v)-2.5*Math.log10(Ui.beamFraction(E))};this.lastSun={altitudeDeg:w.altitudeDeg,azimuthDeg:w.azimuthDeg};const _={...S,phase:WD(v),magnitude:Y0("Moon",v),radiusDeg:mr.apparentRadiusDeg(v,f)},D=VD.map(I=>({body:I,position:Fu(I,v,f),magnitude:Y0(I,v)}));this.sceneRenderer.setAstronomy({sun:w,moon:_,planets:D,comet:this.cometAt(v,f),novae:ty.appearancesAt(v,f).map(({outburst:I,position:O,magnitude:L})=>({id:I.id,position:O,magnitude:L})),stars:this.starCatalog?{catalog:this.starCatalog,date:v,observer:f}:void 0,frame:{date:v,observer:f},localHour:((v.getUTCHours()+v.getUTCMinutes()/60+(i.event.utcOffsetHours??Math.round(u/15)))%24+24)%24,eclipse:E}),this.ufoElement.setSunAltitude(w.altitudeDeg)}static LIMB_FROM_OBSCURATION=.98;limbRelief;limbRequested=!1;limbCache;limbFor(t,e){if(!this.limbRelief){this.limbRequested||(this.limbRequested=!0,gh.load(DO).then(s=>{this.limbRelief=s,this.lastSkyKey="",s&&this.isConnected&&this.updateAstronomy(this.lastTimeMs)}));return}const i=this.limbCache;if(i&&Math.abs(t.getTime()-i.atMs)<5e3&&i.lat===e.lat&&i.lng===e.lng&&i.elevationM===e.elevationM)return i.profile;const n=ws.profile(t,e,this.limbRelief);return this.limbCache={profile:n,atMs:t.getTime(),lat:e.lat,lng:e.lng,elevationM:e.elevationM},n}pushSatellitesAt(t,e,i){if(this.ensureSatellites(t),!t||!this.satellites){this.sceneRenderer.setSatellites([]);return}const n=new Date(t.getTime()+e),s=[];for(const r of this.satellites.passes.positionsAt(n,i,-1))r.magnitude!==void 0&&s.push({norad:r.object.norad,name:r.object.name,position:{altitudeDeg:r.altitudeDeg,azimuthDeg:r.azimuthDeg},magnitude:r.magnitude,heightKm:r.heightKm});this.sceneRenderer.setSatellites(s)}ensureFireballs(t){const e=this.ufoElement.sighting,i=Math.max((e.event.durationSeconds??0)*1e3,this.ufoElement.seekableDuration),n=t?.getTime(),s=n===void 0?"":`${n}+${i}`;if(this.fireballs?.key===s)return;if(n===void 0||!gr.mayCover(n+i)){this.fireballs={key:s,status:"outside",reentries:[]};return}const r={key:s,status:"loading",reentries:[]};this.fireballs=r,be.fireballArchive.between(n,n+i).then(a=>{r.status=a?"ready":"unavailable",r.records=a??[],r.reentries=r.records.map(c=>gr.asReentry(c,n)),!(this.fireballs!==r||!this.isConnected)&&(this.dispatchEvent(new CustomEvent(_O)),r.reentries.length>0&&this.updateAstronomy(this.lastTimeMs))})}decorWithTraffic(t){const e=this.ensureTraffic(t);if(!e||e.objects.length===0)return t.decor;const i=this.decorMemo;if(i&&i.base===t.decor&&i.traffic===e.objects)return i.merged;const n=[...t.decor,...e.objects];return this.decorMemo={base:t.decor,traffic:e.objects,merged:n},n}seatedDecor(t,e){if(!t.some(r=>r.observerKeyframes?.length))return t;const i=t.map(r=>{if(!r.observerKeyframes?.length)return"";const a=F1(r,e);return`${a.side??"-"}/${a.facing??"-"}`}).join("|"),n=this.seatedMemo;if(n&&n.base===t&&n.seats===i)return n.seated;const s=t.map(r=>{if(!r.observerKeyframes?.length)return r;const a=F1(r,e);return{...r,observerSide:a.side,observerFacing:a.facing}});return this.seatedMemo={base:t,seats:i,seated:s},s}ensureTraffic(t){const e=ze(t,0),i=e?.lng===void 0?void 0:ja(t.event.time??{},e.lng,t.event.utcOffsetHours),n=Math.max((t.event.durationSeconds??0)*1e3,this.ufoElement.seekableDuration),s=i?.getTime(),r=s===void 0||e?.lat===void 0||e.lng===void 0?"":`${this.aircraftSource.id}|${s}+${n}|${e.lat.toFixed(3)},${e.lng.toFixed(3)}|${Math.round(e.elevationM??0)}`;if(this.traffic?.key===r)return this.traffic.set;if(this.upperAirHeardLive=void 0,r===""||s===void 0||e?.lat===void 0||e.lng===void 0){this.traffic={key:r,status:"outside"};return}let a=be.aircraftProviders.get(this.aircraftSource.id);if(a||be.aircraftProviders.set(this.aircraftSource.id,a=this.aircraftSource.create()),a.mayCover&&!a.mayCover(s+n)){this.traffic={key:r,status:"outside"};return}const c={key:r,status:"loading",startMs:s,observer:{lat:e.lat,lng:e.lng}};this.traffic=c;const l={lat:e.lat,lng:e.lng,heightM:e.elevationM??0},h=kn.MAX_GAP_S*1e3,u=be.SOUND_LOOKBACK_MS,d={lat:e.lat,lng:e.lng,elevationM:e.elevationM??0},f=(p,g)=>p.TrafficDecor.from(c.tracks??[],l,s,p.TrafficDecor.MAX_OBJECTS,{models:g,sunElevationAt:m=>this.sunElevationAt(m,d)});a.between(l,s-u,s+n+h).then(async p=>{if(this.traffic!==c)return;if(p.status!=="found"){c.status=p.status==="outside"?"outside":"unavailable",this.announceTraffic();return}let g;try{g=await be.loadTrafficRuntime()}catch{this.traffic===c&&(c.status="unavailable",this.announceTraffic());return}this.traffic===c&&(c.status="ready",c.tracks=p.tracks,c.set=f(g),this.startAircraftSound(c,g),this.announceTraffic(),this.describeTraffic(a,c,g,f),c.set.shown>0&&(this.readUpperAir(c,g,s-u,s+n+h),this.readTrailTraffic(a,c,g,l,s-be.TRAIL_LOOKBACK_MS,s+n+h)))})}trafficSunlight(t){const e=new Map,i=this.traffic,n=i?.set,s=this.lastSun;if(!n||!s||i.startMs===void 0||!i.observer)return e;for(const[r,a]of n.presence){if(t<a.fromMs||t>a.untilMs)continue;const c=n.flights.get(r),l=c?kn.positionAt(c,i.startMs+t):void 0;l&&e.set(r,{heightM:l.geo.heightM,sunElevationDeg:zn.sunElevationDeg(s,i.observer,l.geo)})}return e}trafficTooltipAt(t,e){const i=this.sceneRenderer.pickTrafficAt(t,e),n=i?this.trafficInfoAt(i):void 0;if(!n)return;const s=this.naming,r=be.trafficRuntime;return r?.TrafficTooltip.text(n,s.names?.trafficTooltip??r.TrafficTooltip.ENGLISH,a=>s.towards(a))}trafficInfoAt(t){const e=this.traffic,i=e?.set?.flights.get(t);if(!e||!i||e.startMs===void 0||!e.observer)return;const n=be.trafficRuntime;if(!n)return;const s=e.descriptions?.get(gn.keyOf(i)),r=ze(this.ufoElement.sighting,this.lastTimeMs),a={lat:e.observer.lat,lng:e.observer.lng,heightM:r?.elevationM??0},c=n.AmbientNoise.dbA(wl(this.ufoElement.sighting,this.lastTimeMs)),l=n.TrafficInfos.at(i,s,a,e.startMs+this.lastTimeMs,{ambientDbA:c}),h=l&&this.contrailAt(t,this.lastTimeMs);return l&&h?{...l,contrail:h}:l}contrailAt(t,e){const i=this.traffic?.contrails?.find(s=>s.id===t);if(!i)return;let n;for(const s of i.points){if(s.tMs>e)break;n=s}return n?.forms?{persistent:n.persistent,iceRelativeHumidity:n.iceRelativeHumidity}:void 0}startAircraftSound(t,e){this.aircraftAudio??=this.newAircraftAudio(e),this.sortOutAudible(t,e)}sortOutAudible(t,e){!t.set||!t.observer||(t.audible=e.TrafficSound.candidates(t.set.flights,t.descriptions??new Map,gn.keyOf,{...t.observer,heightM:0},{ambientDbA:e.AmbientNoise.BASE_DB_A}))}pushAircraftSound(t,e){this.startDecorAircraftSound(t),this.startBodySound();const i=this.aircraftAudio;if(!i)return;const n=be.trafficRuntime;if(!n){i.setVoices([]);return}const s=ze(t,e),r=wl(t,e),a={ambientDbA:n.AmbientNoise.dbA(r),referenceAmplitude:n.AmbientNoise.referenceAmplitude(r)},c=this.trafficVoices(e,s,a,n),l=t.event.place?.[0],h={lat:s?.lat??l?.lat,lng:s?.lng??l?.lng};h.lat!==void 0&&h.lng!==void 0&&(this.decorAircraftHearing??=new n.DecorAircraftHearing,c.push(...this.decorAircraftHearing.voices(t,e,{lat:h.lat,lng:h.lng,heightM:s?.elevationM??0},a,u=>this.decorModelSounds.get(u.model?.id??""))),c.push(...this.bodyVoices(t,e,a,n)),c.sort((u,d)=>d.levelDbA-u.levelDbA),c.length=Math.min(c.length,4)),i.setVoices(c,s?.headingDeg??0)}startBodySound(){this.aircraftAudio||!this.interpretationShown?.bodies.some(t=>t.sound)||(be.trafficRuntime?this.aircraftAudio=this.newAircraftAudio(be.trafficRuntime):be.loadTrafficRuntime().catch(()=>{}))}bodyVoices(t,e,i,n){const s=this.interpretationShown,r=t.event.place?.[0];if(!s||!r||!s.bodies.some(f=>f.sound))return[];const a=this.sceneRenderer.bodyGround,c=f=>Wt.eyeOf(t,f,a),l=c(e);if(!l)return[];const h=new Map,u=(f,p)=>{let g=h.get(f.id);return g||h.set(f.id,g=new Wt(f,a,c)),g.at(p)};this.bodyHearing??=new n.BodyHearing;const d=Math.max(t.observerTrack.duration,(t.event.durationSeconds??0)*1e3);return this.bodyHearing.voices(s.bodies,u,l,r,e,d,i)}trafficVoices(t,e,i,n){const s=this.traffic,r=s?.set;if(!s||!r||!s.audible||s.startMs===void 0||!s.observer)return[];const a={lat:s.observer.lat,lng:s.observer.lng,heightM:e?.elevationM??0};return n.TrafficSound.voices(s.audible,r.flights,s.descriptions??new Map,gn.keyOf,a,s.startMs+t,i)}startDecorAircraftSound(t){const e=t.decor.filter(i=>i.kind==="aircraft"&&i.track?.some(n=>(n.altitudeM??0)>0));if(e.length!==0){for(const i of e){const n=i.model?.id;!n||i.model?.url!==void 0||this.decorModelSounds.has(n)||(this.decorModelSounds.set(n,void 0),this.sceneRenderer.entryOfDecorModel(n).then(s=>{this.decorModelSounds.set(n,s?.parameters?.sound)}))}if(this.aircraftAudio||be.trafficRuntime){!this.aircraftAudio&&be.trafficRuntime&&(this.aircraftAudio=this.newAircraftAudio(be.trafficRuntime));return}be.loadTrafficRuntime().catch(()=>{})}}newAircraftAudio(t){const e=new t.AircraftAudio;return e.setLevel(this.ufoElement.level),this.interacted&&e.resume(),e.setPaused(this.ufoElement.playbackState!=="playing"),e}announceTraffic(){this.isConnected&&(this.dispatchEvent(new CustomEvent(RO)),this.updateAstronomy(this.lastTimeMs))}async describeTraffic(t,e,i,n){if(!t.describe||!e.set||!e.tracks)return;const s=new Set([...e.set.flights.values()].map(l=>gn.keyOf(l))),r=e.tracks.filter(l=>s.has(gn.keyOf(l))&&l.points.length>0),a=new Map,c=new Map;await Promise.all(r.map(async l=>{const h=new Date(l.points[0].t).toISOString().slice(0,10),u=await t.describe(l,h).catch(()=>{});u&&(c.set(gn.keyOf(l),u),a.set(gn.keyOf(l),i.AircraftModels.of(u)))})),!(this.traffic!==e||a.size===0)&&(e.descriptions=c,e.models=a,e.set=n(i,a),this.planContrails(e,i),this.sortOutAudible(e,i),this.announceTraffic())}async readTrailTraffic(t,e,i,n,s,r){if(e.startMs===void 0)return;const a=await t.between(n,s,r).catch(()=>{});if(this.traffic!==e||a?.status!=="found")return;const c=a.tracks.filter(u=>u.points.some(d=>d.altitudeFt>=i.AircraftContrails.MIN_ALTITUDE_FT)),l=new Map(e.models??[]);if(t.describe&&await Promise.all(c.filter(u=>u.points.length>0&&!l.has(gn.keyOf(u))).map(async u=>{const d=await t.describe(u,new Date(u.points[0].t).toISOString().slice(0,10)).catch(()=>{});d&&l.set(gn.keyOf(u),i.AircraftModels.of(d))})),this.traffic!==e||e.startMs===void 0)return;const h=i.TrafficDecor.from(c,n,e.startMs,be.TRAIL_MAX_AIRCRAFT,{models:l});e.trailSet=be.alignTrailIds(h,e.set),e.models=new Map([...l,...e.models??[]]),this.planContrails(e,i),this.announceTraffic()}static alignTrailIds(t,e){if(!e)return t;const i=new Map;for(const[a,c]of e.flights){const l=e.presence.get(a);if(l)for(const[h,u]of t.flights){const d=t.presence.get(h);!d||gn.keyOf(u)!==gn.keyOf(c)||d.fromMs<=l.untilMs&&l.fromMs<=d.untilMs&&i.set(h,a)}}const n=a=>i.get(a)??`${a}-trail`,s=new Set(i.values()),r=e.objects.filter(a=>!s.has(a.id));return{...t,objects:[...t.objects.map(a=>({...a,id:n(a.id)})),...r],presence:new Map([...[...t.presence].map(([a,c])=>[n(a),c]),...r.map(a=>[a.id,e.presence.get(a.id)])]),flights:new Map([...[...t.flights].map(([a,c])=>[n(a),c]),...r.map(a=>[a.id,e.flights.get(a.id)])])}}async readUpperAir(t,e,i,n){if(!t.observer)return;const s=Wc.held(this.ufoElement.sighting.frozen,"upperAir");let r;if(s){const l=ti.address(s.src,this.documentUrl);r=be.upperAirProviders.get(l),r||be.upperAirProviders.set(l,r=new Vc(ti.json(l)))}else{const l=this.upperAirSource??e.UPPER_AIR_SOURCES[0];r=be.upperAirProviders.get(l.id),r||be.upperAirProviders.set(l.id,r=l.create())}const a={lat:t.observer.lat,lng:t.observer.lng},c=await r.between(a,i,n);this.traffic!==t||c.status!=="found"||(s||(this.upperAirHeardLive={...a,startMs:i,endMs:n,answer:c}),t.air=c.samples,t.airSource=c.source,this.planContrails(t,e),this.announceTraffic())}planContrails(t,e){const i=t.trailSet??t.set;!i||!t.air||t.startMs===void 0||(t.contrails=e.AircraftContrails.plan(i,t.models,t.air,t.startMs))}contrailSunlight(t){const e=new Map,i=this.traffic,n=i?.trailSet??i?.set,s=this.lastSun;if(!i||!n||!s||!i.contrails?.length||i.startMs===void 0||!i.observer)return e;for(const r of i.contrails){const a=n.presence.get(r.id),c=n.flights.get(r.id);if(!a||!c)continue;const l=kn.positionAt(c,i.startMs+Math.min(a.untilMs,Math.max(a.fromMs,t)));l&&e.set(r.id,{heightM:l.geo.heightM,sunElevationDeg:zn.sunElevationDeg(s,i.observer,l.geo)})}return e}sunElevationAt(t,e){const i=Fu("Sun",new Date(t.t),e);return zn.sunElevationDeg(i,e,t)}upperAirSource;upperAirHeardLive;get upperAirHeard(){return this.upperAirHeardLive}setUpperAirSource(t){t.id!==this.upperAirSource?.id&&(this.upperAirSource=t,this.traffic=void 0,this.decorMemo=void 0,this.updateAstronomy(this.lastTimeMs))}setAircraftSource(t){t.id!==this.aircraftSource.id&&(this.aircraftSource=t,this.traffic=void 0,this.decorMemo=void 0,this.updateAstronomy(this.lastTimeMs))}get aircraftState(){const t=this.traffic?.contrails?.length?this.upperAirSource??be.trafficRuntime?.UPPER_AIR_SOURCES[0]:void 0;return{trailCredit:t&&{credit:t.credit,creditUrl:t.creditUrl},status:this.traffic?.status??"none",total:this.traffic?.set?.total??0,shown:this.traffic?.set?.shown??0,credit:this.aircraftSource.credit,creditUrl:this.aircraftSource.creditUrl}}get fireballState(){return{status:this.fireballs?.status??"none",records:this.fireballs?.records??[]}}ensureSatellites(t){const e=t?String(t.getTime()):"";if(e===this.satellitesFor)return;this.satellitesFor=e,this.satellites=void 0,this.satellitePassesMemo=void 0;const i=++this.satelliteRequest;if(!t){this.satelliteStatus="none";return}this.satelliteStatus="loading";const n=r=>{i===this.satelliteRequest&&(this.satelliteStatus=r,this.isConnected&&this.dispatchEvent(new CustomEvent(AO)))},s=be.tleArchive;(async()=>{if(!await s.covers(t))return n("outside");const[r,a]=await Promise.all([s.at(t),we(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(i===this.satelliteRequest){if(!r)return n("unavailable");this.satellites={snapshot:r,passes:new a.SatellitePasses(r.objects)},n("ready"),this.isConnected&&this.updateAstronomy(this.lastTimeMs)}})().catch(()=>n("unavailable"))}get satelliteState(){const t=this.satellites?.snapshot;return{status:this.satelliteStatus,coverage:t?.coverage,credit:t?.credit,creditUrl:t?.creditUrl}}burningCandidates(){return{reentries:this.ufoElement.sighting.skyEvents?.reentries??[],fireballs:this.fireballs?.reentries??[]}}trafficCandidates(){const t=this.traffic;if(!(t?.status!=="ready"||!t.tracks||t.startMs===void 0))return{tracks:t.tracks,startMs:t.startMs,describe:e=>t.descriptions?.get(gn.keyOf(e))}}satellitePositionsAt(t){const e=this.satellites,i=this.ufoElement.sighting,n=ze(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,a=n?.lng??s?.lng;if(!(!e||r===void 0||a===void 0))return e.passes.positionsAt(t,{lat:r,lng:a,elevationM:n?.elevationM??0})}satellitePassesDuring(t){const e=this.satellites,i=this.ufoElement.sighting,n=ze(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,a=n?.lng??s?.lng;if(!e||r===void 0||a===void 0)return[];const c=ja(i.event.time??{},a,i.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(t,0),4*36e5),h={lat:r,lng:a,elevationM:n?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),r,a,h.elevationM,l]);if(this.satellitePassesMemo?.key===u)return this.satellitePassesMemo.passes;const d=Math.max(10,Math.ceil(l/1e3/600)),f=e.passes.passesDuring(c,new Date(c.getTime()+l),h,d);return this.satellitePassesMemo={key:u,passes:f},f}cometAt(t,e){const i=dO.brightestAt(t,e);if(i)return{id:i.apparition.id,position:i.position,tailEnd:i.tailEnd,magnitude:i.magnitude}}pushPhenomenaAt(t){const e=this.ufoElement.sighting;e!==this.sizeEstimatesFor&&(this.sizeEstimates.clear(),this.distanceHypotheses.clear(),this.sizeEstimatesFor=e);const i=e.timeline,n=this.ufoElement.canvasElement,s=this.ufoElement.frameShiftPx,r=this.projectionAt(t),a=new Map,c=new Map,l=new Set;for(const p of i.sourceIds){const g=i.getInterpolatedShapeAt(t,p);if(!g)continue;const m={...g,bounds:{...g.bounds,x:g.bounds.x+s.x,y:g.bounds.y+s.y}};a.set(p,m);const v=g.aim?this.sceneRenderer.screenPointOf(ks.directionOf(g.aim,this.directionScratch)):{ndcX:(m.bounds.x+m.bounds.width/2)/n.width*2-1,ndcY:-((m.bounds.y+m.bounds.height/2)/n.height*2-1)},y=v!==void 0&&Math.abs(v.ndcX)<=1&&Math.abs(v.ndcY)<=1,x=y?this.sceneRenderer.decorDistancesAt(v.ndcX,v.ndcY,p):{};l.add(p),(y||g.aim)&&l.delete(p);const M=g.angular?.widthDeg??r.pxToDeg(g.bounds.width),b=this.sizeEstimateOf(p);b.add(M,x);const S=Mh.of(e,p);c.set(p,Ln.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:S&&M>0?Ze.distanceMAt(S.widthM,M):void 0,range:b.distanceRangeAt(M),crossing:x}))}for(const[p,g]of a)for(const[m,v]of a){if(m===p||v.transparency>=1||v.bounds.width*v.bounds.height<=g.bounds.width*g.bounds.height||!(g.bounds.x>=v.bounds.x&&g.bounds.y>=v.bounds.y&&g.bounds.x+g.bounds.width<=v.bounds.x+v.bounds.width&&g.bounds.y+g.bounds.height<=v.bounds.y+v.bounds.height))continue;const x=c.get(m);x&&c.set(p,{distanceM:x.distanceM*.999,basis:x.basis});break}this.depths=c;const h=i.sourceIds,u=[];for(const[p,g]of a)u.push({sourceId:p,shape:g,distanceM:c.get(p).distanceM,renderOrder:h.indexOf(p),aim:g.aim,hidden:l.has(p)||this.interpretationShown!==void 0&&(!this.comparing||g.transparency>=1),ghost:this.interpretationShown!==void 0&&this.comparing});const f=(ze(e,t)?.rollDeg??0)+Xe.bodyAt(e,t,this.ufoElement.steadyBody).rollDeg;this.sceneRenderer.setPhenomena(u,{projection:r,canvasWidthPx:n.width,canvasHeightPx:n.height,scale:Math.max(1,this.sceneCanvas.height/Math.max(1,n.height)),starPoints:Bi.starPointsOf(e.instrument),rollRad:f*Math.PI/180})}get interpretation(){return this.interpretationShown}set interpretation(t){this.interpretationShown=mi.expand(Nn.expand(t)),this.ufoElement.playerTitle=t?.title,this.syncAccountHidden(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.repaintChrome()}redrawSky(){this.updateAstronomy(this.lastTimeMs)}syncAccountHidden(){this.ufoElement.accountHidden=this.interpretationShown!==void 0&&!this.comparing}get accountInTheRound(){return this.inTheRound}set accountInTheRound(t){this.inTheRound=t}get compareAccount(){return this.comparing}set compareAccount(t){t!==this.comparing&&(this.comparing=t,this.syncAccountHidden(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.repaintChrome())}get confrontation(){return this.confrontationReadings}groundAlong(t,e,i){const n=this.sceneRenderer.bodyGround,s=Wt.eyeOf(this.ufoElement.sighting,i,n);return s?Wt.lineOfSightMeetsGround(s,t,e,n):void 0}bodyMaskedBy(t,e){return this.sceneRenderer.bodyMaskedByDecor(t,e)}bodyReading(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=d=>Wt.eyeOf(n,d,i),r=new Wt(t,i,s).at(e),a=s(e);if(!r||!a)return;const c=r.eastM-a.eastM,l=r.northM-a.northM,h=r.upM-a.upM,u=Math.hypot(c,l);return{azimuthDeg:(Math.atan2(c,l)*180/Math.PI+360)%360,altitudeDeg:Math.atan2(h,u)*180/Math.PI,distanceM:Math.hypot(u,h),eastM:r.eastM,northM:r.northM,aboveGroundM:r.upM-r.sizeM.heightM/2-i.heightAt(r.eastM,r.northM),sizeM:r.sizeM,attitude:r.attitude,appearance:r.appearance}}bodyProjectionAt(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=c=>Wt.eyeOf(n,c,i),r=new Wt(t,i,s).at(e),a=s(e);return r&&a?gi.projectionOf(r,a):void 0}directionToBody(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=p=>Wt.eyeOf(n,p,i),r=new Wt(t,i,s),a=r.at(e)?e:t.track[0]?.t,c=a===void 0?void 0:r.at(a),l=a===void 0?void 0:s(a);if(!c||!l)return;const h=c.eastM-l.eastM,u=c.northM-l.northM,d=c.upM-l.upM,f=Math.hypot(h,u);if(!(f===0&&d===0))return{azimuthDeg:(Math.atan2(h,u)*180/Math.PI+360)%360,altitudeDeg:Math.atan2(d,f)*180/Math.PI}}placeBodiesAt(t,e){const i=this.interpretationShown,n=this.ufoElement.sighting;let s=[],r=[];const a=this.sceneRenderer.bodyGround,c=p=>Wt.eyeOf(n,p,a);i&&(s=i.bodies.map(p=>new Wt(p,a,c).at(t)).filter(p=>p!==void 0));const l=_c(n,t),h=l.windDirectionDeg*Math.PI/180,u={x:l.windSpeed*Math.sin(h),z:-l.windSpeed*Math.cos(h)};this.sceneRenderer.setBodies(s,t/1e3,i?.bodies.map(p=>p.id)??[],i?.smoke??[],u);const d=i&&this.comparing?c(t):void 0;if(d&&(r=new gi(n.timeline,this.confrontationTolerance).at(t,s,d,p=>p.outlineNode?this.sceneRenderer.bodyOutline?.(p.id,p.outlineNode):void 0)),this.confrontationReadings=r,!e)return;const f=JSON.stringify(r);f!==this.confrontationSignature&&(this.confrontationSignature=f,this.dispatchEvent(new CustomEvent(Cb,{detail:r})))}setDistanceHypothesis(t,e){e===void 0||!(e>0)?this.distanceHypotheses.delete(t):this.distanceHypotheses.set(t,e),this.updateAstronomy(this.lastTimeMs)}depthOf(t){return this.depths.get(t)}sizeRangeOf(t){return this.sizeEstimateOf(t).sizeRange}distanceRangeAt(t,e){const i=this.ufoElement.sighting.timeline.getInterpolatedShapeAt(e,t);if(!i)return{};const n=i.angular?.widthDeg??this.projectionAt(e).pxToDeg(i.bounds.width);return this.sizeEstimateOf(t).distanceRangeAt(n)}sizeContradictory(t){return this.sizeEstimateOf(t).contradictory}updateMeteorShower(t,e){this.ensureMeteorSchedule(t),this.sceneRenderer.updateMeteors(e)}updateLightning(t,e,i){if(this.ensureLightningSchedule(t),this.sceneRenderer.updateLightning(e),i)return;const n=this.lastLightningT;if(this.lastLightningT=e,n===void 0||e<n||this.ufoElement.playbackState!=="playing")return;const s=this.lightningFlashes.filter(r=>r.t>n&&r.t<=e).pop();s&&_c(t,s.t).storm&&this.handleLightningFlash(s)}ensureLightningSchedule(t){const e=_c(t,0).precipitationIntensity,i=`${this.meteorInputsOf(t)}|${e}`;if(i===this.lightningScheduleFor)return;this.lightningScheduleFor=i;const n=t.event.time,s=t.event.place?.[0],r=n?.year!==void 0?ja(n,s?.lng??0,t.event.utcOffsetHours):void 0,a=(t.event.durationSeconds??0)*1e3||t.timeline.duration||2e4,c=Math.round((r?.getTime()??0)/1e3)+Math.round((s?.lat??0)*1e3)+7;this.lightningFlashes=Qi.schedule({durationMs:a,seed:c,intensity:e}),this.sceneRenderer.setLightning(this.lightningFlashes)}ensureMeteorSchedule(t){const e=this.meteorInputsOf(t);e!==this.meteorScheduleFor&&(this.meteorScheduleFor=e,this.scheduleMeteors(t))}meteorInputsOf(t){const e=t.event.place?.[0],i=t.event.time;return JSON.stringify([e?.lat,e?.lng,i?.year,i?.month,i?.day,i?.hour,i?.minute,i?.second,t.event.utcOffsetHours,t.event.durationSeconds,t.timeline.duration])}scheduleMeteors(t){const e=t.event.place?.[0],i=t.event.time,n=e?.lat!==void 0&&e.lng!==void 0&&i?.year!==void 0?ja(i,e.lng,t.event.utcOffsetHours):void 0;if(!n||e?.lat===void 0||e.lng===void 0){this.sceneRenderer.setMeteorShower([],0,0);return}const s={lat:e.lat,lng:e.lng,elevationM:0},r=(t.event.durationSeconds??0)*1e3||t.timeline.duration||2e4,a=Math.round(n.getTime()/1e3)+Math.round(e.lat*1e3),c=Ci.schedule({ratePerHour:Ci.observedRatePerHour(Ci.apexPosition(n,s).altitudeDeg),durationMs:r,velocityKmS:Ci.TYPICAL_VELOCITY_KM_S,seed:a}),l=bp.activeAt(n).map(u=>{const d=bp.radiantPosition(u.shower,n,s);return{entry:u,position:d,rate:bp.observedRatePerHour(u.zhr,d.altitudeDeg,u.shower.populationIndex)}}).sort((u,d)=>d.rate-u.rate)[0];if(!l||l.rate<=0){this.sceneRenderer.setMeteorShower(c,0,0);return}const h=Hs.schedule({ratePerHour:l.rate,durationMs:r,velocityKmS:l.entry.shower.velocityKmS,seed:a+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}groundHides(t,e){return this.sceneRenderer.groundHidesDirection(t,e)}get groundKey(){return this.sceneRenderer.groundKey}meteorByRank(t,e=Number.POSITIVE_INFINITY){this.ensureMeteorSchedule(this.ufoElement.sighting);const i=[...this.sceneRenderer.meteorSchedule].filter(r=>r.t+r.durationMs<=this.ufoElement.seekableDuration).filter(r=>Hs.magnitudeOf(r)<=e).filter(r=>{const a=this.sceneRenderer.meteorMidpoint(r);return a!==void 0&&!this.sceneRenderer.groundHidesDirection(a.altitudeDeg,a.azimuthDeg)}).sort((r,a)=>a.brightness-r.brightness);if(i.length===0)return;const n=i[t%i.length],s=this.sceneRenderer.meteorMidpoint(n);if(s)return{t:Math.round(n.t+n.durationMs*.45),...s}}lensOpticsAt(t){const e=this.ufoElement.sighting,i=e.instrument,n=i.frame,s=ze(e,t),r=s?.fNumber??i.fNumber;if(!n||r===void 0)return;const a=Bi.focalLengthMmFor(i,In.fovOf(e,t));if(a!==void 0)return{focalLengthMm:a,fNumber:r,focusDistance:s?.focusDistanceM??0,frameHeightMm:n.heightMm}}projectionAt(t){const e=this.ufoElement.sighting;return yr.of(e.instrument,Ze.CANVAS_HEIGHT_PX,In.fovOf(e,t))}sizeEstimateOf(t){let e=this.sizeEstimates.get(t);return e||(e=new pO,this.sizeEstimates.set(t,e)),e}}const wf="rr0-scene";function Ob(){Vy(),customElements.get(wf)||customElements.define(wf,be)}const NO={color:"Color",transparency:"Transparency",halo:"Halo",blur:"Blur",brightness:"Brilliance",shapeTitle:"Name",utcOffset:"Time zone",cloudBase:"Cloud base",elevation:"Altitude",heightAboveGround:"Height above ground",duration:"Duration",placeName:"Place",latitude:"Latitude",longitude:"Longitude",heading:"Heading",pitch:"Tilt",roll:"Roll",sway:"Sway at rest",swayTitle:"How much the body holding the instrument moves the view when not walking: 1 for a person standing, 0 for a tripod. Blank: 1 (0 if the account says the observer was paralysed)",referenceGhosts:"Ghosts in the picture",referenceFindGhosts:"Look for ghosts",referenceGhostsSearching:"Looking…",referenceGhostsFound:"{count} ghosts found, each across the lens's axis from its light.",referenceGhostsFoundScaled:"{count} ghosts found, each at {scale} times its light's offset from the lens's axis.",referenceGhostsLow:"Perhaps {count} ghost(s): too few to be sure.",referenceGhostsNone:"No ghost found: no faint spot lies across one point from a light.",referenceGhostsCropped:"The lens's axis is off the picture's centre: the picture was cropped.",lensGlass:"Taken through",lensGlassNone:"the lens alone",lensGlassFilter:"a filter on the lens",lensGlassWindow:"a window",lensGlassWindscreen:"a windscreen",lensDrops:"Drops on the glass",lensDropsTitle:"0 to 1: how much of the outermost glass drops of water cover. Blank: from the rain or snow falling, unless the glass is sheltered",lensCondensation:"Condensation",lensCondensationTitle:"0 to 1: condensation on the glass, as on a lens taken from the warm into the cold. Blank: none",lensDirt:"Dirt",lensDirtTitle:"0 to 1: dirt, grease or fingerprints on the glass. Blank: none",lensSheltered:"Sheltered from the rain",lensShelteredTitle:"The outermost glass was out of the rain or snow: under a roof, or behind a windscreen whose wipers run",lightPollution:"Night sky",lightPollutionTitle:'The zenith of a moonless night at this place, in magnitudes per square arcsecond, as a Sky Quality Meter reads it or as the World Atlas of artificial sky brightness (Falchi et al. 2016, lightpollutionmap.info, "SQM") gives it. 22 is a natural sky; a suburb is about 19, a city centre 17. Blank: a natural sky',observationTime:"Observation start",observationEndTime:"Observation end",assessmentGroup:"Assessment",assessmentNames:{coverage:"Observer info"},assessmentVerdicts:{"hynek.nl":"NL — nocturnal light","hynek.dd":"DD — daylight disc","hynek.rv":"RV — radar-visual","hynek.ce1":"CE1 — close encounter","hynek.ce2":"CE2 — with a physical trace","hynek.ce3":"CE3 — with entities"},timeQualifierApproximate:"Approximate",timeQualifierUncertain:"Uncertain",timeQualifierBoth:"Uncertain and approximate",timeSeasonSpring:"Spring",timeSeasonSummer:"Summer",timeSeasonAutumn:"Autumn",timeSeasonWinter:"Winter",summaryGroups:{observation:"Observation",location:"Position",temporal:"Time",weather:"Weather",sound:"Sound"},summaryGroup:"Summary",summaryDescription:"Description",closeDescription:"Close the description",observerGroup:"Observer",observerId:"ID",observerTitle:"Title",observerLastName:"Last name",observerFirstNames:"First names",sightingId:"ID",tags:"Tags",cloudCover:"Cloud cover",highCloudCover:"Ice cloud (cirrus)",focalLength:"Focal length",fieldOfView:"Field of view",aperture:"Aperture",exposure:"Exposure",focusDistance:"Focused at",iceCrystalAlignment:"Crystal alignment",rareIceCrystals:"Rare crystals",cloudDarkness:"Cloud darkness",precipitationType:"Precipitation",precipitationNone:"None",precipitationRain:"Rain",precipitationSnow:"Snow",precipitationHail:"Hail",precipitationIntensity:"Intensity",windDirection:"Wind direction",windSpeed:"Wind speed",storm:"Storm",cloudsGroup:"Clouds",precipitationGroup:"Precipitation",windGroup:"Wind",soundKind:"Sound",soundNone:"None (silent)",soundHum:"Hum",soundWhistle:"Whistle",soundRumble:"Rumble",soundCrackle:"Crackle",soundVolume:"Loudness",soundPitch:"Pitch",soundSrc:"Recording",instrument:"Observed through",filter:"In front of it",filterNone:"nothing",filterSolarVisual:"a solar filter for the eye (eclipse glasses, density 5)",filterSolarPhoto:"a solar film for a camera (density 3.8)",decorAircraft:"Aircraft",decorEntity:"Being",decorAltitude:"Altitude",decorLights:"Lights",decorLightsNone:"none",decor:"Environment",decorBuilding:"Building",decorTree:"Tree",decorShrub:"Shrub",decorBridge:"Bridge",decorWire:"Overhead line",decorCrop:"Crop row",decorTerrace:"Terrace (restanque)",decorMound:"Stone heap",decorWall:"Dry-stone wall",decorStreetlight:"Streetlight",decorTrafficLight:"Traffic light",decorCrossing:"Pedestrian crossing",decorRoadSign:"Road sign",decorVehicle:"Vehicle",decorObserver:"Other observer",decorEast:"Distance east",decorNorth:"Distance north",decorHeading:"Heading",decorColor:"Colour",decorLit:"Lit",decorTitle:"Name",milestones:"Moments",milestoneLabel:"Label",milestoneNote:"What happens",addMilestone:"Name this moment",deleteMilestone:"Delete moment",goToMilestone:"Go to this moment",decorWidth:"Width",decorLength:"Length",decorHeight:"Height",decorModel:"3D model",decorModelAdvanced:"Model from an address",decorModelUrl:"glTF/GLB address",decorModelTitle:"Model name",decorModelAuthor:"Author",decorModelLicense:"Licence",decorModelSource:"Where it came from",decorObserverSide:"Observer location",decorObserverSideNone:"Not present",decorSideFront:"Front",decorSideBehind:"Behind",decorSideLeft:"Left",decorSideRight:"Right",decorSideFrontLeft:"Front-left",decorSideFrontRight:"Front-right",decorSideBehindLeft:"Behind-left",decorSideBehindRight:"Behind-right"},th={...NO,accountBy:"Account by",unnamedObserver:"Observer {n}",about:"About",close:"Close",observation:"Observation",date:"Date",location:"Location",case:"Case",description:"Description",source:"Source",basis:{measured:"measured",stated:"stated",derived:"derived",assumed:"assumed"},credits:"Credits",editThisObservation:"Edit this observation",share:"Share",embedObservation:"Embed the observation",back:"Back",shareScope:"Share",shareScopeCase:"Whole case",shareOpensOn:"Opens on",shareStartAt:"Start at",shareOptionLabels:"Show summary chips",shareOptionMap:"Open map",shareOptionMilestones:"Show moments",shareOptionCompare:"Compare account",showLabels:"Show what it states",interpretation:"Interpretation",account:"Account",interpretationBy:"{title}, by {by}",confrontation:"Against the account",confrontationDirection:"{deg}° off",confrontationWidth:"width ×{ratio}",confrontationHeight:"height ×{ratio}",showComparison:"Compare with the account",hideComparison:"Stop comparing with the account",hideLabels:"Hide what it states",variant:"Variant: {name}",verdicts:{consolidated:"compatible with consolidated biases",contested:"only by invoking contested biases",incompatible:"incompatible even at the bounds"},variantFields:{time:"Time",heading:"Heading",elevation:"Elevation",size:"Size",duration:"Duration",sweep:"Sweep across the sky"},variantReadings:{grouped:"lights read as one body","still-seen-moving":"a still light seen moving","moving-seen-still":"a moving light seen hovering","brightening-as-approach":"growing brighter read as coming nearer"}},kO=Object.freeze(Object.defineProperty({__proto__:null,sightingMessages_en:th},Symbol.toStringTag,{value:"Module"}));class vr{static PACKAGE="@rr0/ufoathome";static CDN="https://cdn.jsdelivr.net/npm";static DIRECTORIES={"rr0-sighting":"dist-embed-sighting","rr0-sighting-editor":"dist-embed-sighting-editor"};static current(t,e,i){const n=new URL(`${t}.mjs`,e);return n.href.startsWith(`${vr.CDN}/`)?`${i}/lib/${t}.mjs`:(n.pathname=n.pathname.replace(/\/lib\/\d+\.\d+\.\d+[^/]*\//,"/lib/"),n.href)}static VERSION_PARAMETER="v";static freezable(t){return t in vr.DIRECTORIES}static frozenLink(t,e){const i=new URL(t);return i.searchParams.set(vr.VERSION_PARAMETER,e),i.href}static frozen(t,e){return`${vr.CDN}/${vr.PACKAGE}@${e}/${vr.DIRECTORIES[t]}/${t}.mjs`}}class Uh{static PRODUCTION="https://ufoathome.org";static home(){try{const t=new URL(import.meta.url),e=new URL(location.href);return(e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname==="[::1]"||e.hostname.endsWith(".localhost"))&&t.origin===e.origin?e.origin:Uh.PRODUCTION}catch{return Uh.PRODUCTION}}}const sg={share:"Share",close:"Close",link:"Link",embed:"Embed",copy:"Copy",copied:"Copied",freeze:"Freeze version {version}",freezeHint:"The embed keeps the rendering of this version of UFO@home, loaded from jsDelivr, and gets none of the later fixes. Unticked, it follows each release.",unsaved:"The link opens the file at its address: your unsaved changes are not in it. Save the file there first.",unavailable:"Only a file loaded from an address can be shared: put it online, then open it from its address."},UO=Object.freeze(Object.defineProperty({__proto__:null,shareMessages_en:sg},Symbol.toStringTag,{value:"Module"})),FO=`
9335
+ ${ti.generation}`;return this.frozenMap?.key!==i&&(this.frozenMap={key:i,imagery:Mf.map(e,this.documentUrl)}),this.frozenMap.imagery}frozenMap;setDecorModelProvider(t){this.sceneRenderer.setDecorModelProvider(t)}get decorModelCredits(){return[...new Map(this.sceneRenderer.currentDecorModelCredits.map(e=>[`${e.title}|${e.author??""}|${e.license}|${e.sourceUrl??""}`,e])).values()]}applyFrameFormat(){const t=this.ufoElement.sighting.instrument,e=Ze.CANVAS_HEIGHT_PX,i=Bi.frameWidthPx(t,e);this.frameElement.style.setProperty("--frame-aspect",`${i} / ${e}`)}resizeToStage(){const t=this.frameElement.getBoundingClientRect(),e=Math.max(1,Math.round(t.width)),i=Math.max(1,Math.round(t.height));this.sceneCanvas.width=e,this.sceneCanvas.height=i,this.sceneRenderer.resize(e,i)}async loadStars(){const t=[{magnitudeLimit:Mp,url:this.getAttribute("star-catalog-src")??CO},{magnitudeLimit:yp,url:this.getAttribute("deep-star-catalog-src")??OO}],e=this.instrumentReach(),i=++this.starCatalogRequest;this.starCatalogDepth=e>Mp?yp:Mp;const n=await ar.upTo(t,e);i===this.starCatalogRequest&&(this.starCatalog=n,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=yp||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const t=this.ufoElement.sighting,e=fn.gainFor(t.instrument,{fNumber:ze(t,0)?.fNumber,fieldOfViewDeg:In.fovOf(t,0),exposureSeconds:t.exposure});return md(PO,e)}updateAstronomy(t){this.ensureStarsDeepEnough(),this.applySceneAt(t);const e=Fs.windowEndingAt(t,this.exposureSeconds()),i=e.seconds,n=this.degreesPerPixelAt(t),s=No.instants(i,n),r=Math.max(s,this.ufoElement.exposureTimes(t).length,Fs.instants(this.decorWithTraffic(this.ufoElement.sighting),ze(this.ufoElement.sighting,t)?.elevationM??0,e.fromMs,i,n));if(r<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(r,a=>this.applySceneAt(e.fromMs+e.ms*a/(r-1),{sky:Math.floor(a*s/r)!==Math.floor((a-1)*s/r),stepMs:e.ms/r}))}exposureSeconds(){return this.ufoElement.sighting.exposure??0}degreesPerPixelAt(t){const e=this.sceneCanvas.height;return e<=0?0:In.fovOf(this.ufoElement.sighting,t)/e}roadGradeAt(t,e){return t.observerTrack.allKeyframes.length<2?0:Dc.at(t,e,this.sceneRenderer.bodyGround)}get roadGradeDeg(){return this.roadGradeAt(this.ufoElement.sighting,this.ufoElement.currentTime)}applySceneAt(t,e){const i=this.ufoElement.sighting;this.setWeather(wl(i,t)),this.sceneRenderer.setInstrument(i.instrument),this.sceneRenderer.setLightPollution(i.lightPollution),e||this.vehicleAudio.setVoices(this.vehicleHearing.at(i,t)),e||this.pushAircraftSound(i,t),this.updateMeteorShower(i,t),this.updateLightning(i,t,e!==void 0),this.sceneRenderer.setDecor(this.seatedDecor(this.decorWithTraffic(i),t)),this.sceneRenderer.setDecorPresence(this.traffic?.set?.presence??be.NO_PRESENCE),this.sceneRenderer.setDecorSunlight(this.trafficSunlight(t)),this.sceneRenderer.setContrails(this.traffic?.contrails??be.NO_CONTRAILS),this.sceneRenderer.setContrailSunlight(this.contrailSunlight(t));const n=ze(i,t);this.sceneRenderer.setReferences(i.references,n?.lat!==void 0&&n.lng!==void 0?{lat:n.lat,lng:n.lng}:void 0);const s=ze(i,0),r=_c(i,0),a=ja(i.event.time??{},n?.lng??Qu.lng,i.event.utcOffsetHours),c=i.weatherSource!==void 0&&a?wS(a):void 0,l=Object.fromEntries(yd(_c(i,t)).map(I=>[I.id,q1(t,i.weatherTrack,r,s,n,I.id,I.instances?.length?void 0:c)]));this.sceneRenderer.setCloudOffset(q1(t,i.weatherTrack,r,s,n,void 0,c),l),this.sceneRenderer.setObserverPose(n?{...n,pitchDeg:n.pitchDeg+this.roadGradeAt(i,t)}:Qu),this.sceneRenderer.setLensOptics(this.lensOpticsAt(t)),this.sceneRenderer.setInstrumentGain(fn.gainFor(i.instrument,{fNumber:n?.fNumber,fieldOfViewDeg:In.fovOf(i,t),exposureSeconds:i.exposure}),i.instrument.detailUm!==void 0,Gs.byId(n?.filter).opticalDensity),this.sceneRenderer.setMedium(i.instrument.medium,i.exposure,n?.fNumber??i.instrument.fNumber,i.iso),this.sceneRenderer.setLensGhosts(di.optics(i.instrument,n?.fNumber??i.instrument.fNumber,i.lens,this.glassWettingOf(i).stateAt(t/1e3))),this.sceneRenderer.setPerception(vh.perceptionOf(i.account?.observerPerception)),this.sceneRenderer.setGait(Xe.bodyAt(i,t,this.ufoElement.steadyBody)),this.sceneRenderer.updateDecorAnchoring(ze(i,0),n,t),this.placeBodiesAt(t,e===void 0),this.sceneRenderer.updateDecorLitState(t,e?.stepMs??0),this.applyFrozen(i.frozen),this.sceneRenderer.setObserverRoute(this.routeOf(i.observerTrack)),this.sceneRenderer.setObserverHeadlights(this.observerHeadlightsAt(i,t)),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng,()=>{this.placeBodiesAt(this.lastTimeMs,!0),this.sceneRenderer.render()}),this.sceneRenderer.setStatedRoads(i.roads),this.sceneRenderer.setTraces(i.traces,this.traceLabels(i.traces)),this.pushPhenomenaAt(t);const h=n?.lat??Qu.lat,u=n?.lng??Qu.lng,d=ja(i.event.time??{},u,i.event.utcOffsetHours),f={lat:h,lng:u,elevationM:n?.elevationM??0};this.pushSatellitesAt(d,t,f),this.ensureFireballs(d);const p=i.skyEvents,g=[...p?.reentries??[],...this.fireballs?.reentries??[]];this.sceneRenderer.setReentries(g.length===0?[]:Ae.viewsAt(g,t,{lat:h,lng:u,heightM:f.elevationM})),this.sceneRenderer.setBeams(p?.beams??be.NO_BEAMS);const m=p?.launches??[];if(this.sceneRenderer.setLaunchPlumes(m.length===0||!d?[]:It.viewsAt(m,t,{lat:h,lng:u,heightM:f.elevationM},It.sunDirectionAt(new Date(d.getTime()+t)))),e&&!e.sky)return;if(this.sceneRenderer.setSkyUnknown(!d),!d){this.sceneRenderer.setAstronomy(LO);return}const v=new Date(d.getTime()+t),y=Math.max(1,Math.round(.25*this.degreesPerPixelAt(t)/No.DEG_PER_SECOND*1e3)),x=Math.max(1e-8,this.degreesPerPixelAt(t)*.1),M=`${Math.floor(v.getTime()/y)}|${Math.round(h/x)}|${Math.round(u/x)}|${Math.round(f.elevationM)}|${this.starCatalog?this.starCatalogDepth:0}`;if(M===this.lastSkyKey){this.sceneRenderer.render();return}this.lastSkyKey=M;const b=Fu("Sun",v,f),S=Fu("Moon",v,f);let E=Ui.separationOf(b,S)<1?Ui.viewAt(v,f):void 0;if(E){const I=Ui.offsetOf(b,S,E.separationDeg);if(E.obscuration>be.LIMB_FROM_OBSCURATION){const O=this.limbFor(v,f);O&&(E={...E,obscuration:1-ws.uncoveredFraction(O,E.sunRadiusDeg,I),limb:O})}E={...E,horizonShare:Ui.horizonShare(E,I,b.altitudeDeg,b.azimuthDeg,mr.distanceKm(v,f))}}const w={...b,magnitude:Y0("Sun",v)-2.5*Math.log10(Ui.beamFraction(E))};this.lastSun={altitudeDeg:w.altitudeDeg,azimuthDeg:w.azimuthDeg};const _={...S,phase:WD(v),magnitude:Y0("Moon",v),radiusDeg:mr.apparentRadiusDeg(v,f)},D=VD.map(I=>({body:I,position:Fu(I,v,f),magnitude:Y0(I,v)}));this.sceneRenderer.setAstronomy({sun:w,moon:_,planets:D,comet:this.cometAt(v,f),novae:ty.appearancesAt(v,f).map(({outburst:I,position:O,magnitude:L})=>({id:I.id,position:O,magnitude:L})),stars:this.starCatalog?{catalog:this.starCatalog,date:v,observer:f}:void 0,frame:{date:v,observer:f},localHour:((v.getUTCHours()+v.getUTCMinutes()/60+(i.event.utcOffsetHours??Math.round(u/15)))%24+24)%24,eclipse:E}),this.ufoElement.setSunAltitude(w.altitudeDeg)}static LIMB_FROM_OBSCURATION=.98;limbRelief;limbRequested=!1;limbCache;limbFor(t,e){if(!this.limbRelief){this.limbRequested||(this.limbRequested=!0,gh.load(DO).then(s=>{this.limbRelief=s,this.lastSkyKey="",s&&this.isConnected&&this.updateAstronomy(this.lastTimeMs)}));return}const i=this.limbCache;if(i&&Math.abs(t.getTime()-i.atMs)<5e3&&i.lat===e.lat&&i.lng===e.lng&&i.elevationM===e.elevationM)return i.profile;const n=ws.profile(t,e,this.limbRelief);return this.limbCache={profile:n,atMs:t.getTime(),lat:e.lat,lng:e.lng,elevationM:e.elevationM},n}pushSatellitesAt(t,e,i){if(this.ensureSatellites(t),!t||!this.satellites){this.sceneRenderer.setSatellites([]);return}const n=new Date(t.getTime()+e),s=[];for(const r of this.satellites.passes.positionsAt(n,i,-1))r.magnitude!==void 0&&s.push({norad:r.object.norad,name:r.object.name,position:{altitudeDeg:r.altitudeDeg,azimuthDeg:r.azimuthDeg},magnitude:r.magnitude,heightKm:r.heightKm});this.sceneRenderer.setSatellites(s)}ensureFireballs(t){const e=this.ufoElement.sighting,i=Math.max((e.event.durationSeconds??0)*1e3,this.ufoElement.seekableDuration),n=t?.getTime(),s=n===void 0?"":`${n}+${i}`;if(this.fireballs?.key===s)return;if(n===void 0||!gr.mayCover(n+i)){this.fireballs={key:s,status:"outside",reentries:[]};return}const r={key:s,status:"loading",reentries:[]};this.fireballs=r,be.fireballArchive.between(n,n+i).then(a=>{r.status=a?"ready":"unavailable",r.records=a??[],r.reentries=r.records.map(c=>gr.asReentry(c,n)),!(this.fireballs!==r||!this.isConnected)&&(this.dispatchEvent(new CustomEvent(_O)),r.reentries.length>0&&this.updateAstronomy(this.lastTimeMs))})}decorWithTraffic(t){const e=this.ensureTraffic(t);if(!e||e.objects.length===0)return t.decor;const i=this.decorMemo;if(i&&i.base===t.decor&&i.traffic===e.objects)return i.merged;const n=[...t.decor,...e.objects];return this.decorMemo={base:t.decor,traffic:e.objects,merged:n},n}seatedDecor(t,e){if(!t.some(r=>r.observerKeyframes?.length))return t;const i=t.map(r=>{if(!r.observerKeyframes?.length)return"";const a=F1(r,e);return`${a.side??"-"}/${a.facing??"-"}`}).join("|"),n=this.seatedMemo;if(n&&n.base===t&&n.seats===i)return n.seated;const s=t.map(r=>{if(!r.observerKeyframes?.length)return r;const a=F1(r,e);return{...r,observerSide:a.side,observerFacing:a.facing}});return this.seatedMemo={base:t,seats:i,seated:s},s}ensureTraffic(t){const e=ze(t,0),i=e?.lng===void 0?void 0:ja(t.event.time??{},e.lng,t.event.utcOffsetHours),n=Math.max((t.event.durationSeconds??0)*1e3,this.ufoElement.seekableDuration),s=i?.getTime(),r=s===void 0||e?.lat===void 0||e.lng===void 0?"":`${this.aircraftSource.id}|${s}+${n}|${e.lat.toFixed(3)},${e.lng.toFixed(3)}|${Math.round(e.elevationM??0)}`;if(this.traffic?.key===r)return this.traffic.set;if(this.upperAirHeardLive=void 0,r===""||s===void 0||e?.lat===void 0||e.lng===void 0){this.traffic={key:r,status:"outside"};return}let a=be.aircraftProviders.get(this.aircraftSource.id);if(a||be.aircraftProviders.set(this.aircraftSource.id,a=this.aircraftSource.create()),a.mayCover&&!a.mayCover(s+n)){this.traffic={key:r,status:"outside"};return}const c={key:r,status:"loading",startMs:s,observer:{lat:e.lat,lng:e.lng}};this.traffic=c;const l={lat:e.lat,lng:e.lng,heightM:e.elevationM??0},h=kn.MAX_GAP_S*1e3,u=be.SOUND_LOOKBACK_MS,d={lat:e.lat,lng:e.lng,elevationM:e.elevationM??0},f=(p,g)=>p.TrafficDecor.from(c.tracks??[],l,s,p.TrafficDecor.MAX_OBJECTS,{models:g,sunElevationAt:m=>this.sunElevationAt(m,d)});a.between(l,s-u,s+n+h).then(async p=>{if(this.traffic!==c)return;if(p.status!=="found"){c.status=p.status==="outside"?"outside":"unavailable",this.announceTraffic();return}let g;try{g=await be.loadTrafficRuntime()}catch{this.traffic===c&&(c.status="unavailable",this.announceTraffic());return}this.traffic===c&&(c.status="ready",c.tracks=p.tracks,c.set=f(g),this.startAircraftSound(c,g),this.announceTraffic(),this.describeTraffic(a,c,g,f),c.set.shown>0&&(this.readUpperAir(c,g,s-u,s+n+h),this.readTrailTraffic(a,c,g,l,s-be.TRAIL_LOOKBACK_MS,s+n+h)))})}trafficSunlight(t){const e=new Map,i=this.traffic,n=i?.set,s=this.lastSun;if(!n||!s||i.startMs===void 0||!i.observer)return e;for(const[r,a]of n.presence){if(t<a.fromMs||t>a.untilMs)continue;const c=n.flights.get(r),l=c?kn.positionAt(c,i.startMs+t):void 0;l&&e.set(r,{heightM:l.geo.heightM,sunElevationDeg:zn.sunElevationDeg(s,i.observer,l.geo)})}return e}trafficTooltipAt(t,e){const i=this.sceneRenderer.pickTrafficAt(t,e),n=i?this.trafficInfoAt(i):void 0;if(!n)return;const s=this.naming,r=be.trafficRuntime;return r?.TrafficTooltip.text(n,s.names?.trafficTooltip??r.TrafficTooltip.ENGLISH,a=>s.towards(a))}trafficInfoAt(t){const e=this.traffic,i=e?.set?.flights.get(t);if(!e||!i||e.startMs===void 0||!e.observer)return;const n=be.trafficRuntime;if(!n)return;const s=e.descriptions?.get(gn.keyOf(i)),r=ze(this.ufoElement.sighting,this.lastTimeMs),a={lat:e.observer.lat,lng:e.observer.lng,heightM:r?.elevationM??0},c=n.AmbientNoise.dbA(wl(this.ufoElement.sighting,this.lastTimeMs)),l=n.TrafficInfos.at(i,s,a,e.startMs+this.lastTimeMs,{ambientDbA:c}),h=l&&this.contrailAt(t,this.lastTimeMs);return l&&h?{...l,contrail:h}:l}contrailAt(t,e){const i=this.traffic?.contrails?.find(s=>s.id===t);if(!i)return;let n;for(const s of i.points){if(s.tMs>e)break;n=s}return n?.forms?{persistent:n.persistent,iceRelativeHumidity:n.iceRelativeHumidity}:void 0}startAircraftSound(t,e){this.aircraftAudio??=this.newAircraftAudio(e),this.sortOutAudible(t,e)}sortOutAudible(t,e){!t.set||!t.observer||(t.audible=e.TrafficSound.candidates(t.set.flights,t.descriptions??new Map,gn.keyOf,{...t.observer,heightM:0},{ambientDbA:e.AmbientNoise.BASE_DB_A}))}pushAircraftSound(t,e){this.startDecorAircraftSound(t),this.startBodySound();const i=this.aircraftAudio;if(!i)return;const n=be.trafficRuntime;if(!n){i.setVoices([]);return}const s=ze(t,e),r=wl(t,e),a={ambientDbA:n.AmbientNoise.dbA(r),referenceAmplitude:n.AmbientNoise.referenceAmplitude(r)},c=this.trafficVoices(e,s,a,n),l=t.event.place?.[0],h={lat:s?.lat??l?.lat,lng:s?.lng??l?.lng};h.lat!==void 0&&h.lng!==void 0&&(this.decorAircraftHearing??=new n.DecorAircraftHearing,c.push(...this.decorAircraftHearing.voices(t,e,{lat:h.lat,lng:h.lng,heightM:s?.elevationM??0},a,u=>this.decorModelSounds.get(u.model?.id??""))),c.push(...this.bodyVoices(t,e,a,n)),c.sort((u,d)=>d.levelDbA-u.levelDbA),c.length=Math.min(c.length,4)),i.setVoices(c,s?.headingDeg??0)}startBodySound(){this.aircraftAudio||!this.interpretationShown?.bodies.some(t=>t.sound)||(be.trafficRuntime?this.aircraftAudio=this.newAircraftAudio(be.trafficRuntime):be.loadTrafficRuntime().catch(()=>{}))}bodyVoices(t,e,i,n){const s=this.interpretationShown,r=t.event.place?.[0];if(!s||!r||!s.bodies.some(f=>f.sound))return[];const a=this.sceneRenderer.bodyGround,c=f=>Wt.eyeOf(t,f,a),l=c(e);if(!l)return[];const h=new Map,u=(f,p)=>{let g=h.get(f.id);return g||h.set(f.id,g=new Wt(f,a,c)),g.at(p)};this.bodyHearing??=new n.BodyHearing;const d=Math.max(t.observerTrack.duration,(t.event.durationSeconds??0)*1e3);return this.bodyHearing.voices(s.bodies,u,l,r,e,d,i)}trafficVoices(t,e,i,n){const s=this.traffic,r=s?.set;if(!s||!r||!s.audible||s.startMs===void 0||!s.observer)return[];const a={lat:s.observer.lat,lng:s.observer.lng,heightM:e?.elevationM??0};return n.TrafficSound.voices(s.audible,r.flights,s.descriptions??new Map,gn.keyOf,a,s.startMs+t,i)}startDecorAircraftSound(t){const e=t.decor.filter(i=>i.kind==="aircraft"&&i.track?.some(n=>(n.altitudeM??0)>0));if(e.length!==0){for(const i of e){const n=i.model?.id;!n||i.model?.url!==void 0||this.decorModelSounds.has(n)||(this.decorModelSounds.set(n,void 0),this.sceneRenderer.entryOfDecorModel(n).then(s=>{this.decorModelSounds.set(n,s?.parameters?.sound)}))}if(this.aircraftAudio||be.trafficRuntime){!this.aircraftAudio&&be.trafficRuntime&&(this.aircraftAudio=this.newAircraftAudio(be.trafficRuntime));return}be.loadTrafficRuntime().catch(()=>{})}}newAircraftAudio(t){const e=new t.AircraftAudio;return e.setLevel(this.ufoElement.level),this.interacted&&e.resume(),e.setPaused(this.ufoElement.playbackState!=="playing"),e}announceTraffic(){this.isConnected&&(this.dispatchEvent(new CustomEvent(RO)),this.updateAstronomy(this.lastTimeMs))}async describeTraffic(t,e,i,n){if(!t.describe||!e.set||!e.tracks)return;const s=new Set([...e.set.flights.values()].map(l=>gn.keyOf(l))),r=e.tracks.filter(l=>s.has(gn.keyOf(l))&&l.points.length>0),a=new Map,c=new Map;await Promise.all(r.map(async l=>{const h=new Date(l.points[0].t).toISOString().slice(0,10),u=await t.describe(l,h).catch(()=>{});u&&(c.set(gn.keyOf(l),u),a.set(gn.keyOf(l),i.AircraftModels.of(u)))})),!(this.traffic!==e||a.size===0)&&(e.descriptions=c,e.models=a,e.set=n(i,a),this.planContrails(e,i),this.sortOutAudible(e,i),this.announceTraffic())}async readTrailTraffic(t,e,i,n,s,r){if(e.startMs===void 0)return;const a=await t.between(n,s,r).catch(()=>{});if(this.traffic!==e||a?.status!=="found")return;const c=a.tracks.filter(u=>u.points.some(d=>d.altitudeFt>=i.AircraftContrails.MIN_ALTITUDE_FT)),l=new Map(e.models??[]);if(t.describe&&await Promise.all(c.filter(u=>u.points.length>0&&!l.has(gn.keyOf(u))).map(async u=>{const d=await t.describe(u,new Date(u.points[0].t).toISOString().slice(0,10)).catch(()=>{});d&&l.set(gn.keyOf(u),i.AircraftModels.of(d))})),this.traffic!==e||e.startMs===void 0)return;const h=i.TrafficDecor.from(c,n,e.startMs,be.TRAIL_MAX_AIRCRAFT,{models:l});e.trailSet=be.alignTrailIds(h,e.set),e.models=new Map([...l,...e.models??[]]),this.planContrails(e,i),this.announceTraffic()}static alignTrailIds(t,e){if(!e)return t;const i=new Map;for(const[a,c]of e.flights){const l=e.presence.get(a);if(l)for(const[h,u]of t.flights){const d=t.presence.get(h);!d||gn.keyOf(u)!==gn.keyOf(c)||d.fromMs<=l.untilMs&&l.fromMs<=d.untilMs&&i.set(h,a)}}const n=a=>i.get(a)??`${a}-trail`,s=new Set(i.values()),r=e.objects.filter(a=>!s.has(a.id));return{...t,objects:[...t.objects.map(a=>({...a,id:n(a.id)})),...r],presence:new Map([...[...t.presence].map(([a,c])=>[n(a),c]),...r.map(a=>[a.id,e.presence.get(a.id)])]),flights:new Map([...[...t.flights].map(([a,c])=>[n(a),c]),...r.map(a=>[a.id,e.flights.get(a.id)])])}}async readUpperAir(t,e,i,n){if(!t.observer)return;const s=Wc.held(this.ufoElement.sighting.frozen,"upperAir");let r;if(s){const l=ti.address(s.src,this.documentUrl);r=be.upperAirProviders.get(l),r||be.upperAirProviders.set(l,r=new Vc(ti.json(l)))}else{const l=this.upperAirSource??e.UPPER_AIR_SOURCES[0];r=be.upperAirProviders.get(l.id),r||be.upperAirProviders.set(l.id,r=l.create())}const a={lat:t.observer.lat,lng:t.observer.lng},c=await r.between(a,i,n);this.traffic!==t||c.status!=="found"||(s||(this.upperAirHeardLive={...a,startMs:i,endMs:n,answer:c}),t.air=c.samples,t.airSource=c.source,this.planContrails(t,e),this.announceTraffic())}planContrails(t,e){const i=t.trailSet??t.set;!i||!t.air||t.startMs===void 0||(t.contrails=e.AircraftContrails.plan(i,t.models,t.air,t.startMs))}contrailSunlight(t){const e=new Map,i=this.traffic,n=i?.trailSet??i?.set,s=this.lastSun;if(!i||!n||!s||!i.contrails?.length||i.startMs===void 0||!i.observer)return e;for(const r of i.contrails){const a=n.presence.get(r.id),c=n.flights.get(r.id);if(!a||!c)continue;const l=kn.positionAt(c,i.startMs+Math.min(a.untilMs,Math.max(a.fromMs,t)));l&&e.set(r.id,{heightM:l.geo.heightM,sunElevationDeg:zn.sunElevationDeg(s,i.observer,l.geo)})}return e}sunElevationAt(t,e){const i=Fu("Sun",new Date(t.t),e);return zn.sunElevationDeg(i,e,t)}upperAirSource;upperAirHeardLive;get upperAirHeard(){return this.upperAirHeardLive}setUpperAirSource(t){t.id!==this.upperAirSource?.id&&(this.upperAirSource=t,this.traffic=void 0,this.decorMemo=void 0,this.updateAstronomy(this.lastTimeMs))}setAircraftSource(t){t.id!==this.aircraftSource.id&&(this.aircraftSource=t,this.traffic=void 0,this.decorMemo=void 0,this.updateAstronomy(this.lastTimeMs))}get aircraftState(){const t=this.traffic?.contrails?.length?this.upperAirSource??be.trafficRuntime?.UPPER_AIR_SOURCES[0]:void 0;return{trailCredit:t&&{credit:t.credit,creditUrl:t.creditUrl},status:this.traffic?.status??"none",total:this.traffic?.set?.total??0,shown:this.traffic?.set?.shown??0,credit:this.aircraftSource.credit,creditUrl:this.aircraftSource.creditUrl}}get fireballState(){return{status:this.fireballs?.status??"none",records:this.fireballs?.records??[]}}ensureSatellites(t){const e=t?String(t.getTime()):"";if(e===this.satellitesFor)return;this.satellitesFor=e,this.satellites=void 0,this.satellitePassesMemo=void 0;const i=++this.satelliteRequest;if(!t){this.satelliteStatus="none";return}this.satelliteStatus="loading";const n=r=>{i===this.satelliteRequest&&(this.satelliteStatus=r,this.isConnected&&this.dispatchEvent(new CustomEvent(AO)))},s=be.tleArchive;(async()=>{if(!await s.covers(t))return n("outside");const[r,a]=await Promise.all([s.at(t),we(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(i===this.satelliteRequest){if(!r)return n("unavailable");this.satellites={snapshot:r,passes:new a.SatellitePasses(r.objects)},n("ready"),this.isConnected&&this.updateAstronomy(this.lastTimeMs)}})().catch(()=>n("unavailable"))}get satelliteState(){const t=this.satellites?.snapshot;return{status:this.satelliteStatus,coverage:t?.coverage,credit:t?.credit,creditUrl:t?.creditUrl}}burningCandidates(){return{reentries:this.ufoElement.sighting.skyEvents?.reentries??[],fireballs:this.fireballs?.reentries??[]}}trafficCandidates(){const t=this.traffic;if(!(t?.status!=="ready"||!t.tracks||t.startMs===void 0))return{tracks:t.tracks,startMs:t.startMs,describe:e=>t.descriptions?.get(gn.keyOf(e))}}satellitePositionsAt(t){const e=this.satellites,i=this.ufoElement.sighting,n=ze(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,a=n?.lng??s?.lng;if(!(!e||r===void 0||a===void 0))return e.passes.positionsAt(t,{lat:r,lng:a,elevationM:n?.elevationM??0})}satellitePassesDuring(t){const e=this.satellites,i=this.ufoElement.sighting,n=ze(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,a=n?.lng??s?.lng;if(!e||r===void 0||a===void 0)return[];const c=ja(i.event.time??{},a,i.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(t,0),4*36e5),h={lat:r,lng:a,elevationM:n?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),r,a,h.elevationM,l]);if(this.satellitePassesMemo?.key===u)return this.satellitePassesMemo.passes;const d=Math.max(10,Math.ceil(l/1e3/600)),f=e.passes.passesDuring(c,new Date(c.getTime()+l),h,d);return this.satellitePassesMemo={key:u,passes:f},f}cometAt(t,e){const i=dO.brightestAt(t,e);if(i)return{id:i.apparition.id,position:i.position,tailEnd:i.tailEnd,magnitude:i.magnitude}}pushPhenomenaAt(t){const e=this.ufoElement.sighting;e!==this.sizeEstimatesFor&&(this.sizeEstimates.clear(),this.distanceHypotheses.clear(),this.sizeEstimatesFor=e);const i=e.timeline,n=this.ufoElement.canvasElement,s=this.ufoElement.frameShiftPx,r=this.projectionAt(t),a=new Map,c=new Map,l=new Set;for(const p of i.sourceIds){const g=i.getInterpolatedShapeAt(t,p);if(!g)continue;const m={...g,bounds:{...g.bounds,x:g.bounds.x+s.x,y:g.bounds.y+s.y}};a.set(p,m);const v=g.aim?this.sceneRenderer.screenPointOf(ks.directionOf(g.aim,this.directionScratch)):{ndcX:(m.bounds.x+m.bounds.width/2)/n.width*2-1,ndcY:-((m.bounds.y+m.bounds.height/2)/n.height*2-1)},y=v!==void 0&&Math.abs(v.ndcX)<=1&&Math.abs(v.ndcY)<=1,x=y?this.sceneRenderer.decorDistancesAt(v.ndcX,v.ndcY,p):{};l.add(p),(y||g.aim)&&l.delete(p);const M=g.angular?.widthDeg??r.pxToDeg(g.bounds.width),b=this.sizeEstimateOf(p);b.add(M,x);const S=Mh.of(e,p);c.set(p,Ln.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:S&&M>0?Ze.distanceMAt(S.widthM,M):void 0,range:b.distanceRangeAt(M),crossing:x}))}for(const[p,g]of a)for(const[m,v]of a){if(m===p||v.transparency>=1||v.bounds.width*v.bounds.height<=g.bounds.width*g.bounds.height||!(g.bounds.x>=v.bounds.x&&g.bounds.y>=v.bounds.y&&g.bounds.x+g.bounds.width<=v.bounds.x+v.bounds.width&&g.bounds.y+g.bounds.height<=v.bounds.y+v.bounds.height))continue;const x=c.get(m);x&&c.set(p,{distanceM:x.distanceM*.999,basis:x.basis});break}this.depths=c;const h=i.sourceIds,u=[];for(const[p,g]of a)u.push({sourceId:p,shape:g,distanceM:c.get(p).distanceM,renderOrder:h.indexOf(p),aim:g.aim,hidden:l.has(p)||this.interpretationShown!==void 0&&(!this.comparing||g.transparency>=1),ghost:this.interpretationShown!==void 0&&this.comparing});const f=(ze(e,t)?.rollDeg??0)+Xe.bodyAt(e,t,this.ufoElement.steadyBody).rollDeg;this.sceneRenderer.setPhenomena(u,{projection:r,canvasWidthPx:n.width,canvasHeightPx:n.height,scale:Math.max(1,this.sceneCanvas.height/Math.max(1,n.height)),starPoints:Bi.starPointsOf(e.instrument),rollRad:f*Math.PI/180})}get interpretation(){return this.interpretationShown}set interpretation(t){this.interpretationShown=mi.expand(Nn.expand(t)),this.ufoElement.playerTitle=t?.title,this.syncAccountHidden(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.repaintChrome()}redrawSky(){this.updateAstronomy(this.lastTimeMs)}syncAccountHidden(){this.ufoElement.accountHidden=this.interpretationShown!==void 0&&!this.comparing}get accountInTheRound(){return this.inTheRound}set accountInTheRound(t){this.inTheRound=t}get compareAccount(){return this.comparing}set compareAccount(t){t!==this.comparing&&(this.comparing=t,this.syncAccountHidden(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.repaintChrome())}get confrontation(){return this.confrontationReadings}groundAlong(t,e,i){const n=this.sceneRenderer.bodyGround,s=Wt.eyeOf(this.ufoElement.sighting,i,n);return s?Wt.lineOfSightMeetsGround(s,t,e,n):void 0}bodyMaskedBy(t,e){return this.sceneRenderer.bodyMaskedByDecor(t,e)}bodyReading(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=d=>Wt.eyeOf(n,d,i),r=new Wt(t,i,s).at(e),a=s(e);if(!r||!a)return;const c=r.eastM-a.eastM,l=r.northM-a.northM,h=r.upM-a.upM,u=Math.hypot(c,l);return{azimuthDeg:(Math.atan2(c,l)*180/Math.PI+360)%360,altitudeDeg:Math.atan2(h,u)*180/Math.PI,distanceM:Math.hypot(u,h),eastM:r.eastM,northM:r.northM,aboveGroundM:r.upM-r.sizeM.heightM/2-i.heightAt(r.eastM,r.northM),sizeM:r.sizeM,attitude:r.attitude,appearance:r.appearance}}bodyProjectionAt(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=c=>Wt.eyeOf(n,c,i),r=new Wt(t,i,s).at(e),a=s(e);return r&&a?gi.projectionOf(r,a):void 0}directionToBody(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=p=>Wt.eyeOf(n,p,i),r=new Wt(t,i,s),a=r.at(e)?e:t.track[0]?.t,c=a===void 0?void 0:r.at(a),l=a===void 0?void 0:s(a);if(!c||!l)return;const h=c.eastM-l.eastM,u=c.northM-l.northM,d=c.upM-l.upM,f=Math.hypot(h,u);if(!(f===0&&d===0))return{azimuthDeg:(Math.atan2(h,u)*180/Math.PI+360)%360,altitudeDeg:Math.atan2(d,f)*180/Math.PI}}placeBodiesAt(t,e){const i=this.interpretationShown,n=this.ufoElement.sighting;let s=[],r=[];const a=this.sceneRenderer.bodyGround,c=p=>Wt.eyeOf(n,p,a);i&&(s=i.bodies.map(p=>new Wt(p,a,c).at(t)).filter(p=>p!==void 0));const l=_c(n,t),h=l.windDirectionDeg*Math.PI/180,u={x:l.windSpeed*Math.sin(h),z:-l.windSpeed*Math.cos(h)};this.sceneRenderer.setBodies(s,t/1e3,i?.bodies.map(p=>p.id)??[],i?.smoke??[],u);const d=i&&this.comparing?c(t):void 0;if(d&&(r=new gi(n.timeline,this.confrontationTolerance).at(t,s,d,p=>p.outlineNode?this.sceneRenderer.bodyOutline?.(p.id,p.outlineNode):void 0)),this.confrontationReadings=r,!e)return;const f=JSON.stringify(r);f!==this.confrontationSignature&&(this.confrontationSignature=f,this.dispatchEvent(new CustomEvent(Cb,{detail:r})))}setDistanceHypothesis(t,e){e===void 0||!(e>0)?this.distanceHypotheses.delete(t):this.distanceHypotheses.set(t,e),this.updateAstronomy(this.lastTimeMs)}depthOf(t){return this.depths.get(t)}sizeRangeOf(t){return this.sizeEstimateOf(t).sizeRange}distanceRangeAt(t,e){const i=this.ufoElement.sighting.timeline.getInterpolatedShapeAt(e,t);if(!i)return{};const n=i.angular?.widthDeg??this.projectionAt(e).pxToDeg(i.bounds.width);return this.sizeEstimateOf(t).distanceRangeAt(n)}sizeContradictory(t){return this.sizeEstimateOf(t).contradictory}updateMeteorShower(t,e){this.ensureMeteorSchedule(t),this.sceneRenderer.updateMeteors(e)}updateLightning(t,e,i){if(this.ensureLightningSchedule(t),this.sceneRenderer.updateLightning(e),i)return;const n=this.lastLightningT;if(this.lastLightningT=e,n===void 0||e<n||this.ufoElement.playbackState!=="playing")return;const s=this.lightningFlashes.filter(r=>r.t>n&&r.t<=e).pop();s&&_c(t,s.t).storm&&this.handleLightningFlash(s)}ensureLightningSchedule(t){const e=_c(t,0).precipitationIntensity,i=`${this.meteorInputsOf(t)}|${e}`;if(i===this.lightningScheduleFor)return;this.lightningScheduleFor=i;const n=t.event.time,s=t.event.place?.[0],r=n?.year!==void 0?ja(n,s?.lng??0,t.event.utcOffsetHours):void 0,a=(t.event.durationSeconds??0)*1e3||t.timeline.duration||2e4,c=Math.round((r?.getTime()??0)/1e3)+Math.round((s?.lat??0)*1e3)+7;this.lightningFlashes=Qi.schedule({durationMs:a,seed:c,intensity:e}),this.sceneRenderer.setLightning(this.lightningFlashes)}ensureMeteorSchedule(t){const e=this.meteorInputsOf(t);e!==this.meteorScheduleFor&&(this.meteorScheduleFor=e,this.scheduleMeteors(t))}meteorInputsOf(t){const e=t.event.place?.[0],i=t.event.time;return JSON.stringify([e?.lat,e?.lng,i?.year,i?.month,i?.day,i?.hour,i?.minute,i?.second,t.event.utcOffsetHours,t.event.durationSeconds,t.timeline.duration])}scheduleMeteors(t){const e=t.event.place?.[0],i=t.event.time,n=e?.lat!==void 0&&e.lng!==void 0&&i?.year!==void 0?ja(i,e.lng,t.event.utcOffsetHours):void 0;if(!n||e?.lat===void 0||e.lng===void 0){this.sceneRenderer.setMeteorShower([],0,0);return}const s={lat:e.lat,lng:e.lng,elevationM:0},r=(t.event.durationSeconds??0)*1e3||t.timeline.duration||2e4,a=Math.round(n.getTime()/1e3)+Math.round(e.lat*1e3),c=Ci.schedule({ratePerHour:Ci.observedRatePerHour(Ci.apexPosition(n,s).altitudeDeg),durationMs:r,velocityKmS:Ci.TYPICAL_VELOCITY_KM_S,seed:a}),l=bp.activeAt(n).map(u=>{const d=bp.radiantPosition(u.shower,n,s);return{entry:u,position:d,rate:bp.observedRatePerHour(u.zhr,d.altitudeDeg,u.shower.populationIndex)}}).sort((u,d)=>d.rate-u.rate)[0];if(!l||l.rate<=0){this.sceneRenderer.setMeteorShower(c,0,0);return}const h=Hs.schedule({ratePerHour:l.rate,durationMs:r,velocityKmS:l.entry.shower.velocityKmS,seed:a+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}groundHides(t,e){return this.sceneRenderer.groundHidesDirection(t,e)}get groundKey(){return this.sceneRenderer.groundKey}meteorByRank(t,e=Number.POSITIVE_INFINITY){this.ensureMeteorSchedule(this.ufoElement.sighting);const i=[...this.sceneRenderer.meteorSchedule].filter(r=>r.t+r.durationMs<=this.ufoElement.seekableDuration).filter(r=>Hs.magnitudeOf(r)<=e).filter(r=>{const a=this.sceneRenderer.meteorMidpoint(r);return a!==void 0&&!this.sceneRenderer.groundHidesDirection(a.altitudeDeg,a.azimuthDeg)}).sort((r,a)=>a.brightness-r.brightness);if(i.length===0)return;const n=i[t%i.length],s=this.sceneRenderer.meteorMidpoint(n);if(s)return{t:Math.round(n.t+n.durationMs*.45),...s}}lensOpticsAt(t){const e=this.ufoElement.sighting,i=e.instrument,n=i.frame,s=ze(e,t),r=s?.fNumber??i.fNumber;if(!n||r===void 0)return;const a=Bi.focalLengthMmFor(i,In.fovOf(e,t));if(a!==void 0)return{focalLengthMm:a,fNumber:r,focusDistance:s?.focusDistanceM??0,frameHeightMm:n.heightMm}}projectionAt(t){const e=this.ufoElement.sighting;return yr.of(e.instrument,Ze.CANVAS_HEIGHT_PX,In.fovOf(e,t))}sizeEstimateOf(t){let e=this.sizeEstimates.get(t);return e||(e=new pO,this.sizeEstimates.set(t,e)),e}}const wf="rr0-scene";function Ob(){Vy(),customElements.get(wf)||customElements.define(wf,be)}const NO={color:"Color",transparency:"Transparency",halo:"Halo",blur:"Blur",brightness:"Brilliance",shapeTitle:"Name",utcOffset:"Time zone",cloudBase:"Cloud base",elevation:"Altitude",heightAboveGround:"Height above ground",duration:"Duration",placeName:"Place",latitude:"Latitude",longitude:"Longitude",heading:"Heading",pitch:"Tilt",roll:"Roll",sway:"Sway at rest",swayTitle:"How much the body holding the instrument moves the view when not walking: 1 for a person standing, 0 for a tripod. Blank: 1 (0 if the account says the observer was paralysed)",referenceGhosts:"Ghosts in the picture",referenceFindGhosts:"Look for ghosts",referenceGhostsSearching:"Looking…",referenceGhostsFound:"{count} ghosts found, each across the lens's axis from its light.",referenceGhostsFoundScaled:"{count} ghosts found, each at {scale} times its light's offset from the lens's axis.",referenceGhostsLow:"Perhaps {count} ghost(s): too few to be sure.",referenceGhostsNone:"No ghost found: no faint spot lies across one point from a light.",referenceGhostsCropped:"The lens's axis is off the picture's centre: the picture was cropped.",referenceGhostsHide:"Hide ghosts",referenceGhostsShow:"Show ghosts",lensGlass:"Taken through",lensGlassNone:"the lens alone",lensGlassFilter:"a filter on the lens",lensGlassWindow:"a window",lensGlassWindscreen:"a windscreen",lensDrops:"Drops on the glass",lensDropsTitle:"0 to 1: how much of the outermost glass drops of water cover. Blank: from the rain or snow falling, unless the glass is sheltered",lensCondensation:"Condensation",lensCondensationTitle:"0 to 1: condensation on the glass, as on a lens taken from the warm into the cold. Blank: none",lensDirt:"Dirt",lensDirtTitle:"0 to 1: dirt, grease or fingerprints on the glass. Blank: none",lensSheltered:"Sheltered from the rain",lensShelteredTitle:"The outermost glass was out of the rain or snow: under a roof, or behind a windscreen whose wipers run",lightPollution:"Night sky",lightPollutionTitle:'The zenith of a moonless night at this place, in magnitudes per square arcsecond, as a Sky Quality Meter reads it or as the World Atlas of artificial sky brightness (Falchi et al. 2016, lightpollutionmap.info, "SQM") gives it. 22 is a natural sky; a suburb is about 19, a city centre 17. Blank: a natural sky',observationTime:"Observation start",observationEndTime:"Observation end",assessmentGroup:"Assessment",assessmentNames:{coverage:"Observer info"},assessmentVerdicts:{"hynek.nl":"NL — nocturnal light","hynek.dd":"DD — daylight disc","hynek.rv":"RV — radar-visual","hynek.ce1":"CE1 — close encounter","hynek.ce2":"CE2 — with a physical trace","hynek.ce3":"CE3 — with entities"},timeQualifierApproximate:"Approximate",timeQualifierUncertain:"Uncertain",timeQualifierBoth:"Uncertain and approximate",timeSeasonSpring:"Spring",timeSeasonSummer:"Summer",timeSeasonAutumn:"Autumn",timeSeasonWinter:"Winter",summaryGroups:{observation:"Observation",location:"Position",temporal:"Time",weather:"Weather",sound:"Sound"},summaryGroup:"Summary",summaryDescription:"Description",closeDescription:"Close the description",observerGroup:"Observer",observerId:"ID",observerTitle:"Title",observerLastName:"Last name",observerFirstNames:"First names",sightingId:"ID",tags:"Tags",cloudCover:"Cloud cover",highCloudCover:"Ice cloud (cirrus)",focalLength:"Focal length",fieldOfView:"Field of view",aperture:"Aperture",exposure:"Exposure",focusDistance:"Focused at",iceCrystalAlignment:"Crystal alignment",rareIceCrystals:"Rare crystals",cloudDarkness:"Cloud darkness",precipitationType:"Precipitation",precipitationNone:"None",precipitationRain:"Rain",precipitationSnow:"Snow",precipitationHail:"Hail",precipitationIntensity:"Intensity",windDirection:"Wind direction",windSpeed:"Wind speed",storm:"Storm",cloudsGroup:"Clouds",precipitationGroup:"Precipitation",windGroup:"Wind",soundKind:"Sound",soundNone:"None (silent)",soundHum:"Hum",soundWhistle:"Whistle",soundRumble:"Rumble",soundCrackle:"Crackle",soundVolume:"Loudness",soundPitch:"Pitch",soundSrc:"Recording",instrument:"Observed through",filter:"In front of it",filterNone:"nothing",filterSolarVisual:"a solar filter for the eye (eclipse glasses, density 5)",filterSolarPhoto:"a solar film for a camera (density 3.8)",decorAircraft:"Aircraft",decorEntity:"Being",decorAltitude:"Altitude",decorLights:"Lights",decorLightsNone:"none",decor:"Environment",decorBuilding:"Building",decorTree:"Tree",decorShrub:"Shrub",decorBridge:"Bridge",decorWire:"Overhead line",decorCrop:"Crop row",decorTerrace:"Terrace (restanque)",decorMound:"Stone heap",decorWall:"Dry-stone wall",decorStreetlight:"Streetlight",decorTrafficLight:"Traffic light",decorCrossing:"Pedestrian crossing",decorRoadSign:"Road sign",decorVehicle:"Vehicle",decorObserver:"Other observer",decorEast:"Distance east",decorNorth:"Distance north",decorHeading:"Heading",decorColor:"Colour",decorLit:"Lit",decorTitle:"Name",milestones:"Moments",milestoneLabel:"Label",milestoneNote:"What happens",addMilestone:"Name this moment",deleteMilestone:"Delete moment",goToMilestone:"Go to this moment",decorWidth:"Width",decorLength:"Length",decorHeight:"Height",decorModel:"3D model",decorModelAdvanced:"Model from an address",decorModelUrl:"glTF/GLB address",decorModelTitle:"Model name",decorModelAuthor:"Author",decorModelLicense:"Licence",decorModelSource:"Where it came from",decorObserverSide:"Observer location",decorObserverSideNone:"Not present",decorSideFront:"Front",decorSideBehind:"Behind",decorSideLeft:"Left",decorSideRight:"Right",decorSideFrontLeft:"Front-left",decorSideFrontRight:"Front-right",decorSideBehindLeft:"Behind-left",decorSideBehindRight:"Behind-right"},th={...NO,accountBy:"Account by",unnamedObserver:"Observer {n}",about:"About",close:"Close",observation:"Observation",date:"Date",location:"Location",case:"Case",description:"Description",source:"Source",basis:{measured:"measured",stated:"stated",derived:"derived",assumed:"assumed"},credits:"Credits",editThisObservation:"Edit this observation",share:"Share",embedObservation:"Embed the observation",back:"Back",shareScope:"Share",shareScopeCase:"Whole case",shareOpensOn:"Opens on",shareStartAt:"Start at",shareOptionLabels:"Show summary chips",shareOptionMap:"Open map",shareOptionMilestones:"Show moments",shareOptionCompare:"Compare account",showLabels:"Show what it states",interpretation:"Interpretation",account:"Account",interpretationBy:"{title}, by {by}",confrontation:"Against the account",confrontationDirection:"{deg}° off",confrontationWidth:"width ×{ratio}",confrontationHeight:"height ×{ratio}",showComparison:"Compare with the account",hideComparison:"Stop comparing with the account",hideLabels:"Hide what it states",variant:"Variant: {name}",verdicts:{consolidated:"compatible with consolidated biases",contested:"only by invoking contested biases",incompatible:"incompatible even at the bounds"},variantFields:{time:"Time",heading:"Heading",elevation:"Elevation",size:"Size",duration:"Duration",sweep:"Sweep across the sky"},variantReadings:{grouped:"lights read as one body","still-seen-moving":"a still light seen moving","moving-seen-still":"a moving light seen hovering","brightening-as-approach":"growing brighter read as coming nearer"}},kO=Object.freeze(Object.defineProperty({__proto__:null,sightingMessages_en:th},Symbol.toStringTag,{value:"Module"}));class vr{static PACKAGE="@rr0/ufoathome";static CDN="https://cdn.jsdelivr.net/npm";static DIRECTORIES={"rr0-sighting":"dist-embed-sighting","rr0-sighting-editor":"dist-embed-sighting-editor"};static current(t,e,i){const n=new URL(`${t}.mjs`,e);return n.href.startsWith(`${vr.CDN}/`)?`${i}/lib/${t}.mjs`:(n.pathname=n.pathname.replace(/\/lib\/\d+\.\d+\.\d+[^/]*\//,"/lib/"),n.href)}static VERSION_PARAMETER="v";static freezable(t){return t in vr.DIRECTORIES}static frozenLink(t,e){const i=new URL(t);return i.searchParams.set(vr.VERSION_PARAMETER,e),i.href}static frozen(t,e){return`${vr.CDN}/${vr.PACKAGE}@${e}/${vr.DIRECTORIES[t]}/${t}.mjs`}}class Uh{static PRODUCTION="https://ufoathome.org";static home(){try{const t=new URL(import.meta.url),e=new URL(location.href);return(e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname==="[::1]"||e.hostname.endsWith(".localhost"))&&t.origin===e.origin?e.origin:Uh.PRODUCTION}catch{return Uh.PRODUCTION}}}const sg={share:"Share",close:"Close",link:"Link",embed:"Embed",copy:"Copy",copied:"Copied",freeze:"Freeze version {version}",freezeHint:"The embed keeps the rendering of this version of UFO@home, loaded from jsDelivr, and gets none of the later fixes. Unticked, it follows each release.",unsaved:"The link opens the file at its address: your unsaved changes are not in it. Save the file there first.",unavailable:"Only a file loaded from an address can be shared: put it online, then open it from its address."},UO=Object.freeze(Object.defineProperty({__proto__:null,shareMessages_en:sg},Symbol.toStringTag,{value:"Module"})),FO=`
9336
9336
  <style>
9337
9337
  /* What the dialog is drawn with: light by default, and the dark set when the system asks for it, as the player and the editors
9338
9338
  are. The form controls follow through color-scheme. Defined here and not by the host, so that any element can hold this dialog;
@@ -9558,6 +9558,6 @@ ${ti.generation}`;return this.frozenMap?.key!==i&&(this.frozenMap={key:i,imagery
9558
9558
  <button id="copy" class="share-copy" type="button">Copy</button>
9559
9559
  </div>
9560
9560
  </dialog>
9561
- `;class il extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(il.TAG)||customElements.define(il.TAG,il)}subject;messages=sg;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=FO;const t=e=>this.shadow.getElementById(e);this.dialog=t("dialog"),this.linkField=t("link"),this.copyButton=t("copy"),this.linkBox=t("link-box"),this.embedBox=t("embed-box"),this.linkOption=t("link-option"),this.embedOption=t("embed-option"),this.freeze=t("freeze"),this.embedMarkup=t("embed-markup"),this.noteElement=t("note"),t("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",e=>{e.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(t){const e=++this.languageToken,i=t==="en"?sg:await XS(t);if(e===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(t){this.noteElement.textContent=t??"",this.noteElement.hidden=t===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 t=this.subject;if(!t)return;const e=this.freeze.checked;this.linkField.value=e?vr.frozenLink(t.link(),"0.144.0"):t.link(),this.fitLink();const n=`<script type="module" src="${e?vr.frozen(t.module,"0.144.0"):vr.current(t.module,import.meta.url,Uh.home())}"><\/script>
9562
- ${t.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const t=this.messages,e=(i,n)=>{this.shadow.getElementById(i).textContent=n};e("title",t.share),e("link-label",t.link),e("embed-label",t.embed),e("copy",t.copy),e("freeze-label",t.freeze.replace("{version}","0.144.0")),this.freeze.parentElement.title=t.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",t.close),this.linkField.setAttribute("aria-label",t.link)}show(t){this.linkBox.hidden=t!=="link",this.embedBox.hidden=t!=="embed",this.linkOption.setAttribute("aria-pressed",String(t==="link")),this.embedOption.setAttribute("aria-pressed",String(t==="embed")),t==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=we(async()=>{const{ShareCodeEditor:t}=await import("./ShareCodeEditor-C53SBK2N.js");return{ShareCodeEditor:t}},[],import.meta.url).then(({ShareCodeEditor:t})=>{this.codeEditor=new t(this.shadow.getElementById("embed-code"),this.embedMarkup.value,e=>{this.embedMarkup.value=e},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(t,e){try{await navigator.clipboard.writeText(t),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{e.select()}}}class mn{static PLAIN=/^\d+(?:[.,]\d+)?$/;static COLONS=/^(?:(\d+):)?(\d{1,2}):(\d{1,2}(?:[.,]\d+)?)$/;static UNITS=/^(?:(\d+(?:[.,]\d+)?)h)?(?:(\d+(?:[.,]\d+)?)m)?(?:(\d+(?:[.,]\d+)?)s)?$/i;static CLOCK=/^(?:(\d{4})-(\d{2})-(\d{2})[T ])?T?(\d{1,2}):(\d{2})(?::(\d{2}(?:[.,]\d+)?))?$/;static num(t){return t===void 0?0:Number(t.replace(",","."))}static delta(t){const e=(t??"").trim();if(e==="")return;if(mn.PLAIN.test(e))return mn.num(e);const i=mn.COLONS.exec(e);if(i){const[,s,r,a]=i;return Number(r)>=60||mn.num(a)>=60?void 0:mn.num(s)*3600+Number(r)*60+mn.num(a)}const n=mn.UNITS.exec(e);return n&&(n[1]!==void 0||n[2]!==void 0||n[3]!==void 0)?mn.num(n[1])*3600+mn.num(n[2])*60+mn.num(n[3]):/^P/i.test(e)?Xc.seconds(e.toUpperCase()):void 0}static isClock(t){return mn.clock(t)!==void 0}static clock(t){const e=mn.CLOCK.exec((t??"").trim());if(!e)return;const[,i,n,s,r,a,c]=e,l={hour:Number(r),minute:Number(a),second:mn.num(c)};if(!(l.hour>=24||l.minute>=60||l.second>=60)){if(i!==void 0){const h={year:Number(i),month:Number(n),day:Number(s)};if(h.month<1||h.month>12||h.day<1||h.day>31)return;l.date=h}return l}}static elapsedSince(t,e){if(!t||t.hour===void 0||t.minute===void 0)return;const i=t.hour*3600+t.minute*60+(t.second??0),n=e.hour*3600+e.minute*60+e.second;if(e.date){if(t.year===void 0||t.month===void 0||t.day===void 0)return;const r=Date.UTC(e.date.year,e.date.month-1,e.date.day)/1e3+n,a=Date.UTC(t.year,t.month-1,t.day)/1e3+i;return Math.max(0,r-a)}let s=n-i;return s<=-43200&&(s+=86400),Math.max(0,s)}}Ob();il.register();const Md=Uh.home(),td="compare-account",Ap="start-time",oy="start-clock",Yl="observer",ed="case",id="account",nd="variant-",_p=`${Md}/edit/`;class nl extends HTMLElement{static get observedAttributes(){return["src","show-labels",Ap,oy,Yl,Ar,_r,td]}shadow;sceneElement;toolbarElement;accountElement;accountPrefix;observerText;observerSelect;infoButton;infoPanel;infoAppLink;editLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;shareButton;shareDialog;shareStartOn;shareStart;shareScopeRow;shareScopeLabel;shareScope;shareOpensRow;shareOpensLabel;shareOpens;shareStartLabel;shareOptions;labelsToggle;paramSummary;summaryBuilder=new wh(th,new xf,new Es(["en"]),new rd({}),{messages:th,locale:"en"});summarySignature="";assessmentEntries=[];assessmentToken=0;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];caseSource;interpretationChoice;interpretationLabel;interpretationSelect;confrontationElement;confrontationHeading;confrontationList;compareButton;variantChips;variantMoved;interpretationLoaders=new Map;interpretationToken=0;offeredFor;currentSrc;infoOpen=!1;creditsOpen=!1;labelsShown=!1;language="en";messages=th;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${Hb}</style>${Bb}`,this.shadow.appendChild(t.content.cloneNode(!0)),customElements.upgrade(this.shadow),this.sceneElement=document.createElement(wf),this.forwardPlayerAttributes(),this.sceneElement.ufoElement.creditShownExternally=!0,this.sceneElement.ownCredits=!1,this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.accountElement=this.shadow.getElementById("account"),this.accountPrefix=this.shadow.getElementById("account-prefix"),this.observerText=this.shadow.getElementById("observer-text"),this.observerSelect=this.shadow.getElementById("observer"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.editLink=this.shadow.getElementById("edit-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.labelsToggle=this.shadow.getElementById("info-labels-toggle"),this.paramSummary=this.shadow.getElementById("param-summary"),this.labelsToggle.addEventListener("click",()=>{this.showLabels=!this.showLabels}),this.shareButton=document.createElement("button"),this.shareButton.type="button",this.shareButton.id="share-button",this.shareButton.setAttribute("aria-haspopup","dialog"),this.shareButton.innerHTML=qt.SHARE,this.sceneElement.ufoElement.addControl(this.shareButton),this.shareDialog=this.shadow.getElementById("share-dialog"),this.shareDialog.subject=this.shareSubject,this.shareStartOn=this.shadow.getElementById("share-start-on"),this.shareStart=this.shadow.getElementById("share-start"),this.shareStartLabel=this.shadow.getElementById("share-start-label"),this.shareScopeRow=this.shadow.getElementById("share-scope-row"),this.shareScopeLabel=this.shadow.getElementById("share-scope-label"),this.shareScope=this.shadow.getElementById("share-scope"),this.shareOpensRow=this.shadow.getElementById("share-opens-row"),this.shareOpensLabel=this.shadow.getElementById("share-opens-label"),this.shareOpens=this.shadow.getElementById("share-opens");const e=i=>({input:this.shadow.getElementById(`share-opt-${i}`),label:this.shadow.getElementById(`share-opt-${i}-label`)});this.shareOptions={labels:e("labels"),map:e("map"),milestones:e("milestones"),compare:e("compare")},this.interpretationChoice=this.shadow.getElementById("interpretation-choice"),this.interpretationLabel=this.shadow.getElementById("interpretation-label"),this.interpretationSelect=this.shadow.getElementById("interpretation"),this.confrontationElement=this.shadow.getElementById("confrontation"),this.confrontationHeading=this.shadow.getElementById("confrontation-heading"),this.confrontationList=this.shadow.getElementById("confrontation-list"),this.compareButton=this.shadow.getElementById("compare-account"),this.variantChips=this.shadow.getElementById("variant-chips"),this.variantMoved=this.shadow.getElementById("variant-moved"),this.compareButton.addEventListener("click",()=>this.setComparing(!this.sceneElement.compareAccount)),this.observerSelect.addEventListener("change",()=>this.selectObserver(this.observerSelect.value)),this.interpretationSelect.addEventListener("change",()=>void this.chooseInterpretation(this.interpretationSelect.value)),this.sceneElement.addEventListener(Cb,i=>this.showConfrontation(i.detail)),this.sceneElement.ufoElement.addEventListener("timeupdate",()=>this.refreshParamSummary()),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",i=>{i.newState==="open"&&(this.populateInfoPanel(),this.bringInfoButtonIntoView())}),this.infoPanel.addEventListener("toggle",i=>this.syncInfoOpen(i.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.shareButton.addEventListener("click",()=>this.openShare());for(const i of[this.shareStartOn,this.shareStart,...Object.values(this.shareOptions).map(n=>n.input)])i.addEventListener("input",()=>this.refreshShareLinks());for(const i of[this.shareScope,this.shareOpens])i.addEventListener("change",()=>this.refreshShareLinks());this.isConnected&&this.loadLocaleMessages()}get scene(){return this.sceneElement}async loadLocaleMessages(){const t=++this.localeToken,e=ka.preferencesFor(this);this.preferences=e;const i=dg(e,fg),[n,s,r]=i==="en"?[th,{},void 0]:await Promise.all([VS(i),$S(i),Iy(i)]);if(t!==this.localeToken)return;const a=i!==this.language;this.language=i,this.messages=n,this.tags=new rd(s),this.said=new Es(e),this.summaryBuilder=new wh(this.messages,new xf(r),this.said,this.tags,{messages:this.messages,locale:i}),this.accountPrefix.textContent=this.messages.accountBy,this.interpretationLabel.textContent=this.messages.interpretation,this.confrontationHeading.textContent=this.messages.confrontation;const c=this.entries.find(l=>l.src===this.currentSrc);c&&this.offerInterpretations(c),this.updateCompareButton(),this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.syncLabelsToggle(),this.refreshParamSummary(),a&&this.currentSrc&&this.runAssessments(),this.shareButton.title=this.messages.share,this.shareButton.setAttribute("aria-label",this.messages.share),this.shareStartLabel.textContent=this.messages.shareStartAt,this.shareScopeLabel.textContent=this.messages.shareScope,this.shareOpensLabel.textContent=this.messages.shareOpensOn,this.shareOptions.labels.label.textContent=this.messages.shareOptionLabels,this.shareOptions.map.label.textContent=this.messages.shareOptionMap,this.shareOptions.milestones.label.textContent=this.messages.shareOptionMilestones,this.shareOptions.compare.label.textContent=this.messages.shareOptionCompare,this.shareStart.setAttribute("aria-label",this.messages.shareStartAt),this.shareDialog.useLanguage(i),this.infoOpen&&this.populateInfoPanel(),this.updateAccountLine()}preferences=[];localeToken=0;said=new Es(["en"]);tags=new rd({});connectedCallback(){ka.preferencesFor(this).join()!==this.preferences.join()&&this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t==="show-labels"&&this.applyLabels(this.hasAttribute("show-labels")),(t===Ar||t===_r)&&this.forwardPlayerAttributes(),t===Yl&&this.entries.length>1){const n=this.entryAsked(this.entries);n&&n.src!==this.currentSrc&&this.selectObserver(n.src)}t===td&&this.setComparing(this.hasAttribute(td))}forwardPlayerAttributes(){for(const t of[Ar,_r]){const e=this.getAttribute(t);e===null?this.sceneElement.removeAttribute(t):this.sceneElement.setAttribute(t,e)}}async loadFromSrc(t){this.startPending=!0;const e=Na.recording(t);this.sceneElement.holdForNewScene(e);const i=await e;if(Array.isArray(i))throw new Error(`${t} is a bare list of recordings, which is no longer read: list them as the sighting events of a case.json`);if(tn.isCase(i)){tn.check(i);const n=tn.sightingUrls(i,new URL(t,location.href).href);if(n.length===0)throw new Error(`${t} is a case with no sighting event: no recording to show`);await this.loadObserverUrls(n,{json:i,url:new URL(t,location.href).href})}else this.setEntries([{src:t,sighting:i}],void 0)}get sightingData(){return this.entries.find(t=>t.src===this.currentSrc)?.sighting}set sightingData(t){this.startPending=!0,this.currentSrc="",this.setEntries([{src:"",sighting:t}],void 0)}seekTo(t,e){const i=this.caseSource,n=e===void 0?void 0:this.entries.find(s=>{const r=this.plain(s).id;return(i?tn.accountIds(i.json,i.url,s.src,r):[r]).includes(e)});n&&n.src!==this.currentSrc&&this.selectObserver(n.src),this.sceneElement.ufoElement.currentTime=Math.max(0,t)*1e3}get observerUrls(){return this.entries.map(t=>t.src)}set observerUrls(t){this.loadObserverUrls(t)}async loadObserverUrls(t,e){const i=await Promise.all(t.map(async n=>({src:n,sighting:await Na.recording(n)})));this.setEntries(i,e)}reportCaseProblems(t,e){const{duplicateIds:i,unresolved:n}=tn.problems(t,e.map(s=>this.plain(s).id).filter(s=>s!==void 0));for(const s of i)console.warn(`The case ${t.id??""} gives the id "${s}" to more than one event: a reference to it is ambiguous.`);for(const{reading:s,reference:r}of n)console.warn(`The reading ${s} of the case ${t.id??""} is "interpretationOf" "${r}", which no event of the case has as its id, nor any recording it lists.`)}setEntries(t,e){this.entries=t,this.caseSource=e,e&&this.reportCaseProblems(e.json,t),this.toolbarElement.hidden=t.length===0;const i=t.length>1;this.observerSelect.hidden=!i,this.observerText.hidden=i,this.observerSelect.innerHTML="";const n=t.map((r,a)=>this.observerDisplayName(this.plain(r).observer)??this.messages.unnamedObserver.replace("{n}",String(a+1)));for(const[r,a]of t.entries()){const c=document.createElement("option");c.value=a.src;const l=n.filter(h=>h===n[r]).length>1;c.textContent=(l?this.caseTitleOf(a):void 0)??n[r],this.observerSelect.appendChild(c)}const s=t.find(r=>r.src===this.currentSrc)??this.entryAsked(t)??t[0];s?this.selectObserver(s.src):this.updateAccountLine()}entryAsked(t){const e=this.getAttribute(Yl)?.trim();if(!e)return;const i=t.find(s=>this.plain(s).observer?.id===e);if(i)return i;const n=t.find(s=>s.src.split("/").pop()===e.split("/").pop());return n||(/^\d+$/.test(e)?t[Number(e)-1]:void 0)}observerKeyOf(t){return this.plain(t).observer?.id??String(this.entries.indexOf(t)+1)}sharedEntry(){const t=this.shareScope.value;if(!(!this.caseSource||t===ed))return this.entries.find(e=>e.src===t)}get sharesCase(){return this.caseSource!==void 0&&!this.shareScopeRow.hidden&&this.shareScope.value===ed}editorUrl(){if(!this.currentSrc)return _p;const t=new URL(this.currentSrc,location.href),e=this.caseSource;return e?`${_p}?file=${encodeURIComponent(e.url)}&track=${encodeURIComponent(this.shownTrackUrl()??t.href)}`:`${_p}?file=${encodeURIComponent(t.href)}`}get editorHref(){return this.editorUrl()}shownTrackUrl(){const t=this.caseSource,e=this.entries.find(s=>s.src===this.currentSrc),i=/^case-(\d+)$/.exec(this.interpretationSelect.value);if(!t||!e||!i)return;const n=tn.interpretationEvents(t.json,tn.accountIds(t.json,t.url,e.src,this.plain(e).id))[Number(i[1])];return n?.url?new URL(n.url,t.url).href:void 0}shareSubject={module:"rr0-sighting",link:()=>this.playUrl(),element:()=>this.replayElement()};replayElement(){const t=this.sharedAddress(),i=[...t.observer?[[Yl,t.observer]]:[],...this.replayAttributes()].map(([n,s])=>s===""?` ${n}`:` ${n}="${s}"`).join("");return`<rr0-sighting src="${t.src}"${i}></rr0-sighting>`}playUrl(){const t=this.sharedAddress(),e=[...t.observer?[`${Yl}=${encodeURIComponent(t.observer)}`]:[],...this.replayQuery()].join("&");return t.src?`${Md}/play/?file=${encodeURIComponent(t.src)}${e&&"&"+e}`:`${Md}/play/${e&&"?"+e}`}sharedAddress(){const t=e=>e?new URL(e,location.href).href:"";if(this.sharesCase){const e=this.entries.find(i=>i.src===this.shareOpens.value)??this.entries.find(i=>i.src===this.currentSrc);return{src:this.caseSource.url,observer:e?this.observerKeyOf(e):void 0}}return{src:t(this.sharedEntry()?.src??this.currentSrc??"")}}replayAttributes(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push([Ap,String(this.shareStartSeconds)]),t.labels.input.checked&&e.push(["show-labels",""]),t.map.input.checked&&e.push([Ar,""]),t.milestones.input.checked||e.push([_r,""]),t.compare.input.checked&&e.push([td,""]),e}replayQuery(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push(`d=${this.shareStartSeconds}`),t.labels.input.checked||e.push("labels=0"),t.map.input.checked&&e.push("map=1"),t.milestones.input.checked||e.push("moments=0"),t.compare.input.checked&&e.push("compare=1"),e}get shareStartSeconds(){const t=Math.floor(Number(this.shareStart.value));return this.shareStartOn.checked&&Number.isFinite(t)&&t>=0?t:void 0}refreshShareLinks(){this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.refresh()}openShare(){const t=this.sceneElement.ufoElement;this.shareStart.max=String(Math.floor(t.seekableDuration/1e3)),this.shareStart.value=String(Math.floor(t.currentTime/1e3)),this.shareStartOn.checked=!1,this.shareOptions.labels.input.checked=this.labelsShown,this.shareOptions.map.input.checked=t.observerMapOpen,this.shareOptions.milestones.input.checked=t.milestonesVisible,this.shareOptions.compare.input.checked=this.sceneElement.compareAccount,this.offerShareScope(),this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.open()}offerShareScope(){const t=this.caseSource!==void 0&&this.entries.length>1;if(this.shareScopeRow.hidden=!t,this.shareScope.innerHTML="",this.shareOpens.innerHTML="",!t)return;const e=(i,n,s)=>{const r=document.createElement("option");r.value=n,r.textContent=s,i.appendChild(r)};e(this.shareScope,ed,this.messages.shareScopeCase);for(const i of this.entries){const n=this.observerDisplayName(this.plain(i).observer)??this.messages.unnamedObserver.replace("{n}",String(this.entries.indexOf(i)+1));e(this.shareScope,i.src,n),e(this.shareOpens,i.src,n)}this.shareScope.value=ed,this.shareOpens.value=this.currentSrc??this.entries[0].src}offerInterpretations(t){const e=this.offeredFor===t.sighting,i=this.interpretationSelect.value;this.offeredFor=t.sighting,this.interpretationToken++,this.interpretationLoaders=new Map,this.interpretationSelect.innerHTML="";const n=(u,d,f)=>{const p=document.createElement("option");p.value=u,p.textContent=d,this.interpretationSelect.appendChild(p),this.interpretationLoaders.set(u,f)},s=t===this.entries.find(u=>u.src===this.currentSrc),r=s?this.sceneElement.ufoElement.sighting.interpretation:void 0;n(id,this.messages.account,()=>Promise.resolve(r));const a=this.caseSource;a&&tn.interpretationEvents(a.json,tn.accountIds(a.json,a.url,t.src,this.plain(t).id)).forEach((u,d)=>{const f=this.said.read(u.title)??`#${d+1}`,p=(u.by??[]).map(g=>this.agentName(g)).filter(Boolean).join(", ");n(`case-${d}`,p?this.messages.interpretationBy.replace("{title}",f).replace("{by}",p):f,()=>tn.interpretationOf(u,a.url,g=>Na.recording(g)))});const c=s?this.keptVariants(t):[];for(const{index:u,kept:d}of c)n(`${nd}${u}`,`${this.variantLabel(d)} (${this.messages.verdicts[d.variant.verdict]})`,()=>Promise.resolve(d.bodies.length>0?d:void 0));const h=e&&[...this.interpretationSelect.options].some(u=>u.value===i)?i:id;this.interpretationSelect.value=h,h===id?this.sceneElement.interpretation!==r&&(this.sceneElement.interpretation=r):this.sceneElement.interpretation||this.chooseInterpretation(h),this.interpretationChoice.hidden=this.interpretationSelect.options.length<2,this.showConfrontation(this.sceneElement.confrontation),this.updateCompareButton(),this.showVariants(c)}keptVariants(t){const e={consolidated:0,contested:1,incompatible:2};return(t.sighting.variants??[]).map((i,n)=>({index:n,kept:i})).filter(({kept:i})=>i.variant).sort((i,n)=>e[i.kept.variant.verdict]-e[n.kept.variant.verdict]||i.kept.variant.cost-n.kept.variant.cost)}variantLabel(t){return this.messages.variant.replace("{name}",t.variant.label??t.variant.candidate)}showVariants(t){if(this.variantChips.innerHTML="",this.variantChips.hidden=t.length===0,t.length===0){this.showVariantMoved();return}const e=(i,n,s)=>{const r=document.createElement("button");r.type="button",r.dataset.value=i,s&&(r.dataset.verdict=s,r.title=this.messages.verdicts[s],r.append(Object.assign(document.createElement("span"),{className:"dot"}))),r.append(n),r.addEventListener("click",()=>{this.interpretationSelect.value!==i&&(this.interpretationSelect.value=i,this.chooseInterpretation(i))}),this.variantChips.append(r)};e(id,this.messages.account);for(const{index:i,kept:n}of t)e(`${nd}${i}`,n.variant.label??n.variant.candidate,n.variant.verdict);this.showVariantMoved()}showVariantMoved(){const t=this.interpretationSelect.value;for(const s of this.variantChips.querySelectorAll("button"))s.setAttribute("aria-pressed",String(s.dataset.value===t));this.variantMoved.innerHTML="";const e=t.startsWith(nd)?Number(t.slice(nd.length)):-1,i=this.sceneElement.ufoElement.sighting.variants?.[e]?.variant;if(this.variantMoved.hidden=!i||i.moved.length+(i.readings?.length??0)===0,!i)return;const n=new Intl.NumberFormat(this.language,{maximumFractionDigits:1});for(const s of i.moved){const[r,a]=s.field==="time"?["0 min",`${s.variant>0?"+":""}${n.format(s.variant)} min`]:s.field==="duration"?[`${n.format(s.stated)} s`,`${n.format(s.variant)} s`]:[`${n.format(s.stated)}°`,`${n.format(s.variant)}°`],c=document.createElement("span");c.append(`${this.messages.variantFields[s.field]}${this.colon}`,Object.assign(document.createElement("s"),{textContent:r})," → ",Object.assign(document.createElement("b"),{textContent:a})),this.variantMoved.append(c)}for(const s of i.readings??[]){const r=this.messages.variantReadings[s.reading];r&&this.variantMoved.append(Object.assign(document.createElement("span"),{className:"reading",textContent:r}))}}setComparing(t){this.sceneElement.compareAccount=t,this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation)}updateCompareButton(){const t=this.sceneElement.compareAccount;this.compareButton.hidden=!this.sceneElement.interpretation,this.compareButton.setAttribute("aria-pressed",String(t));const e=t?this.messages.hideComparison:this.messages.showComparison;this.compareButton.title=e,this.compareButton.setAttribute("aria-label",e)}static DATE_LOCALES={en:"en-US",fr:"fr-FR",es:"es-ES",it:"it-IT"};get colon(){return this.language==="fr"?" : ":": "}async chooseInterpretation(t){const e=++this.interpretationToken,i=this.interpretationLoaders.get(t),n=i?await i().catch(s=>{console.warn(`<rr0-sighting>: could not read interpretation "${t}":`,s)}):void 0;e===this.interpretationToken&&(this.sceneElement.interpretation=n,this.editLink.href=this.editorUrl(),this.dispatchEvent(new CustomEvent("interpretationchange",{detail:{track:this.shownTrackUrl()}})),this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation),this.showVariantMoved())}agentName(t){if("people"in t){const[e,...i]=t.people.replace(/([a-z])([A-Z])/g,"$1 $2").split(" ");return[...i,e].join(" ")}return"org"in t?t.org.replace(/([a-z])([A-Z])/g,"$1 $2"):this.observerDisplayName(t)??""}showConfrontation(t){this.confrontationList.innerHTML="",this.confrontationElement.hidden=!this.sceneElement.interpretation||!this.sceneElement.compareAccount;const e=new Intl.NumberFormat(this.language,{maximumFractionDigits:1,minimumFractionDigits:1}),i=new Intl.NumberFormat(this.language,{maximumFractionDigits:2,minimumFractionDigits:2});for(const n of t){const s=document.createElement("li");s.append(`${this.said.read(n.title)??n.sourceId}${this.colon}`);const r=[];n.separationDeg!==void 0&&r.push([this.messages.confrontationDirection.replace("{deg}",e.format(n.separationDeg)),n.disagreements.includes("direction")]),n.widthRatio!==void 0&&r.push([this.messages.confrontationWidth.replace("{ratio}",i.format(n.widthRatio)),n.disagreements.includes("width")]),n.heightRatio!==void 0&&r.push([this.messages.confrontationHeight.replace("{ratio}",i.format(n.heightRatio)),n.disagreements.includes("height")]),r.forEach(([a,c],l)=>{l>0&&s.append(" · ");const h=document.createElement("span");h.textContent=a,c&&(h.className="disagrees"),s.append(h)}),this.confrontationList.appendChild(s)}}startPending=!1;startSeconds(t){const e=mn.clock(this.getAttribute(oy));return(e?mn.elapsedSince(this.plain(t).time,e):void 0)??mn.delta(this.getAttribute(Ap))}selectObserver(t){const e=this.entries.find(n=>n.src===t);if(!e)return;this.currentSrc=t,this.observerSelect.value=t,this.sceneElement.documentUrl=e.src?new URL(e.src,location.href).href:void 0;const i=!this.sceneElement.ufoElement.playRequested;if(e.sighting.image?this.sceneElement.showPoster(e.sighting.image,e.src?new URL(e.src,location.href).href:void 0,i):this.sceneElement.showPoster(this.caseSource?.json.image,this.caseSource?.url,i),this.sceneElement.holdForNewScene(),this.sceneElement.sightingData=e.sighting,this.startPending){this.startPending=!1;const n=this.startSeconds(e);n!==void 0&&(this.sceneElement.ufoElement.currentTime=Math.max(0,n)*1e3)}this.offerInterpretations(e),this.updateAccountLine(),this.refreshParamSummary(),this.runAssessments(),this.infoOpen&&this.populateInfoPanel(),this.dispatchEvent(new CustomEvent(zO,{detail:{src:t}}))}async runAssessments(){const t=++this.assessmentToken,e=await new MS(this.messages).read(this.sceneElement.ufoElement.sighting);t===this.assessmentToken&&(this.assessmentEntries=e.entries,this.refreshParamSummary())}updateAccountLine(){const t=this.entries.find(n=>n.src===this.currentSrc),e=t?this.observerDisplayName(this.plain(t).observer):void 0,i=e!==void 0||this.entries.length>1;this.accountElement.hidden=!i,this.observerText.textContent=e??"",this.editLink.hidden=!this.currentSrc,this.editLink.href=this.editorUrl(),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation)}caseTitleOf(t){const e=this.caseSource;if(!e)return;const i=e.json.events?.find(n=>n.url!==void 0&&!n.interpretationOf&&new URL(n.url,e.url).href===new URL(t.src,location.href).href);return i?this.said.read(i.title):void 0}observerDisplayName(t){if(!t)return;const e=[...t.firstNames??[],t.lastName].filter(Boolean).join(" ");return this.said.read(t.title)||e||t.id}plainRecordings=new WeakMap;plain(t){return this.stripped(t).recording}stripped(t){let e=this.plainRecordings.get(t.sighting);return e||(e=Fn.strip(t.sighting),this.plainRecordings.set(t.sighting,e)),e}basisOf(t,e){const i=this.stripped(t).provenance,n={measured:-1,stated:0,derived:1,assumed:2},s=i.paths().filter(c=>e.some(l=>c===l||c.startsWith(`${l}.`))).map(c=>i.at(c)),r=s.reduce((c,l)=>n[l.basis]>n[c]?l.basis:c,"stated"),a=s.filter(c=>c.basis===r&&c.rationale).map(c=>c.rationale);return{basis:r,rationales:a}}formatDate(t){const e=t.place?.[0],i=ja(t.time??{},e?.lng??0,t.utcOffsetHours);if(!i)return;const n=i.getTime()+this.utcOffsetHoursOf(t,e?.lng??0)*36e5;if(Number.isFinite(n))return new Intl.DateTimeFormat(nl.DATE_LOCALES[this.language],{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(n))}utcOffsetHoursOf(t,e){return t.utcOffsetHours??Math.round(e/15)}formatLocation(t){const e=t.place?.[0];if(e)return`${e.lat.toFixed(4)}, ${e.lng.toFixed(4)}`}toggleInfoPanel(){const t=!this.infoOpen;if(this.supportsPopover){const e=this.infoPanel.matches(":popover-open");t&&!e?this.infoPanel.showPopover():!t&&e&&this.infoPanel.hidePopover();return}t&&this.bringInfoButtonIntoView(),this.syncInfoOpen(t),this.infoPanel.hidden=!t,t?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}bringInfoButtonIntoView(){const t=this.infoButton.getBoundingClientRect(),e=window.innerHeight||document.documentElement.clientHeight;t.top>=0&&t.bottom<=e||this.infoButton.scrollIntoView({block:"center"})}syncInfoOpen(t){t!==this.infoOpen&&(this.infoOpen=t,this.infoButton.setAttribute("aria-expanded",String(t)),t?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=t=>{const e=t.composedPath();!e.includes(this.infoPanel)&&!e.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}revealInPanel(t){t.scrollIntoView?.({block:"nearest"})}get showLabels(){return this.labelsShown}set showLabels(t){this.toggleAttribute("show-labels",t)}applyLabels(t){this.labelsShown=t,this.syncLabelsToggle(),this.refreshParamSummary(),this.populateInfoPanel()}syncLabelsToggle(){this.labelsToggle.textContent=this.labelsShown?this.messages.hideLabels:this.messages.showLabels,this.labelsToggle.setAttribute("aria-pressed",String(this.labelsShown))}refreshParamSummary(){if(this.paramSummary.hidden=!this.labelsShown,!this.labelsShown){this.paramSummary.replaceChildren(),this.summarySignature="";return}const t=this.sceneElement.ufoElement.sighting,e=[...this.summaryBuilder.entriesFor(t,this.sceneElement.ufoElement.currentTime,{roadGradeDeg:this.sceneElement.roadGradeDeg}),...this.assessmentEntries],i=e.map(r=>`${r.field}=${r.label}=${r.value}${r.unit}${r.full??""}${r.fromSource?"*":""}`).join("|");if(i===this.summarySignature)return;this.summarySignature=i;const n=[];let s;for(const r of e){s&&s.group!==r.group&&(s=void 0);const a=r.group==="summary"?this.messages.summaryGroup:r.group==="observer"?this.messages.observerGroup:r.group in this.messages.summaryGroups?this.messages.summaryGroups[r.group]:r.group==="assessment"?this.messages.assessmentGroup:void 0;if(a!==void 0&&!s){const l=document.createElement("span");l.className="param-nest";const h=document.createElement("span");h.className="param-nest-label",h.textContent=a,l.append(h),s={group:r.group,element:l},n.push(l)}const c=this.paramItem(r);s?s.element.append(c):n.push(c)}this.paramSummary.replaceChildren(...n),this.syncDescription(e)}openDescription;syncDescription(t){this.openDescription!==void 0&&!t.some(e=>e.full===this.openDescription)&&(this.openDescription=void 0),hy.sync(this.paramSummary,this.openDescription,this.messages.summaryDescription,this.messages.closeDescription,()=>{this.openDescription=void 0,this.syncDescription(t)})}paramItem(t){const e=document.createElement("span");if(e.className=t.fromSource?"param-label from-source":"param-label",t.full!==void 0){e.classList.add("describable"),e.tabIndex=0,e.setAttribute("role","button");const s=()=>{this.openDescription=t.full,this.syncDescription([t])};e.addEventListener("click",s),e.addEventListener("keydown",r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),s())})}const i=document.createElement("span");if(i.className="param-label-label",i.textContent=`${t.label} `,e.append(i),t.color!==void 0){const s=document.createElement("span");s.className="param-label-swatch",s.style.background=t.color,e.append(s)}const n=document.createElement("span");return n.className="param-label-value",n.textContent=t.unit===""?t.value:`${t.value} ${t.unit}`,e.append(n),e}populateInfoPanel(){const t=this.entries.find(e=>e.src===this.currentSrc);if(this.infoObservationList.innerHTML="",t){const e=this.caseSource&&(this.caseSource.json.title??this.caseSource.json.id);if(e&&this.appendInfoRow(this.infoObservationList,this.messages.case,e),!this.labelsShown){const s=this.formatDate(this.plain(t));s&&this.appendInfoRow(this.infoObservationList,this.messages.date,s,this.basisOf(t,nl.DATE_PATHS));const r=this.formatLocation(this.plain(t));r&&this.appendInfoRow(this.infoObservationList,this.messages.location,r,this.basisOf(t,nl.PLACE_PATHS))}const i=this.said.read(this.plain(t).description);i&&!this.labelsShown&&this.appendInfoRow(this.infoObservationList,this.messages.description,i);for(const s of this.plain(t).sources??[])this.appendInfoSource(this.infoObservationList,this.messages.source,s);const n=this.plain(t).tags;!this.labelsShown&&n&&n.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,n.map(s=>this.tags.name(s)).join(", "))}this.infoAppLink.href=Md,this.infoAppLink.textContent="UFO@home v0.144.0",dn.fill(this.infoCreditsList,this.sceneElement)}appendInfoSource(t,e,i){const n=document.createElement("dt");n.textContent=e;const s=document.createElement("dd"),r=i.title??i.url??"";if(i.url&&/^https?:\/\//i.test(i.url)){const c=document.createElement("a");c.href=i.url,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r,s.appendChild(c)}else s.append(r);const a=[i.authors?.join(", "),i.publication?.publisher,i.publication?.time,i.index].filter(Boolean);a.length>0&&s.append(`, ${a.join(", ")}`),t.append(n,s)}static DATE_PATHS=["time","utcOffsetHours","timeZone"];static PLACE_PATHS=["place.0"];appendInfoRow(t,e,i,n){const s=document.createElement("dt");s.textContent=e;const r=document.createElement("dd");if(r.textContent=i,n){const a=document.createElement("span");a.className=`basis basis-${n.basis}`,a.textContent=this.messages.basis[n.basis],n.rationales.length>0&&(a.title=n.rationales.join(`
9561
+ `;class il extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(il.TAG)||customElements.define(il.TAG,il)}subject;messages=sg;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=FO;const t=e=>this.shadow.getElementById(e);this.dialog=t("dialog"),this.linkField=t("link"),this.copyButton=t("copy"),this.linkBox=t("link-box"),this.embedBox=t("embed-box"),this.linkOption=t("link-option"),this.embedOption=t("embed-option"),this.freeze=t("freeze"),this.embedMarkup=t("embed-markup"),this.noteElement=t("note"),t("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",e=>{e.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(t){const e=++this.languageToken,i=t==="en"?sg:await XS(t);if(e===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(t){this.noteElement.textContent=t??"",this.noteElement.hidden=t===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 t=this.subject;if(!t)return;const e=this.freeze.checked;this.linkField.value=e?vr.frozenLink(t.link(),"0.145.0"):t.link(),this.fitLink();const n=`<script type="module" src="${e?vr.frozen(t.module,"0.145.0"):vr.current(t.module,import.meta.url,Uh.home())}"><\/script>
9562
+ ${t.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const t=this.messages,e=(i,n)=>{this.shadow.getElementById(i).textContent=n};e("title",t.share),e("link-label",t.link),e("embed-label",t.embed),e("copy",t.copy),e("freeze-label",t.freeze.replace("{version}","0.145.0")),this.freeze.parentElement.title=t.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",t.close),this.linkField.setAttribute("aria-label",t.link)}show(t){this.linkBox.hidden=t!=="link",this.embedBox.hidden=t!=="embed",this.linkOption.setAttribute("aria-pressed",String(t==="link")),this.embedOption.setAttribute("aria-pressed",String(t==="embed")),t==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=we(async()=>{const{ShareCodeEditor:t}=await import("./ShareCodeEditor-C53SBK2N.js");return{ShareCodeEditor:t}},[],import.meta.url).then(({ShareCodeEditor:t})=>{this.codeEditor=new t(this.shadow.getElementById("embed-code"),this.embedMarkup.value,e=>{this.embedMarkup.value=e},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(t,e){try{await navigator.clipboard.writeText(t),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{e.select()}}}class mn{static PLAIN=/^\d+(?:[.,]\d+)?$/;static COLONS=/^(?:(\d+):)?(\d{1,2}):(\d{1,2}(?:[.,]\d+)?)$/;static UNITS=/^(?:(\d+(?:[.,]\d+)?)h)?(?:(\d+(?:[.,]\d+)?)m)?(?:(\d+(?:[.,]\d+)?)s)?$/i;static CLOCK=/^(?:(\d{4})-(\d{2})-(\d{2})[T ])?T?(\d{1,2}):(\d{2})(?::(\d{2}(?:[.,]\d+)?))?$/;static num(t){return t===void 0?0:Number(t.replace(",","."))}static delta(t){const e=(t??"").trim();if(e==="")return;if(mn.PLAIN.test(e))return mn.num(e);const i=mn.COLONS.exec(e);if(i){const[,s,r,a]=i;return Number(r)>=60||mn.num(a)>=60?void 0:mn.num(s)*3600+Number(r)*60+mn.num(a)}const n=mn.UNITS.exec(e);return n&&(n[1]!==void 0||n[2]!==void 0||n[3]!==void 0)?mn.num(n[1])*3600+mn.num(n[2])*60+mn.num(n[3]):/^P/i.test(e)?Xc.seconds(e.toUpperCase()):void 0}static isClock(t){return mn.clock(t)!==void 0}static clock(t){const e=mn.CLOCK.exec((t??"").trim());if(!e)return;const[,i,n,s,r,a,c]=e,l={hour:Number(r),minute:Number(a),second:mn.num(c)};if(!(l.hour>=24||l.minute>=60||l.second>=60)){if(i!==void 0){const h={year:Number(i),month:Number(n),day:Number(s)};if(h.month<1||h.month>12||h.day<1||h.day>31)return;l.date=h}return l}}static elapsedSince(t,e){if(!t||t.hour===void 0||t.minute===void 0)return;const i=t.hour*3600+t.minute*60+(t.second??0),n=e.hour*3600+e.minute*60+e.second;if(e.date){if(t.year===void 0||t.month===void 0||t.day===void 0)return;const r=Date.UTC(e.date.year,e.date.month-1,e.date.day)/1e3+n,a=Date.UTC(t.year,t.month-1,t.day)/1e3+i;return Math.max(0,r-a)}let s=n-i;return s<=-43200&&(s+=86400),Math.max(0,s)}}Ob();il.register();const Md=Uh.home(),td="compare-account",Ap="start-time",oy="start-clock",Yl="observer",ed="case",id="account",nd="variant-",_p=`${Md}/edit/`;class nl extends HTMLElement{static get observedAttributes(){return["src","show-labels",Ap,oy,Yl,Ar,_r,td]}shadow;sceneElement;toolbarElement;accountElement;accountPrefix;observerText;observerSelect;infoButton;infoPanel;infoAppLink;editLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;shareButton;shareDialog;shareStartOn;shareStart;shareScopeRow;shareScopeLabel;shareScope;shareOpensRow;shareOpensLabel;shareOpens;shareStartLabel;shareOptions;labelsToggle;paramSummary;summaryBuilder=new wh(th,new xf,new Es(["en"]),new rd({}),{messages:th,locale:"en"});summarySignature="";assessmentEntries=[];assessmentToken=0;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];caseSource;interpretationChoice;interpretationLabel;interpretationSelect;confrontationElement;confrontationHeading;confrontationList;compareButton;variantChips;variantMoved;interpretationLoaders=new Map;interpretationToken=0;offeredFor;currentSrc;infoOpen=!1;creditsOpen=!1;labelsShown=!1;language="en";messages=th;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${Hb}</style>${Bb}`,this.shadow.appendChild(t.content.cloneNode(!0)),customElements.upgrade(this.shadow),this.sceneElement=document.createElement(wf),this.forwardPlayerAttributes(),this.sceneElement.ufoElement.creditShownExternally=!0,this.sceneElement.ownCredits=!1,this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.accountElement=this.shadow.getElementById("account"),this.accountPrefix=this.shadow.getElementById("account-prefix"),this.observerText=this.shadow.getElementById("observer-text"),this.observerSelect=this.shadow.getElementById("observer"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.editLink=this.shadow.getElementById("edit-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.labelsToggle=this.shadow.getElementById("info-labels-toggle"),this.paramSummary=this.shadow.getElementById("param-summary"),this.labelsToggle.addEventListener("click",()=>{this.showLabels=!this.showLabels}),this.shareButton=document.createElement("button"),this.shareButton.type="button",this.shareButton.id="share-button",this.shareButton.setAttribute("aria-haspopup","dialog"),this.shareButton.innerHTML=qt.SHARE,this.sceneElement.ufoElement.addControl(this.shareButton),this.shareDialog=this.shadow.getElementById("share-dialog"),this.shareDialog.subject=this.shareSubject,this.shareStartOn=this.shadow.getElementById("share-start-on"),this.shareStart=this.shadow.getElementById("share-start"),this.shareStartLabel=this.shadow.getElementById("share-start-label"),this.shareScopeRow=this.shadow.getElementById("share-scope-row"),this.shareScopeLabel=this.shadow.getElementById("share-scope-label"),this.shareScope=this.shadow.getElementById("share-scope"),this.shareOpensRow=this.shadow.getElementById("share-opens-row"),this.shareOpensLabel=this.shadow.getElementById("share-opens-label"),this.shareOpens=this.shadow.getElementById("share-opens");const e=i=>({input:this.shadow.getElementById(`share-opt-${i}`),label:this.shadow.getElementById(`share-opt-${i}-label`)});this.shareOptions={labels:e("labels"),map:e("map"),milestones:e("milestones"),compare:e("compare")},this.interpretationChoice=this.shadow.getElementById("interpretation-choice"),this.interpretationLabel=this.shadow.getElementById("interpretation-label"),this.interpretationSelect=this.shadow.getElementById("interpretation"),this.confrontationElement=this.shadow.getElementById("confrontation"),this.confrontationHeading=this.shadow.getElementById("confrontation-heading"),this.confrontationList=this.shadow.getElementById("confrontation-list"),this.compareButton=this.shadow.getElementById("compare-account"),this.variantChips=this.shadow.getElementById("variant-chips"),this.variantMoved=this.shadow.getElementById("variant-moved"),this.compareButton.addEventListener("click",()=>this.setComparing(!this.sceneElement.compareAccount)),this.observerSelect.addEventListener("change",()=>this.selectObserver(this.observerSelect.value)),this.interpretationSelect.addEventListener("change",()=>void this.chooseInterpretation(this.interpretationSelect.value)),this.sceneElement.addEventListener(Cb,i=>this.showConfrontation(i.detail)),this.sceneElement.ufoElement.addEventListener("timeupdate",()=>this.refreshParamSummary()),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",i=>{i.newState==="open"&&(this.populateInfoPanel(),this.bringInfoButtonIntoView())}),this.infoPanel.addEventListener("toggle",i=>this.syncInfoOpen(i.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.shareButton.addEventListener("click",()=>this.openShare());for(const i of[this.shareStartOn,this.shareStart,...Object.values(this.shareOptions).map(n=>n.input)])i.addEventListener("input",()=>this.refreshShareLinks());for(const i of[this.shareScope,this.shareOpens])i.addEventListener("change",()=>this.refreshShareLinks());this.isConnected&&this.loadLocaleMessages()}get scene(){return this.sceneElement}async loadLocaleMessages(){const t=++this.localeToken,e=ka.preferencesFor(this);this.preferences=e;const i=dg(e,fg),[n,s,r]=i==="en"?[th,{},void 0]:await Promise.all([VS(i),$S(i),Iy(i)]);if(t!==this.localeToken)return;const a=i!==this.language;this.language=i,this.messages=n,this.tags=new rd(s),this.said=new Es(e),this.summaryBuilder=new wh(this.messages,new xf(r),this.said,this.tags,{messages:this.messages,locale:i}),this.accountPrefix.textContent=this.messages.accountBy,this.interpretationLabel.textContent=this.messages.interpretation,this.confrontationHeading.textContent=this.messages.confrontation;const c=this.entries.find(l=>l.src===this.currentSrc);c&&this.offerInterpretations(c),this.updateCompareButton(),this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.syncLabelsToggle(),this.refreshParamSummary(),a&&this.currentSrc&&this.runAssessments(),this.shareButton.title=this.messages.share,this.shareButton.setAttribute("aria-label",this.messages.share),this.shareStartLabel.textContent=this.messages.shareStartAt,this.shareScopeLabel.textContent=this.messages.shareScope,this.shareOpensLabel.textContent=this.messages.shareOpensOn,this.shareOptions.labels.label.textContent=this.messages.shareOptionLabels,this.shareOptions.map.label.textContent=this.messages.shareOptionMap,this.shareOptions.milestones.label.textContent=this.messages.shareOptionMilestones,this.shareOptions.compare.label.textContent=this.messages.shareOptionCompare,this.shareStart.setAttribute("aria-label",this.messages.shareStartAt),this.shareDialog.useLanguage(i),this.infoOpen&&this.populateInfoPanel(),this.updateAccountLine()}preferences=[];localeToken=0;said=new Es(["en"]);tags=new rd({});connectedCallback(){ka.preferencesFor(this).join()!==this.preferences.join()&&this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t==="show-labels"&&this.applyLabels(this.hasAttribute("show-labels")),(t===Ar||t===_r)&&this.forwardPlayerAttributes(),t===Yl&&this.entries.length>1){const n=this.entryAsked(this.entries);n&&n.src!==this.currentSrc&&this.selectObserver(n.src)}t===td&&this.setComparing(this.hasAttribute(td))}forwardPlayerAttributes(){for(const t of[Ar,_r]){const e=this.getAttribute(t);e===null?this.sceneElement.removeAttribute(t):this.sceneElement.setAttribute(t,e)}}async loadFromSrc(t){this.startPending=!0;const e=Na.recording(t);this.sceneElement.holdForNewScene(e);const i=await e;if(Array.isArray(i))throw new Error(`${t} is a bare list of recordings, which is no longer read: list them as the sighting events of a case.json`);if(tn.isCase(i)){tn.check(i);const n=tn.sightingUrls(i,new URL(t,location.href).href);if(n.length===0)throw new Error(`${t} is a case with no sighting event: no recording to show`);await this.loadObserverUrls(n,{json:i,url:new URL(t,location.href).href})}else this.setEntries([{src:t,sighting:i}],void 0)}get sightingData(){return this.entries.find(t=>t.src===this.currentSrc)?.sighting}set sightingData(t){this.startPending=!0,this.currentSrc="",this.setEntries([{src:"",sighting:t}],void 0)}seekTo(t,e){const i=this.caseSource,n=e===void 0?void 0:this.entries.find(s=>{const r=this.plain(s).id;return(i?tn.accountIds(i.json,i.url,s.src,r):[r]).includes(e)});n&&n.src!==this.currentSrc&&this.selectObserver(n.src),this.sceneElement.ufoElement.currentTime=Math.max(0,t)*1e3}get observerUrls(){return this.entries.map(t=>t.src)}set observerUrls(t){this.loadObserverUrls(t)}async loadObserverUrls(t,e){const i=await Promise.all(t.map(async n=>({src:n,sighting:await Na.recording(n)})));this.setEntries(i,e)}reportCaseProblems(t,e){const{duplicateIds:i,unresolved:n}=tn.problems(t,e.map(s=>this.plain(s).id).filter(s=>s!==void 0));for(const s of i)console.warn(`The case ${t.id??""} gives the id "${s}" to more than one event: a reference to it is ambiguous.`);for(const{reading:s,reference:r}of n)console.warn(`The reading ${s} of the case ${t.id??""} is "interpretationOf" "${r}", which no event of the case has as its id, nor any recording it lists.`)}setEntries(t,e){this.entries=t,this.caseSource=e,e&&this.reportCaseProblems(e.json,t),this.toolbarElement.hidden=t.length===0;const i=t.length>1;this.observerSelect.hidden=!i,this.observerText.hidden=i,this.observerSelect.innerHTML="";const n=t.map((r,a)=>this.observerDisplayName(this.plain(r).observer)??this.messages.unnamedObserver.replace("{n}",String(a+1)));for(const[r,a]of t.entries()){const c=document.createElement("option");c.value=a.src;const l=n.filter(h=>h===n[r]).length>1;c.textContent=(l?this.caseTitleOf(a):void 0)??n[r],this.observerSelect.appendChild(c)}const s=t.find(r=>r.src===this.currentSrc)??this.entryAsked(t)??t[0];s?this.selectObserver(s.src):this.updateAccountLine()}entryAsked(t){const e=this.getAttribute(Yl)?.trim();if(!e)return;const i=t.find(s=>this.plain(s).observer?.id===e);if(i)return i;const n=t.find(s=>s.src.split("/").pop()===e.split("/").pop());return n||(/^\d+$/.test(e)?t[Number(e)-1]:void 0)}observerKeyOf(t){return this.plain(t).observer?.id??String(this.entries.indexOf(t)+1)}sharedEntry(){const t=this.shareScope.value;if(!(!this.caseSource||t===ed))return this.entries.find(e=>e.src===t)}get sharesCase(){return this.caseSource!==void 0&&!this.shareScopeRow.hidden&&this.shareScope.value===ed}editorUrl(){if(!this.currentSrc)return _p;const t=new URL(this.currentSrc,location.href),e=this.caseSource;return e?`${_p}?file=${encodeURIComponent(e.url)}&track=${encodeURIComponent(this.shownTrackUrl()??t.href)}`:`${_p}?file=${encodeURIComponent(t.href)}`}get editorHref(){return this.editorUrl()}shownTrackUrl(){const t=this.caseSource,e=this.entries.find(s=>s.src===this.currentSrc),i=/^case-(\d+)$/.exec(this.interpretationSelect.value);if(!t||!e||!i)return;const n=tn.interpretationEvents(t.json,tn.accountIds(t.json,t.url,e.src,this.plain(e).id))[Number(i[1])];return n?.url?new URL(n.url,t.url).href:void 0}shareSubject={module:"rr0-sighting",link:()=>this.playUrl(),element:()=>this.replayElement()};replayElement(){const t=this.sharedAddress(),i=[...t.observer?[[Yl,t.observer]]:[],...this.replayAttributes()].map(([n,s])=>s===""?` ${n}`:` ${n}="${s}"`).join("");return`<rr0-sighting src="${t.src}"${i}></rr0-sighting>`}playUrl(){const t=this.sharedAddress(),e=[...t.observer?[`${Yl}=${encodeURIComponent(t.observer)}`]:[],...this.replayQuery()].join("&");return t.src?`${Md}/play/?file=${encodeURIComponent(t.src)}${e&&"&"+e}`:`${Md}/play/${e&&"?"+e}`}sharedAddress(){const t=e=>e?new URL(e,location.href).href:"";if(this.sharesCase){const e=this.entries.find(i=>i.src===this.shareOpens.value)??this.entries.find(i=>i.src===this.currentSrc);return{src:this.caseSource.url,observer:e?this.observerKeyOf(e):void 0}}return{src:t(this.sharedEntry()?.src??this.currentSrc??"")}}replayAttributes(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push([Ap,String(this.shareStartSeconds)]),t.labels.input.checked&&e.push(["show-labels",""]),t.map.input.checked&&e.push([Ar,""]),t.milestones.input.checked||e.push([_r,""]),t.compare.input.checked&&e.push([td,""]),e}replayQuery(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push(`d=${this.shareStartSeconds}`),t.labels.input.checked||e.push("labels=0"),t.map.input.checked&&e.push("map=1"),t.milestones.input.checked||e.push("moments=0"),t.compare.input.checked&&e.push("compare=1"),e}get shareStartSeconds(){const t=Math.floor(Number(this.shareStart.value));return this.shareStartOn.checked&&Number.isFinite(t)&&t>=0?t:void 0}refreshShareLinks(){this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.refresh()}openShare(){const t=this.sceneElement.ufoElement;this.shareStart.max=String(Math.floor(t.seekableDuration/1e3)),this.shareStart.value=String(Math.floor(t.currentTime/1e3)),this.shareStartOn.checked=!1,this.shareOptions.labels.input.checked=this.labelsShown,this.shareOptions.map.input.checked=t.observerMapOpen,this.shareOptions.milestones.input.checked=t.milestonesVisible,this.shareOptions.compare.input.checked=this.sceneElement.compareAccount,this.offerShareScope(),this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.open()}offerShareScope(){const t=this.caseSource!==void 0&&this.entries.length>1;if(this.shareScopeRow.hidden=!t,this.shareScope.innerHTML="",this.shareOpens.innerHTML="",!t)return;const e=(i,n,s)=>{const r=document.createElement("option");r.value=n,r.textContent=s,i.appendChild(r)};e(this.shareScope,ed,this.messages.shareScopeCase);for(const i of this.entries){const n=this.observerDisplayName(this.plain(i).observer)??this.messages.unnamedObserver.replace("{n}",String(this.entries.indexOf(i)+1));e(this.shareScope,i.src,n),e(this.shareOpens,i.src,n)}this.shareScope.value=ed,this.shareOpens.value=this.currentSrc??this.entries[0].src}offerInterpretations(t){const e=this.offeredFor===t.sighting,i=this.interpretationSelect.value;this.offeredFor=t.sighting,this.interpretationToken++,this.interpretationLoaders=new Map,this.interpretationSelect.innerHTML="";const n=(u,d,f)=>{const p=document.createElement("option");p.value=u,p.textContent=d,this.interpretationSelect.appendChild(p),this.interpretationLoaders.set(u,f)},s=t===this.entries.find(u=>u.src===this.currentSrc),r=s?this.sceneElement.ufoElement.sighting.interpretation:void 0;n(id,this.messages.account,()=>Promise.resolve(r));const a=this.caseSource;a&&tn.interpretationEvents(a.json,tn.accountIds(a.json,a.url,t.src,this.plain(t).id)).forEach((u,d)=>{const f=this.said.read(u.title)??`#${d+1}`,p=(u.by??[]).map(g=>this.agentName(g)).filter(Boolean).join(", ");n(`case-${d}`,p?this.messages.interpretationBy.replace("{title}",f).replace("{by}",p):f,()=>tn.interpretationOf(u,a.url,g=>Na.recording(g)))});const c=s?this.keptVariants(t):[];for(const{index:u,kept:d}of c)n(`${nd}${u}`,`${this.variantLabel(d)} (${this.messages.verdicts[d.variant.verdict]})`,()=>Promise.resolve(d.bodies.length>0?d:void 0));const h=e&&[...this.interpretationSelect.options].some(u=>u.value===i)?i:id;this.interpretationSelect.value=h,h===id?this.sceneElement.interpretation!==r&&(this.sceneElement.interpretation=r):this.sceneElement.interpretation||this.chooseInterpretation(h),this.interpretationChoice.hidden=this.interpretationSelect.options.length<2,this.showConfrontation(this.sceneElement.confrontation),this.updateCompareButton(),this.showVariants(c)}keptVariants(t){const e={consolidated:0,contested:1,incompatible:2};return(t.sighting.variants??[]).map((i,n)=>({index:n,kept:i})).filter(({kept:i})=>i.variant).sort((i,n)=>e[i.kept.variant.verdict]-e[n.kept.variant.verdict]||i.kept.variant.cost-n.kept.variant.cost)}variantLabel(t){return this.messages.variant.replace("{name}",t.variant.label??t.variant.candidate)}showVariants(t){if(this.variantChips.innerHTML="",this.variantChips.hidden=t.length===0,t.length===0){this.showVariantMoved();return}const e=(i,n,s)=>{const r=document.createElement("button");r.type="button",r.dataset.value=i,s&&(r.dataset.verdict=s,r.title=this.messages.verdicts[s],r.append(Object.assign(document.createElement("span"),{className:"dot"}))),r.append(n),r.addEventListener("click",()=>{this.interpretationSelect.value!==i&&(this.interpretationSelect.value=i,this.chooseInterpretation(i))}),this.variantChips.append(r)};e(id,this.messages.account);for(const{index:i,kept:n}of t)e(`${nd}${i}`,n.variant.label??n.variant.candidate,n.variant.verdict);this.showVariantMoved()}showVariantMoved(){const t=this.interpretationSelect.value;for(const s of this.variantChips.querySelectorAll("button"))s.setAttribute("aria-pressed",String(s.dataset.value===t));this.variantMoved.innerHTML="";const e=t.startsWith(nd)?Number(t.slice(nd.length)):-1,i=this.sceneElement.ufoElement.sighting.variants?.[e]?.variant;if(this.variantMoved.hidden=!i||i.moved.length+(i.readings?.length??0)===0,!i)return;const n=new Intl.NumberFormat(this.language,{maximumFractionDigits:1});for(const s of i.moved){const[r,a]=s.field==="time"?["0 min",`${s.variant>0?"+":""}${n.format(s.variant)} min`]:s.field==="duration"?[`${n.format(s.stated)} s`,`${n.format(s.variant)} s`]:[`${n.format(s.stated)}°`,`${n.format(s.variant)}°`],c=document.createElement("span");c.append(`${this.messages.variantFields[s.field]}${this.colon}`,Object.assign(document.createElement("s"),{textContent:r})," → ",Object.assign(document.createElement("b"),{textContent:a})),this.variantMoved.append(c)}for(const s of i.readings??[]){const r=this.messages.variantReadings[s.reading];r&&this.variantMoved.append(Object.assign(document.createElement("span"),{className:"reading",textContent:r}))}}setComparing(t){this.sceneElement.compareAccount=t,this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation)}updateCompareButton(){const t=this.sceneElement.compareAccount;this.compareButton.hidden=!this.sceneElement.interpretation,this.compareButton.setAttribute("aria-pressed",String(t));const e=t?this.messages.hideComparison:this.messages.showComparison;this.compareButton.title=e,this.compareButton.setAttribute("aria-label",e)}static DATE_LOCALES={en:"en-US",fr:"fr-FR",es:"es-ES",it:"it-IT"};get colon(){return this.language==="fr"?" : ":": "}async chooseInterpretation(t){const e=++this.interpretationToken,i=this.interpretationLoaders.get(t),n=i?await i().catch(s=>{console.warn(`<rr0-sighting>: could not read interpretation "${t}":`,s)}):void 0;e===this.interpretationToken&&(this.sceneElement.interpretation=n,this.editLink.href=this.editorUrl(),this.dispatchEvent(new CustomEvent("interpretationchange",{detail:{track:this.shownTrackUrl()}})),this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation),this.showVariantMoved())}agentName(t){if("people"in t){const[e,...i]=t.people.replace(/([a-z])([A-Z])/g,"$1 $2").split(" ");return[...i,e].join(" ")}return"org"in t?t.org.replace(/([a-z])([A-Z])/g,"$1 $2"):this.observerDisplayName(t)??""}showConfrontation(t){this.confrontationList.innerHTML="",this.confrontationElement.hidden=!this.sceneElement.interpretation||!this.sceneElement.compareAccount;const e=new Intl.NumberFormat(this.language,{maximumFractionDigits:1,minimumFractionDigits:1}),i=new Intl.NumberFormat(this.language,{maximumFractionDigits:2,minimumFractionDigits:2});for(const n of t){const s=document.createElement("li");s.append(`${this.said.read(n.title)??n.sourceId}${this.colon}`);const r=[];n.separationDeg!==void 0&&r.push([this.messages.confrontationDirection.replace("{deg}",e.format(n.separationDeg)),n.disagreements.includes("direction")]),n.widthRatio!==void 0&&r.push([this.messages.confrontationWidth.replace("{ratio}",i.format(n.widthRatio)),n.disagreements.includes("width")]),n.heightRatio!==void 0&&r.push([this.messages.confrontationHeight.replace("{ratio}",i.format(n.heightRatio)),n.disagreements.includes("height")]),r.forEach(([a,c],l)=>{l>0&&s.append(" · ");const h=document.createElement("span");h.textContent=a,c&&(h.className="disagrees"),s.append(h)}),this.confrontationList.appendChild(s)}}startPending=!1;startSeconds(t){const e=mn.clock(this.getAttribute(oy));return(e?mn.elapsedSince(this.plain(t).time,e):void 0)??mn.delta(this.getAttribute(Ap))}selectObserver(t){const e=this.entries.find(n=>n.src===t);if(!e)return;this.currentSrc=t,this.observerSelect.value=t,this.sceneElement.documentUrl=e.src?new URL(e.src,location.href).href:void 0;const i=!this.sceneElement.ufoElement.playRequested;if(e.sighting.image?this.sceneElement.showPoster(e.sighting.image,e.src?new URL(e.src,location.href).href:void 0,i):this.sceneElement.showPoster(this.caseSource?.json.image,this.caseSource?.url,i),this.sceneElement.holdForNewScene(),this.sceneElement.sightingData=e.sighting,this.startPending){this.startPending=!1;const n=this.startSeconds(e);n!==void 0&&(this.sceneElement.ufoElement.currentTime=Math.max(0,n)*1e3)}this.offerInterpretations(e),this.updateAccountLine(),this.refreshParamSummary(),this.runAssessments(),this.infoOpen&&this.populateInfoPanel(),this.dispatchEvent(new CustomEvent(zO,{detail:{src:t}}))}async runAssessments(){const t=++this.assessmentToken,e=await new MS(this.messages).read(this.sceneElement.ufoElement.sighting);t===this.assessmentToken&&(this.assessmentEntries=e.entries,this.refreshParamSummary())}updateAccountLine(){const t=this.entries.find(n=>n.src===this.currentSrc),e=t?this.observerDisplayName(this.plain(t).observer):void 0,i=e!==void 0||this.entries.length>1;this.accountElement.hidden=!i,this.observerText.textContent=e??"",this.editLink.hidden=!this.currentSrc,this.editLink.href=this.editorUrl(),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation)}caseTitleOf(t){const e=this.caseSource;if(!e)return;const i=e.json.events?.find(n=>n.url!==void 0&&!n.interpretationOf&&new URL(n.url,e.url).href===new URL(t.src,location.href).href);return i?this.said.read(i.title):void 0}observerDisplayName(t){if(!t)return;const e=[...t.firstNames??[],t.lastName].filter(Boolean).join(" ");return this.said.read(t.title)||e||t.id}plainRecordings=new WeakMap;plain(t){return this.stripped(t).recording}stripped(t){let e=this.plainRecordings.get(t.sighting);return e||(e=Fn.strip(t.sighting),this.plainRecordings.set(t.sighting,e)),e}basisOf(t,e){const i=this.stripped(t).provenance,n={measured:-1,stated:0,derived:1,assumed:2},s=i.paths().filter(c=>e.some(l=>c===l||c.startsWith(`${l}.`))).map(c=>i.at(c)),r=s.reduce((c,l)=>n[l.basis]>n[c]?l.basis:c,"stated"),a=s.filter(c=>c.basis===r&&c.rationale).map(c=>c.rationale);return{basis:r,rationales:a}}formatDate(t){const e=t.place?.[0],i=ja(t.time??{},e?.lng??0,t.utcOffsetHours);if(!i)return;const n=i.getTime()+this.utcOffsetHoursOf(t,e?.lng??0)*36e5;if(Number.isFinite(n))return new Intl.DateTimeFormat(nl.DATE_LOCALES[this.language],{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(n))}utcOffsetHoursOf(t,e){return t.utcOffsetHours??Math.round(e/15)}formatLocation(t){const e=t.place?.[0];if(e)return`${e.lat.toFixed(4)}, ${e.lng.toFixed(4)}`}toggleInfoPanel(){const t=!this.infoOpen;if(this.supportsPopover){const e=this.infoPanel.matches(":popover-open");t&&!e?this.infoPanel.showPopover():!t&&e&&this.infoPanel.hidePopover();return}t&&this.bringInfoButtonIntoView(),this.syncInfoOpen(t),this.infoPanel.hidden=!t,t?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}bringInfoButtonIntoView(){const t=this.infoButton.getBoundingClientRect(),e=window.innerHeight||document.documentElement.clientHeight;t.top>=0&&t.bottom<=e||this.infoButton.scrollIntoView({block:"center"})}syncInfoOpen(t){t!==this.infoOpen&&(this.infoOpen=t,this.infoButton.setAttribute("aria-expanded",String(t)),t?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=t=>{const e=t.composedPath();!e.includes(this.infoPanel)&&!e.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}revealInPanel(t){t.scrollIntoView?.({block:"nearest"})}get showLabels(){return this.labelsShown}set showLabels(t){this.toggleAttribute("show-labels",t)}applyLabels(t){this.labelsShown=t,this.syncLabelsToggle(),this.refreshParamSummary(),this.populateInfoPanel()}syncLabelsToggle(){this.labelsToggle.textContent=this.labelsShown?this.messages.hideLabels:this.messages.showLabels,this.labelsToggle.setAttribute("aria-pressed",String(this.labelsShown))}refreshParamSummary(){if(this.paramSummary.hidden=!this.labelsShown,!this.labelsShown){this.paramSummary.replaceChildren(),this.summarySignature="";return}const t=this.sceneElement.ufoElement.sighting,e=[...this.summaryBuilder.entriesFor(t,this.sceneElement.ufoElement.currentTime,{roadGradeDeg:this.sceneElement.roadGradeDeg}),...this.assessmentEntries],i=e.map(r=>`${r.field}=${r.label}=${r.value}${r.unit}${r.full??""}${r.fromSource?"*":""}`).join("|");if(i===this.summarySignature)return;this.summarySignature=i;const n=[];let s;for(const r of e){s&&s.group!==r.group&&(s=void 0);const a=r.group==="summary"?this.messages.summaryGroup:r.group==="observer"?this.messages.observerGroup:r.group in this.messages.summaryGroups?this.messages.summaryGroups[r.group]:r.group==="assessment"?this.messages.assessmentGroup:void 0;if(a!==void 0&&!s){const l=document.createElement("span");l.className="param-nest";const h=document.createElement("span");h.className="param-nest-label",h.textContent=a,l.append(h),s={group:r.group,element:l},n.push(l)}const c=this.paramItem(r);s?s.element.append(c):n.push(c)}this.paramSummary.replaceChildren(...n),this.syncDescription(e)}openDescription;syncDescription(t){this.openDescription!==void 0&&!t.some(e=>e.full===this.openDescription)&&(this.openDescription=void 0),hy.sync(this.paramSummary,this.openDescription,this.messages.summaryDescription,this.messages.closeDescription,()=>{this.openDescription=void 0,this.syncDescription(t)})}paramItem(t){const e=document.createElement("span");if(e.className=t.fromSource?"param-label from-source":"param-label",t.full!==void 0){e.classList.add("describable"),e.tabIndex=0,e.setAttribute("role","button");const s=()=>{this.openDescription=t.full,this.syncDescription([t])};e.addEventListener("click",s),e.addEventListener("keydown",r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),s())})}const i=document.createElement("span");if(i.className="param-label-label",i.textContent=`${t.label} `,e.append(i),t.color!==void 0){const s=document.createElement("span");s.className="param-label-swatch",s.style.background=t.color,e.append(s)}const n=document.createElement("span");return n.className="param-label-value",n.textContent=t.unit===""?t.value:`${t.value} ${t.unit}`,e.append(n),e}populateInfoPanel(){const t=this.entries.find(e=>e.src===this.currentSrc);if(this.infoObservationList.innerHTML="",t){const e=this.caseSource&&(this.caseSource.json.title??this.caseSource.json.id);if(e&&this.appendInfoRow(this.infoObservationList,this.messages.case,e),!this.labelsShown){const s=this.formatDate(this.plain(t));s&&this.appendInfoRow(this.infoObservationList,this.messages.date,s,this.basisOf(t,nl.DATE_PATHS));const r=this.formatLocation(this.plain(t));r&&this.appendInfoRow(this.infoObservationList,this.messages.location,r,this.basisOf(t,nl.PLACE_PATHS))}const i=this.said.read(this.plain(t).description);i&&!this.labelsShown&&this.appendInfoRow(this.infoObservationList,this.messages.description,i);for(const s of this.plain(t).sources??[])this.appendInfoSource(this.infoObservationList,this.messages.source,s);const n=this.plain(t).tags;!this.labelsShown&&n&&n.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,n.map(s=>this.tags.name(s)).join(", "))}this.infoAppLink.href=Md,this.infoAppLink.textContent="UFO@home v0.145.0",dn.fill(this.infoCreditsList,this.sceneElement)}appendInfoSource(t,e,i){const n=document.createElement("dt");n.textContent=e;const s=document.createElement("dd"),r=i.title??i.url??"";if(i.url&&/^https?:\/\//i.test(i.url)){const c=document.createElement("a");c.href=i.url,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r,s.appendChild(c)}else s.append(r);const a=[i.authors?.join(", "),i.publication?.publisher,i.publication?.time,i.index].filter(Boolean);a.length>0&&s.append(`, ${a.join(", ")}`),t.append(n,s)}static DATE_PATHS=["time","utcOffsetHours","timeZone"];static PLACE_PATHS=["place.0"];appendInfoRow(t,e,i,n){const s=document.createElement("dt");s.textContent=e;const r=document.createElement("dd");if(r.textContent=i,n){const a=document.createElement("span");a.className=`basis basis-${n.basis}`,a.textContent=this.messages.basis[n.basis],n.rationales.length>0&&(a.title=n.rationales.join(`
9563
9563
  `)),r.append(" ",a)}t.appendChild(s),t.appendChild(r)}}const cy="rr0-sighting",zO="observerchange",ly="rr0-eyeobserver";class BO extends nl{}function HO(){Ob(),il.register(),customElements.get(cy)||customElements.define(cy,nl),customElements.get(ly)||customElements.define(ly,BO)}HO();export{Mn as $,Io as A,ne as B,st as C,Ic as D,Jn as E,le as F,Oe as G,dd as H,e8 as I,ia as J,Cl as K,Cp as L,RA as M,es as N,Bn as O,xm as P,Xt as Q,Ae as R,Mh as S,gn as T,AA as U,Ps as V,ZO as W,en as X,nn as Y,QO as Z,Uo as _,kn as a,vn as a0,ye as a1,xi as a2,Gi as a3,Gn as a4,bi as a5,MO as a6,o1 as a7,GO as a8,WO as a9,px as aA,KO as aB,jn as aC,Is as aD,fx as aE,rM as aF,F3 as aG,jC as aH,Yd as aI,Mm as aJ,Ix as aK,kg as aL,Ug as aM,De as aN,za as aO,Bh as aP,VO as aa,Hh as ab,t8 as ac,JO as ad,Zd as ae,Cx as af,uM as ag,YO as ah,ts as ai,zv as aj,jO as ak,i8 as al,ux as am,Xs as an,jh as ao,n0 as ap,FE as aq,ei as ar,Ho as as,Hp as at,Oi as au,Pr as av,W3 as aw,Ke as ax,$O as ay,qO as az,bt as b,Fu as c,it as d,ch as e,Ia as f,ae as g,ce as h,Rs as i,n8 as j,tf as k,fs as l,hn as m,ea as n,R as o,US as p,Se as q,Er as r,ja as s,lr as t,Mt as u,_e as v,s8 as w,he as x,XO as y,eE as z};