@rr0/ufoathome 0.69.0 → 0.69.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -726,7 +726,7 @@ input[type=range] {
726
726
  pointer-events: none;
727
727
  white-space: nowrap;
728
728
  }
729
- `,Xo=[{id:"eye",name:{en:"Naked eye",fr:"Œil nu"},flare:0,projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",name:{en:"Camera, unknown device",fr:"Appareil, modèle inconnu"},projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"instamatic-126",name:{en:"Instamatic, 126 film",fr:"Instamatic, film 126"},projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20},{id:"slr-35mm-50",name:{en:"35 mm SLR, 50 mm lens",fr:"Reflex 35 mm, objectif 50 mm"},projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20},{id:"slr-35mm-zoom",name:{en:"35 mm SLR, 70-210 mm zoom",fr:"Reflex 35 mm, zoom 70-210 mm"},projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20},{id:"phone-landscape",name:{en:"Phone, held sideways",fr:"Téléphone, tenu couché"},projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4},{id:"phone-portrait",name:{en:"Phone, held upright",fr:"Téléphone, tenu debout"},projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4}];class li{static get default(){return Xo[0]}static byId(t){return Xo.find(e=>e.id===t)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(t){const e=t.frame;return e?2*Math.atan(e.heightMm/(2*e.focalLengthMm))*180/Math.PI:li.UNAIDED_FIELD_DEG}static aspectOf(t){const e=t.frame;return e?e.widthMm/e.heightMm:li.UNAIDED_ASPECT}static frameWidthPx(t,e){return Math.round(e*li.aspectOf(t))}static availableAt(t){return t===void 0?Xo:Xo.filter(e=>!e.years||t>=e.years.from&&(e.years.to===void 0||t<=e.years.to))}static fieldOfViewDegAt(t,e){const i=t.frame;if(!(!i||e<=0))return 2*Math.atan(i.heightMm/(2*e))*180/Math.PI}static focalLengthMmFor(t,e){const i=t.frame;if(!(!i||e<=0||e>=180))return i.heightMm/(2*Math.tan(e*Math.PI/360))}static bladesShowing(t,e){const i=e??t.fNumber;if(i===void 0||t.apertureBlades===void 0)return 0;const n=t.fNumberRange;return!n||n.max<=n.min?1:Math.max(0,Math.min(1,(i-n.min)/(n.max-n.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(t){return t.flare??li.LENS_FLARE_ARTIFACTS}static starPointsOf(t){const e=t.apertureBlades;return e===void 0||e<3?0:e%2===0?e:e*2}}class fa{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 fa(e)}static TRAVEL_M=50;get travels(){return this.spanM>fa.TRAVEL_M}get moved(){return this.spanM>fa.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(ci(e,t.east,e,t.west).x),Math.abs(ci(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:gs(0,-s,i,n).lat,south:gs(0,s,i,n).lat,east:gs(s,0,i,n).lng,west:gs(-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 bn{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 HZ=[.11,.23,.17,.29,.37,.07];static of(t){const e=t.sway??(t.event.tags?.includes("paralysis")?0:1);if(e>0)return new bn(Math.max(1-(t.instrument.stabilization??0),bn.GAZE_DRIFT_SHARE),e)}offsetAt(t){const e=t/1e3,i=this.scale,n=(u,d)=>Math.sin(2*Math.PI*u*e+d),[s,r,o,c,l,h]=bn.HZ;return{eastM:i*bn.SWAY_M*(.7*n(s,.3)+.3*n(c,1.9)),northM:i*bn.SWAY_M*(.6*n(o,2.2)+.4*n(l,.8)),upM:i*bn.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*bn.DRIFT_YAW_DEG*(.6*n(h,1.1)+.4*n(c,2.7)),pitchDeg:i*this.rotationPassed*bn.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(o,.4)),rollDeg:i*this.rotationPassed*bn.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=fa.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],o=e.points[s],c=(o.t-r.t)/1e3;if(c<=0)continue;const l=ci(o.lat,o.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:o.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],o=i[s+1];i[s].rampsIn=r===void 0||r.stepHz===0,i[s].rampsOut=o===void 0||o.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,bn.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=(o,c,l,h)=>{if(o<0||o>xe.JOLT_LASTS_MS)return;const u=o/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),o=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*o*Math.cos(n/2),pitchDeg:-1.25*o*Math.cos(n),yawDeg:xe.HEAD_YAW_DEG*o*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,o=Math.min(t.rampsIn?s/n:1,t.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(o,0)))/2}}class Pe{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(t){return 2*Math.atan(t.sizeM/(2*t.distanceM))*180/Math.PI}static inMoons(t){return t/Pe.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(t,e,i){if(!(!t||!e))return{widthDeg:t.widthDeg+(e.widthDeg-t.widthDeg)*i,heightDeg:t.heightDeg+(e.heightDeg-t.heightDeg)*i}}static sizeMAt(t,e){return 2*t*Math.tan(e*Math.PI/360)}static distanceMAt(t,e){return t/(2*Math.tan(e*Math.PI/360))}}function $1(a,t,e){if(!a||!t)return e<1?a:t;const i=((t.azimuthDeg-a.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((a.azimuthDeg+i*e)%360+360)%360,altitudeDeg:a.altitudeDeg+(t.altitudeDeg-a.altitudeDeg)*e}}function Z1(a,t,e){const{bounds:i}=a;return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}function qi(a,t,e){return a+(t-a)*e}function X0(a){const t=/^#([0-9a-f]{6})$/i.exec(a);if(!t)return;const e=parseInt(t[1],16);return[e>>16&255,e>>8&255,e&255]}function J1(a){return`#${a.map(t=>Math.round(t).toString(16).padStart(2,"0")).join("")}`}function j1(a,t,e){const i=X0(a),n=X0(t);return!i||!n?e<1?a:t:J1([qi(i[0],n[0],e),qi(i[1],n[1],e),qi(i[2],n[2],e)])}function Q1(a,t,e){const i={x:qi(a.bounds.x,t.bounds.x,e),y:qi(a.bounds.y,t.bounds.y,e),width:qi(a.bounds.width,t.bounds.width,e),height:qi(a.bounds.height,t.bounds.height,e)},n=qi(a.angle,t.angle,e),s=qi(a.transparency,t.transparency,e),r=qi(a.haloScale,t.haloScale,e),o=qi(a.blur??0,t.blur??0,e),c=qi(a.brightness??0,t.brightness??0,e),l=j1(a.color,t.color,e),h=Pe.lerpAngular(a.angular,t.angular,e),u=$1(a.aim,t.aim,e);return a.kind==="polygon"&&t.kind==="polygon"&&a.points.length===t.points.length?{...a,bounds:i,angle:n,transparency:s,haloScale:r,blur:o,brightness:c,color:l,angular:h,aim:u,points:a.points.map((d,f)=>({x:qi(d.x,t.points[f].x,e),y:qi(d.y,t.points[f].y,e)}))}:{...e<1?a:t,bounds:i,angle:n,transparency:s,haloScale:r,blur:o,brightness:c,color:l,angular:h,aim:u}}class Pl{keyframes=[];order=[];groups=[];addKeyframe(t,e){const i=this.findInsertIndex(t);if(this.keyframes[i]?.t===t){const n=new Set(e.map(s=>s.sourceId));this.keyframes[i]={t,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...e]}}else this.keyframes.splice(i,0,{t,shapes:[...e]});for(const n of e)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getKeyframeAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e];return i?.t===t?i:void 0}getShapeAt(t,e){return this.getKeyframeAt(t)?.shapes.find(i=>i.sourceId===e)?.shape}getLatestShapeAt(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return n.shape}}getInterpolatedShapeAt(t,e){const i=this.findShapeAtOrBefore(t,e);if(i?.t===t)return i.shape;const n=this.findShapeAtOrAfter(t,e);return i?n?Q1(i.shape,n.shape,(t-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(t,e){for(let i=this.findInsertIndex(t);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(t,e,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const o=this.getInterpolatedShapeAt(t,s[r]);if(o&&Z1(o,e,i))return{sourceId:s[r],shape:o}}}removeSource(t){for(let e=this.keyframes.length-1;e>=0;e--){const i=this.keyframes[e].shapes.filter(n=>n.sourceId!==t);i.length===0?this.keyframes.splice(e,1):i.length!==this.keyframes[e].shapes.length&&(this.keyframes[e]={t:this.keyframes[e].t,shapes:i})}this.order=this.order.filter(e=>e!==t),this.removeFromGroup(t)}group(t){if(!(t.length<2)){for(const e of t)this.removeFromGroup(e);this.groups.push([...t])}}ungroup(t){const e=this.groups.findIndex(i=>i.includes(t));e!==-1&&this.groups.splice(e,1)}groupMembers(t){return this.groups.find(e=>e.includes(t))}removeFromGroup(t){const e=this.groups.findIndex(n=>n.includes(t));if(e===-1)return;const i=this.groups[e].filter(n=>n!==t);i.length<2?this.groups.splice(e,1):this.groups[e]=i}bringToFront(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.push(t))}sendToBack(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.unshift(t))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(t){const e=new Pl;for(const i of t.keyframes)e.addKeyframe(i.t,i.shapes);if(t.order){const i=e.order.filter(n=>!t.order.includes(n));e.order=[...t.order,...i]}return t.groups&&(e.groups=t.groups.map(i=>i.filter(n=>e.order.includes(n))).filter(i=>i.length>=2)),e}}function tv(a,t,e){return Math.max(t,Math.min(e,a))}function ev(a,t,e){const i=((t-a)%360+540)%360-180;return((a+i*e)%360+360)%360}function Nr(a,t,e){return a+(t-a)*e}function iv(a,t,e){return{lat:a.lat===void 0||t.lat===void 0?void 0:Nr(a.lat,t.lat,e),lng:a.lng===void 0||t.lng===void 0?void 0:Nr(a.lng,t.lng,e),elevationM:Nr(a.elevationM,t.elevationM,e),headingDeg:a.headingDeg===void 0||t.headingDeg===void 0?void 0:ev(a.headingDeg,t.headingDeg,e),pitchDeg:Nr(a.pitchDeg,t.pitchDeg,e),rollDeg:Nr(a.rollDeg??0,t.rollDeg??0,e),fovDeg:Nr(a.fovDeg,t.fovDeg,e),fNumber:a.fNumber,focusDistanceM:a.focusDistanceM}}class wr{static at(t,e,i,n,s){const r=t[i],c=t[i+1]-r;if(c<=0)return e[i];const l=wr.tangent(t,e,i,s),h=wr.tangent(t,e,i+1,s),u=(n-r)/c,d=u*u,f=d*u;return(2*f-3*d+1)*e[i]+(f-2*d+u)*c*l+(-2*f+3*d)*e[i+1]+(f-d)*c*h}static BRAKE_S=.8;static paced(t,e,i,n){if(!i&&!n)return t;const s=e>0?Math.min(.5,wr.BRAKE_S/e):.5;if(i&&n){const o=1/(1-s);return t<=s?o*t*t/(2*s):t>=1-s?1-o*(1-t)*(1-t)/(2*s):o*(t-s/2)}const r=o=>{const c=1/(1-s/2);if(o<=1-s)return c*o;const l=o-(1-s);return c*(1-s)+c*(l-l*l/(2*s))};return n?r(t):1-r(1-t)}static tangent(t,e,i,n){const s=t.length-1,r=f=>(e[f+1]-e[f])/(t[f+1]-t[f]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-1);const o=r(i-1),c=r(i);if(o*c<=0)return 0;const l=t[i]-t[i-1],h=t[i+1]-t[i],u=2*h+l,d=h+2*l;return(u+d)/(u/o+d/c)}}class Eo{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,pose:e}:this.keyframes.splice(i,0,{t,pose:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestPoseAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].pose:void 0}getInterpolatedPoseAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.pose;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.pose;if(!n)return i.pose;const s=iv(i.pose,n.pose,tv((t-i.t)/(n.t-i.t),0,1));return this.humanly(e-1,t,s)}humanly(t,e,i){const n=Math.max(0,t-1),s=Math.min(this.keyframes.length-1,t+2),r=this.keyframes.slice(n,s+1),o=t-n,c=r.map(S=>S.t),l=(S,M)=>{const b=r.map(w=>S(w.pose));if(!b.some(w=>w===void 0))return wr.at(c,b,o,e,M)},h=r.map(S=>S.pose.headingDeg);let u;if(h.every(S=>S!==void 0)){const S=[h[0]];for(let M=1;M<h.length;M++)S.push(S[M-1]+((h[M]-h[M-1])%360+540)%360-180);u=(wr.at(c,S,o,e,!0)%360+360)%360}const d=this.keyframes[t],f=this.keyframes[t+1],p=(S,M)=>S.lat===M.lat&&S.lng===M.lng&&S.elevationM===M.elevationM,v=!p(d.pose,f.pose),m=v&&t>0&&p(this.keyframes[t-1].pose,d.pose),g=v&&t+2<this.keyframes.length&&p(f.pose,this.keyframes[t+2].pose);let _;if(m||g){const S=wr.paced((e-d.t)/(f.t-d.t),(f.t-d.t)/1e3,m,g),M=(b,w)=>b===void 0||w===void 0?void 0:b+(w-b)*S;_={lat:M(d.pose.lat,f.pose.lat),lng:M(d.pose.lng,f.pose.lng),elevationM:M(d.pose.elevationM,f.pose.elevationM)}}return{...i,lat:_?_.lat:l(S=>S.lat,!1)??i.lat,lng:_?_.lng:l(S=>S.lng,!1)??i.lng,elevationM:_?_.elevationM:l(S=>S.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:l(S=>S.pitchDeg,!0)??i.pitchDeg,rollDeg:l(S=>S.rollDeg??0,!0)??i.rollDeg,fovDeg:l(S=>S.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Eo;for(const i of t.keyframes)e.addKeyframe(i.t,i.pose);return e}}class zs{static MAX_CHANGE_PER_S=.05;points;followed;constructor(t){let e="none",i=0;this.points=t.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(e=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:e,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(zs.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.t)/1e3))}}at(t){if(this.points.length===0||t<this.points[0].t)return;let e=this.points.length-1;for(;e>0&&this.points[e].t>t;)e--;const i=this.points[e],n=this.points[e+1],s=n?zs.follow(this.followed[e],i.intensity,n.intensity,(n.t-i.t)/1e3,(t-i.t)/1e3):zs.follow(this.followed[e],i.intensity,i.intensity,1,(t-i.t)/1e3);return{type:zs.typeBetween(i,n,t,s),intensity:s,character:zs.characterBetween(i,n,t)}}static characterBetween(t,e,i){return t.type==="none"?e&&e.type!=="none"?e.intensity:t.lastFallingIntensity:!e||e.type==="none"?t.intensity:t.intensity+(e.intensity-t.intensity)*(i-t.t)/(e.t-t.t||1)}static typeBetween(t,e,i,n){return t.type==="none"?e&&e.type!=="none"&&i>t.t?e.type:n>0?t.lastFalling:"none":e&&e.type==="none"&&n<=0?"none":t.type}static follow(t,e,i,n,s){const r=zs.MAX_CHANGE_PER_S,o=n>0?(i-e)/n:0,c=u=>e+o*Math.min(Math.max(u,0),n);let l=t,h=0;for(let u=0;u<8&&h<s;u++){const d=c(h)-l;if(Math.abs(d)<1e-9){const S=h<n?o:0;if(Math.abs(S)<=r){const b=h<n?Math.min(s,n):s;l=c(b),h=b;continue}const M=Math.min(s,n);l+=Math.sign(S)*r*(M-h),h=M;continue}const f=Math.sign(d),p=h<n?o:0,v=r-f*p,m=v>0?h+Math.abs(d)/v:1/0,g=h<n?n:1/0,_=Math.min(s,m,g);l+=f*r*(_-h),h=_,_===m&&(l=c(h))}return Math.min(1,Math.max(0,l))}}function Ne(a,t,e){return a+(t-a)*e}function Vd(a,t,e){const i=((t-a)%360+540)%360-180;return((a+i*e)%360+360)%360}function nv(a,t,e){return Math.max(t,Math.min(e,a))}function sv(a=[],t=[],e){if(!(!a.length&&!t.length))return[...new Set([...a.map(i=>i.id),...t.map(i=>i.id)])].map(i=>{const n=a.find(c=>c.id===i),s=t.find(c=>c.id===i),r=n??{...s,density:0},o=s??{...n,density:0};return{...r,eastM:Ne(r.eastM,o.eastM,e),northM:Ne(r.northM,o.northM,e),baseM:Ne(r.baseM,o.baseM,e),thicknessM:Ne(r.thicknessM,o.thicknessM,e),widthM:Ne(r.widthM,o.widthM,e),depthM:Ne(r.depthM,o.depthM,e),rotationDeg:Vd(r.rotationDeg,o.rotationDeg,e),density:Ne(r.density,o.density,e),darkness:Ne(r.darkness??0,o.darkness??0,e)}})}function rv(a,t,e){if(a.cloudLayers===void 0&&t.cloudLayers===void 0)return;const i=ol(a),n=ol(t);return e>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const o=i.find(u=>u.id===r),c=n.find(u=>u.id===r),l=o??{...c,coverage:0},h=c??{...o,coverage:0};return{...l,instances:sv(o?.instances,c?.instances,e),baseM:Ne(l.baseM,h.baseM,e),thicknessM:Ne(l.thicknessM,h.thicknessM,e),coverage:Ne(l.coverage,h.coverage,e),sizeM:Ne(l.sizeM,h.sizeM,e),density:Ne(l.density,h.density,e),darkness:Ne(l.darkness??a.cloudDarkness,h.darkness??t.cloudDarkness,e),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Ne(l.iceCrystalAlignment,h.iceCrystalAlignment,e),windSpeed:l.windSpeed===void 0&&h.windSpeed===void 0?void 0:Ne(l.windSpeed??a.windSpeed,h.windSpeed??t.windSpeed,e),windDirectionDeg:l.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Vd(l.windDirectionDeg??a.windDirectionDeg,h.windDirectionDeg??t.windDirectionDeg,e)}})}function av(a,t,e){return{cloudLayers:rv(a,t,e),cloudCover:Ne(a.cloudCover,t.cloudCover,e),cloudDarkness:Ne(a.cloudDarkness,t.cloudDarkness,e),highCloudCover:a.highCloudCover===void 0||t.highCloudCover===void 0?void 0:Ne(a.highCloudCover,t.highCloudCover,e),iceCrystalAlignment:a.iceCrystalAlignment===void 0||t.iceCrystalAlignment===void 0?void 0:Ne(a.iceCrystalAlignment,t.iceCrystalAlignment,e),lowerCloudCover:a.lowerCloudCover===void 0||t.lowerCloudCover===void 0?void 0:Ne(a.lowerCloudCover,t.lowerCloudCover,e),cloudBaseM:a.cloudBaseM===void 0||t.cloudBaseM===void 0?void 0:Ne(a.cloudBaseM,t.cloudBaseM,e),relativeHumidity:a.relativeHumidity===void 0||t.relativeHumidity===void 0?void 0:Ne(a.relativeHumidity,t.relativeHumidity,e),precipitationType:e<1?a.precipitationType:t.precipitationType,precipitationIntensity:Ne(a.precipitationIntensity,t.precipitationIntensity,e),windDirectionDeg:Vd(a.windDirectionDeg,t.windDirectionDeg,e),windSpeed:Ne(a.windSpeed,t.windSpeed,e),storm:e<1?a.storm:t.storm}}class Ao{keyframes=[];ramp;addKeyframe(t,e){this.ramp=void 0;const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,weather:e}:this.keyframes.splice(i,0,{t,weather:e})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(t){this.ramp=void 0;const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestWeatherAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].weather:void 0}getInterpolatedWeatherAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.weather;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];return i?n?av(i.weather,n.weather,nv((t-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(t){const e=this.getInterpolatedWeatherAt(t);if(!e)return;const i=(this.ramp??=new zs(this.keyframes)).at(t);if(!i)return e;const{type:n,intensity:s,character:r}=i,o=r>0?Math.min(1,s/r):n==="none"?0:1;return{...e,precipitationType:n,precipitationIntensity:r,precipitationAmount:o}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Ao;for(const i of t.keyframes)e.addKeyframe(i.t,i.weather);return e}}class To{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,sound:e}:this.keyframes.splice(i,0,{t,sound:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}getLatestSoundAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].sound:void 0}getInterpolatedSoundAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.sound;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.sound;if(!n)return i.sound;const s=(t-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new To;for(const i of t.keyframes)e.addKeyframe(i.t,i.sound);return e}lerp(t,e,i){return{kind:i<1?t.kind:e.kind,volume:t.volume+(e.volume-t.volume)*i,pitchHz:t.pitchHz+(e.pitchHz-t.pitchHz)*i,src:i<1?t.src:e.src}}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}}const ov=100,cv={kind:"none",volume:0,pitchHz:ov};class pn{constructor(t){this.entries=t}static empty(){return new pn(new Map)}get size(){return this.entries.size}at(t){return this.entries.get(t)}paths(){return[...this.entries.keys()]}set(t,e){e.basis==="stated"&&e.rationale===void 0?this.entries.delete(t):this.entries.set(t,e)}clear(t){for(const e of this.entries.keys())(e===t||e.startsWith(`${t}.`))&&this.entries.delete(e)}static strip(t){const e=new pn(new Map);return{recording:pn.stripValue(t,[],e),provenance:e}}static restore(t,e){if(e.size===0)return t;const i=structuredClone(t);for(const n of e.paths()){const s=e.at(n),r=n.split("."),o=pn.holderOf(i,r);if(!o)continue;const c=r[r.length-1],l=o[c];l!==void 0&&(s.of!==void 0&&JSON.stringify(s.of)!==JSON.stringify(l)||(o[c]={value:l,...s.basis==="stated"?{}:{basis:s.basis},...s.rationale===void 0?{}:{rationale:s.rationale}}))}return i}static isWrapper(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&"value"in t}static stripValue(t,e,i){return pn.isWrapper(t)?(i.set(e.join("."),{basis:t.basis??"stated",...t.rationale===void 0?{}:{rationale:t.rationale},of:t.value}),pn.stripValue(t.value,e,i)):Array.isArray(t)?t.map((n,s)=>pn.stripValue(n,[...e,String(s)],i)):typeof t=="object"&&t!==null?Object.fromEntries(Object.entries(t).map(([n,s])=>[n,pn.stripValue(s,[...e,n],i)])):t}static holderOf(t,e){let i=t;for(const n of e.slice(0,-1)){if(typeof i!="object"||i===null)return;i=i[n]}return typeof i=="object"&&i!==null?i:void 0}}function gu(a){if(a.year!==void 0)return Date.UTC(a.year,(a.month??1)-1,a.day??1,a.hour??0,a.minute??0,a.second??0)}function q0(a){return(((a.day??0)*24+(a.hour??0))*60+(a.minute??0))*6e4+(a.second??0)*1e3}const lv=["year","month","day","hour","minute"],hv=["day","hour","minute"];function Y0(a,t){return t.filter(e=>a[e]!==void 0).join(",")}function uv(a){if(a.durationSeconds!==void 0)return a.durationSeconds*1e3;if(!a.time||!a.endTime)return;const t=a.time.year!==void 0&&a.endTime.year!==void 0,e=t?lv:hv,i=Y0(a.time,e);if(!(i===""||i!==Y0(a.endTime,e)))return t?gu(a.endTime)-gu(a.time):q0(a.endTime)-q0(a.time)}class Ll{constructor(t,e,i,n,s,r,o,c,l=[],h,u,d,f=[],p=[],v=[]){this.event=t,this.timeline=e,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,this.observer=r,this.id=o,this.weather=c,this.decor=l,this.weatherSource=h,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p,this.roads=v}provenance=pn.empty();account;interpretation;sway;vehicle;get observerCount(){return 1+this.decor.filter(t=>t.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return li.byId(this.instrumentId)}static create(t,e,i){return new Ll({eventType:"sighting",time:t,place:e},new Pl,new Eo,new Ao,new To,i)}}const dv=0,fv=0;function oi(a,t){const e=a.observerTrack.getInterpolatedPoseAt(t);if(e)return e;const i=a.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:dv,headingDeg:void 0,pitchDeg:fv,fovDeg:li.fieldOfViewDeg(a.instrument)}}function Na(a,t){return a.weatherTrack.getInterpolatedWeatherAt(t)??a.weather??Gd}function K0(a,t){return a.weatherTrack.getActualWeatherAt(t)??a.weather??Gd}function pv(a,t){return a.soundTrack.getInterpolatedSoundAt(t)??cv}class mv{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 $m=["nw","n","ne","e","se","s","sw","w"],gv=24,qo=8,vv=3,Mv=8;function Yo(a,t,e){const i=a.x-t.x,n=a.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 Fa(a){return{x:a.x+a.width/2,y:a.y+a.height/2}}const xv={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 rn{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-gv}},o=Fa(t.bounds),c={};for(const l of Object.keys(r))c[l]=Yo(r[l],o,t.angle);return c}static hitTestHandle(t,e,i=8,n=[...$m,"rotate"]){const s=rn.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=((rn.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=Fa(t),r=Yo(n,s,-e),{x:o,y:c,width:l,height:h}=t,u=xv[i];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(r.x,p-qo)),u.right&&(p=Math.max(r.x,d+qo)),u.top&&(f=Math.min(r.y,v-qo)),u.bottom&&(v=Math.max(r.y,f+qo)),{x:d,y:f,width:p-d,height:v-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=rn.resizeBounds(t.bounds,t.angle,e,i);if(t.kind==="oval")return{...t,bounds:r};const o=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*o,y:l.y*c}))}}static rotateShape(t,e){const i=Fa(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=Fa(t.bounds);return t.points.map(i=>Yo({x:t.bounds.x+i.x,y:t.bounds.y+i.y},e,t.angle))}static hitTestVertex(t,e,i=Mv){const n=rn.vertexPointsFor(t);let s,r=i;return n.forEach((o,c)=>{const l=Math.hypot(e.x-o.x,e.y-o.y);l<=r&&(r=l,s=c)}),s}static toLocalPoint(t,e){const i=Fa(t.bounds),n=Yo(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?rn.toLocalPoint(t,i):u),s=Math.min(...n.map(u=>u.x)),r=Math.min(...n.map(u=>u.y)),o=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:o-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=rn.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=rn.distanceToSegment(i,l,h);u<r&&(r=u,s=c)}const o=[...n.slice(0,s+1),i,...n.slice(s+1)];return{...t,points:o}}static distanceToSegment(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=n*n+s*s,o=r===0?0:Math.max(0,Math.min(1,((t.x-e.x)*n+(t.y-e.y)*s)/r)),c=e.x+o*n,l=e.y+o*s;return Math.hypot(t.x-c,t.y-l)}static deleteVertex(t,e){return t.points.length<=vv?t:{...t,points:t.points.filter((i,n)=>n!==e)}}}const vu=6,Ko=vu/2,$0=20,Z0=24,J0=9,j0=6,Q0=7,tf=6,kn=4;class Ro{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,o=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+J0*f),tf*f)-d:0,v=f>0?d*(1+Q0*f)-d:0,m=3*Z0*(t.blur??0)+1.5*$0*t.haloScale,g=Math.max(p,v,0)+m+2;return{x:r-h-g,y:o-u-g,width:2*(h+g),height:2*(u+g)}}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(${(Z0*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,o=i+s/2,c=n+r/2,l=Math.max(s,r)/2,h=Math.max(l*(1+J0*e),tf*e);if(h<=0)return;this.ctx.save(),this.ctx.globalCompositeOperation="lighter";const u=this.ctx.createRadialGradient(o,c,0,o,c,h);for(let d=0;d<=j0;d++){const f=d/j0,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(o,c,h,0,2*Math.PI),this.ctx.fill(),this.starPoints>0){const d=l*(1+Q0*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,v=o+Math.cos(p)*d,m=c+Math.sin(p)*d,g=this.ctx.createLinearGradient(o,c,v,m);g.addColorStop(0,this.withAlpha(t.color,e*.55)),g.addColorStop(.35,this.withAlpha(t.color,e*.22)),g.addColorStop(1,this.withAlpha(t.color,0)),this.ctx.strokeStyle=g,this.ctx.beginPath(),this.ctx.moveTo(o,c),this.ctx.lineTo(v,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,o=s/2;this.ctx.ellipse(e+r,i+o,r,o,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,o)=>{o===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=$0*t.haloScale,this.paintBase(t),this.ctx.restore()}paintSelectionHandles(t){this.paintHandleFrame(rn.handlePointsFor(t),{includeRotate:!0}),t.kind==="polygon"&&this.paintVertexHandles(t)}paintVertexHandles(t){this.ctx.fillStyle="#39f";for(const e of rn.vertexPointsFor(t))this.ctx.beginPath(),this.ctx.ellipse(e.x,e.y,kn,kn,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(t){this.paintOutline(rn.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=Ro.landmarkColour(s.residualDeg),o=s.selected?3:2;s.selected&&(n.strokeStyle="#fff",n.lineWidth=o+3,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,kn+2,kn+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,kn,kn,0,0,2*Math.PI),n.fill()),n.strokeStyle=r,n.lineWidth=o,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,kn+2,kn+2,0,0,2*Math.PI),n.stroke(),this.paintLabel(s.label,s.picture.x+kn+5,s.picture.y-kn-2,r)}i&&this.paintLabel(i,8,8,"#fff",13),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 o=r.measureText(t).width;r.fillStyle="rgba(0, 0, 0, 0.6)",r.fillRect(e-3,i-2,o+6,s+4),r.fillStyle=n,r.fillText(t,e,i),r.restore()}paintGroupHandles(t){this.paintHandleFrame(rn.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 $m){const n=t[i];this.ctx.fillRect(n.x-Ko,n.y-Ko,vu,vu)}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,Ko+1,Ko+1,0,0,2*Math.PI),this.ctx.fill())}}const ef=.05,nf=.08,sf=2,rf=3,yv=14,_v=.02;class Sv{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;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}}this.context.state==="suspended"&&this.context.resume()}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.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,ef);for(const{param:s,ratio:r}of t.pitch)s.setTargetAtTime(Math.min(e.pitchHz*r,i.sampleRate/2-1),n,ef)}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(t.destination),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(t.destination),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(t.destination),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 o=t.createGain();return o.gain.value=0,r.connect(o).connect(s.gain),i.connect(n).connect(s).connect(t.destination),i.start(),r.start(),{key:e,nodes:[n,s,o],sources:[i,r],volumeParam:o.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 o=n.createGain();o.gain.value=0,r.connect(o).connect(n.destination),r.start(),this.voice={key:e,nodes:[o],sources:[r],volumeParam:o.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*sf),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*sf),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*rf),t.sampleRate),i=e.getChannelData(0),n=Math.max(1,Math.floor(_v*t.sampleRate)),s=Math.round(rf*yv);for(let r=0;r<s;r++){const o=Math.floor(Math.random()*i.length),c=.4+Math.random()*.6;for(let l=0;l<n&&o+l<i.length;l++)i[o+l]=Math.max(i[o+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,nf/3);const n=i+nf;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()}}}}function cl(a){return[...a].sort((t,e)=>t.t-e.t)}function af(a,t){let e;for(const i of cl(a)){if(i.t>t)break;e=i}return e}const Zl=Math.PI/180,$o=180/Math.PI;class vs{constructor(t,e,i){this.kind=t,this.canvasHeightPx=e,this.fovDeg=i;const n=i*Zl/2;this.focalPx=t==="equidistant"?e/2/n:e/2/Math.tan(n)}focalPx;static of(t,e,i){return new vs(t.projection,e,i)}degToPx(t){const e=t*Zl;return this.kind==="equidistant"?this.focalPx*e:2*this.focalPx*Math.tan(e/2)}pxToDeg(t){return this.kind==="equidistant"?t/this.focalPx*$o:2*Math.atan(t/(2*this.focalPx))*$o}angleDegToRadiusPx(t){const e=t*Zl;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*$o:Math.atan(t/this.focalPx)*$o}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(Pe.angularWidthDeg(t))}}class Ki{static fovOf(t,e){return oi(t,e)?.fovDeg??li.fieldOfViewDeg(t.instrument)}static toAngular(t){this.eachKeyframe(t,(e,i)=>({...e,angular:i.ofBounds(e.bounds)}))}static toBounds(t){this.eachKeyframe(t,(e,i)=>{if(!e.angular)return e;const{width:n,height:s}=i.toBoundsSize(e.angular),r={x:e.bounds.x+(e.bounds.width-n)/2,y:e.bounds.y+(e.bounds.height-s)/2,width:n,height:s};if(e.kind!=="polygon")return{...e,bounds:r};const o=e.bounds.width===0?1:n/e.bounds.width,c=e.bounds.height===0?1:s/e.bounds.height;return{...e,bounds:r,points:e.points.map(l=>({x:l.x*o,y:l.y*c}))}})}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)<Ki.UNMOVED_PX&&Math.abs(s.y-e.bounds.y)<Ki.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=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,this.fovOf(t,e));return this.aimFrom(t,n,oi(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),o=e.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+o}}static toPosition(t){this.eachKeyframe(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 positionOf(t,e,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(t),o=this.shortestArc(e.azimuthDeg-s.headingDeg),c=e.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,o)-i.width/2,y:r.y-this.offAxisPx(n,c)-i.height/2}}static frameCentre(t){return{x:li.frameWidthPx(t.instrument,Pe.CANVAS_HEIGHT_PX)/2,y:Pe.CANVAS_HEIGHT_PX/2}}static shortestArc(t){return(t%360+540)%360-180}static offAxisPx(t,e){return Math.abs(e)>=Ki.OFF_CANVAS_DEG?Math.sign(e)*Ki.OFF_CANVAS_PX:t.angleDegToRadiusPx(e)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(t,e,i){const n=li.frameWidthPx(e,Pe.CANVAS_HEIGHT_PX)/2,s=li.frameWidthPx(t.instrument,Pe.CANVAS_HEIGHT_PX)/2,r=Pe.CANVAS_HEIGHT_PX/2;for(const o of[...t.timeline.allKeyframes]){const c=this.fovOf(t,o.t),l=i?.get(o.t)??c,h=vs.of(e,Pe.CANVAS_HEIGHT_PX,l),u=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,c);t.timeline.addKeyframe(o.t,o.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-n,v=f.y+f.height/2-r,m=Math.hypot(p,v),g=m===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,_={...f,x:s+p*g-f.width/2,y:r+v*g-f.height/2};return{...d,shape:{...d.shape,bounds:_}}}))}this.toBounds(t)}static eachKeyframe(t,e){const{timeline:i}=t;for(const n of[...i.allKeyframes]){const s=oi(t,n.t),r=this.fovOf(t,n.t),o=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,r);i.addKeyframe(n.t,n.shapes.map(c=>({...c,shape:e(c.shape,o,s)})))}}}function bv(a){return pn.restore(wv(a),a.provenance)}function wv(a){return Ki.toAngular(a),Ki.toAim(a),{version:1,id:a.id,time:a.event.time,endTime:a.event.endTime,durationSeconds:a.event.durationSeconds,utcOffsetHours:a.event.utcOffsetHours,timeZone:a.event.timeZone,place:a.event.place,observer:a.observer,account:a.account,sway:a.sway,vehicle:a.vehicle,description:a.event.description,tags:a.event.tags,timeline:a.timeline.toJSON(),observerTrack:a.observerTrack.toJSON(),weatherTrack:a.weatherTrack.toJSON(),soundTrack:a.soundTrack.toJSON(),weather:a.weather,decor:a.decor,milestones:a.milestones.length>0?a.milestones:void 0,references:a.references.length>0?a.references:void 0,roads:a.roads.length>0?a.roads:void 0,weatherSource:a.weatherSource,instrument:a.instrumentId,exposureSeconds:a.exposureSeconds,interpretation:a.interpretation}}function Ev(a){const{recording:t,provenance:e}=pn.strip(a),i=Av(t);return i.provenance=e,i}function Av(a){const t=new Ll({eventType:"sighting",time:a.time,endTime:a.endTime,durationSeconds:a.durationSeconds,utcOffsetHours:a.utcOffsetHours,timeZone:a.timeZone,place:a.place,description:a.description,tags:a.tags},Pl.fromJSON(a.timeline),a.observerTrack?Eo.fromJSON(a.observerTrack):new Eo,a.weatherTrack?Ao.fromJSON(a.weatherTrack):new Ao,a.soundTrack?To.fromJSON(a.soundTrack):new To,a.observer&&{id:a.observer.id,title:a.observer.title,lastName:a.observer.lastName,firstNames:a.observer.firstNames},a.id,a.weather,a.decor??[],a.weatherSource,a.instrument,a.exposureSeconds??a.observerTrack?.keyframes.map(e=>e.pose.exposureSeconds).find(e=>e!==void 0),cl(a.milestones??[]),a.references??[],a.roads??[]);return t.account=a.account,t.sway=a.sway,t.vehicle=a.vehicle,t.interpretation=a.interpretation,Ki.toBounds(t),Ki.toPosition(t),t}class Tn{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?Tn.travelDegOver(t,e,i,i+n*1e3)/s/Tn.PIXELS_PER_INSTANT:0,o=Tn.flashesOver(t,n)*Tn.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(r,o));return c<2?1:Math.min(Tn.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 o=Tn.directionAt(r,e,i),c=Tn.directionAt(r,e,n),l=Math.min(1,Math.max(-1,o.x*c.x+o.y*c.y+o.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=bo(t,i),s=n.eastM,r=n.altitudeM-e,o=n.northM,c=Math.hypot(s,r,o);return c===0?{x:0,y:1,z:0}:{x:s/c,y:r/c,z:o/c}}}function ll(a,t){for(const e of a){const i=e.toLowerCase().split("-")[0];if(t.includes(i))return i}return"en"}class po{static preferencesFor(t){const e=navigator.languages??[],i=this.declaredFor(t);return i?[i,...e]:e}static declaredFor(t){for(let e=t;e;){const i=e.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const n=e.getRootNode();e=n instanceof ShadowRoot?n.host:void 0}}}class Vs{constructor(t){this.preferences=t}read(t){if(t===void 0||typeof t=="string")return t===""?void 0:t;for(const i of this.preferences){const n=t[i]??t[Vs.base(i)];if(n)return n}const e=new Set(this.preferences.map(i=>Vs.base(i)));for(const[i,n]of Object.entries(t))if(n&&e.has(Vs.base(i)))return n;return Object.values(t).find(i=>i)??void 0}write(t,e,i){const n=e?.trim()?e.trim():void 0;if(t===void 0||typeof t=="string")return n;const s={...t},r=Object.keys(s).find(o=>o===i)??Object.keys(s).find(o=>Vs.base(o)===Vs.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(t){return t.toLowerCase().split("-")[0]}}const Tv=["en","fr"],Rv={en:()=>sl(()=>Promise.resolve().then(()=>Cv),void 0,import.meta.url).then(a=>a.ufoMessages_en),fr:()=>sl(()=>import("./UfoMessages_fr-_6zR9Sw1.js"),[],import.meta.url).then(a=>a.ufoMessages_fr)};function Dv(a){return Rv[a]()}const Zm={play:"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",showObserverMap:"Show where the observer was",hideObserverMap:"Hide where the observer was",mapImageryUnavailable:"Aerial imagery unavailable",showReferences:"Show the pictures of the place",hideReferences:"Hide the pictures of the place",referenceOpacity:"Picture opacity",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",observerHere:"The observer, here",decorHere:"Scenery"},Cv=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Zm},Symbol.toStringTag,{value:"Module"})),Jm=Math.PI/180,Iv=180/Math.PI,Pv=256,jm=19,Lv=1.25;function Qm(a,t){return 156543.03392*Math.cos(a*Jm)/2**t}function tg(a,t){return Qm(a,t)*Pv}function Ov(a,t){let e=0;for(;e<jm&&tg(a,e+1)>=t;)e++;return e}function eg(a,t){return tg(a,t)}function Nv(a,t){const e=t*Lv;let i=0;for(;i<jm&&Qm(a,i)>e;)i++;return i}function Yc(a){const t=a*Jm;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}function ig(a,t,e){const i=2**e;return{x:(a+180)/360*i,y:Yc(t)*i}}function ng(a,t,e){const i=Yc(a.north),n=Yc(a.south);return{x:(t-a.west)/(a.east-a.west),y:(Yc(e)-i)/(n-i)}}function Fv(a,t,e){const{x:i,y:n}=ig(a,t,e);return{x:Math.floor(i),y:Math.floor(n),z:e}}function Uv(a){const t=2**a.z,e=a.x/t*360-180,i=(a.x+1)/t*360-180,n=of(a.y,t);return{south:of(a.y+1,t),north:n,west:e,east:i}}function of(a,t){const e=a/t;return Math.atan(Math.sinh(Math.PI*(1-2*e)))*Iv}function sg(a,t,e,i){const n=Fv(a,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 o=r.map(Uv),c={south:Math.min(...o.map(l=>l.south)),north:Math.max(...o.map(l=>l.north)),west:Math.min(...o.map(l=>l.west)),east:Math.max(...o.map(l=>l.east))};return{tiles:r,bounds:c}}class ur{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),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=ng(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()}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),o=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,o,c-l,c+l),s.closePath();const h=s.createRadialGradient(r.x,r.y,0,r.x,r.y,o);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:ur.MARKER_RADIUS_PX}),e.beginPath(),e.arc(n.x,n.y,ur.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 o=ci(r.lat,r.lng,e.lat,e.lng);return Math.hypot(o.x,o.z)<=ur.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?ur.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(ci(r,t.east,r,t.west).x)/this.width,l=ur.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}}const hn=256,cf=3,kv=32768;class zv{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(ci(i,t.east,i,t.west).x),r=Math.abs(ci(t.north,n,t.south,n).z),o=Ov(i,Math.max(s,r)),{tiles:c}=sg(n,i,o,cf),l=cf*hn,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 v=0;v<e.width;v++){const m=t.west+(t.east-t.west)*(v/(e.width-1));d[f*e.width+v]=this.sampleAt(p,m,o,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 o=await createImageBitmap(await r.blob()),c=document.createElement("canvas");c.width=hn,c.height=hn;const l=c.getContext("2d");if(!l)throw new Error("2D canvas context unavailable");l.drawImage(o,0,0);const{data:h}=l.getImageData(0,0,hn,hn),u=(t.x-e.x)*hn,d=(t.y-e.y)*hn;for(let f=0;f<hn;f++)for(let p=0;p<hn;p++){const v=(f*hn+p)*4,m=h[v]*256+h[v+1]+h[v+2]/256-kv,g=u+p,_=d+f;i[_*n+g]=m}}sampleAt(t,e,i,n,s,r){const{x:o,y:c}=ig(e,t,i),l=(o-n.x)*hn,h=(c-n.y)*hn,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),v=l-u,m=h-d,g=s[d*r+u],_=s[d*r+f],S=s[p*r+u],M=s[p*r+f],b=g+(_-g)*v,w=S+(M-S)*v;return b+(w-b)*m}}const Kc=256,Bv=5;async function Hv(a,t,e,i){const n=(a.south+a.north)/2,s=(a.west+a.east)/2,r=Math.abs(ci(n,a.east,n,a.west).x),o=Math.abs(ci(a.north,s,a.south,s).z),c=Math.max(r,o),{zoom:l,gridSize:h}=Gv(n,c,Math.max(t.width,t.height)),{tiles:u,bounds:d}=sg(s,n,l,h),f=h*Kc,p=document.createElement("canvas");p.width=f,p.height=f;const v=p.getContext("2d");if(!v)throw new Error("2D canvas context unavailable");const m=u[0];await Promise.all(u.map(async M=>{const b=e(M),w=await i(b);if(!w.ok)throw new Error(`Imagery tile fetch failed (${w.status}): ${b}`);const T=await createImageBitmap(await w.blob());v.drawImage(T,(M.x-m.x)*Kc,(M.y-m.y)*Kc)}));const g=Math.min(Math.max(t.width,t.height),f);if(g===f)return{source:p,width:f,height:f,bounds:d};const _=document.createElement("canvas");_.width=g,_.height=g;const S=_.getContext("2d");if(!S)throw new Error("2D canvas context unavailable");return S.drawImage(p,0,0,f,f,0,0,g,g),{source:_,width:g,height:g,bounds:d}}function Gv(a,t,e){let i=Nv(a,t/Math.max(1,e)),n=lf(a,i,t);for(;n>Bv&&i>0;)i--,n=lf(a,i,t);return{zoom:i,gridSize:n,mPerPixel:eg(a,i)/Kc}}function lf(a,t,e){const i=Math.ceil(e/2/eg(a,t));return Math.max(3,2*i+1)}class Vv{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 Hv(t,e,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class wn{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;static ENDPOINTS=["https://overpass-api.de/api/interpreter","https://overpass.kumi.systems/api/interpreter","https://overpass.private.coffee/api/interpreter"];fetchImpl;endpoints;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.endpoints=t.endpoints??wn.ENDPOINTS}static queue=Promise.resolve();static RETRY_MS=4e3;async getRoads(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];way["highway"~"^(${wn.DRIVABLE.join("|")})$"](${e});out geom;`;return this.waysFrom(await this.queued(()=>this.ask(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:wn.surfaceOf(s),widthM:wn.widthOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return e}queued(t){const e=wn.queue.then(t,t);return wn.queue=e.catch(()=>{}),e}async ask(t){let e;for(const i of this.endpoints)for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(t)}`);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,wn.RETRY_MS))}throw e??new Error("No Overpass instance answered")}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:wn.WIDTH_M[t.highway]??wn.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 Jl="https://ufoathome.org/roads/index.json";class Wd{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Wd.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(){return this.index??=this.fetchFirstAvailable(),this.index}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.68.0")}`,e=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(e&&e!==Jl?[e,Jl]:[Jl]).map(i=>i+t)}}function Wv(){return{elevation:new zv,imagery:rg(),roads:Xv()}}function rg(){return new Vv}function Xv(){return new Wd({fallback:new wn})}const qv=new Set,pa="show-observer-map",ma="hide-milestones";class Wi extends HTMLElement{static get observedAttributes(){return["src",pa,ma]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;static OBSERVER_MAP_MIN_SPAN_M=400;static OBSERVER_MAP_MARGIN=.6;static OBSERVER_MAP_IMAGERY_PX=768;fullscreenButton;observerMapButton;referencesButton;referenceOpacityInput;referencesShownState=!0;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;observerPath;observerMapBounds;observerMapImagery;observerMapImageryRequested=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Ll.create();sightingAudio=new Sv;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Zm;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.resizeObserverMap()};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=>{const e=this.observerMapTargetFrom(t);if(!e){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="default";return}this.observerMapCanvas.style.cursor="pointer",this.tooltip.textContent=e.label,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=>{const e=this.observerMapTargetFrom(t);if(e){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};constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${K1}</style>${Y1}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Ro(this.canvas.getContext("2d")),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),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 ur(this.observerMapCanvas.getContext("2d")),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");for(const e of[this.timeStartLabel,this.timeEndLabel])e.addEventListener("click",()=>this.toggleTimeDisplay()),e.addEventListener("keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),this.toggleTimeDisplay())});this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),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.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",e=>{this.seekSnapArmed=!0,this.nameMarkUnder(e)}),this.seekInput.addEventListener("pointerup",()=>{this.seekSnapArmed=!1}),this.seekInput.addEventListener("pointermove",e=>this.nameMarkUnder(e)),this.seekInput.addEventListener("pointerleave",()=>this.seekInput.removeAttribute("title")),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.canvas.addEventListener("click",e=>{this.enableClickToPlay&&(e.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause())}),this.canvas.addEventListener("dblclick",e=>{this.enableClickToPlay&&(e.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateMilestonesButton(),this.refresh(),this.loadLocaleMessages()}connectedCallback(){this.saidTexts=void 0;const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.observerMapResizeObserver?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(t,e,i){t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===pa&&this.applyObserverMapDefault(),t===ma&&this.setMilestonesShown(!this.hasAttribute(ma))}async loadFromSrc(t){this.sightingData=await Km.json(t)}get sightingData(){return bv(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Ev(t),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault()}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(){this.player.seekableDuration<=0||this.playbackState==="playing"||this.togglePlayPause()}pause(){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)}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.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.player.seek(this.player.time)}hostControls(t){const e=[this.milestonesButton,this.referenceOpacityInput,this.referencesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else for(const i of e)this.toolbar.appendChild(i)}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}toggleReferences(){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)),this.updateReferencesButton()}updateReferencesButton(){const t=this.currentSighting.references.length>0;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState,this.referencesButton.setAttribute("aria-pressed",String(this.referencesShownState));const e=this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=e,this.referencesButton.setAttribute("aria-label",e),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}dispatchReferenceView(){this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?cl(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),o=r?`${s} — ${r}`:s;return n.title=o,n.setAttribute("aria-label",o),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n}))}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=Wi.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const o=Number(r.dataset.t);Math.abs(o-t)>n||(!s||Math.abs(o-t)<Math.abs(s.t-t))&&(s={t:o,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?af(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,!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=Tn.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Wi.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Wi.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Wi.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Wi.EXPOSURE_STEP_PX),s=Math.min(Wi.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let o=0;o<s;o++)r.push(e.fromMs+e.ms*o/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,o]of i){const c=n.get(r);if(!c)continue;const l=c.bounds.x+c.bounds.width/2-(o.bounds.x+o.bounds.width/2),h=c.bounds.y+c.bounds.height/2-(o.bounds.y+o.bounds.height/2);s=Math.max(s,Math.hypot(l,h))}return s}shapeAt(t,e,i){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=li.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:qv;this.canvasRenderer.setStarPoints(li.starPointsOf(this.sighting.instrument));const n=(oi(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 o of s)for(const[,c]of o.shapes){const l=o.share,h=l===1?c:{...c,transparency:1-(1-c.transparency)*l};this.canvasRenderer.paintShape(this.shifted(h,r))}for(const[o,c]of s[0].shapes)!this.selectionShown||!i.has(o)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));if(this.selectionShown&&i.size>1){const o=rn.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.overlayPainter?.(this.canvasRenderer),this.mapShapeBounds=s.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(pv(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),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 mv(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;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*Wi.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.preventDefault(),this.togglePlayPause())};togglePlayPause(){this.player.seekableDuration<=0||(this.player.playbackState==="playing"?(this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh()):(this.sightingAudio.resume(),this.player.play()),this.updatePlayPauseButton(),this.flashPlayback())}flashPlayback(){const t=this.playbackFlash;t.textContent=this.player.playbackState==="playing"?"▶":"⏸",t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.playPauseButton.textContent=t?"⏸":"▶";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()}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()}toggleObserverMap(){this.setObserverMapOpen(this.observerMapPanel.hidden)}applyObserverMapDefault(){const t=this.getAttribute(pa),e=t===null?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 e=!this.observerMapPanel.hidden?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e)}updateObserverMap(){const t=this.observerPath!==void 0;if(this.observerPath=fa.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.observerPath.boundsAround(Wi.OBSERVER_MAP_MIN_SPAN_M,Wi.OBSERVER_MAP_MARGIN);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,e))&&(this.observerMapBounds=e,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryRequested=!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(){if(this.observerMapImageryRequested||!this.observerMapBounds)return;this.observerMapImageryRequested=!0;const t=rg(),e=this.observerMapBounds;try{const i=await t.getImageryTexture(e,{width:Wi.OBSERVER_MAP_IMAGERY_PX,height:Wi.OBSERVER_MAP_IMAGERY_PX});if(this.observerMapBounds!==e)return;this.observerMapImagery=i,this.observerMapImageryCredit=t.attribution}catch{this.observerMapImageryFailed=!0}this.paintObserverMap(this.currentTime)}get observerMapCredit(){return this.observerMapImageryCredit}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=Wi.OBSERVER_MAP_CLEARANCE_PX,o=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",o&&c),this.observerMapPanel.classList.contains("on-the-left")){!o&&(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=oi(this.currentSighting,t),i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?af(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?cl(this.currentSighting.milestones):[]){const o=oi(this.currentSighting,r.t);o?.lat===void 0||o.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:o.lat,lng:o.lng,current:r===s})}this.observerMapRenderer.paint({bounds:this.observerMapBounds,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?vs.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(li.aspectOf(i)):void 0,markers:n,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.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;const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=oi(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=bo(i,t),{lat:s,lng:r}=gs(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=oi(this.currentSighting,this.currentTime),s=vs.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.steadyObserver)}updateFullscreenButton(){const t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Vs(po.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=ll(po.preferencesFor(this),Tv);t!=="en"&&this.applyMessages(await Dv(t))}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;for(const i of[this.timeStartLabel,this.timeEndLabel])i.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(i.setAttribute("role","button"),i.setAttribute("tabindex","0")):(i.removeAttribute("role"),i.removeAttribute("tabindex"))}applyMessages(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateMilestonesButton()}updateTimeLabels(){const t=this.currentSighting.event,e=uv(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?gu(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.updateTimeLabelTitles()}formatPosition(t){if(this.realDurationMs===void 0)return Zo(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?uf(hf(this.realStartMs+i)):Zo(i)}formatEndOfTimeline(){return this.realDurationMs===void 0?Zo(this.currentSighting.timeline.duration):this.canShowClockTime?uf(hf(this.realStartMs+this.realDurationMs)):Zo(this.realDurationMs)}}function hf(a){const t=new Date(a);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function uf(a){if(a.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return a.second?`${t(a.hour)}:${t(a.minute??0)}:${t(a.second)}`:`${t(a.hour)}:${t(a.minute??0)}`}function Zo(a){const t=Math.round(a/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Mu="rr0-ufo";function ag(){customElements.get(Mu)||customElements.define(Mu,Wi)}/**
729
+ `,Xo=[{id:"eye",name:{en:"Naked eye",fr:"Œil nu"},flare:0,projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",name:{en:"Camera, unknown device",fr:"Appareil, modèle inconnu"},projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"instamatic-126",name:{en:"Instamatic, 126 film",fr:"Instamatic, film 126"},projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20},{id:"slr-35mm-50",name:{en:"35 mm SLR, 50 mm lens",fr:"Reflex 35 mm, objectif 50 mm"},projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20},{id:"slr-35mm-zoom",name:{en:"35 mm SLR, 70-210 mm zoom",fr:"Reflex 35 mm, zoom 70-210 mm"},projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20},{id:"phone-landscape",name:{en:"Phone, held sideways",fr:"Téléphone, tenu couché"},projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4},{id:"phone-portrait",name:{en:"Phone, held upright",fr:"Téléphone, tenu debout"},projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4}];class li{static get default(){return Xo[0]}static byId(t){return Xo.find(e=>e.id===t)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(t){const e=t.frame;return e?2*Math.atan(e.heightMm/(2*e.focalLengthMm))*180/Math.PI:li.UNAIDED_FIELD_DEG}static aspectOf(t){const e=t.frame;return e?e.widthMm/e.heightMm:li.UNAIDED_ASPECT}static frameWidthPx(t,e){return Math.round(e*li.aspectOf(t))}static availableAt(t){return t===void 0?Xo:Xo.filter(e=>!e.years||t>=e.years.from&&(e.years.to===void 0||t<=e.years.to))}static fieldOfViewDegAt(t,e){const i=t.frame;if(!(!i||e<=0))return 2*Math.atan(i.heightMm/(2*e))*180/Math.PI}static focalLengthMmFor(t,e){const i=t.frame;if(!(!i||e<=0||e>=180))return i.heightMm/(2*Math.tan(e*Math.PI/360))}static bladesShowing(t,e){const i=e??t.fNumber;if(i===void 0||t.apertureBlades===void 0)return 0;const n=t.fNumberRange;return!n||n.max<=n.min?1:Math.max(0,Math.min(1,(i-n.min)/(n.max-n.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(t){return t.flare??li.LENS_FLARE_ARTIFACTS}static starPointsOf(t){const e=t.apertureBlades;return e===void 0||e<3?0:e%2===0?e:e*2}}class fa{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 fa(e)}static TRAVEL_M=50;get travels(){return this.spanM>fa.TRAVEL_M}get moved(){return this.spanM>fa.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(ci(e,t.east,e,t.west).x),Math.abs(ci(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:gs(0,-s,i,n).lat,south:gs(0,s,i,n).lat,east:gs(s,0,i,n).lng,west:gs(-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 bn{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 HZ=[.11,.23,.17,.29,.37,.07];static of(t){const e=t.sway??(t.event.tags?.includes("paralysis")?0:1);if(e>0)return new bn(Math.max(1-(t.instrument.stabilization??0),bn.GAZE_DRIFT_SHARE),e)}offsetAt(t){const e=t/1e3,i=this.scale,n=(u,d)=>Math.sin(2*Math.PI*u*e+d),[s,r,o,c,l,h]=bn.HZ;return{eastM:i*bn.SWAY_M*(.7*n(s,.3)+.3*n(c,1.9)),northM:i*bn.SWAY_M*(.6*n(o,2.2)+.4*n(l,.8)),upM:i*bn.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*bn.DRIFT_YAW_DEG*(.6*n(h,1.1)+.4*n(c,2.7)),pitchDeg:i*this.rotationPassed*bn.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(o,.4)),rollDeg:i*this.rotationPassed*bn.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=fa.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],o=e.points[s],c=(o.t-r.t)/1e3;if(c<=0)continue;const l=ci(o.lat,o.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:o.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],o=i[s+1];i[s].rampsIn=r===void 0||r.stepHz===0,i[s].rampsOut=o===void 0||o.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,bn.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=(o,c,l,h)=>{if(o<0||o>xe.JOLT_LASTS_MS)return;const u=o/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),o=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*o*Math.cos(n/2),pitchDeg:-1.25*o*Math.cos(n),yawDeg:xe.HEAD_YAW_DEG*o*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,o=Math.min(t.rampsIn?s/n:1,t.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(o,0)))/2}}class Pe{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(t){return 2*Math.atan(t.sizeM/(2*t.distanceM))*180/Math.PI}static inMoons(t){return t/Pe.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(t,e,i){if(!(!t||!e))return{widthDeg:t.widthDeg+(e.widthDeg-t.widthDeg)*i,heightDeg:t.heightDeg+(e.heightDeg-t.heightDeg)*i}}static sizeMAt(t,e){return 2*t*Math.tan(e*Math.PI/360)}static distanceMAt(t,e){return t/(2*Math.tan(e*Math.PI/360))}}function $1(a,t,e){if(!a||!t)return e<1?a:t;const i=((t.azimuthDeg-a.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((a.azimuthDeg+i*e)%360+360)%360,altitudeDeg:a.altitudeDeg+(t.altitudeDeg-a.altitudeDeg)*e}}function Z1(a,t,e){const{bounds:i}=a;return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}function qi(a,t,e){return a+(t-a)*e}function X0(a){const t=/^#([0-9a-f]{6})$/i.exec(a);if(!t)return;const e=parseInt(t[1],16);return[e>>16&255,e>>8&255,e&255]}function J1(a){return`#${a.map(t=>Math.round(t).toString(16).padStart(2,"0")).join("")}`}function j1(a,t,e){const i=X0(a),n=X0(t);return!i||!n?e<1?a:t:J1([qi(i[0],n[0],e),qi(i[1],n[1],e),qi(i[2],n[2],e)])}function Q1(a,t,e){const i={x:qi(a.bounds.x,t.bounds.x,e),y:qi(a.bounds.y,t.bounds.y,e),width:qi(a.bounds.width,t.bounds.width,e),height:qi(a.bounds.height,t.bounds.height,e)},n=qi(a.angle,t.angle,e),s=qi(a.transparency,t.transparency,e),r=qi(a.haloScale,t.haloScale,e),o=qi(a.blur??0,t.blur??0,e),c=qi(a.brightness??0,t.brightness??0,e),l=j1(a.color,t.color,e),h=Pe.lerpAngular(a.angular,t.angular,e),u=$1(a.aim,t.aim,e);return a.kind==="polygon"&&t.kind==="polygon"&&a.points.length===t.points.length?{...a,bounds:i,angle:n,transparency:s,haloScale:r,blur:o,brightness:c,color:l,angular:h,aim:u,points:a.points.map((d,f)=>({x:qi(d.x,t.points[f].x,e),y:qi(d.y,t.points[f].y,e)}))}:{...e<1?a:t,bounds:i,angle:n,transparency:s,haloScale:r,blur:o,brightness:c,color:l,angular:h,aim:u}}class Pl{keyframes=[];order=[];groups=[];addKeyframe(t,e){const i=this.findInsertIndex(t);if(this.keyframes[i]?.t===t){const n=new Set(e.map(s=>s.sourceId));this.keyframes[i]={t,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...e]}}else this.keyframes.splice(i,0,{t,shapes:[...e]});for(const n of e)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getKeyframeAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e];return i?.t===t?i:void 0}getShapeAt(t,e){return this.getKeyframeAt(t)?.shapes.find(i=>i.sourceId===e)?.shape}getLatestShapeAt(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return n.shape}}getInterpolatedShapeAt(t,e){const i=this.findShapeAtOrBefore(t,e);if(i?.t===t)return i.shape;const n=this.findShapeAtOrAfter(t,e);return i?n?Q1(i.shape,n.shape,(t-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(t,e){for(let i=this.findInsertIndex(t);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(t,e,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const o=this.getInterpolatedShapeAt(t,s[r]);if(o&&Z1(o,e,i))return{sourceId:s[r],shape:o}}}removeSource(t){for(let e=this.keyframes.length-1;e>=0;e--){const i=this.keyframes[e].shapes.filter(n=>n.sourceId!==t);i.length===0?this.keyframes.splice(e,1):i.length!==this.keyframes[e].shapes.length&&(this.keyframes[e]={t:this.keyframes[e].t,shapes:i})}this.order=this.order.filter(e=>e!==t),this.removeFromGroup(t)}group(t){if(!(t.length<2)){for(const e of t)this.removeFromGroup(e);this.groups.push([...t])}}ungroup(t){const e=this.groups.findIndex(i=>i.includes(t));e!==-1&&this.groups.splice(e,1)}groupMembers(t){return this.groups.find(e=>e.includes(t))}removeFromGroup(t){const e=this.groups.findIndex(n=>n.includes(t));if(e===-1)return;const i=this.groups[e].filter(n=>n!==t);i.length<2?this.groups.splice(e,1):this.groups[e]=i}bringToFront(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.push(t))}sendToBack(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.unshift(t))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(t){const e=new Pl;for(const i of t.keyframes)e.addKeyframe(i.t,i.shapes);if(t.order){const i=e.order.filter(n=>!t.order.includes(n));e.order=[...t.order,...i]}return t.groups&&(e.groups=t.groups.map(i=>i.filter(n=>e.order.includes(n))).filter(i=>i.length>=2)),e}}function tv(a,t,e){return Math.max(t,Math.min(e,a))}function ev(a,t,e){const i=((t-a)%360+540)%360-180;return((a+i*e)%360+360)%360}function Nr(a,t,e){return a+(t-a)*e}function iv(a,t,e){return{lat:a.lat===void 0||t.lat===void 0?void 0:Nr(a.lat,t.lat,e),lng:a.lng===void 0||t.lng===void 0?void 0:Nr(a.lng,t.lng,e),elevationM:Nr(a.elevationM,t.elevationM,e),headingDeg:a.headingDeg===void 0||t.headingDeg===void 0?void 0:ev(a.headingDeg,t.headingDeg,e),pitchDeg:Nr(a.pitchDeg,t.pitchDeg,e),rollDeg:Nr(a.rollDeg??0,t.rollDeg??0,e),fovDeg:Nr(a.fovDeg,t.fovDeg,e),fNumber:a.fNumber,focusDistanceM:a.focusDistanceM}}class wr{static at(t,e,i,n,s){const r=t[i],c=t[i+1]-r;if(c<=0)return e[i];const l=wr.tangent(t,e,i,s),h=wr.tangent(t,e,i+1,s),u=(n-r)/c,d=u*u,f=d*u;return(2*f-3*d+1)*e[i]+(f-2*d+u)*c*l+(-2*f+3*d)*e[i+1]+(f-d)*c*h}static BRAKE_S=.8;static paced(t,e,i,n){if(!i&&!n)return t;const s=e>0?Math.min(.5,wr.BRAKE_S/e):.5;if(i&&n){const o=1/(1-s);return t<=s?o*t*t/(2*s):t>=1-s?1-o*(1-t)*(1-t)/(2*s):o*(t-s/2)}const r=o=>{const c=1/(1-s/2);if(o<=1-s)return c*o;const l=o-(1-s);return c*(1-s)+c*(l-l*l/(2*s))};return n?r(t):1-r(1-t)}static tangent(t,e,i,n){const s=t.length-1,r=f=>(e[f+1]-e[f])/(t[f+1]-t[f]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-1);const o=r(i-1),c=r(i);if(o*c<=0)return 0;const l=t[i]-t[i-1],h=t[i+1]-t[i],u=2*h+l,d=h+2*l;return(u+d)/(u/o+d/c)}}class Eo{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,pose:e}:this.keyframes.splice(i,0,{t,pose:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestPoseAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].pose:void 0}getInterpolatedPoseAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.pose;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.pose;if(!n)return i.pose;const s=iv(i.pose,n.pose,tv((t-i.t)/(n.t-i.t),0,1));return this.humanly(e-1,t,s)}humanly(t,e,i){const n=Math.max(0,t-1),s=Math.min(this.keyframes.length-1,t+2),r=this.keyframes.slice(n,s+1),o=t-n,c=r.map(S=>S.t),l=(S,M)=>{const b=r.map(w=>S(w.pose));if(!b.some(w=>w===void 0))return wr.at(c,b,o,e,M)},h=r.map(S=>S.pose.headingDeg);let u;if(h.every(S=>S!==void 0)){const S=[h[0]];for(let M=1;M<h.length;M++)S.push(S[M-1]+((h[M]-h[M-1])%360+540)%360-180);u=(wr.at(c,S,o,e,!0)%360+360)%360}const d=this.keyframes[t],f=this.keyframes[t+1],p=(S,M)=>S.lat===M.lat&&S.lng===M.lng&&S.elevationM===M.elevationM,v=!p(d.pose,f.pose),m=v&&t>0&&p(this.keyframes[t-1].pose,d.pose),g=v&&t+2<this.keyframes.length&&p(f.pose,this.keyframes[t+2].pose);let _;if(m||g){const S=wr.paced((e-d.t)/(f.t-d.t),(f.t-d.t)/1e3,m,g),M=(b,w)=>b===void 0||w===void 0?void 0:b+(w-b)*S;_={lat:M(d.pose.lat,f.pose.lat),lng:M(d.pose.lng,f.pose.lng),elevationM:M(d.pose.elevationM,f.pose.elevationM)}}return{...i,lat:_?_.lat:l(S=>S.lat,!1)??i.lat,lng:_?_.lng:l(S=>S.lng,!1)??i.lng,elevationM:_?_.elevationM:l(S=>S.elevationM,!1)??i.elevationM,headingDeg:u??i.headingDeg,pitchDeg:l(S=>S.pitchDeg,!0)??i.pitchDeg,rollDeg:l(S=>S.rollDeg??0,!0)??i.rollDeg,fovDeg:l(S=>S.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Eo;for(const i of t.keyframes)e.addKeyframe(i.t,i.pose);return e}}class zs{static MAX_CHANGE_PER_S=.05;points;followed;constructor(t){let e="none",i=0;this.points=t.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(e=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:e,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(zs.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.t)/1e3))}}at(t){if(this.points.length===0||t<this.points[0].t)return;let e=this.points.length-1;for(;e>0&&this.points[e].t>t;)e--;const i=this.points[e],n=this.points[e+1],s=n?zs.follow(this.followed[e],i.intensity,n.intensity,(n.t-i.t)/1e3,(t-i.t)/1e3):zs.follow(this.followed[e],i.intensity,i.intensity,1,(t-i.t)/1e3);return{type:zs.typeBetween(i,n,t,s),intensity:s,character:zs.characterBetween(i,n,t)}}static characterBetween(t,e,i){return t.type==="none"?e&&e.type!=="none"?e.intensity:t.lastFallingIntensity:!e||e.type==="none"?t.intensity:t.intensity+(e.intensity-t.intensity)*(i-t.t)/(e.t-t.t||1)}static typeBetween(t,e,i,n){return t.type==="none"?e&&e.type!=="none"&&i>t.t?e.type:n>0?t.lastFalling:"none":e&&e.type==="none"&&n<=0?"none":t.type}static follow(t,e,i,n,s){const r=zs.MAX_CHANGE_PER_S,o=n>0?(i-e)/n:0,c=u=>e+o*Math.min(Math.max(u,0),n);let l=t,h=0;for(let u=0;u<8&&h<s;u++){const d=c(h)-l;if(Math.abs(d)<1e-9){const S=h<n?o:0;if(Math.abs(S)<=r){const b=h<n?Math.min(s,n):s;l=c(b),h=b;continue}const M=Math.min(s,n);l+=Math.sign(S)*r*(M-h),h=M;continue}const f=Math.sign(d),p=h<n?o:0,v=r-f*p,m=v>0?h+Math.abs(d)/v:1/0,g=h<n?n:1/0,_=Math.min(s,m,g);l+=f*r*(_-h),h=_,_===m&&(l=c(h))}return Math.min(1,Math.max(0,l))}}function Ne(a,t,e){return a+(t-a)*e}function Vd(a,t,e){const i=((t-a)%360+540)%360-180;return((a+i*e)%360+360)%360}function nv(a,t,e){return Math.max(t,Math.min(e,a))}function sv(a=[],t=[],e){if(!(!a.length&&!t.length))return[...new Set([...a.map(i=>i.id),...t.map(i=>i.id)])].map(i=>{const n=a.find(c=>c.id===i),s=t.find(c=>c.id===i),r=n??{...s,density:0},o=s??{...n,density:0};return{...r,eastM:Ne(r.eastM,o.eastM,e),northM:Ne(r.northM,o.northM,e),baseM:Ne(r.baseM,o.baseM,e),thicknessM:Ne(r.thicknessM,o.thicknessM,e),widthM:Ne(r.widthM,o.widthM,e),depthM:Ne(r.depthM,o.depthM,e),rotationDeg:Vd(r.rotationDeg,o.rotationDeg,e),density:Ne(r.density,o.density,e),darkness:Ne(r.darkness??0,o.darkness??0,e)}})}function rv(a,t,e){if(a.cloudLayers===void 0&&t.cloudLayers===void 0)return;const i=ol(a),n=ol(t);return e>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const o=i.find(u=>u.id===r),c=n.find(u=>u.id===r),l=o??{...c,coverage:0},h=c??{...o,coverage:0};return{...l,instances:sv(o?.instances,c?.instances,e),baseM:Ne(l.baseM,h.baseM,e),thicknessM:Ne(l.thicknessM,h.thicknessM,e),coverage:Ne(l.coverage,h.coverage,e),sizeM:Ne(l.sizeM,h.sizeM,e),density:Ne(l.density,h.density,e),darkness:Ne(l.darkness??a.cloudDarkness,h.darkness??t.cloudDarkness,e),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Ne(l.iceCrystalAlignment,h.iceCrystalAlignment,e),windSpeed:l.windSpeed===void 0&&h.windSpeed===void 0?void 0:Ne(l.windSpeed??a.windSpeed,h.windSpeed??t.windSpeed,e),windDirectionDeg:l.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Vd(l.windDirectionDeg??a.windDirectionDeg,h.windDirectionDeg??t.windDirectionDeg,e)}})}function av(a,t,e){return{cloudLayers:rv(a,t,e),cloudCover:Ne(a.cloudCover,t.cloudCover,e),cloudDarkness:Ne(a.cloudDarkness,t.cloudDarkness,e),highCloudCover:a.highCloudCover===void 0||t.highCloudCover===void 0?void 0:Ne(a.highCloudCover,t.highCloudCover,e),iceCrystalAlignment:a.iceCrystalAlignment===void 0||t.iceCrystalAlignment===void 0?void 0:Ne(a.iceCrystalAlignment,t.iceCrystalAlignment,e),lowerCloudCover:a.lowerCloudCover===void 0||t.lowerCloudCover===void 0?void 0:Ne(a.lowerCloudCover,t.lowerCloudCover,e),cloudBaseM:a.cloudBaseM===void 0||t.cloudBaseM===void 0?void 0:Ne(a.cloudBaseM,t.cloudBaseM,e),relativeHumidity:a.relativeHumidity===void 0||t.relativeHumidity===void 0?void 0:Ne(a.relativeHumidity,t.relativeHumidity,e),precipitationType:e<1?a.precipitationType:t.precipitationType,precipitationIntensity:Ne(a.precipitationIntensity,t.precipitationIntensity,e),windDirectionDeg:Vd(a.windDirectionDeg,t.windDirectionDeg,e),windSpeed:Ne(a.windSpeed,t.windSpeed,e),storm:e<1?a.storm:t.storm}}class Ao{keyframes=[];ramp;addKeyframe(t,e){this.ramp=void 0;const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,weather:e}:this.keyframes.splice(i,0,{t,weather:e})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(t){this.ramp=void 0;const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestWeatherAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].weather:void 0}getInterpolatedWeatherAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.weather;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];return i?n?av(i.weather,n.weather,nv((t-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(t){const e=this.getInterpolatedWeatherAt(t);if(!e)return;const i=(this.ramp??=new zs(this.keyframes)).at(t);if(!i)return e;const{type:n,intensity:s,character:r}=i,o=r>0?Math.min(1,s/r):n==="none"?0:1;return{...e,precipitationType:n,precipitationIntensity:r,precipitationAmount:o}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Ao;for(const i of t.keyframes)e.addKeyframe(i.t,i.weather);return e}}class To{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,sound:e}:this.keyframes.splice(i,0,{t,sound:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}getLatestSoundAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].sound:void 0}getInterpolatedSoundAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.sound;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.sound;if(!n)return i.sound;const s=(t-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new To;for(const i of t.keyframes)e.addKeyframe(i.t,i.sound);return e}lerp(t,e,i){return{kind:i<1?t.kind:e.kind,volume:t.volume+(e.volume-t.volume)*i,pitchHz:t.pitchHz+(e.pitchHz-t.pitchHz)*i,src:i<1?t.src:e.src}}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}}const ov=100,cv={kind:"none",volume:0,pitchHz:ov};class pn{constructor(t){this.entries=t}static empty(){return new pn(new Map)}get size(){return this.entries.size}at(t){return this.entries.get(t)}paths(){return[...this.entries.keys()]}set(t,e){e.basis==="stated"&&e.rationale===void 0?this.entries.delete(t):this.entries.set(t,e)}clear(t){for(const e of this.entries.keys())(e===t||e.startsWith(`${t}.`))&&this.entries.delete(e)}static strip(t){const e=new pn(new Map);return{recording:pn.stripValue(t,[],e),provenance:e}}static restore(t,e){if(e.size===0)return t;const i=structuredClone(t);for(const n of e.paths()){const s=e.at(n),r=n.split("."),o=pn.holderOf(i,r);if(!o)continue;const c=r[r.length-1],l=o[c];l!==void 0&&(s.of!==void 0&&JSON.stringify(s.of)!==JSON.stringify(l)||(o[c]={value:l,...s.basis==="stated"?{}:{basis:s.basis},...s.rationale===void 0?{}:{rationale:s.rationale}}))}return i}static isWrapper(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&"value"in t}static stripValue(t,e,i){return pn.isWrapper(t)?(i.set(e.join("."),{basis:t.basis??"stated",...t.rationale===void 0?{}:{rationale:t.rationale},of:t.value}),pn.stripValue(t.value,e,i)):Array.isArray(t)?t.map((n,s)=>pn.stripValue(n,[...e,String(s)],i)):typeof t=="object"&&t!==null?Object.fromEntries(Object.entries(t).map(([n,s])=>[n,pn.stripValue(s,[...e,n],i)])):t}static holderOf(t,e){let i=t;for(const n of e.slice(0,-1)){if(typeof i!="object"||i===null)return;i=i[n]}return typeof i=="object"&&i!==null?i:void 0}}function gu(a){if(a.year!==void 0)return Date.UTC(a.year,(a.month??1)-1,a.day??1,a.hour??0,a.minute??0,a.second??0)}function q0(a){return(((a.day??0)*24+(a.hour??0))*60+(a.minute??0))*6e4+(a.second??0)*1e3}const lv=["year","month","day","hour","minute"],hv=["day","hour","minute"];function Y0(a,t){return t.filter(e=>a[e]!==void 0).join(",")}function uv(a){if(a.durationSeconds!==void 0)return a.durationSeconds*1e3;if(!a.time||!a.endTime)return;const t=a.time.year!==void 0&&a.endTime.year!==void 0,e=t?lv:hv,i=Y0(a.time,e);if(!(i===""||i!==Y0(a.endTime,e)))return t?gu(a.endTime)-gu(a.time):q0(a.endTime)-q0(a.time)}class Ll{constructor(t,e,i,n,s,r,o,c,l=[],h,u,d,f=[],p=[],v=[]){this.event=t,this.timeline=e,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,this.observer=r,this.id=o,this.weather=c,this.decor=l,this.weatherSource=h,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p,this.roads=v}provenance=pn.empty();account;interpretation;sway;vehicle;get observerCount(){return 1+this.decor.filter(t=>t.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return li.byId(this.instrumentId)}static create(t,e,i){return new Ll({eventType:"sighting",time:t,place:e},new Pl,new Eo,new Ao,new To,i)}}const dv=0,fv=0;function oi(a,t){const e=a.observerTrack.getInterpolatedPoseAt(t);if(e)return e;const i=a.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:dv,headingDeg:void 0,pitchDeg:fv,fovDeg:li.fieldOfViewDeg(a.instrument)}}function Na(a,t){return a.weatherTrack.getInterpolatedWeatherAt(t)??a.weather??Gd}function K0(a,t){return a.weatherTrack.getActualWeatherAt(t)??a.weather??Gd}function pv(a,t){return a.soundTrack.getInterpolatedSoundAt(t)??cv}class mv{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 $m=["nw","n","ne","e","se","s","sw","w"],gv=24,qo=8,vv=3,Mv=8;function Yo(a,t,e){const i=a.x-t.x,n=a.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 Fa(a){return{x:a.x+a.width/2,y:a.y+a.height/2}}const xv={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 rn{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-gv}},o=Fa(t.bounds),c={};for(const l of Object.keys(r))c[l]=Yo(r[l],o,t.angle);return c}static hitTestHandle(t,e,i=8,n=[...$m,"rotate"]){const s=rn.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=((rn.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=Fa(t),r=Yo(n,s,-e),{x:o,y:c,width:l,height:h}=t,u=xv[i];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(r.x,p-qo)),u.right&&(p=Math.max(r.x,d+qo)),u.top&&(f=Math.min(r.y,v-qo)),u.bottom&&(v=Math.max(r.y,f+qo)),{x:d,y:f,width:p-d,height:v-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=rn.resizeBounds(t.bounds,t.angle,e,i);if(t.kind==="oval")return{...t,bounds:r};const o=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*o,y:l.y*c}))}}static rotateShape(t,e){const i=Fa(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=Fa(t.bounds);return t.points.map(i=>Yo({x:t.bounds.x+i.x,y:t.bounds.y+i.y},e,t.angle))}static hitTestVertex(t,e,i=Mv){const n=rn.vertexPointsFor(t);let s,r=i;return n.forEach((o,c)=>{const l=Math.hypot(e.x-o.x,e.y-o.y);l<=r&&(r=l,s=c)}),s}static toLocalPoint(t,e){const i=Fa(t.bounds),n=Yo(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?rn.toLocalPoint(t,i):u),s=Math.min(...n.map(u=>u.x)),r=Math.min(...n.map(u=>u.y)),o=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:o-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=rn.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=rn.distanceToSegment(i,l,h);u<r&&(r=u,s=c)}const o=[...n.slice(0,s+1),i,...n.slice(s+1)];return{...t,points:o}}static distanceToSegment(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=n*n+s*s,o=r===0?0:Math.max(0,Math.min(1,((t.x-e.x)*n+(t.y-e.y)*s)/r)),c=e.x+o*n,l=e.y+o*s;return Math.hypot(t.x-c,t.y-l)}static deleteVertex(t,e){return t.points.length<=vv?t:{...t,points:t.points.filter((i,n)=>n!==e)}}}const vu=6,Ko=vu/2,$0=20,Z0=24,J0=9,j0=6,Q0=7,tf=6,kn=4;class Ro{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,o=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+J0*f),tf*f)-d:0,v=f>0?d*(1+Q0*f)-d:0,m=3*Z0*(t.blur??0)+1.5*$0*t.haloScale,g=Math.max(p,v,0)+m+2;return{x:r-h-g,y:o-u-g,width:2*(h+g),height:2*(u+g)}}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(${(Z0*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,o=i+s/2,c=n+r/2,l=Math.max(s,r)/2,h=Math.max(l*(1+J0*e),tf*e);if(h<=0)return;this.ctx.save(),this.ctx.globalCompositeOperation="lighter";const u=this.ctx.createRadialGradient(o,c,0,o,c,h);for(let d=0;d<=j0;d++){const f=d/j0,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(o,c,h,0,2*Math.PI),this.ctx.fill(),this.starPoints>0){const d=l*(1+Q0*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,v=o+Math.cos(p)*d,m=c+Math.sin(p)*d,g=this.ctx.createLinearGradient(o,c,v,m);g.addColorStop(0,this.withAlpha(t.color,e*.55)),g.addColorStop(.35,this.withAlpha(t.color,e*.22)),g.addColorStop(1,this.withAlpha(t.color,0)),this.ctx.strokeStyle=g,this.ctx.beginPath(),this.ctx.moveTo(o,c),this.ctx.lineTo(v,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,o=s/2;this.ctx.ellipse(e+r,i+o,r,o,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,o)=>{o===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=$0*t.haloScale,this.paintBase(t),this.ctx.restore()}paintSelectionHandles(t){this.paintHandleFrame(rn.handlePointsFor(t),{includeRotate:!0}),t.kind==="polygon"&&this.paintVertexHandles(t)}paintVertexHandles(t){this.ctx.fillStyle="#39f";for(const e of rn.vertexPointsFor(t))this.ctx.beginPath(),this.ctx.ellipse(e.x,e.y,kn,kn,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(t){this.paintOutline(rn.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=Ro.landmarkColour(s.residualDeg),o=s.selected?3:2;s.selected&&(n.strokeStyle="#fff",n.lineWidth=o+3,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,kn+2,kn+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,kn,kn,0,0,2*Math.PI),n.fill()),n.strokeStyle=r,n.lineWidth=o,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,kn+2,kn+2,0,0,2*Math.PI),n.stroke(),this.paintLabel(s.label,s.picture.x+kn+5,s.picture.y-kn-2,r)}i&&this.paintLabel(i,8,8,"#fff",13),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 o=r.measureText(t).width;r.fillStyle="rgba(0, 0, 0, 0.6)",r.fillRect(e-3,i-2,o+6,s+4),r.fillStyle=n,r.fillText(t,e,i),r.restore()}paintGroupHandles(t){this.paintHandleFrame(rn.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 $m){const n=t[i];this.ctx.fillRect(n.x-Ko,n.y-Ko,vu,vu)}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,Ko+1,Ko+1,0,0,2*Math.PI),this.ctx.fill())}}const ef=.05,nf=.08,sf=2,rf=3,yv=14,_v=.02;class Sv{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;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}}this.context.state==="suspended"&&this.context.resume()}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.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,ef);for(const{param:s,ratio:r}of t.pitch)s.setTargetAtTime(Math.min(e.pitchHz*r,i.sampleRate/2-1),n,ef)}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(t.destination),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(t.destination),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(t.destination),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 o=t.createGain();return o.gain.value=0,r.connect(o).connect(s.gain),i.connect(n).connect(s).connect(t.destination),i.start(),r.start(),{key:e,nodes:[n,s,o],sources:[i,r],volumeParam:o.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 o=n.createGain();o.gain.value=0,r.connect(o).connect(n.destination),r.start(),this.voice={key:e,nodes:[o],sources:[r],volumeParam:o.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*sf),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*sf),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*rf),t.sampleRate),i=e.getChannelData(0),n=Math.max(1,Math.floor(_v*t.sampleRate)),s=Math.round(rf*yv);for(let r=0;r<s;r++){const o=Math.floor(Math.random()*i.length),c=.4+Math.random()*.6;for(let l=0;l<n&&o+l<i.length;l++)i[o+l]=Math.max(i[o+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,nf/3);const n=i+nf;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()}}}}function cl(a){return[...a].sort((t,e)=>t.t-e.t)}function af(a,t){let e;for(const i of cl(a)){if(i.t>t)break;e=i}return e}const Zl=Math.PI/180,$o=180/Math.PI;class vs{constructor(t,e,i){this.kind=t,this.canvasHeightPx=e,this.fovDeg=i;const n=i*Zl/2;this.focalPx=t==="equidistant"?e/2/n:e/2/Math.tan(n)}focalPx;static of(t,e,i){return new vs(t.projection,e,i)}degToPx(t){const e=t*Zl;return this.kind==="equidistant"?this.focalPx*e:2*this.focalPx*Math.tan(e/2)}pxToDeg(t){return this.kind==="equidistant"?t/this.focalPx*$o:2*Math.atan(t/(2*this.focalPx))*$o}angleDegToRadiusPx(t){const e=t*Zl;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*$o:Math.atan(t/this.focalPx)*$o}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(Pe.angularWidthDeg(t))}}class Ki{static fovOf(t,e){return oi(t,e)?.fovDeg??li.fieldOfViewDeg(t.instrument)}static toAngular(t){this.eachKeyframe(t,(e,i)=>({...e,angular:i.ofBounds(e.bounds)}))}static toBounds(t){this.eachKeyframe(t,(e,i)=>{if(!e.angular)return e;const{width:n,height:s}=i.toBoundsSize(e.angular),r={x:e.bounds.x+(e.bounds.width-n)/2,y:e.bounds.y+(e.bounds.height-s)/2,width:n,height:s};if(e.kind!=="polygon")return{...e,bounds:r};const o=e.bounds.width===0?1:n/e.bounds.width,c=e.bounds.height===0?1:s/e.bounds.height;return{...e,bounds:r,points:e.points.map(l=>({x:l.x*o,y:l.y*c}))}})}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)<Ki.UNMOVED_PX&&Math.abs(s.y-e.bounds.y)<Ki.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=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,this.fovOf(t,e));return this.aimFrom(t,n,oi(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),o=e.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+o}}static toPosition(t){this.eachKeyframe(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 positionOf(t,e,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(t),o=this.shortestArc(e.azimuthDeg-s.headingDeg),c=e.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,o)-i.width/2,y:r.y-this.offAxisPx(n,c)-i.height/2}}static frameCentre(t){return{x:li.frameWidthPx(t.instrument,Pe.CANVAS_HEIGHT_PX)/2,y:Pe.CANVAS_HEIGHT_PX/2}}static shortestArc(t){return(t%360+540)%360-180}static offAxisPx(t,e){return Math.abs(e)>=Ki.OFF_CANVAS_DEG?Math.sign(e)*Ki.OFF_CANVAS_PX:t.angleDegToRadiusPx(e)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(t,e,i){const n=li.frameWidthPx(e,Pe.CANVAS_HEIGHT_PX)/2,s=li.frameWidthPx(t.instrument,Pe.CANVAS_HEIGHT_PX)/2,r=Pe.CANVAS_HEIGHT_PX/2;for(const o of[...t.timeline.allKeyframes]){const c=this.fovOf(t,o.t),l=i?.get(o.t)??c,h=vs.of(e,Pe.CANVAS_HEIGHT_PX,l),u=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,c);t.timeline.addKeyframe(o.t,o.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-n,v=f.y+f.height/2-r,m=Math.hypot(p,v),g=m===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,_={...f,x:s+p*g-f.width/2,y:r+v*g-f.height/2};return{...d,shape:{...d.shape,bounds:_}}}))}this.toBounds(t)}static eachKeyframe(t,e){const{timeline:i}=t;for(const n of[...i.allKeyframes]){const s=oi(t,n.t),r=this.fovOf(t,n.t),o=vs.of(t.instrument,Pe.CANVAS_HEIGHT_PX,r);i.addKeyframe(n.t,n.shapes.map(c=>({...c,shape:e(c.shape,o,s)})))}}}function bv(a){return pn.restore(wv(a),a.provenance)}function wv(a){return Ki.toAngular(a),Ki.toAim(a),{version:1,id:a.id,time:a.event.time,endTime:a.event.endTime,durationSeconds:a.event.durationSeconds,utcOffsetHours:a.event.utcOffsetHours,timeZone:a.event.timeZone,place:a.event.place,observer:a.observer,account:a.account,sway:a.sway,vehicle:a.vehicle,description:a.event.description,tags:a.event.tags,timeline:a.timeline.toJSON(),observerTrack:a.observerTrack.toJSON(),weatherTrack:a.weatherTrack.toJSON(),soundTrack:a.soundTrack.toJSON(),weather:a.weather,decor:a.decor,milestones:a.milestones.length>0?a.milestones:void 0,references:a.references.length>0?a.references:void 0,roads:a.roads.length>0?a.roads:void 0,weatherSource:a.weatherSource,instrument:a.instrumentId,exposureSeconds:a.exposureSeconds,interpretation:a.interpretation}}function Ev(a){const{recording:t,provenance:e}=pn.strip(a),i=Av(t);return i.provenance=e,i}function Av(a){const t=new Ll({eventType:"sighting",time:a.time,endTime:a.endTime,durationSeconds:a.durationSeconds,utcOffsetHours:a.utcOffsetHours,timeZone:a.timeZone,place:a.place,description:a.description,tags:a.tags},Pl.fromJSON(a.timeline),a.observerTrack?Eo.fromJSON(a.observerTrack):new Eo,a.weatherTrack?Ao.fromJSON(a.weatherTrack):new Ao,a.soundTrack?To.fromJSON(a.soundTrack):new To,a.observer&&{id:a.observer.id,title:a.observer.title,lastName:a.observer.lastName,firstNames:a.observer.firstNames},a.id,a.weather,a.decor??[],a.weatherSource,a.instrument,a.exposureSeconds??a.observerTrack?.keyframes.map(e=>e.pose.exposureSeconds).find(e=>e!==void 0),cl(a.milestones??[]),a.references??[],a.roads??[]);return t.account=a.account,t.sway=a.sway,t.vehicle=a.vehicle,t.interpretation=a.interpretation,Ki.toBounds(t),Ki.toPosition(t),t}class Tn{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?Tn.travelDegOver(t,e,i,i+n*1e3)/s/Tn.PIXELS_PER_INSTANT:0,o=Tn.flashesOver(t,n)*Tn.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(r,o));return c<2?1:Math.min(Tn.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 o=Tn.directionAt(r,e,i),c=Tn.directionAt(r,e,n),l=Math.min(1,Math.max(-1,o.x*c.x+o.y*c.y+o.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=bo(t,i),s=n.eastM,r=n.altitudeM-e,o=n.northM,c=Math.hypot(s,r,o);return c===0?{x:0,y:1,z:0}:{x:s/c,y:r/c,z:o/c}}}function ll(a,t){for(const e of a){const i=e.toLowerCase().split("-")[0];if(t.includes(i))return i}return"en"}class po{static preferencesFor(t){const e=navigator.languages??[],i=this.declaredFor(t);return i?[i,...e]:e}static declaredFor(t){for(let e=t;e;){const i=e.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const n=e.getRootNode();e=n instanceof ShadowRoot?n.host:void 0}}}class Vs{constructor(t){this.preferences=t}read(t){if(t===void 0||typeof t=="string")return t===""?void 0:t;for(const i of this.preferences){const n=t[i]??t[Vs.base(i)];if(n)return n}const e=new Set(this.preferences.map(i=>Vs.base(i)));for(const[i,n]of Object.entries(t))if(n&&e.has(Vs.base(i)))return n;return Object.values(t).find(i=>i)??void 0}write(t,e,i){const n=e?.trim()?e.trim():void 0;if(t===void 0||typeof t=="string")return n;const s={...t},r=Object.keys(s).find(o=>o===i)??Object.keys(s).find(o=>Vs.base(o)===Vs.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(t){return t.toLowerCase().split("-")[0]}}const Tv=["en","fr"],Rv={en:()=>sl(()=>Promise.resolve().then(()=>Cv),void 0,import.meta.url).then(a=>a.ufoMessages_en),fr:()=>sl(()=>import("./UfoMessages_fr-_6zR9Sw1.js"),[],import.meta.url).then(a=>a.ufoMessages_fr)};function Dv(a){return Rv[a]()}const Zm={play:"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",showObserverMap:"Show where the observer was",hideObserverMap:"Hide where the observer was",mapImageryUnavailable:"Aerial imagery unavailable",showReferences:"Show the pictures of the place",hideReferences:"Hide the pictures of the place",referenceOpacity:"Picture opacity",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",observerHere:"The observer, here",decorHere:"Scenery"},Cv=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Zm},Symbol.toStringTag,{value:"Module"})),Jm=Math.PI/180,Iv=180/Math.PI,Pv=256,jm=19,Lv=1.25;function Qm(a,t){return 156543.03392*Math.cos(a*Jm)/2**t}function tg(a,t){return Qm(a,t)*Pv}function Ov(a,t){let e=0;for(;e<jm&&tg(a,e+1)>=t;)e++;return e}function eg(a,t){return tg(a,t)}function Nv(a,t){const e=t*Lv;let i=0;for(;i<jm&&Qm(a,i)>e;)i++;return i}function Yc(a){const t=a*Jm;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}function ig(a,t,e){const i=2**e;return{x:(a+180)/360*i,y:Yc(t)*i}}function ng(a,t,e){const i=Yc(a.north),n=Yc(a.south);return{x:(t-a.west)/(a.east-a.west),y:(Yc(e)-i)/(n-i)}}function Fv(a,t,e){const{x:i,y:n}=ig(a,t,e);return{x:Math.floor(i),y:Math.floor(n),z:e}}function Uv(a){const t=2**a.z,e=a.x/t*360-180,i=(a.x+1)/t*360-180,n=of(a.y,t);return{south:of(a.y+1,t),north:n,west:e,east:i}}function of(a,t){const e=a/t;return Math.atan(Math.sinh(Math.PI*(1-2*e)))*Iv}function sg(a,t,e,i){const n=Fv(a,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 o=r.map(Uv),c={south:Math.min(...o.map(l=>l.south)),north:Math.max(...o.map(l=>l.north)),west:Math.min(...o.map(l=>l.west)),east:Math.max(...o.map(l=>l.east))};return{tiles:r,bounds:c}}class ur{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),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=ng(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()}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),o=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,o,c-l,c+l),s.closePath();const h=s.createRadialGradient(r.x,r.y,0,r.x,r.y,o);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:ur.MARKER_RADIUS_PX}),e.beginPath(),e.arc(n.x,n.y,ur.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 o=ci(r.lat,r.lng,e.lat,e.lng);return Math.hypot(o.x,o.z)<=ur.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?ur.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(ci(r,t.east,r,t.west).x)/this.width,l=ur.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}}const hn=256,cf=3,kv=32768;class zv{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(ci(i,t.east,i,t.west).x),r=Math.abs(ci(t.north,n,t.south,n).z),o=Ov(i,Math.max(s,r)),{tiles:c}=sg(n,i,o,cf),l=cf*hn,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 v=0;v<e.width;v++){const m=t.west+(t.east-t.west)*(v/(e.width-1));d[f*e.width+v]=this.sampleAt(p,m,o,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 o=await createImageBitmap(await r.blob()),c=document.createElement("canvas");c.width=hn,c.height=hn;const l=c.getContext("2d");if(!l)throw new Error("2D canvas context unavailable");l.drawImage(o,0,0);const{data:h}=l.getImageData(0,0,hn,hn),u=(t.x-e.x)*hn,d=(t.y-e.y)*hn;for(let f=0;f<hn;f++)for(let p=0;p<hn;p++){const v=(f*hn+p)*4,m=h[v]*256+h[v+1]+h[v+2]/256-kv,g=u+p,_=d+f;i[_*n+g]=m}}sampleAt(t,e,i,n,s,r){const{x:o,y:c}=ig(e,t,i),l=(o-n.x)*hn,h=(c-n.y)*hn,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),v=l-u,m=h-d,g=s[d*r+u],_=s[d*r+f],S=s[p*r+u],M=s[p*r+f],b=g+(_-g)*v,w=S+(M-S)*v;return b+(w-b)*m}}const Kc=256,Bv=5;async function Hv(a,t,e,i){const n=(a.south+a.north)/2,s=(a.west+a.east)/2,r=Math.abs(ci(n,a.east,n,a.west).x),o=Math.abs(ci(a.north,s,a.south,s).z),c=Math.max(r,o),{zoom:l,gridSize:h}=Gv(n,c,Math.max(t.width,t.height)),{tiles:u,bounds:d}=sg(s,n,l,h),f=h*Kc,p=document.createElement("canvas");p.width=f,p.height=f;const v=p.getContext("2d");if(!v)throw new Error("2D canvas context unavailable");const m=u[0];await Promise.all(u.map(async M=>{const b=e(M),w=await i(b);if(!w.ok)throw new Error(`Imagery tile fetch failed (${w.status}): ${b}`);const T=await createImageBitmap(await w.blob());v.drawImage(T,(M.x-m.x)*Kc,(M.y-m.y)*Kc)}));const g=Math.min(Math.max(t.width,t.height),f);if(g===f)return{source:p,width:f,height:f,bounds:d};const _=document.createElement("canvas");_.width=g,_.height=g;const S=_.getContext("2d");if(!S)throw new Error("2D canvas context unavailable");return S.drawImage(p,0,0,f,f,0,0,g,g),{source:_,width:g,height:g,bounds:d}}function Gv(a,t,e){let i=Nv(a,t/Math.max(1,e)),n=lf(a,i,t);for(;n>Bv&&i>0;)i--,n=lf(a,i,t);return{zoom:i,gridSize:n,mPerPixel:eg(a,i)/Kc}}function lf(a,t,e){const i=Math.ceil(e/2/eg(a,t));return Math.max(3,2*i+1)}class Vv{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 Hv(t,e,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class wn{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;static ENDPOINTS=["https://overpass-api.de/api/interpreter","https://overpass.kumi.systems/api/interpreter","https://overpass.private.coffee/api/interpreter"];fetchImpl;endpoints;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.endpoints=t.endpoints??wn.ENDPOINTS}static queue=Promise.resolve();static RETRY_MS=4e3;async getRoads(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];way["highway"~"^(${wn.DRIVABLE.join("|")})$"](${e});out geom;`;return this.waysFrom(await this.queued(()=>this.ask(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:wn.surfaceOf(s),widthM:wn.widthOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return e}queued(t){const e=wn.queue.then(t,t);return wn.queue=e.catch(()=>{}),e}async ask(t){let e;for(const i of this.endpoints)for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(t)}`);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,wn.RETRY_MS))}throw e??new Error("No Overpass instance answered")}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:wn.WIDTH_M[t.highway]??wn.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 Jl="https://ufoathome.org/roads/index.json";class Wd{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Wd.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(){return this.index??=this.fetchFirstAvailable(),this.index}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.69.0")}`,e=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(e&&e!==Jl?[e,Jl]:[Jl]).map(i=>i+t)}}function Wv(){return{elevation:new zv,imagery:rg(),roads:Xv()}}function rg(){return new Vv}function Xv(){return new Wd({fallback:new wn})}const qv=new Set,pa="show-observer-map",ma="hide-milestones";class Wi extends HTMLElement{static get observedAttributes(){return["src",pa,ma]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;static OBSERVER_MAP_MIN_SPAN_M=400;static OBSERVER_MAP_MARGIN=.6;static OBSERVER_MAP_IMAGERY_PX=768;fullscreenButton;observerMapButton;referencesButton;referenceOpacityInput;referencesShownState=!0;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;observerPath;observerMapBounds;observerMapImagery;observerMapImageryRequested=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Ll.create();sightingAudio=new Sv;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Zm;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.resizeObserverMap()};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=>{const e=this.observerMapTargetFrom(t);if(!e){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="default";return}this.observerMapCanvas.style.cursor="pointer",this.tooltip.textContent=e.label,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=>{const e=this.observerMapTargetFrom(t);if(e){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};constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${K1}</style>${Y1}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Ro(this.canvas.getContext("2d")),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),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 ur(this.observerMapCanvas.getContext("2d")),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");for(const e of[this.timeStartLabel,this.timeEndLabel])e.addEventListener("click",()=>this.toggleTimeDisplay()),e.addEventListener("keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),this.toggleTimeDisplay())});this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),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.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",e=>{this.seekSnapArmed=!0,this.nameMarkUnder(e)}),this.seekInput.addEventListener("pointerup",()=>{this.seekSnapArmed=!1}),this.seekInput.addEventListener("pointermove",e=>this.nameMarkUnder(e)),this.seekInput.addEventListener("pointerleave",()=>this.seekInput.removeAttribute("title")),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.canvas.addEventListener("click",e=>{this.enableClickToPlay&&(e.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause())}),this.canvas.addEventListener("dblclick",e=>{this.enableClickToPlay&&(e.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateMilestonesButton(),this.refresh(),this.loadLocaleMessages()}connectedCallback(){this.saidTexts=void 0;const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.observerMapResizeObserver?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(t,e,i){t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===pa&&this.applyObserverMapDefault(),t===ma&&this.setMilestonesShown(!this.hasAttribute(ma))}async loadFromSrc(t){this.sightingData=await Km.json(t)}get sightingData(){return bv(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Ev(t),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault()}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(){this.player.seekableDuration<=0||this.playbackState==="playing"||this.togglePlayPause()}pause(){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)}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.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.player.seek(this.player.time)}hostControls(t){const e=[this.milestonesButton,this.referenceOpacityInput,this.referencesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else for(const i of e)this.toolbar.appendChild(i)}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}toggleReferences(){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)),this.updateReferencesButton()}updateReferencesButton(){const t=this.currentSighting.references.length>0;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState,this.referencesButton.setAttribute("aria-pressed",String(this.referencesShownState));const e=this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=e,this.referencesButton.setAttribute("aria-label",e),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}dispatchReferenceView(){this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?cl(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),o=r?`${s} — ${r}`:s;return n.title=o,n.setAttribute("aria-label",o),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n}))}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=Wi.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const o=Number(r.dataset.t);Math.abs(o-t)>n||(!s||Math.abs(o-t)<Math.abs(s.t-t))&&(s={t:o,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?af(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,!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=Tn.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Wi.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Wi.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Wi.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Wi.EXPOSURE_STEP_PX),s=Math.min(Wi.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let o=0;o<s;o++)r.push(e.fromMs+e.ms*o/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,o]of i){const c=n.get(r);if(!c)continue;const l=c.bounds.x+c.bounds.width/2-(o.bounds.x+o.bounds.width/2),h=c.bounds.y+c.bounds.height/2-(o.bounds.y+o.bounds.height/2);s=Math.max(s,Math.hypot(l,h))}return s}shapeAt(t,e,i){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=li.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:qv;this.canvasRenderer.setStarPoints(li.starPointsOf(this.sighting.instrument));const n=(oi(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 o of s)for(const[,c]of o.shapes){const l=o.share,h=l===1?c:{...c,transparency:1-(1-c.transparency)*l};this.canvasRenderer.paintShape(this.shifted(h,r))}for(const[o,c]of s[0].shapes)!this.selectionShown||!i.has(o)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));if(this.selectionShown&&i.size>1){const o=rn.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.overlayPainter?.(this.canvasRenderer),this.mapShapeBounds=s.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(pv(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),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 mv(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;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*Wi.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.preventDefault(),this.togglePlayPause())};togglePlayPause(){this.player.seekableDuration<=0||(this.player.playbackState==="playing"?(this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh()):(this.sightingAudio.resume(),this.player.play()),this.updatePlayPauseButton(),this.flashPlayback())}flashPlayback(){const t=this.playbackFlash;t.textContent=this.player.playbackState==="playing"?"▶":"⏸",t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.playPauseButton.textContent=t?"⏸":"▶";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()}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()}toggleObserverMap(){this.setObserverMapOpen(this.observerMapPanel.hidden)}applyObserverMapDefault(){const t=this.getAttribute(pa),e=t===null?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 e=!this.observerMapPanel.hidden?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e)}updateObserverMap(){const t=this.observerPath!==void 0;if(this.observerPath=fa.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.observerPath.boundsAround(Wi.OBSERVER_MAP_MIN_SPAN_M,Wi.OBSERVER_MAP_MARGIN);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,e))&&(this.observerMapBounds=e,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryRequested=!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(){if(this.observerMapImageryRequested||!this.observerMapBounds)return;this.observerMapImageryRequested=!0;const t=rg(),e=this.observerMapBounds;try{const i=await t.getImageryTexture(e,{width:Wi.OBSERVER_MAP_IMAGERY_PX,height:Wi.OBSERVER_MAP_IMAGERY_PX});if(this.observerMapBounds!==e)return;this.observerMapImagery=i,this.observerMapImageryCredit=t.attribution}catch{this.observerMapImageryFailed=!0}this.paintObserverMap(this.currentTime)}get observerMapCredit(){return this.observerMapImageryCredit}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=Wi.OBSERVER_MAP_CLEARANCE_PX,o=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",o&&c),this.observerMapPanel.classList.contains("on-the-left")){!o&&(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=oi(this.currentSighting,t),i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?af(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?cl(this.currentSighting.milestones):[]){const o=oi(this.currentSighting,r.t);o?.lat===void 0||o.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:o.lat,lng:o.lng,current:r===s})}this.observerMapRenderer.paint({bounds:this.observerMapBounds,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?vs.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(li.aspectOf(i)):void 0,markers:n,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.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;const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=oi(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=bo(i,t),{lat:s,lng:r}=gs(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=oi(this.currentSighting,this.currentTime),s=vs.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.steadyObserver)}updateFullscreenButton(){const t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Vs(po.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=ll(po.preferencesFor(this),Tv);t!=="en"&&this.applyMessages(await Dv(t))}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;for(const i of[this.timeStartLabel,this.timeEndLabel])i.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(i.setAttribute("role","button"),i.setAttribute("tabindex","0")):(i.removeAttribute("role"),i.removeAttribute("tabindex"))}applyMessages(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateMilestonesButton()}updateTimeLabels(){const t=this.currentSighting.event,e=uv(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?gu(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.updateTimeLabelTitles()}formatPosition(t){if(this.realDurationMs===void 0)return Zo(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?uf(hf(this.realStartMs+i)):Zo(i)}formatEndOfTimeline(){return this.realDurationMs===void 0?Zo(this.currentSighting.timeline.duration):this.canShowClockTime?uf(hf(this.realStartMs+this.realDurationMs)):Zo(this.realDurationMs)}}function hf(a){const t=new Date(a);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function uf(a){if(a.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return a.second?`${t(a.hour)}:${t(a.minute??0)}:${t(a.second)}`:`${t(a.hour)}:${t(a.minute??0)}`}function Zo(a){const t=Math.round(a/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Mu="rr0-ufo";function ag(){customElements.get(Mu)||customElements.define(Mu,Wi)}/**
730
730
  * @license
731
731
  * Copyright 2010-2026 Three.js Authors
732
732
  * SPDX-License-Identifier: MIT
@@ -6543,7 +6543,7 @@ void main()
6543
6543
  if (ice <= 0.0) discard;
6544
6544
  gl_FragColor = vec4(iceHaloLight(dir, ice), 1.0);
6545
6545
  }
6546
- `,transparent:!0,blending:Pi,depthWrite:!1,side:Be,fog:!1}),this.object=new Rt(new ei(Ri.RADIUS,64,32),this.material),this.object.renderOrder=-1,this.object.frustumCulled=!1,this.object.visible=!1;const i=this.material.uniforms;this.deckUniforms={uSource:i.uSource,uUp:i.uUp,uStrength:i.uStrength,uTint:i.uTint,uMap:i.uMap,uGain:i.uGain,uHaloShown:{value:0}}}deckUniforms;shown=!1;hostedByDeck=!1;set hosted(t){this.hostedByDeck=t,this.show(this.shown)}show(t){this.shown=t,this.object.visible=t&&!this.hostedByDeck,this.deckUniforms.uHaloShown.value=t?1:0}get awaitingFirstDisplay(){return this.tracing&&!this.everDisplayed}setUrgent(t){this.urgent=t}set onReady(t){this.onRepaint=t}update(t,e,i,n,s,r){const o=this.material.uniforms;if(i<=0){o.uStrength.value=0,this.show(!1),this.stopWork();return}o.uSource.value.set(t.x,t.y,t.z).normalize(),o.uStrength.value=i,o.uTint.value.set(n[0],n[1],n[2]),o.uIceCover.value=s.cover,o.uIceHeight.value=s.layerHeight,this.show(this.everDisplayed),this.requestMap(e,r)}requestMap(t,e){if(!(!(Math.abs(t-this.mappedAltitudeDeg)<Ri.ALTITUDE_STEP_DEG)||!(Math.abs(e-this.mappedAlignment)<Ri.ALIGNMENT_STEP))){this.next=void 0;return}if(this.tracing){if(this.tracingFor(t,e)){this.next=void 0;return}if(!(!(Math.abs(t-this.pendingAltitudeDeg)<Ri.LEAP_ALTITUDE_DEG)||!(Math.abs(e-this.pendingAlignment)<Ri.LEAP_ALIGNMENT))){this.next={sourceAltitudeDeg:t,alignment:e};return}}this.next=void 0,this.pendingAltitudeDeg=t,this.pendingAlignment=e,this.sky.begin(t,e),this.tracing=!0,this.scheduleWork()}pendingAltitudeDeg=Number.NaN;pendingAlignment=Number.NaN;next;tracingFor(t,e){return this.tracing&&Math.abs(t-this.pendingAltitudeDeg)<Ri.ALTITUDE_STEP_DEG&&Math.abs(e-this.pendingAlignment)<Ri.ALIGNMENT_STEP}scheduleWork(){if(this.workHandle!==void 0)return;const t=()=>{if(this.workHandle=void 0,!this.tracing)return;const e=performance.now(),i=this.urgent?Ri.URGENT_BUDGET_MS:Ri.BUDGET_MS;do this.sky.trace(Ri.RAYS_PER_BATCH);while(this.sky.tracedRays<Ri.RAYS&&performance.now()-e<i);if(this.sky.tracedRays>=Ri.RAYS){this.publish(),this.tracing=!1,this.mappedAltitudeDeg=this.pendingAltitudeDeg,this.mappedAlignment=this.pendingAlignment;const s=this.next;s&&this.requestMap(s.sourceAltitudeDeg,s.alignment);return}this.workHandle=requestAnimationFrame(t)};this.workHandle=requestAnimationFrame(t)}stopWork(){this.workHandle!==void 0&&cancelAnimationFrame(this.workHandle),this.workHandle=void 0,this.tracing=!1,this.next=void 0}publish(){const e=this.sky.harvest().data;for(let i=0,n=0;n<e.length;i+=4,n+=3)this.texels[i]=Pn.toHalfFloat(e[n]),this.texels[i+1]=Pn.toHalfFloat(e[n+1]),this.texels[i+2]=Pn.toHalfFloat(e[n+2]),this.texels[i+3]=1;this.texture.needsUpdate=!0,this.everDisplayed=!0,this.show(this.material.uniforms.uStrength.value>0),this.onRepaint?.()}dispose(){this.stopWork(),this.texture.dispose(),this.object.geometry.dispose(),this.material.dispose()}}class gi{static MAX_CONCURRENT=24;static POINTS=8;static SEGMENTS=gi.POINTS-1;static ACROSS=3;static VERTICES_PER_SEGMENT=(gi.ACROSS-1)*6;static RADIUS=840;static MIN_HALF_WIDTH_DEG=.05;static BRIGHT_HALF_WIDTH_DEG=.22;object;positions;colors;meteors=[];radiantAltitudeDeg=0;radiantAzimuthDeg=0;constructor(){const t=gi.MAX_CONCURRENT*gi.SEGMENTS*gi.VERTICES_PER_SEGMENT;this.positions=new Float32Array(t*3),this.colors=new Float32Array(t*3);const e=new oe;e.setAttribute("position",new ee(this.positions,3)),e.setAttribute("color",new ee(this.colors,3)),e.setDrawRange(0,0),this.object=new Rt(e,new Mn({vertexColors:!0,transparent:!0,blending:Pi,depthWrite:!1,fog:!1,side:$i})),this.object.frustumCulled=!1}get schedule(){return this.meteors}setShower(t,e,i){this.meteors=t,this.radiantAltitudeDeg=e,this.radiantAzimuthDeg=i}update(t){const e=this.object.geometry;if(this.meteors.length===0){e.setDrawRange(0,0);return}const i=Er.aliveAt(this.meteors,t).slice(0,gi.MAX_CONCURRENT);let n=0;for(const{meteor:s,progress:r}of i){const o=this.radiantOf(s);if(!o)continue;const c=ri(o.altitudeDeg,o.azimuthDeg,1),[l,h]=this.basisAround(c),u=s.fromRadiantDeg+r*s.lengthDeg,d=Math.max(s.fromRadiantDeg,u-s.lengthDeg*.6),f=Math.min(1,(1-r)*2.5),p=this.turn(l,h,s.bearingDeg),v=(.15+.85*s.brightness)*f,m=S=>v*S**1.6,g=S=>this.onSphere(c,p,d+(u-d)*S),_=S=>gi.RADIUS*((gi.MIN_HALF_WIDTH_DEG+gi.BRIGHT_HALF_WIDTH_DEG*s.brightness*S)*Math.PI/180);for(let S=1;S<gi.POINTS;S++){const M=(S-1)/gi.SEGMENTS,b=S/gi.SEGMENTS;n=this.pushRibbon(n,g(M),g(b),_(M),_(b),m(M),m(b))}}e.setDrawRange(0,n),e.getAttribute("position").needsUpdate=!0,e.getAttribute("color").needsUpdate=!0}midpointOf(t){const e=this.radiantOf(t);if(!e)return;const i=ri(e.altitudeDeg,e.azimuthDeg,1),[n,s]=this.basisAround(i),r=this.turn(n,s,t.bearingDeg),o=this.onSphere(i,r,t.fromRadiantDeg+t.lengthDeg/2),c=Math.hypot(o.x,o.y,o.z)||1;return{altitudeDeg:Math.asin(o.y/c)*180/Math.PI,azimuthDeg:(Math.atan2(o.x,-o.z)*180/Math.PI+360)%360}}radiantOf(t){return t.radiant?t.radiant:this.radiantAltitudeDeg>0?{altitudeDeg:this.radiantAltitudeDeg,azimuthDeg:this.radiantAzimuthDeg}:void 0}pushRibbon(t,e,i,n,s,r,o){const c=this.normalise(this.cross(this.normalise(e),this.normalise(this.subtract(i,e))));for(let l=0;l<gi.ACROSS-1;l++){const h=l-1,u=l,d=this.across(e,c,n,h),f=this.across(i,c,s,h),p=this.across(e,c,n,u),v=this.across(i,c,s,u),m=(g,_)=>g===0?_:0;t=this.push(t,d,m(h,r)),t=this.push(t,f,m(h,o)),t=this.push(t,p,m(u,r)),t=this.push(t,f,m(h,o)),t=this.push(t,v,m(u,o)),t=this.push(t,p,m(u,r))}return t}across(t,e,i,n){return{x:t.x+e.x*i*n,y:t.y+e.y*i*n,z:t.z+e.z*i*n}}push(t,e,i){const n=t*3;this.positions[n]=e.x,this.positions[n+1]=e.y,this.positions[n+2]=e.z;const s=Et.relativeOfResponse(Math.max(0,Math.min(1,i)));return this.colors[n]=s*.9,this.colors[n+1]=s*.95,this.colors[n+2]=s,t+1}turn(t,e,i){const n=i*Math.PI/180,s=Math.cos(n),r=Math.sin(n);return{x:t.x*s+e.x*r,y:t.y*s+e.y*r,z:t.z*s+e.z*r}}onSphere(t,e,i){const n=i*Math.PI/180,s=Math.cos(n),r=Math.sin(n);return{x:(t.x*s+e.x*r)*gi.RADIUS,y:(t.y*s+e.y*r)*gi.RADIUS,z:(t.z*s+e.z*r)*gi.RADIUS}}basisAround(t){const e=Math.abs(t.y)<.9?{x:0,y:1,z:0}:{x:1,y:0,z:0},i=this.normalise(this.cross(t,e));return[i,this.normalise(this.cross(t,i))]}subtract(t,e){return{x:t.x-e.x,y:t.y-e.y,z:t.z-e.z}}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}}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}}dispose(){this.object.geometry.dispose(),this.object.material.dispose()}}class Ie{constructor(t,e={}){this.size=t,this.span=Math.min(t.lengthM,Math.max(0,e.spanM??t.lengthM)),this.bank=(t.lengthM-this.span)/2,this.deck=Math.min(t.heightM,e.deckThicknessM??Ie.DEFAULT_DECK_THICKNESS_M),this.railHeight=e.railing?.heightM??Ie.DEFAULT_RAILING_HEIGHT_M,this.postSpacing=Math.max(.3,e.railing?.postSpacingM??Ie.DEFAULT_POST_SPACING_M),this.rails=Math.max(0,Math.round(e.railing?.rails??Ie.DEFAULT_RAILS))}static DEFAULT_DECK_THICKNESS_M=1.2;static DEFAULT_RAILING_HEIGHT_M=1.05;static DEFAULT_POST_SPACING_M=1.5;static DEFAULT_RAILS=2;static BANK_SLOPE=1.5;static ABUTMENT_THICKNESS_M=1;static POST_SIDE_M=.08;static RAIL_HEIGHT_M=.08;static RAIL_DEPTH_M=.06;static BANK_STATIONS=12;static NATURAL_SIZE=Object.freeze({widthM:9,lengthM:40,heightM:6.5});span;bank;deck;railHeight;postSpacing;rails;roadAt(t){const e=Math.abs(t)-this.span/2;return e<=0?this.size.heightM:this.bank<=0?0:Math.max(0,this.size.heightM*(1-e/this.bank))}build(){const{widthM:t,heightM:e}=this.size,i=this.span/2,n=[];if(this.span>0){n.push(Ie.box(t,this.deck,this.span,0,e-this.deck/2,0));for(const c of[-1,1]){const l=e-this.deck;l>0&&this.bank>0&&n.push(Ie.box(t+1,l,Ie.ABUTMENT_THICKNESS_M,0,l/2,c*(i-Ie.ABUTMENT_THICKNESS_M/2)))}}const s=[];this.span>0&&s.push(Ie.box(t,.04,this.span,0,e+.02,0));const r=[];for(const c of[-1,1])this.bank<=0||(r.push(this.embankment(c)),s.push(this.bankRoad(c)));const o=[];for(const c of[-1,1])o.push(...this.railing(c*(t/2-Ie.POST_SIDE_M)));return{concrete:Ie.merge(n),road:Ie.merge(s),earth:Ie.merge(r),railing:Ie.merge(o)}}embankment(t){const e=this.size.widthM/2,i=this.stations(t),n=[],s=(l,h,u,d)=>{n.push(l.x,l.y,l.z,h.x,h.y,h.z,u.x,u.y,u.z,l.x,l.y,l.z,u.x,u.y,u.z,d.x,d.y,d.z)},r=l=>{const h=this.roadAt(l),u=e+Ie.BANK_SLOPE*h;return{leftFoot:new R(-u,0,l),leftTop:new R(-e,h,l),rightTop:new R(e,h,l),rightFoot:new R(u,0,l)}};for(let l=1;l<i.length;l++){const h=r(i[l-1]),u=r(i[l]),d=t>0,f=(p,v,m,g)=>d?s(p,v,m,g):s(g,m,v,p);f(h.leftFoot,h.leftTop,u.leftTop,u.leftFoot),f(h.leftTop,h.rightTop,u.rightTop,u.leftTop),f(h.rightTop,h.rightFoot,u.rightFoot,u.rightTop)}const o=r(i[0]);t>0?s(o.leftFoot,o.rightFoot,o.rightTop,o.leftTop):s(o.leftTop,o.rightTop,o.rightFoot,o.leftFoot);const c=new oe;return c.setAttribute("position",new ue(n,3)),c.computeVertexNormals(),c}bankRoad(t){const e=this.size.widthM/2,i=this.stations(t),n=[];for(let r=1;r<i.length;r++){const o=i[r-1],c=i[r],l=this.roadAt(o)+.02,h=this.roadAt(c)+.02,u=t>0?[[-e,l,o],[e,l,o],[e,h,c],[-e,h,c]]:[[-e,h,c],[e,h,c],[e,l,o],[-e,l,o]];for(const d of[0,2,1,0,3,2])n.push(...u[d])}const s=new oe;return s.setAttribute("position",new ue(n,3)),s.computeVertexNormals(),s}stations(t){const e=[];for(let i=0;i<=Ie.BANK_STATIONS;i++)e.push(t*(this.span/2+this.bank*i/Ie.BANK_STATIONS));return e}railing(t){const e=this.size.lengthM/2,i=Math.max(1,Math.round(this.size.lengthM/this.postSpacing)),n=[];for(let o=0;o<=i;o++)n.push(-e+this.size.lengthM*o/i);const s=[],r=Ie.POST_SIDE_M;for(const o of n)s.push(Ie.box(r,this.railHeight,r,t,this.roadAt(o)+this.railHeight/2,o));for(let o=1;o<=this.rails;o++){const c=this.railHeight*o/this.rails-Ie.RAIL_HEIGHT_M/2;for(let l=1;l<n.length;l++){const h=new R(t,this.roadAt(n[l-1])+c,n[l-1]),u=new R(t,this.roadAt(n[l])+c,n[l]);s.push(Ie.beam(h,u))}}return s}static box(t,e,i,n,s,r){return new Bi(t,e,i).translate(n,s,r)}static beam(t,e){const i=new R().subVectors(e,t),n=new Bi(Ie.RAIL_DEPTH_M,Ie.RAIL_HEIGHT_M,i.length()),s=new Zi().setFromUnitVectors(new R(0,0,1),i.clone().normalize()),r=new R().addVectors(t,e).multiplyScalar(.5);return n.applyMatrix4(new Zt().compose(r,s,new R(1,1,1)))}static merge(t){const e=t.map(c=>c.getIndex()?c.toNonIndexed():c),i=e.reduce((c,l)=>c+l.getAttribute("position").count,0),n=new Float32Array(i*3),s=new Float32Array(i*3);let r=0;for(const c of e){const l=c.getAttribute("position"),h=c.getAttribute("normal");n.set(l.array,r*3),h&&s.set(h.array,r*3),r+=l.count}const o=new oe;o.setAttribute("position",new ue(n,3)),o.setAttribute("normal",new ue(s,3));for(const c of t)c.dispose();for(const c of e)c.dispose();return o}}const Vh=Math.PI/180;function Oe(a,t,e,i,n=!1){const s=n?new Mn({color:new st(...e)}):new Ia({color:new st(...e)}),r=new Rt(t,s);return r.position.y=i,r.userData={emissive:n},r.castShadow=!n,r.receiveShadow=!n,a.add(r),r}const Wh=.25,q5=.002,Y5=100,K5=1500,$5=.25,Z5=1e3,J5=.15;function j5(a){const t=/^#([0-9a-f]{6})$/i.exec(a);if(!t)return[1,1,1];const e=parseInt(t[1],16);return[(e>>16&255)/255,(e>>8&255)/255,(e&255)/255]}const Q5=[.32,.32,.3],y1=[1,.85,.5],tw=[.25,.25,.25],_1=[1,.97,.85],ew=[.55,.68,.72],Yn=.03,Kn=.05,S1={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function Ui(a,t){return a?.[t]}function $n(a,t,e,i,n,s,r,o){if(o===void 0)return;const c=new Ia({color:new st(...ew),transparent:!0,opacity:o/100}),l=new Rt(new Bi(t,e,i),c);l.position.set(n,s,r),a.add(l)}const fn=.05,Xh=[.6,.58,.53],Kp=[.5,.5,.48];function ua(a,t,e,i,n,s,r,o){const c=new Ia({color:new st(...o),side:Be}),l=new Rt(new Bi(t,e,i),c);l.position.set(n,s,r),a.add(l)}function iw(a,t,e,i,n,s,r,o,c){const l=(i-s)/2,h=(p,v,m,g)=>{p<=0||(t?ua(a,p,v,fn,m,o+g,r,c):ua(a,fn,v,p,r,o+g,m,c))};h(e,l,0,i/2-l/2),h(e,l,0,-(i/2-l/2));const u=[...n].sort((p,v)=>p.center-v.center);let d=-e/2;for(const p of u){const m=p.center-p.main/2-d;h(m,s,d+m/2,0),d=p.center+p.main/2}const f=e/2-d;h(f,s,d+f/2,0)}function b1(a,t,e,i,n,s,r,o,c,l){const h=(i+n)/2,u=n-i,d=(f,p,v,m)=>{f.length===0?p?ua(a,v,u,fn,0,h,m,Xh):ua(a,fn,u,v,m,h,0,Xh):iw(a,p,v,u,f,s,m,h,Xh)};d(r,!0,t*2,-e+fn),d(o,!0,t*2,e-fn),d(c,!1,e*2,-t+fn),d(l,!1,e*2,t-fn),ua(a,t*2,fn,e*2,0,i+fn,0,Kp),ua(a,t*2,fn,e*2,0,n-fn,0,Kp)}function Fd(a,t,e,i){switch(a){case"front":return{x:0,z:-(e-i)};case"behind":return{x:0,z:e-i};case"left":return{x:-(t-i),z:0};case"right":return{x:t-i,z:0};case"front-left":return{x:-(t-i),z:-Zn};case"front-right":return{x:t-i,z:-Zn};case"behind-left":return{x:-(t-i),z:Zn};case"behind-right":return{x:t-i,z:Zn}}}function w1(a,t,e,i,n,s,r){const o=zd();o.scale.setScalar(i),o.rotation.y=S1[t];const{x:c,z:l}=Fd(t,n,s,r);o.position.set(c,e,l),a.add(o)}const Ud=6,kd=6,Gs=3,Qa=1.4,to=Gs*.5,E1=1.2,A1=.35,nw=.75,sw=1.6;function $p(a,t,e,i){const n=new Re,s=Math.max(1,a+1),r=s*Gs;Oe(n,new Bi(Ud,r,kd),[.55,.54,.5],r/2);const o=Ud/2,c=kd/2;for(let l=0;l<s;l++){const h=l*Gs+Gs/2;$n(n,Qa,to,Kn,0,h,-c-Yn,Ui(t,"front")),$n(n,Qa,to,Kn,0,h,c+Yn,Ui(t,"behind")),$n(n,Kn,to,Qa,-o-Yn,h,0,Ui(t,"left")),$n(n,Kn,to,Qa,o+Yn,h,0,Ui(t,"right"))}if(e){const l=Math.min(Math.max(i??0,0),s-1);w1(n,e,l*Gs,.72,o,c,E1);const h=u=>Ui(t,u)!==void 0?[{main:Qa,center:0}]:[];b1(n,o,c,l*Gs,(l+1)*Gs,to,h("front"),h("behind"),h("left"),h("right"))}return n}function Zp(){const a=new Re,t=[[0,0,.55,.5],[.4,.1,.35,.4],[-.35,-.2,.4,.38],[.1,-.4,.35,.36],[-.15,.4,.3,.34]];for(const[e,i,n,s]of t){const r=new ei(n,10,7);r.scale(1,.85,1),r.translate(e,0,i),Oe(a,r,[.26,.28,.17],s)}return a}function rw(a){const t=new Re,e=new Ie(ai.sizeOf(a),a.bridge).build();Oe(t,e.concrete,[.6,.6,.58],0);const i=Oe(t,e.road,[.2,.2,.21],0),n=Oe(t,e.earth,[.3,.36,.22],0);for(const s of[i,n])s.material.side=$i;return Oe(t,e.railing,[.5,.52,.55],0),t}function Jp(){const a=new Re;return Oe(a,new ns(.15,.22,2,8),[.32,.22,.14],1),Oe(a,new Ca(1.4,3,8),[.16,.32,.14],3.5),a}const jp=.275,aw=.35,ow=.9,cw=34,lw=8,hw=1.4;function Qp(){const a=new Re,t=new ei(jp,7,3,0,Math.PI*2,0,Math.PI/2);t.scale(1,aw/jp,1);const e=ai.repeatOnGrid(t,cw,ow,lw,hw),i=Oe(a,e,[.26,.28,.22],0);return i.castShadow=!0,i.userData.cropBasePositions=e.getAttribute("position").array.slice(),i.userData.cropVerticesPerClump=t.getAttribute("position").count,t.dispose(),a}function tm(){const a=new Re,t=new ei(1,7,3,0,Math.PI*2,0,Math.PI/2);return Oe(a,t,[.38,.36,.32],0),a}function em(a){const t=new Re;return Oe(t,new ns(.05,.08,5,8),[.28,.28,.3],2.5),Oe(t,new ei(.25,12,8),a?y1:Q5,5.1,!0),t}const uw=[.08,.08,.08],ks=.8,ra=1,Gn=1.7,qh=.6,or=.4,Fc=1.2,na=.7,Zn=.5,dw=Gn;function im(a,t,e){const i=new Re;Oe(i,new Bi(1.8,1.4,4.2),[.45,.14,.14],.7),Oe(i,new Bi(ks*2,qh,ra*2),[.4,.12,.12],Gn);for(const s of[-1.4,1.4])for(const r of[-.95,.95]){const o=Oe(i,new ns(.4,.4,.3,12),uw,.4);o.rotation.z=Math.PI/2,o.position.x=r,o.position.z=s}const n=a?_1:tw;for(const s of[-.7,.7])Oe(i,new ei(.15,8,6),n,.7,!0).position.set(s,.7,-2.1);if($n(i,Fc,or,Kn,0,Gn,-ra-Yn,Ui(t,"front")),$n(i,Fc,or,Kn,0,Gn,ra+Yn,Ui(t,"behind")),$n(i,Kn,or,na,-ks-Yn,Gn,-Zn,Ui(t,"front-left")),$n(i,Kn,or,na,-ks-Yn,Gn,Zn,Ui(t,"behind-left")),$n(i,Kn,or,na,ks+Yn,Gn,-Zn,Ui(t,"front-right")),$n(i,Kn,or,na,ks+Yn,Gn,Zn,Ui(t,"behind-right")),e){w1(i,e,nw,.5,ks,ra,A1);const s=(c,l)=>{const h=[];return Ui(t,c)!==void 0&&h.push({main:na,center:-Zn}),Ui(t,l)!==void 0&&h.push({main:na,center:Zn}),h},r=Ui(t,"front")!==void 0?[{main:Fc,center:0}]:[],o=Ui(t,"behind")!==void 0?[{main:Fc,center:0}]:[];b1(i,ks,ra,Gn-qh/2,Gn+qh/2,or,r,o,s("front-left","behind-left"),s("front-right","behind-right"))}return i}const nm=new Map;function sm(a,t){if(!a)return;const e=[[a.lengthM,t.lengthM],[a.heightM,t.heightM],[a.widthM,t.widthM]];for(const[i,n]of e)if(i!==void 0&&n>1e-6)return i/n}function Yh(a,t){return t>1e-6?a/t:1}const T1=[.95,.9,.82],rm=[.72,.74,.78];function am(){const a=new Re;Oe(a,new ns(.25,.3,1.5,10),rm,.75),Oe(a,new ei(.26,10,8),rm,1.74);const t=Oe(a,new Ca(.07,.16,8),T1,1.74);return t.rotation.x=-Math.PI/2,t.position.z=-.22,a}function zd(){const a=new Re;Oe(a,new ns(.25,.3,1.5,10),[.3,.3,.35],.75),Oe(a,new ei(.22,10,8),[.62,.52,.46],1.72);const t=Oe(a,new Ca(.07,.16,8),T1,1.72);return t.rotation.x=-Math.PI/2,t.position.z=-.2,a}const fw=17,om=18.5,Kh=[.16,.16,.18];function cm(){const a=new Re,t=Oe(a,new ns(1.8,1.8,om*2,10),Kh,0);t.rotation.x=Math.PI/2,Oe(a,new Bi(fw*2,.5,4.5),Kh,0);const e=Oe(a,new Bi(.4,5.5,4),Kh,3);return e.position.z=-om+2,a}class ai{static GROWS_FROM_GROUND=new Set(["tree","shrub","crop","mound"]);static groundUnderFootprint(t,e,i,n,s,r=0){const o=ai.sizeOf(t);if(r>o.heightM)return s(e,i);const c=(n??0)*Math.PI/180,l=Math.min(21,Math.max(2,Math.ceil(o.lengthM/.75)+1)),h=Math.min(21,Math.max(2,Math.ceil(o.widthM/.75)+1)),u=ai.GROWS_FROM_GROUND.has(t.kind);let d=u?1/0:-1/0;for(let f=0;f<l;f++){const p=(f/(l-1)-.5)*o.lengthM;for(let v=0;v<h;v++){const m=(v/(h-1)-.5)*o.widthM,g=e+Math.sin(c)*p+Math.cos(c)*m,_=i-Math.cos(c)*p+Math.sin(c)*m;d=u?Math.min(d,s(g,_)):Math.max(d,s(g,_))}}return Number.isFinite(d)?d:s(e,i)}static occupantView(t){const e=t.observerSide;if(!e)throw new Error("occupantView requires object.observerSide to be set");const{x:i,z:n}=t.kind==="vehicle"?Fd(e,ks,ra,A1):Fd(e,Ud/2,kd/2,E1),s=t.kind==="vehicle"?dw:(t.occupiedFloor??0)*Gs+sw,r=(t.headingDeg??0)-S1[e]/Vh,o=this.scaleFor(t);return{x:i*o.x,z:n*o.z,eyeY:s*o.y,headingDeg:r}}static BODY_NAME="decor-body";static bodyOf(t){return t.getObjectByName(ai.BODY_NAME)??t}static repeatOnGrid(t,e,i,n,s){const r=t.getAttribute("position"),o=t.getAttribute("normal"),c=t.getIndex();if(!c)throw new Error("repeatOnGrid needs an indexed geometry");const l=r.count,h=e*n,u=new Float32Array(l*h*3),d=new Float32Array(l*h*3),f=new Uint32Array(c.count*h),p=-((e-1)*i)/2,v=-((n-1)*s)/2;let m=0;for(let _=0;_<n;_++)for(let S=0;S<e;S++,m++){const M=v+_*s,b=p+S*i;for(let w=0;w<l;w++){const T=(m*l+w)*3;u[T]=r.getX(w)+M,u[T+1]=r.getY(w),u[T+2]=r.getZ(w)+b,d[T]=o.getX(w),d[T+1]=o.getY(w),d[T+2]=o.getZ(w)}for(let w=0;w<c.count;w++)f[m*c.count+w]=c.getX(w)+m*l}const g=new oe;return g.setAttribute("position",new ue(u,3)),g.setAttribute("normal",new ue(d,3)),g.setIndex(new a0(f,1)),g}static fitCropToGround(t,e){t.updateMatrixWorld(!0);const i=new R;t.traverse(n=>{const s=n,r=s.userData.cropBasePositions,o=s.userData.cropVerticesPerClump;if(!s.isMesh||!r||!o)return;const c=s.geometry.getAttribute("position"),l=new Zt().copy(s.matrixWorld).invert();for(let h=0;h<c.count;h+=o){i.set(r[h*3],0,r[h*3+2]).applyMatrix4(s.matrixWorld),i.y=e(i.x,i.z),i.applyMatrix4(l);for(let u=h;u<h+o;u++)c.setY(u,r[u*3+1]+i.y)}c.needsUpdate=!0,s.geometry.computeBoundingBox(),s.geometry.computeBoundingSphere()})}static paint(t,e){t.traverse(i=>{const n=i,s=n.userData;if(!n.isMesh||s?.emissive)return;const r=n.material;r?.color&&r.color.set(e)})}static build(t,e){const i=t.kind==="building"?$p(t.floors??G0,t.windows,t.observerSide,t.occupiedFloor):t.kind==="tree"?Jp():t.kind==="shrub"?Zp():t.kind==="bridge"?rw(t):t.kind==="crop"?Qp():t.kind==="mound"?tm():t.kind==="streetlight"?em(e):t.kind==="vehicle"?im(e,t.windows,t.observerSide):t.kind==="aircraft"?cm():t.kind==="entity"?am():zd();t.color&&this.paint(i,t.color);const n=this.scaleFor(t),s=new Re;return i.name=ai.BODY_NAME,i.scale.copy(n),s.add(i),t.headingDeg!==void 0&&(s.rotation.y=-t.headingDeg*Vh),this.addLights(s,t.lights),s}static scaleFor(t){const e=t.sizeM;if(!e||t.kind==="bridge")return new R(1,1,1);const i=this.naturalSize(t.kind,t.floors);return new R(e.widthM===void 0?1:Yh(e.widthM,i.widthM),e.heightM===void 0?1:Yh(e.heightM,i.heightM),e.lengthM===void 0?1:Yh(e.lengthM,i.lengthM))}static naturalSize(t,e){const i=t==="building"?Math.max(1,(e??G0)+1):0;if(t==="bridge")return Ie.NATURAL_SIZE;const n=`${t}:${i}`,s=nm.get(n);if(s)return s;const r=t==="building"?$p(i-1,void 0,void 0,void 0):t==="tree"?Jp():t==="shrub"?Zp():t==="crop"?Qp():t==="mound"?tm():t==="streetlight"?em(!1):t==="vehicle"?im(!1,void 0,void 0):t==="aircraft"?cm():t==="entity"?am():zd(),o=new zi().setFromObject(r),c={widthM:o.max.x-o.min.x,heightM:o.max.y-o.min.y,lengthM:o.max.z-o.min.z};return this.dispose(r),nm.set(n,c),c}static usesModel(t){return t.model!==void 0&&!(t.observerSide!==void 0&&Xm(t.kind))}static applyModel(t,e,i,n={}){const s=this.bodyOf(t),r=new Re;r.name=ai.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*Vh,i.updateMatrixWorld(!0);const o=new zi().setFromObject(i),c={lengthM:o.max.z-o.min.z,heightM:o.max.y-o.min.y,widthM:o.max.x-o.min.x},l=sm(e.sizeM,c)??sm(n.depictedSizeM,c)??1;i.scale.multiplyScalar(l);const h=o.getCenter(new R).multiplyScalar(l);i.position.x-=h.x,i.position.z-=h.z,i.position.y-=e.kind==="aircraft"?h.y:o.min.y*l,i.traverse(u=>{u instanceof Rt&&(u.castShadow=!0,u.receiveShadow=!0)}),r.add(i),s.parent?(s.parent.add(r),s.removeFromParent()):t.add(r),this.dispose(s)}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=j5(i.color),s=Oe(t,new ei(Wh,8,6),n,i.offsetM.y,!0);s.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),s.userData={emissive:!0,lightId:i.id,lightColor:n},s.visible=!1}}static setLights(t,e,i,n,s=0,r=1){if(!e||e.length===0)return;const o=new Map(e.map(u=>[u.id,u])),c=Math.max(1,n*q5/Wh),l=Wh*c,h=r/(Math.PI*l*l);for(const u of t.children){if(!(u instanceof Rt))continue;const d=u.userData.lightId;if(!d)continue;const f=o.get(d);if(!f)continue;const p=s>0?qm(f,i,i+s):V1(f,i)?1:0;u.visible=p>0;const v=u.material,m=u.userData.lightColor;if(m){const g=p*Y5*(f.intensity??1)*h;v.color.setRGB(m[0]*g,m[1]*g,m[2]*g)}u.scale.setScalar(c)}}static setLit(t,e,i,n=1){const[s,r,o]=e==="streetlight"?[K5,$5,y1]:[Z5,J5,_1],c=i?s*n/(Math.PI*r*r):0,l=[o[0]*c,o[1]*c,o[2]*c];t.traverse(h=>{const u=h.userData;!(h instanceof Rt)||!u.emissive||u.lightId||h.material.color.setRGB(...l)})}static dispose(t){t.traverse(e=>{if(!(e instanceof Rt))return;e.geometry.dispose();const i=e.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const $h="https://ufoathome.org/models/index.json";class pw{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??mw()}async entries(t){const e=await this.load();return t?e.filter(i=>i.kind===t):e}async entry(t){return(await this.load()).find(e=>e.id===t)}load(){return this.loading??=this.fetchFirstAvailable(),this.loading}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 mw(){const a=`?v=${encodeURIComponent("0.68.0")}`,t=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(t&&t!==$h?[t,$h]:[$h]).map(e=>e+a)}const gw=[{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 pw}];async function lm(a){const{GLTFLoader:t}=await sl(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-BumifFuq.js");return{GLTFLoader:i}},[],import.meta.url),e=new t;return new Promise((i,n)=>{e.load(a,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${a}: ${s instanceof Error?s.message:String(s)}`)))})}const R1=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class an{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(t,e){this.mesh=new Rt(new Hi(2,2),new ce({uniforms:{uColor:{value:new st(0,0,0)},uRadius:{value:1}},vertexShader:an.VERTEX,fragmentShader:an.FRAGMENT,transparent:!0,depthWrite:!1,blending:Pi,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*an.MIN_ANGLE_RAD),r=an.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(an.MAX_SHARE,e/r)}}static conserving(t){return Math.sqrt(t/(an.MAX_SHARE*an.FILL*Math.PI))}static VERTEX=`
6546
+ `,transparent:!0,blending:Pi,depthWrite:!1,side:Be,fog:!1}),this.object=new Rt(new ei(Ri.RADIUS,64,32),this.material),this.object.renderOrder=-1,this.object.frustumCulled=!1,this.object.visible=!1;const i=this.material.uniforms;this.deckUniforms={uSource:i.uSource,uUp:i.uUp,uStrength:i.uStrength,uTint:i.uTint,uMap:i.uMap,uGain:i.uGain,uHaloShown:{value:0}}}deckUniforms;shown=!1;hostedByDeck=!1;set hosted(t){this.hostedByDeck=t,this.show(this.shown)}show(t){this.shown=t,this.object.visible=t&&!this.hostedByDeck,this.deckUniforms.uHaloShown.value=t?1:0}get awaitingFirstDisplay(){return this.tracing&&!this.everDisplayed}setUrgent(t){this.urgent=t}set onReady(t){this.onRepaint=t}update(t,e,i,n,s,r){const o=this.material.uniforms;if(i<=0){o.uStrength.value=0,this.show(!1),this.stopWork();return}o.uSource.value.set(t.x,t.y,t.z).normalize(),o.uStrength.value=i,o.uTint.value.set(n[0],n[1],n[2]),o.uIceCover.value=s.cover,o.uIceHeight.value=s.layerHeight,this.show(this.everDisplayed),this.requestMap(e,r)}requestMap(t,e){if(!(!(Math.abs(t-this.mappedAltitudeDeg)<Ri.ALTITUDE_STEP_DEG)||!(Math.abs(e-this.mappedAlignment)<Ri.ALIGNMENT_STEP))){this.next=void 0;return}if(this.tracing){if(this.tracingFor(t,e)){this.next=void 0;return}if(!(!(Math.abs(t-this.pendingAltitudeDeg)<Ri.LEAP_ALTITUDE_DEG)||!(Math.abs(e-this.pendingAlignment)<Ri.LEAP_ALIGNMENT))){this.next={sourceAltitudeDeg:t,alignment:e};return}}this.next=void 0,this.pendingAltitudeDeg=t,this.pendingAlignment=e,this.sky.begin(t,e),this.tracing=!0,this.scheduleWork()}pendingAltitudeDeg=Number.NaN;pendingAlignment=Number.NaN;next;tracingFor(t,e){return this.tracing&&Math.abs(t-this.pendingAltitudeDeg)<Ri.ALTITUDE_STEP_DEG&&Math.abs(e-this.pendingAlignment)<Ri.ALIGNMENT_STEP}scheduleWork(){if(this.workHandle!==void 0)return;const t=()=>{if(this.workHandle=void 0,!this.tracing)return;const e=performance.now(),i=this.urgent?Ri.URGENT_BUDGET_MS:Ri.BUDGET_MS;do this.sky.trace(Ri.RAYS_PER_BATCH);while(this.sky.tracedRays<Ri.RAYS&&performance.now()-e<i);if(this.sky.tracedRays>=Ri.RAYS){this.publish(),this.tracing=!1,this.mappedAltitudeDeg=this.pendingAltitudeDeg,this.mappedAlignment=this.pendingAlignment;const s=this.next;s&&this.requestMap(s.sourceAltitudeDeg,s.alignment);return}this.workHandle=requestAnimationFrame(t)};this.workHandle=requestAnimationFrame(t)}stopWork(){this.workHandle!==void 0&&cancelAnimationFrame(this.workHandle),this.workHandle=void 0,this.tracing=!1,this.next=void 0}publish(){const e=this.sky.harvest().data;for(let i=0,n=0;n<e.length;i+=4,n+=3)this.texels[i]=Pn.toHalfFloat(e[n]),this.texels[i+1]=Pn.toHalfFloat(e[n+1]),this.texels[i+2]=Pn.toHalfFloat(e[n+2]),this.texels[i+3]=1;this.texture.needsUpdate=!0,this.everDisplayed=!0,this.show(this.material.uniforms.uStrength.value>0),this.onRepaint?.()}dispose(){this.stopWork(),this.texture.dispose(),this.object.geometry.dispose(),this.material.dispose()}}class gi{static MAX_CONCURRENT=24;static POINTS=8;static SEGMENTS=gi.POINTS-1;static ACROSS=3;static VERTICES_PER_SEGMENT=(gi.ACROSS-1)*6;static RADIUS=840;static MIN_HALF_WIDTH_DEG=.05;static BRIGHT_HALF_WIDTH_DEG=.22;object;positions;colors;meteors=[];radiantAltitudeDeg=0;radiantAzimuthDeg=0;constructor(){const t=gi.MAX_CONCURRENT*gi.SEGMENTS*gi.VERTICES_PER_SEGMENT;this.positions=new Float32Array(t*3),this.colors=new Float32Array(t*3);const e=new oe;e.setAttribute("position",new ee(this.positions,3)),e.setAttribute("color",new ee(this.colors,3)),e.setDrawRange(0,0),this.object=new Rt(e,new Mn({vertexColors:!0,transparent:!0,blending:Pi,depthWrite:!1,fog:!1,side:$i})),this.object.frustumCulled=!1}get schedule(){return this.meteors}setShower(t,e,i){this.meteors=t,this.radiantAltitudeDeg=e,this.radiantAzimuthDeg=i}update(t){const e=this.object.geometry;if(this.meteors.length===0){e.setDrawRange(0,0);return}const i=Er.aliveAt(this.meteors,t).slice(0,gi.MAX_CONCURRENT);let n=0;for(const{meteor:s,progress:r}of i){const o=this.radiantOf(s);if(!o)continue;const c=ri(o.altitudeDeg,o.azimuthDeg,1),[l,h]=this.basisAround(c),u=s.fromRadiantDeg+r*s.lengthDeg,d=Math.max(s.fromRadiantDeg,u-s.lengthDeg*.6),f=Math.min(1,(1-r)*2.5),p=this.turn(l,h,s.bearingDeg),v=(.15+.85*s.brightness)*f,m=S=>v*S**1.6,g=S=>this.onSphere(c,p,d+(u-d)*S),_=S=>gi.RADIUS*((gi.MIN_HALF_WIDTH_DEG+gi.BRIGHT_HALF_WIDTH_DEG*s.brightness*S)*Math.PI/180);for(let S=1;S<gi.POINTS;S++){const M=(S-1)/gi.SEGMENTS,b=S/gi.SEGMENTS;n=this.pushRibbon(n,g(M),g(b),_(M),_(b),m(M),m(b))}}e.setDrawRange(0,n),e.getAttribute("position").needsUpdate=!0,e.getAttribute("color").needsUpdate=!0}midpointOf(t){const e=this.radiantOf(t);if(!e)return;const i=ri(e.altitudeDeg,e.azimuthDeg,1),[n,s]=this.basisAround(i),r=this.turn(n,s,t.bearingDeg),o=this.onSphere(i,r,t.fromRadiantDeg+t.lengthDeg/2),c=Math.hypot(o.x,o.y,o.z)||1;return{altitudeDeg:Math.asin(o.y/c)*180/Math.PI,azimuthDeg:(Math.atan2(o.x,-o.z)*180/Math.PI+360)%360}}radiantOf(t){return t.radiant?t.radiant:this.radiantAltitudeDeg>0?{altitudeDeg:this.radiantAltitudeDeg,azimuthDeg:this.radiantAzimuthDeg}:void 0}pushRibbon(t,e,i,n,s,r,o){const c=this.normalise(this.cross(this.normalise(e),this.normalise(this.subtract(i,e))));for(let l=0;l<gi.ACROSS-1;l++){const h=l-1,u=l,d=this.across(e,c,n,h),f=this.across(i,c,s,h),p=this.across(e,c,n,u),v=this.across(i,c,s,u),m=(g,_)=>g===0?_:0;t=this.push(t,d,m(h,r)),t=this.push(t,f,m(h,o)),t=this.push(t,p,m(u,r)),t=this.push(t,f,m(h,o)),t=this.push(t,v,m(u,o)),t=this.push(t,p,m(u,r))}return t}across(t,e,i,n){return{x:t.x+e.x*i*n,y:t.y+e.y*i*n,z:t.z+e.z*i*n}}push(t,e,i){const n=t*3;this.positions[n]=e.x,this.positions[n+1]=e.y,this.positions[n+2]=e.z;const s=Et.relativeOfResponse(Math.max(0,Math.min(1,i)));return this.colors[n]=s*.9,this.colors[n+1]=s*.95,this.colors[n+2]=s,t+1}turn(t,e,i){const n=i*Math.PI/180,s=Math.cos(n),r=Math.sin(n);return{x:t.x*s+e.x*r,y:t.y*s+e.y*r,z:t.z*s+e.z*r}}onSphere(t,e,i){const n=i*Math.PI/180,s=Math.cos(n),r=Math.sin(n);return{x:(t.x*s+e.x*r)*gi.RADIUS,y:(t.y*s+e.y*r)*gi.RADIUS,z:(t.z*s+e.z*r)*gi.RADIUS}}basisAround(t){const e=Math.abs(t.y)<.9?{x:0,y:1,z:0}:{x:1,y:0,z:0},i=this.normalise(this.cross(t,e));return[i,this.normalise(this.cross(t,i))]}subtract(t,e){return{x:t.x-e.x,y:t.y-e.y,z:t.z-e.z}}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}}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}}dispose(){this.object.geometry.dispose(),this.object.material.dispose()}}class Ie{constructor(t,e={}){this.size=t,this.span=Math.min(t.lengthM,Math.max(0,e.spanM??t.lengthM)),this.bank=(t.lengthM-this.span)/2,this.deck=Math.min(t.heightM,e.deckThicknessM??Ie.DEFAULT_DECK_THICKNESS_M),this.railHeight=e.railing?.heightM??Ie.DEFAULT_RAILING_HEIGHT_M,this.postSpacing=Math.max(.3,e.railing?.postSpacingM??Ie.DEFAULT_POST_SPACING_M),this.rails=Math.max(0,Math.round(e.railing?.rails??Ie.DEFAULT_RAILS))}static DEFAULT_DECK_THICKNESS_M=1.2;static DEFAULT_RAILING_HEIGHT_M=1.05;static DEFAULT_POST_SPACING_M=1.5;static DEFAULT_RAILS=2;static BANK_SLOPE=1.5;static ABUTMENT_THICKNESS_M=1;static POST_SIDE_M=.08;static RAIL_HEIGHT_M=.08;static RAIL_DEPTH_M=.06;static BANK_STATIONS=12;static NATURAL_SIZE=Object.freeze({widthM:9,lengthM:40,heightM:6.5});span;bank;deck;railHeight;postSpacing;rails;roadAt(t){const e=Math.abs(t)-this.span/2;return e<=0?this.size.heightM:this.bank<=0?0:Math.max(0,this.size.heightM*(1-e/this.bank))}build(){const{widthM:t,heightM:e}=this.size,i=this.span/2,n=[];if(this.span>0){n.push(Ie.box(t,this.deck,this.span,0,e-this.deck/2,0));for(const c of[-1,1]){const l=e-this.deck;l>0&&this.bank>0&&n.push(Ie.box(t+1,l,Ie.ABUTMENT_THICKNESS_M,0,l/2,c*(i-Ie.ABUTMENT_THICKNESS_M/2)))}}const s=[];this.span>0&&s.push(Ie.box(t,.04,this.span,0,e+.02,0));const r=[];for(const c of[-1,1])this.bank<=0||(r.push(this.embankment(c)),s.push(this.bankRoad(c)));const o=[];for(const c of[-1,1])o.push(...this.railing(c*(t/2-Ie.POST_SIDE_M)));return{concrete:Ie.merge(n),road:Ie.merge(s),earth:Ie.merge(r),railing:Ie.merge(o)}}embankment(t){const e=this.size.widthM/2,i=this.stations(t),n=[],s=(l,h,u,d)=>{n.push(l.x,l.y,l.z,h.x,h.y,h.z,u.x,u.y,u.z,l.x,l.y,l.z,u.x,u.y,u.z,d.x,d.y,d.z)},r=l=>{const h=this.roadAt(l),u=e+Ie.BANK_SLOPE*h;return{leftFoot:new R(-u,0,l),leftTop:new R(-e,h,l),rightTop:new R(e,h,l),rightFoot:new R(u,0,l)}};for(let l=1;l<i.length;l++){const h=r(i[l-1]),u=r(i[l]),d=t>0,f=(p,v,m,g)=>d?s(p,v,m,g):s(g,m,v,p);f(h.leftFoot,h.leftTop,u.leftTop,u.leftFoot),f(h.leftTop,h.rightTop,u.rightTop,u.leftTop),f(h.rightTop,h.rightFoot,u.rightFoot,u.rightTop)}const o=r(i[0]);t>0?s(o.leftFoot,o.rightFoot,o.rightTop,o.leftTop):s(o.leftTop,o.rightTop,o.rightFoot,o.leftFoot);const c=new oe;return c.setAttribute("position",new ue(n,3)),c.computeVertexNormals(),c}bankRoad(t){const e=this.size.widthM/2,i=this.stations(t),n=[];for(let r=1;r<i.length;r++){const o=i[r-1],c=i[r],l=this.roadAt(o)+.02,h=this.roadAt(c)+.02,u=t>0?[[-e,l,o],[e,l,o],[e,h,c],[-e,h,c]]:[[-e,h,c],[e,h,c],[e,l,o],[-e,l,o]];for(const d of[0,2,1,0,3,2])n.push(...u[d])}const s=new oe;return s.setAttribute("position",new ue(n,3)),s.computeVertexNormals(),s}stations(t){const e=[];for(let i=0;i<=Ie.BANK_STATIONS;i++)e.push(t*(this.span/2+this.bank*i/Ie.BANK_STATIONS));return e}railing(t){const e=this.size.lengthM/2,i=Math.max(1,Math.round(this.size.lengthM/this.postSpacing)),n=[];for(let o=0;o<=i;o++)n.push(-e+this.size.lengthM*o/i);const s=[],r=Ie.POST_SIDE_M;for(const o of n)s.push(Ie.box(r,this.railHeight,r,t,this.roadAt(o)+this.railHeight/2,o));for(let o=1;o<=this.rails;o++){const c=this.railHeight*o/this.rails-Ie.RAIL_HEIGHT_M/2;for(let l=1;l<n.length;l++){const h=new R(t,this.roadAt(n[l-1])+c,n[l-1]),u=new R(t,this.roadAt(n[l])+c,n[l]);s.push(Ie.beam(h,u))}}return s}static box(t,e,i,n,s,r){return new Bi(t,e,i).translate(n,s,r)}static beam(t,e){const i=new R().subVectors(e,t),n=new Bi(Ie.RAIL_DEPTH_M,Ie.RAIL_HEIGHT_M,i.length()),s=new Zi().setFromUnitVectors(new R(0,0,1),i.clone().normalize()),r=new R().addVectors(t,e).multiplyScalar(.5);return n.applyMatrix4(new Zt().compose(r,s,new R(1,1,1)))}static merge(t){const e=t.map(c=>c.getIndex()?c.toNonIndexed():c),i=e.reduce((c,l)=>c+l.getAttribute("position").count,0),n=new Float32Array(i*3),s=new Float32Array(i*3);let r=0;for(const c of e){const l=c.getAttribute("position"),h=c.getAttribute("normal");n.set(l.array,r*3),h&&s.set(h.array,r*3),r+=l.count}const o=new oe;o.setAttribute("position",new ue(n,3)),o.setAttribute("normal",new ue(s,3));for(const c of t)c.dispose();for(const c of e)c.dispose();return o}}const Vh=Math.PI/180;function Oe(a,t,e,i,n=!1){const s=n?new Mn({color:new st(...e)}):new Ia({color:new st(...e)}),r=new Rt(t,s);return r.position.y=i,r.userData={emissive:n},r.castShadow=!n,r.receiveShadow=!n,a.add(r),r}const Wh=.25,q5=.002,Y5=100,K5=1500,$5=.25,Z5=1e3,J5=.15;function j5(a){const t=/^#([0-9a-f]{6})$/i.exec(a);if(!t)return[1,1,1];const e=parseInt(t[1],16);return[(e>>16&255)/255,(e>>8&255)/255,(e&255)/255]}const Q5=[.32,.32,.3],y1=[1,.85,.5],tw=[.25,.25,.25],_1=[1,.97,.85],ew=[.55,.68,.72],Yn=.03,Kn=.05,S1={front:0,behind:Math.PI,left:Math.PI/2,right:-Math.PI/2,"front-left":Math.PI/2,"behind-left":Math.PI/2,"front-right":-Math.PI/2,"behind-right":-Math.PI/2};function Ui(a,t){return a?.[t]}function $n(a,t,e,i,n,s,r,o){if(o===void 0)return;const c=new Ia({color:new st(...ew),transparent:!0,opacity:o/100}),l=new Rt(new Bi(t,e,i),c);l.position.set(n,s,r),a.add(l)}const fn=.05,Xh=[.6,.58,.53],Kp=[.5,.5,.48];function ua(a,t,e,i,n,s,r,o){const c=new Ia({color:new st(...o),side:Be}),l=new Rt(new Bi(t,e,i),c);l.position.set(n,s,r),a.add(l)}function iw(a,t,e,i,n,s,r,o,c){const l=(i-s)/2,h=(p,v,m,g)=>{p<=0||(t?ua(a,p,v,fn,m,o+g,r,c):ua(a,fn,v,p,r,o+g,m,c))};h(e,l,0,i/2-l/2),h(e,l,0,-(i/2-l/2));const u=[...n].sort((p,v)=>p.center-v.center);let d=-e/2;for(const p of u){const m=p.center-p.main/2-d;h(m,s,d+m/2,0),d=p.center+p.main/2}const f=e/2-d;h(f,s,d+f/2,0)}function b1(a,t,e,i,n,s,r,o,c,l){const h=(i+n)/2,u=n-i,d=(f,p,v,m)=>{f.length===0?p?ua(a,v,u,fn,0,h,m,Xh):ua(a,fn,u,v,m,h,0,Xh):iw(a,p,v,u,f,s,m,h,Xh)};d(r,!0,t*2,-e+fn),d(o,!0,t*2,e-fn),d(c,!1,e*2,-t+fn),d(l,!1,e*2,t-fn),ua(a,t*2,fn,e*2,0,i+fn,0,Kp),ua(a,t*2,fn,e*2,0,n-fn,0,Kp)}function Fd(a,t,e,i){switch(a){case"front":return{x:0,z:-(e-i)};case"behind":return{x:0,z:e-i};case"left":return{x:-(t-i),z:0};case"right":return{x:t-i,z:0};case"front-left":return{x:-(t-i),z:-Zn};case"front-right":return{x:t-i,z:-Zn};case"behind-left":return{x:-(t-i),z:Zn};case"behind-right":return{x:t-i,z:Zn}}}function w1(a,t,e,i,n,s,r){const o=zd();o.scale.setScalar(i),o.rotation.y=S1[t];const{x:c,z:l}=Fd(t,n,s,r);o.position.set(c,e,l),a.add(o)}const Ud=6,kd=6,Gs=3,Qa=1.4,to=Gs*.5,E1=1.2,A1=.35,nw=.75,sw=1.6;function $p(a,t,e,i){const n=new Re,s=Math.max(1,a+1),r=s*Gs;Oe(n,new Bi(Ud,r,kd),[.55,.54,.5],r/2);const o=Ud/2,c=kd/2;for(let l=0;l<s;l++){const h=l*Gs+Gs/2;$n(n,Qa,to,Kn,0,h,-c-Yn,Ui(t,"front")),$n(n,Qa,to,Kn,0,h,c+Yn,Ui(t,"behind")),$n(n,Kn,to,Qa,-o-Yn,h,0,Ui(t,"left")),$n(n,Kn,to,Qa,o+Yn,h,0,Ui(t,"right"))}if(e){const l=Math.min(Math.max(i??0,0),s-1);w1(n,e,l*Gs,.72,o,c,E1);const h=u=>Ui(t,u)!==void 0?[{main:Qa,center:0}]:[];b1(n,o,c,l*Gs,(l+1)*Gs,to,h("front"),h("behind"),h("left"),h("right"))}return n}function Zp(){const a=new Re,t=[[0,0,.55,.5],[.4,.1,.35,.4],[-.35,-.2,.4,.38],[.1,-.4,.35,.36],[-.15,.4,.3,.34]];for(const[e,i,n,s]of t){const r=new ei(n,10,7);r.scale(1,.85,1),r.translate(e,0,i),Oe(a,r,[.26,.28,.17],s)}return a}function rw(a){const t=new Re,e=new Ie(ai.sizeOf(a),a.bridge).build();Oe(t,e.concrete,[.6,.6,.58],0);const i=Oe(t,e.road,[.2,.2,.21],0),n=Oe(t,e.earth,[.3,.36,.22],0);for(const s of[i,n])s.material.side=$i;return Oe(t,e.railing,[.5,.52,.55],0),t}function Jp(){const a=new Re;return Oe(a,new ns(.15,.22,2,8),[.32,.22,.14],1),Oe(a,new Ca(1.4,3,8),[.16,.32,.14],3.5),a}const jp=.275,aw=.35,ow=.9,cw=34,lw=8,hw=1.4;function Qp(){const a=new Re,t=new ei(jp,7,3,0,Math.PI*2,0,Math.PI/2);t.scale(1,aw/jp,1);const e=ai.repeatOnGrid(t,cw,ow,lw,hw),i=Oe(a,e,[.26,.28,.22],0);return i.castShadow=!0,i.userData.cropBasePositions=e.getAttribute("position").array.slice(),i.userData.cropVerticesPerClump=t.getAttribute("position").count,t.dispose(),a}function tm(){const a=new Re,t=new ei(1,7,3,0,Math.PI*2,0,Math.PI/2);return Oe(a,t,[.38,.36,.32],0),a}function em(a){const t=new Re;return Oe(t,new ns(.05,.08,5,8),[.28,.28,.3],2.5),Oe(t,new ei(.25,12,8),a?y1:Q5,5.1,!0),t}const uw=[.08,.08,.08],ks=.8,ra=1,Gn=1.7,qh=.6,or=.4,Fc=1.2,na=.7,Zn=.5,dw=Gn;function im(a,t,e){const i=new Re;Oe(i,new Bi(1.8,1.4,4.2),[.45,.14,.14],.7),Oe(i,new Bi(ks*2,qh,ra*2),[.4,.12,.12],Gn);for(const s of[-1.4,1.4])for(const r of[-.95,.95]){const o=Oe(i,new ns(.4,.4,.3,12),uw,.4);o.rotation.z=Math.PI/2,o.position.x=r,o.position.z=s}const n=a?_1:tw;for(const s of[-.7,.7])Oe(i,new ei(.15,8,6),n,.7,!0).position.set(s,.7,-2.1);if($n(i,Fc,or,Kn,0,Gn,-ra-Yn,Ui(t,"front")),$n(i,Fc,or,Kn,0,Gn,ra+Yn,Ui(t,"behind")),$n(i,Kn,or,na,-ks-Yn,Gn,-Zn,Ui(t,"front-left")),$n(i,Kn,or,na,-ks-Yn,Gn,Zn,Ui(t,"behind-left")),$n(i,Kn,or,na,ks+Yn,Gn,-Zn,Ui(t,"front-right")),$n(i,Kn,or,na,ks+Yn,Gn,Zn,Ui(t,"behind-right")),e){w1(i,e,nw,.5,ks,ra,A1);const s=(c,l)=>{const h=[];return Ui(t,c)!==void 0&&h.push({main:na,center:-Zn}),Ui(t,l)!==void 0&&h.push({main:na,center:Zn}),h},r=Ui(t,"front")!==void 0?[{main:Fc,center:0}]:[],o=Ui(t,"behind")!==void 0?[{main:Fc,center:0}]:[];b1(i,ks,ra,Gn-qh/2,Gn+qh/2,or,r,o,s("front-left","behind-left"),s("front-right","behind-right"))}return i}const nm=new Map;function sm(a,t){if(!a)return;const e=[[a.lengthM,t.lengthM],[a.heightM,t.heightM],[a.widthM,t.widthM]];for(const[i,n]of e)if(i!==void 0&&n>1e-6)return i/n}function Yh(a,t){return t>1e-6?a/t:1}const T1=[.95,.9,.82],rm=[.72,.74,.78];function am(){const a=new Re;Oe(a,new ns(.25,.3,1.5,10),rm,.75),Oe(a,new ei(.26,10,8),rm,1.74);const t=Oe(a,new Ca(.07,.16,8),T1,1.74);return t.rotation.x=-Math.PI/2,t.position.z=-.22,a}function zd(){const a=new Re;Oe(a,new ns(.25,.3,1.5,10),[.3,.3,.35],.75),Oe(a,new ei(.22,10,8),[.62,.52,.46],1.72);const t=Oe(a,new Ca(.07,.16,8),T1,1.72);return t.rotation.x=-Math.PI/2,t.position.z=-.2,a}const fw=17,om=18.5,Kh=[.16,.16,.18];function cm(){const a=new Re,t=Oe(a,new ns(1.8,1.8,om*2,10),Kh,0);t.rotation.x=Math.PI/2,Oe(a,new Bi(fw*2,.5,4.5),Kh,0);const e=Oe(a,new Bi(.4,5.5,4),Kh,3);return e.position.z=-om+2,a}class ai{static GROWS_FROM_GROUND=new Set(["tree","shrub","crop","mound"]);static groundUnderFootprint(t,e,i,n,s,r=0){const o=ai.sizeOf(t);if(r>o.heightM)return s(e,i);const c=(n??0)*Math.PI/180,l=Math.min(21,Math.max(2,Math.ceil(o.lengthM/.75)+1)),h=Math.min(21,Math.max(2,Math.ceil(o.widthM/.75)+1)),u=ai.GROWS_FROM_GROUND.has(t.kind);let d=u?1/0:-1/0;for(let f=0;f<l;f++){const p=(f/(l-1)-.5)*o.lengthM;for(let v=0;v<h;v++){const m=(v/(h-1)-.5)*o.widthM,g=e+Math.sin(c)*p+Math.cos(c)*m,_=i-Math.cos(c)*p+Math.sin(c)*m;d=u?Math.min(d,s(g,_)):Math.max(d,s(g,_))}}return Number.isFinite(d)?d:s(e,i)}static occupantView(t){const e=t.observerSide;if(!e)throw new Error("occupantView requires object.observerSide to be set");const{x:i,z:n}=t.kind==="vehicle"?Fd(e,ks,ra,A1):Fd(e,Ud/2,kd/2,E1),s=t.kind==="vehicle"?dw:(t.occupiedFloor??0)*Gs+sw,r=(t.headingDeg??0)-S1[e]/Vh,o=this.scaleFor(t);return{x:i*o.x,z:n*o.z,eyeY:s*o.y,headingDeg:r}}static BODY_NAME="decor-body";static bodyOf(t){return t.getObjectByName(ai.BODY_NAME)??t}static repeatOnGrid(t,e,i,n,s){const r=t.getAttribute("position"),o=t.getAttribute("normal"),c=t.getIndex();if(!c)throw new Error("repeatOnGrid needs an indexed geometry");const l=r.count,h=e*n,u=new Float32Array(l*h*3),d=new Float32Array(l*h*3),f=new Uint32Array(c.count*h),p=-((e-1)*i)/2,v=-((n-1)*s)/2;let m=0;for(let _=0;_<n;_++)for(let S=0;S<e;S++,m++){const M=v+_*s,b=p+S*i;for(let w=0;w<l;w++){const T=(m*l+w)*3;u[T]=r.getX(w)+M,u[T+1]=r.getY(w),u[T+2]=r.getZ(w)+b,d[T]=o.getX(w),d[T+1]=o.getY(w),d[T+2]=o.getZ(w)}for(let w=0;w<c.count;w++)f[m*c.count+w]=c.getX(w)+m*l}const g=new oe;return g.setAttribute("position",new ue(u,3)),g.setAttribute("normal",new ue(d,3)),g.setIndex(new a0(f,1)),g}static fitCropToGround(t,e){t.updateMatrixWorld(!0);const i=new R;t.traverse(n=>{const s=n,r=s.userData.cropBasePositions,o=s.userData.cropVerticesPerClump;if(!s.isMesh||!r||!o)return;const c=s.geometry.getAttribute("position"),l=new Zt().copy(s.matrixWorld).invert();for(let h=0;h<c.count;h+=o){i.set(r[h*3],0,r[h*3+2]).applyMatrix4(s.matrixWorld),i.y=e(i.x,i.z),i.applyMatrix4(l);for(let u=h;u<h+o;u++)c.setY(u,r[u*3+1]+i.y)}c.needsUpdate=!0,s.geometry.computeBoundingBox(),s.geometry.computeBoundingSphere()})}static paint(t,e){t.traverse(i=>{const n=i,s=n.userData;if(!n.isMesh||s?.emissive)return;const r=n.material;r?.color&&r.color.set(e)})}static build(t,e){const i=t.kind==="building"?$p(t.floors??G0,t.windows,t.observerSide,t.occupiedFloor):t.kind==="tree"?Jp():t.kind==="shrub"?Zp():t.kind==="bridge"?rw(t):t.kind==="crop"?Qp():t.kind==="mound"?tm():t.kind==="streetlight"?em(e):t.kind==="vehicle"?im(e,t.windows,t.observerSide):t.kind==="aircraft"?cm():t.kind==="entity"?am():zd();t.color&&this.paint(i,t.color);const n=this.scaleFor(t),s=new Re;return i.name=ai.BODY_NAME,i.scale.copy(n),s.add(i),t.headingDeg!==void 0&&(s.rotation.y=-t.headingDeg*Vh),this.addLights(s,t.lights),s}static scaleFor(t){const e=t.sizeM;if(!e||t.kind==="bridge")return new R(1,1,1);const i=this.naturalSize(t.kind,t.floors);return new R(e.widthM===void 0?1:Yh(e.widthM,i.widthM),e.heightM===void 0?1:Yh(e.heightM,i.heightM),e.lengthM===void 0?1:Yh(e.lengthM,i.lengthM))}static naturalSize(t,e){const i=t==="building"?Math.max(1,(e??G0)+1):0;if(t==="bridge")return Ie.NATURAL_SIZE;const n=`${t}:${i}`,s=nm.get(n);if(s)return s;const r=t==="building"?$p(i-1,void 0,void 0,void 0):t==="tree"?Jp():t==="shrub"?Zp():t==="crop"?Qp():t==="mound"?tm():t==="streetlight"?em(!1):t==="vehicle"?im(!1,void 0,void 0):t==="aircraft"?cm():t==="entity"?am():zd(),o=new zi().setFromObject(r),c={widthM:o.max.x-o.min.x,heightM:o.max.y-o.min.y,lengthM:o.max.z-o.min.z};return this.dispose(r),nm.set(n,c),c}static usesModel(t){return t.model!==void 0&&!(t.observerSide!==void 0&&Xm(t.kind))}static applyModel(t,e,i,n={}){const s=this.bodyOf(t),r=new Re;r.name=ai.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*Vh,i.updateMatrixWorld(!0);const o=new zi().setFromObject(i),c={lengthM:o.max.z-o.min.z,heightM:o.max.y-o.min.y,widthM:o.max.x-o.min.x},l=sm(e.sizeM,c)??sm(n.depictedSizeM,c)??1;i.scale.multiplyScalar(l);const h=o.getCenter(new R).multiplyScalar(l);i.position.x-=h.x,i.position.z-=h.z,i.position.y-=e.kind==="aircraft"?h.y:o.min.y*l,i.traverse(u=>{u instanceof Rt&&(u.castShadow=!0,u.receiveShadow=!0)}),r.add(i),s.parent?(s.parent.add(r),s.removeFromParent()):t.add(r),this.dispose(s)}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=j5(i.color),s=Oe(t,new ei(Wh,8,6),n,i.offsetM.y,!0);s.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),s.userData={emissive:!0,lightId:i.id,lightColor:n},s.visible=!1}}static setLights(t,e,i,n,s=0,r=1){if(!e||e.length===0)return;const o=new Map(e.map(u=>[u.id,u])),c=Math.max(1,n*q5/Wh),l=Wh*c,h=r/(Math.PI*l*l);for(const u of t.children){if(!(u instanceof Rt))continue;const d=u.userData.lightId;if(!d)continue;const f=o.get(d);if(!f)continue;const p=s>0?qm(f,i,i+s):V1(f,i)?1:0;u.visible=p>0;const v=u.material,m=u.userData.lightColor;if(m){const g=p*Y5*(f.intensity??1)*h;v.color.setRGB(m[0]*g,m[1]*g,m[2]*g)}u.scale.setScalar(c)}}static setLit(t,e,i,n=1){const[s,r,o]=e==="streetlight"?[K5,$5,y1]:[Z5,J5,_1],c=i?s*n/(Math.PI*r*r):0,l=[o[0]*c,o[1]*c,o[2]*c];t.traverse(h=>{const u=h.userData;!(h instanceof Rt)||!u.emissive||u.lightId||h.material.color.setRGB(...l)})}static dispose(t){t.traverse(e=>{if(!(e instanceof Rt))return;e.geometry.dispose();const i=e.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const $h="https://ufoathome.org/models/index.json";class pw{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??mw()}async entries(t){const e=await this.load();return t?e.filter(i=>i.kind===t):e}async entry(t){return(await this.load()).find(e=>e.id===t)}load(){return this.loading??=this.fetchFirstAvailable(),this.loading}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 mw(){const a=`?v=${encodeURIComponent("0.69.0")}`,t=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(t&&t!==$h?[t,$h]:[$h]).map(e=>e+a)}const gw=[{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 pw}];async function lm(a){const{GLTFLoader:t}=await sl(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-BumifFuq.js");return{GLTFLoader:i}},[],import.meta.url),e=new t;return new Promise((i,n)=>{e.load(a,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${a}: ${s instanceof Error?s.message:String(s)}`)))})}const R1=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class an{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(t,e){this.mesh=new Rt(new Hi(2,2),new ce({uniforms:{uColor:{value:new st(0,0,0)},uRadius:{value:1}},vertexShader:an.VERTEX,fragmentShader:an.FRAGMENT,transparent:!0,depthWrite:!1,blending:Pi,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*an.MIN_ANGLE_RAD),r=an.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(an.MAX_SHARE,e/r)}}static conserving(t){return Math.sqrt(t/(an.MAX_SHARE*an.FILL*Math.PI))}static VERTEX=`
6547
6547
  uniform float uRadius;
6548
6548
  varying vec2 vOffset;
6549
6549
  void main() {
@@ -7168,4 +7168,4 @@ void main() {
7168
7168
  gl_FragColor = vec4(color, tex.a * uOpacity * (1.0 - blur * 0.5));
7169
7169
  }
7170
7170
  `;function km(a){const e=document.createElement("canvas");e.width=128,e.height=128;const i=e.getContext("2d"),n=128/2-2,s=128/2,r=128/2,o="#010101",c="#f4f1e2";i.fillStyle=o,i.beginPath(),i.arc(s,r,n,0,Math.PI*2),i.fill();const l=da(a.illuminatedFraction,0,1),h=a.phaseFraction<.5,u=n*Math.abs(1-2*l),d=l<.5;return i.save(),i.beginPath(),i.arc(s,r,n,0,Math.PI*2),i.clip(),i.fillStyle=c,i.beginPath(),h?(i.arc(s,r,n,-Math.PI/2,Math.PI/2,!1),i.ellipse(s,r,u,n,0,Math.PI/2,-Math.PI/2,d)):(i.arc(s,r,n,Math.PI/2,-Math.PI/2,!1),i.ellipse(s,r,u,n,0,-Math.PI/2,Math.PI/2,d)),i.fill(),i.restore(),new Es(e)}function pE(a){const t=document.createElement("canvas");t.width=128,t.height=128;const e=t.getContext("2d");return e.fillStyle="rgba(0, 0, 0, 0.55)",e.beginPath(),e.arc(64,64,60,0,Math.PI*2),e.fill(),e.fillStyle="#ffffff",e.font="bold 52px sans-serif",e.textAlign="center",e.textBaseline="middle",e.fillText(a,64,68),new Es(t)}function lu(a){let t=a;return function(){t|=0,t=t+1831565813|0;let i=Math.imul(t^t>>>15,1|t);return i=i+Math.imul(i^i>>>7,61|i)^i,((i^i>>>14)>>>0)/4294967296}}const hu=7.5,uu=9;class Vn{static cache=new Map;static load(t){let e=Vn.cache.get(t);return e||(e=fetch(t).then(i=>i.arrayBuffer()).then(i=>Vn.parse(i)),Vn.cache.set(t,e)),e}static upTo(t,e){const i=t.filter((r,o)=>o===0||t[o-1].magnitudeLimit<e);if(i.length<=1)return Vn.load(t[0].url);const n=i.map(r=>r.url).join(`
7171
- `);let s=Vn.cache.get(n);return s||(s=Promise.all(i.map(r=>Vn.load(r.url))).then(r=>r.reduce((o,c)=>Vn.concat(o,c))),Vn.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)}}}const mE="“Thunder” by Jerimee",gE="https://creativecommons.org/licenses/by/3.0/",vE="CC BY 3.0";class Wn{static fill(t,e){t.innerHTML="";const i=l=>t.appendChild(l),n=e.currentTerrainAttribution;n&&i(Wn.text(n));const s=e.currentRoadAttribution;s&&i(Wn.text(s));const r=e.ufoElement.observerMapCredit;r&&!n?.includes(r)&&i(Wn.text(r));for(const l of e.decorModelCredits){const h=l.author?` — ${l.author}`:"",u=document.createElement("li");l.sourceUrl?u.append(Wn.link(l.sourceUrl,l.title),document.createTextNode(`${h} (${l.license})`)):u.textContent=`${l.title}${h} (${l.license})`,i(u)}for(const l of e.ufoElement.sighting.references){if(!l.credit)continue;const h=document.createElement("li");l.creditUrl?h.appendChild(Wn.link(l.creditUrl,l.credit)):h.textContent=l.credit,i(h)}const o=e.satelliteState;if(o.status==="ready"&&o.credit){const l=document.createElement("li");l.appendChild(Wn.link(o.creditUrl??"",o.credit)),i(l)}const c=Wn.text(`${mE} (`);c.append(Wn.link(gE,vE),document.createTextNode(")")),i(c)}static text(t){const e=document.createElement("li");return e.textContent=t,e}static link(t,e){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener",i.textContent=e,i}}const ME=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,xE=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,yE=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,_E=20,SE=1;class bE{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};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}}this.context.state==="suspended"&&this.context.resume()}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(ME,this.ambientVolume).then(o=>this.applyIfCurrent(o,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/_E,1);const s=i>SE;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(xE,this.windVolume).then(o=>this.applyIfCurrent(o,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(yE,.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.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(i.destination),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(i.destination),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 fs{constructor(t){this.elements=t;const{eccentricity:e,perihelionAu:i}=t,[n,s]=this.perifocalAxes(),r=Math.sqrt(fs.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*fs.stumpffC(n),o=e-i*i*i/Math.sqrt(fs.SUN_GM_AU3_PER_DAY2)*fs.stumpffS(n);return{x:r*this.perihelionPosition.x+o*this.perihelionVelocity.x,y:r*this.perihelionPosition.y+o*this.perihelionVelocity.y,z:r*this.perihelionPosition.z+o*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(fs.SUN_GM_AU3_PER_DAY2)*Math.abs(t),n=o=>{const c=this.inverseSemiMajorAxis*o*o,l=this.elements.perihelionAu;return(1-this.inverseSemiMajorAxis*l)*o*o*o*fs.stumpffS(c)+l*o};let s=Math.max(1,i/this.elements.perihelionAu);for(;n(s)<i;)s*=2;let r=0;for(let o=0;o<fs.MAX_ITERATIONS&&s-r>1e-13*Math.max(1,s);o++){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),o=Math.sin(e),c=Math.cos(i),l=Math.sin(i);return[{x:n*r-s*o*c,y:s*r+n*o*c,z:o*l},{x:-n*o-s*r*c,y:-s*o+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 I1=[{id:"halley-1910",designation:"1P/Halley",name:{en:"Halley's Comet",fr:"comète de Halley"},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:{en:"Comet Brooks",fr:"comète 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:{en:"Comet Skjellerup-Maristany",fr:"comète 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:{en:"Comet de Kock-Paraskevopoulos",fr:"comète 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:{en:"the Southern Comet",fr:"comète australe"},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:{en:"the Eclipse Comet",fr:"comète de l'éclipse"},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:{en:"Comet Arend-Roland",fr:"comète 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:{en:"Comet Mrkos",fr:"comète 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:{en:"Comet Seki-Lines",fr:"comète 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:{en:"Comet Ikeya-Seki",fr:"comète 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:{en:"Comet Bennett",fr:"comète 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:{en:"Comet White-Ortiz-Bolelli",fr:"comète 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:{en:"Comet Kohoutek",fr:"comète 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:{en:"Comet West",fr:"comète 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:{en:"Comet IRAS-Araki-Alcock",fr:"comète 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:{en:"Halley's Comet",fr:"comète de Halley"},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:{en:"Comet Hyakutake",fr:"comète 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:{en:"Comet Hale-Bopp",fr:"comète 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:{en:"Comet McNaught",fr:"comète 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:{en:"Comet Lovejoy",fr:"comète 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:{en:"Comet PANSTARRS",fr:"comète 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:{en:"Comet NEOWISE",fr:"comète 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:{en:"Comet Tsuchinshan-ATLAS",fr:"comète 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 wE{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 I1.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=Ve(e),s=this.earthPositionAt(n),r=this.apparentPositionOf(t,2451545+n.tt,s),o=this.subtract(r,s),c=this.length(r),l=this.length(o),h=this.tailEndAt(t,r,s,c,n,e,i),u=this.horizontalOf(o,n,e,i);return{apparition:t,position:u,...h,heliocentricDistanceAu:c,earthDistanceAu:l,elongationDeg:this.angleBetween(o,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,o){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,o),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 o=this.length(this.subtract(s,i))/this.LIGHT_SPEED_AU_PER_DAY;s=n.positionAt(e-o)}return s}static horizontalOf(t,e,i,n){const s=wa(m5(),new Le(t.x,t.y,t.z,e)),r=wa(v1(e),s),o=Kb(e,new E0(n.lat,n.lng,n.elevationM)),c=new Le(r.x-o.x,r.y-o.y,r.z-o.z,e),l=T0(c);return R0(l.ra,l.dec,i,n)}static earthPositionAt(t){return wa(p5(),Zs(bt.Earth,t))}static julianDayOf(t){return 2451545+Ve(t).tt}static orbitOf(t){const e=this.orbits.get(t.id);if(e)return e;const i=new fs(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 du=[{id:"sn-1006",kind:"supernova",designation:"SN 1006",name:{en:"Supernova of 1006",fr:"supernova de 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:{en:"Supernova of 1054",fr:"supernova de 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:{en:"Supernova of 1181",fr:"supernova de 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:{en:"Tycho's Supernova",fr:"supernova de Tycho"},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:{en:"Kepler's Supernova",fr:"supernova de Kepler"},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:{en:"Nova Coronae Borealis 1866",fr:"nova de la Couronne boréale 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:{en:"Nova Aurigae 1891",fr:"nova du Cocher 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:{en:"Nova Persei 1901",fr:"nova de Persée 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:{en:"Nova Geminorum 1912",fr:"nova des Gémeaux 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:{en:"Nova Aquilae 1918",fr:"nova de l'Aigle 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:{en:"Nova Cygni 1920",fr:"nova du Cygne 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:{en:"Nova Pictoris 1925",fr:"nova du Peintre 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:{en:"Nova Herculis 1934",fr:"nova d'Hercule 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:{en:"Nova Lacertae 1936",fr:"nova du Lézard 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:{en:"Nova Puppis 1942",fr:"nova de la Poupe 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:{en:"Nova Coronae Borealis 1946",fr:"nova de la Couronne boréale 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:{en:"Nova Herculis 1960",fr:"nova d'Hercule 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:{en:"Nova Herculis 1963",fr:"nova d'Hercule 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:{en:"Nova Delphini 1967",fr:"nova du Dauphin 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:{en:"Nova Vulpeculae 1968",fr:"nova du Petit Renard 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:{en:"Nova Serpentis 1970",fr:"nova du Serpent 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:{en:"Nova Cygni 1975",fr:"nova du Cygne 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:{en:"Nova Centauri 1986",fr:"nova du Centaure 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:{en:"Supernova 1987A",fr:"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:{en:"Nova Cygni 1992",fr:"nova du Cygne 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:{en:"Nova Velorum 1999",fr:"nova des Voiles 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:{en:"Nova Aquilae 1999",fr:"nova de l'Aigle 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:{en:"Nova Sagittarii 2002",fr:"nova du Sagittaire 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:{en:"Nova Ophiuchi 2006",fr:"nova d'Ophiuchus 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:{en:"Nova Scorpii 2007",fr:"nova du Scorpion 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:{en:"Nova Delphini 2013",fr:"nova du Dauphin 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:{en:"Nova Centauri 2013",fr:"nova du Centaure 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:{en:"Nova Ophiuchi 2021",fr:"nova d'Ophiuchus 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 zm{static UNIX_EPOCH_JD=24405875e-1;static aroundDate(t){const e=this.julianDayOf(t);return du.filter(i=>this.magnitudeAt(i,e)!==void 0)}static appearancesAt(t,e){const i=this.julianDayOf(t),n=[];for(const s of du){const r=this.magnitudeAt(s,i);r!==void 0&&n.push({outburst:s,position:Rn.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 du.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,o]=i[s-1]??i[0],[c,l]=i[s]??i[0];if(c===r)return o;const h=Math.min(1,Math.max(0,(n-r)/(c-r)));return o+h*(l-o)}static julianDayOf(t){return t.getTime()/864e5+this.UNIX_EPOCH_JD}}const EE=[{id:"quadrantids",code:"QUA",name:{en:"Quadrantids",fr:"Quadrantides"},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:{en:"April Lyrids",fr:"Lyrides d'avril"},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:{en:"eta Aquariids",fr:"Êta Aquarides"},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:{en:"alpha Capricornids",fr:"Alpha Capricornides"},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:{en:"Southern delta Aquariids",fr:"Delta Aquarides du Sud"},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:{en:"Perseids",fr:"Perséides"},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:{en:"Southern Taurids",fr:"Taurides du Sud"},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:{en:"October Draconids",fr:"Draconides d'octobre"},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:{en:"Orionids",fr:"Orionides"},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:{en:"Northern Taurids",fr:"Taurides du Nord"},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:{en:"Leonids",fr:"Léonides"},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:{en:"Geminids",fr:"Géminides"},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:{en:"Ursids",fr:"Ursides"},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}],Il=6.5;class fu{static activeAt(t){return EE.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)),o=this.wrappedDelta(i,s),c=this.wrappedDelta(s,n),l=this.wrappedDelta(r,s);return o<0?o<-c?0:1+o/c:o>0?o>l?0:1-o/l:1}static observedRatePerHour(t,e,i,n=Il){if(e<=0)return 0;const s=Il-n;return t*Math.sin(e*Math.PI/180)/Math.pow(i,s)}static radiantPosition(t,e,i){return Rn.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 $e{static QUIET_RATE_PER_HOUR=2;static APEX_RATE_PER_HOUR=8;static POPULATION_INDEX=3;static apexPosition(t,e){const i=Ve(t),n=new Wl(0,qb(t).elon-90,1),s=wa(v5(i),A0(n,i)),r=T0(s);return R0(r.ra,r.dec,t,e)}static observedRatePerHour(t,e=Il){const i=$e.APEX_RATE_PER_HOUR*Math.max(0,Math.sin(t*Math.PI/180)),n=Il-e;return($e.QUIET_RATE_PER_HOUR+i)/Math.pow($e.POPULATION_INDEX,n)}static schedule(t){const e=new Yl(t.seed^1542469173);return Er.schedule(t).map(i=>{const n=$e.toCartesian({altitudeDeg:Math.asin(e.next())*180/Math.PI,azimuthDeg:e.between(0,360)}),s=i.fromRadiantDeg*Math.PI/180,r=$e.turnAround(n,e.between(0,360)),o={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:$e.toHorizontal(o),bearingDeg:$e.bearingFrom(o,n)}})}static turnAround(t,e){const[i,n]=$e.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]=$e.basisAround(t),s=t.x*e.x+t.y*e.y+t.z*e.z,r=$e.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=$e.normalise($e.cross(t,e));return[i,$e.normalise($e.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=$e.toCartesian(t.radiant??{altitudeDeg:90,azimuthDeg:0}),i=$e.turnAround(e,t.bearingDeg),n=t.fromRadiantDeg*Math.PI/180;return $e.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 Bm="https://ufoathome.org/tle/index.json";class Ti{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??Ti.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(Bm)||t.push(Bm),t}static FIRST_SNAPSHOT="2021-02-22";async covers(t){const e=Date.parse(`${Ti.FIRST_SNAPSHOT}T00:00:00Z`)-Ti.MAX_ELEMENT_AGE_DAYS*Ti.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)-Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS&&t.getTime()<=Date.parse(n.to)+Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS):!1}async at(t){const e=await this.loadIndex();if(!e)return;const{index:i,base:n}=e,s=[],r=[];for(const o of Object.keys(i.kinds)){const c=await this.kindAt(o,t,i,n);s.push(...c),r.push(this.coverageOf(o,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*Ti.DAY_MS,o=Math.floor(s/r),c=s-o*r<r/2?o-1:o+1,l=new Set(i.kinds[t].bins),h=[o,c].map(v=>new Date(v*r).toISOString().slice(0,10)).filter(v=>l.has(v));if(h.length===0)return[];const[u,...d]=await Promise.all([this.json(new URL(`objects-${t}.json`,n).href),...h.map(v=>this.binary(new URL(`${t}/${v}.bin`,n).href))]),f=new Map;for(const v of d)for(const m of Ti.decode(v,i.recordBytes)){const g=f.get(m.norad);(!g||Math.abs(m.epochMs-s)<Math.abs(g.epochMs-s))&&f.set(m.norad,m)}const p=[];for(const v of f.values()){const m=Math.abs(v.epochMs-s)/Ti.DAY_MS;if(m>Ti.MAX_ELEMENT_AGE_DAYS)continue;const g=u[v.norad]??{name:String(v.norad)};g.launch&&Date.parse(`${g.launch}T00:00:00Z`)>s||p.push({norad:v.norad,name:g.name,kind:t,launch:g.launch,stdMag:g.stdMag,elements:v,ageDays:m})}return p}coverageOf(t,e,i,n){const{from:s,to:r}=i.kinds[t],o=e.getTime(),c=Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS,l=n?"covered":o<Date.parse(s)-c?"before":o>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 AE{lowerM;upperM;add(t,e){if(!(t<=0)){if(e.behindM!==void 0){const i=Pe.sizeMAt(e.behindM,t);this.lowerM=this.lowerM===void 0?i:Math.max(this.lowerM,i)}if(e.inFrontM!==void 0){const i=Pe.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:Pe.distanceMAt(this.lowerM,t),maxM:this.upperM===void 0?void 0:Pe.distanceMAt(this.upperM,t)}}clear(){this.lowerM=void 0,this.upperM=void 0}}class Tr{static DEG_PER_SECOND=360/86164.0905;static degOver(t){return Math.max(0,t)*Tr.DEG_PER_SECOND}static instants(t,e){if(!(e>0))return 1;const i=Tr.degOver(t)/e;return i<1?1:Math.min(Tr.MAX_INSTANTS,Math.max(2,Math.ceil(i)))}static MAX_INSTANTS=64}class Fi{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 Tr.DEG_PER_SECOND*3600}static graspOf(t,e={}){const i=e.exposureSeconds??t.exposureSeconds,n=e.fNumber??t.fNumber;if(i===void 0||n===void 0||!(i>0)||!(n>0))return Fi.EYE;const s=e.focalLengthMm??t.frame?.focalLengthMm??Fi.UNKNOWN_CAMERA_FOCAL_MM,r=s/n,o=Fi.resolutionArcsec(t,s,r);return{apertureMm:r,exposureSeconds:Math.min(i,Fi.trailLimitedSeconds(o)),resolutionArcsec:o}}static resolutionArcsec(t,e,i){const s=(t.detailUm??Fi.UNKNOWN_CAMERA_DETAIL_UM)/1e3/e*Fi.ARCSEC_PER_RADIAN,r=1.22*Fi.WAVELENGTH_M/(i/1e3)*Fi.ARCSEC_PER_RADIAN;return Math.max(s,r)}static trailLimitedSeconds(t){return t/Fi.skyDriftArcsecPerSecond}static gainOverEye(t,e={}){const i=Fi.graspOf(t,e),n=Fi.EYE,s=(i.apertureMm/n.apertureMm)**2,r=i.exposureSeconds/n.exposureSeconds,o=(n.resolutionArcsec/i.resolutionArcsec)**2;return 1.25*Math.log10(s*r*o)}static gainFor(t,e){const i=e.fieldOfViewDeg===void 0?void 0:li.focalLengthMmFor(t,e.fieldOfViewDeg);return Fi.gainOverEye(t,{fNumber:e.fNumber,focalLengthMm:i,exposureSeconds:e.exposureSeconds})}}const Hm=111320,ro=Math.PI/180,TE=1.02,RE=1;class So{static of(t,e){const i=So.sightings(t,e);if(i.length<2)return;const n=So.baseline(i);if(!n)return;const{near:s,far:r,closedM:o}=n,c=Math.tan(r.widthDeg/2*ro)===0?0:Math.tan(s.widthDeg/2*ro)/Math.tan(r.widthDeg/2*ro);if(c<TE)return;const l=o/(c-1),h=Pe.sizeMAt(l,s.widthDeg),u=i.map(d=>({t:d.t,m:Pe.distanceMAt(h,d.widthDeg)}));return{widthM:h,distanceM:u,nearestM:Math.min(...u.map(d=>d.m)),fromT:r.t,toT:s.t,closedM:o}}static sightings(t,e){return t.timeline.allKeyframes.flatMap(i=>{const n=i.shapes.find(o=>o.sourceId===e)?.shape,s=n?.angular?.widthDeg,r=oi(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=So.closedAlongSight(i,n),[r,o,c]=s>=0?[n,i,s]:[i,n,-s];c<RE||r.widthDeg<=o.widthDeg||(!e||c>e.closedM)&&(e={near:r,far:o,closedM:c})}return e}static closedAlongSight(t,e){const i=(e.lat-t.lat)*Hm,n=(e.lng-t.lng)*Hm*Math.cos(t.lat*ro),s=(t.sightAzimuthDeg??0)*ro;return i*Math.cos(s)+n*Math.sin(s)}}class Ni{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:Ni.atLeastNearest(t.statedM),basis:"stated"};if(t.hypothesisM!==void 0&&t.hypothesisM>0)return{distanceM:Ni.atLeastNearest(t.hypothesisM),basis:"hypothesis"};if(t.derivedM!==void 0&&t.derivedM>0)return{distanceM:Ni.atLeastNearest(t.derivedM),basis:"derived"};const e=Ni.largest(t.range?.minM,t.crossing?.behindM),i=Ni.smallest(t.range?.maxM,t.crossing?.inFrontM),n=e===void 0?void 0:e*Ni.MARGIN,s=i===void 0?void 0:i/Ni.MARGIN;return n!==void 0&&s!==void 0?{distanceM:Ni.atLeastNearest(n<=s?Math.sqrt(n*s):n),basis:"bounded"}:n!==void 0?{distanceM:Ni.atLeastNearest(n),basis:"bounded"}:s!==void 0&&s<Ni.CONVENTIONAL_M?{distanceM:Ni.atLeastNearest(s),basis:"bounded"}:{distanceM:Ni.CONVENTIONAL_M,basis:"conventional"}}static atLeastNearest(t){return Math.max(Ni.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 pu=Math.PI/180;class Qt{constructor(t,e,i){this.body=t,this.ground=e;const n=[...t.track].sort((s,r)=>s.t-r.t);this.keys=this.place(n,i);for(const s of n)Qt.collect(this.motionKeys,s.t,s.motions),Qt.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};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 Qt.channelsAt(this.motionKeys,t,0)}lightsAt(t){return this.lightKeys.size>0?Qt.channelsAt(this.lightKeys,t,void 0):void 0}static channelsAt(t,e,i){const n={};for(const[s,r]of t){let o=r.length-1;for(;o>=0&&r[o].t>e;)o--;if(o<0){i!==void 0&&(n[s]=i);continue}const c=r[o],l=r[Math.min(o+1,r.length-1)],h=l===c||l.t===c.t?0:Math.min(1,(e-c.t)/(l.t-c.t));n[s]=Qt.lerp(c.value,l.value,h)}return n}static eyeOf(t,e,i){const n=oi(t,0),s=oi(t,e),o=n?.lat!==void 0&&n.lng!==void 0&&s?.lat!==void 0&&s.lng!==void 0?ci(s.lat,s.lng,n.lat,n.lng):void 0,c=o?o.x:0,l=o?-o.z:0;return{eastM:c,northM:l,upM:i.heightAt(c,l)+Qt.EYE_HEIGHT_M+(s?.elevationM??0),headingDeg:s?.headingDeg}}static lineOfSightMeetsGround(t,e,i,n){const s=Qt.directionOf(e,i),r=l=>t.upM+s.upM*l-n.heightAt(t.eastM+s.eastM*l,t.northM+s.northM*l);let o=0,c=0;for(;c<Qt.MAX_RANGE_M;){if(c=o+Math.max(.5,o*.01),r(c)<=0){for(let l=0;l<30;l++){const h=(o+c)/2;r(h)<=0?c=h:o=h}return c}o=c}}static directionOf(t,e){const i=t*pu,n=e*pu;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=e.length-1;for(;i>0&&e[i].t>t;)i--;const n=e[i];if(!n.present)return;const s=e[Math.min(i+1,e.length-1)],r=s===n||s.t===n.t?0:Math.min(1,(t-n.t)/(s.t-n.t)),o=Qt.lerp(n.eastM,s.eastM,r),c=Qt.lerp(n.northM,s.northM,r),l={widthM:Qt.lerp(n.sizeM.widthM,s.sizeM.widthM,r),lengthM:Qt.lerp(n.sizeM.lengthM,s.sizeM.lengthM,r),heightM:Qt.lerp(n.sizeM.heightM,s.sizeM.heightM,r)},h={headingDeg:Qt.lerpAngle(n.attitude.headingDeg,s.attitude.headingDeg,r),pitchDeg:Qt.lerp(n.attitude.pitchDeg,s.attitude.pitchDeg,r),rollDeg:Qt.lerp(n.attitude.rollDeg,s.attitude.rollDeg,r)};let u;if("aboveGroundM"in n.vertical&&"aboveGroundM"in s.vertical){const d=Qt.lerp(n.vertical.aboveGroundM,s.vertical.aboveGroundM,r);u=this.groundUnderFootprint(o,c,l,h.headingDeg)+d+l.heightM/2}else u=Qt.lerp(this.centreUpOf(n),this.centreUpOf(s),r);return{id:this.body.id,model:this.body.model,explains:this.body.explains??[],outlineNode:this.body.outlineNode,eastM:o,northM:c,upM:u,sizeM:l,attitude:h,appearance:{color:(r<1?n:s).appearance.color,albedo:Qt.lerp(n.appearance.albedo,s.appearance.albedo,r),luminanceCdM2:Qt.lerp(n.appearance.luminanceCdM2,s.appearance.luminanceCdM2,r)},flame:Qt.flameBetween(n.flame,s.flame,r),motions:this.motionsAt(t),lights:this.lightsAt(t),throwsFlame:this.body.track.some(d=>d.flame!==void 0&&d.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:Qt.lerp(n.lengthM,s.lengthM,i),widthM:Qt.lerp(n.widthM,s.widthM,i),luminanceCdM2:Qt.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*pu,r={eastM:Math.cos(s),northM:-Math.sin(s)},o={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+o.eastM*d,e+r.northM*u+o.northM*d))}return c}place(t,e){const i=[];let n;for(const s of t){const r=s.sizeM??n?.sizeM??Qt.DEFAULT_SIZE,o={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??Qt.DEFAULT_APPEARANCE.color,albedo:s.appearance?.albedo??n?.appearance.albedo??Qt.DEFAULT_APPEARANCE.albedo,luminanceCdM2:s.appearance?.luminanceCdM2??n?.appearance.luminanceCdM2??Qt.DEFAULT_APPEARANCE.luminanceCdM2},l=this.positionOf(s,e)??(n&&{eastM:n.eastM,northM:n.northM,vertical:this.verticalOf(s)??n.vertical});if(!l)continue;const h=s.flame??n?.flame,u=s.present??n?.present??!0;n={t:s.t,...l,sizeM:r,attitude:o,appearance:c,flame:h,present:u},i.push(n)}return i}verticalOf(t){if(t.onGround)return{aboveGroundM:0};if(t.altitudeAboveGroundM!==void 0)return{aboveGroundM:t.altitudeAboveGroundM}}positionOf(t,e){if(t.eastM!==void 0&&t.northM!==void 0)return{eastM:t.eastM,northM:t.northM,vertical:this.verticalOf(t)??{aboveGroundM:0}};if(t.azimuthDeg===void 0||t.altitudeDeg===void 0)return;const i=e(t.t);if(!i)return;const n=t.distanceM??(t.onGround?Qt.lineOfSightMeetsGround(i,t.azimuthDeg,t.altitudeDeg,this.ground):void 0);if(n===void 0)return;const s=Qt.directionOf(t.azimuthDeg,t.altitudeDeg),r=i.eastM+s.eastM*n,o=i.northM+s.northM*n;return{eastM:r,northM:o,vertical:this.verticalOf(t)??{upM:i.upM+s.upM*n}}}static lerp(t,e,i){return t+(e-t)*i}static lerpAngle(t,e,i){const n=((e-t)%360+540)%360-180;return((t+n*i)%360+360)%360}}const sa=Math.PI/180,ao=180/Math.PI;class Ke{constructor(t){this.timeline=t}static DIRECTION_TOLERANCE_DEG=1;static SIZE_TOLERANCE=1.5;static RINGS=12;static SEGMENTS=24;at(t,e,i,n){const s=[];for(const r of e){const o=Ke.projectionOf(r,i,n?.(r));if(o)for(const c of r.explains){const l=this.timeline.getInterpolatedShapeAt(t,c);!l||l.transparency>=1||s.push({...Ke.compare(c,r.id,{aim:l.aim,angular:l.angular},o),title:l.title})}}return s}static compare(t,e,i,n){const s=[],r=i.aim?Ke.separationDeg(i.aim,n.aim):void 0;if(r!==void 0){const l=Math.max(i.angular?.widthDeg??0,n.angular.widthDeg)/2;r>Math.max(Ke.DIRECTION_TOLERANCE_DEG,l)&&s.push("direction")}const o=i.angular&&i.angular.widthDeg>0?n.angular.widthDeg/i.angular.widthDeg:void 0,c=i.angular&&i.angular.heightDeg>0?n.angular.heightDeg/i.angular.heightDeg:void 0;return o!==void 0&&!Ke.withinSize(o)&&s.push("width"),c!==void 0&&!Ke.withinSize(c)&&s.push("height"),{sourceId:t,bodyId:e,stated:i,predicted:n,separationDeg:r,widthRatio:o,heightRatio:c,disagreements:s}}static projectionOf(t,e,i){const n=i&&i.length>0?i:Ke.outlineOf(t),s=i&&i.length>0?Ke.centreOf(i):t,r=Ke.normalized({eastM:s.eastM-e.eastM,northM:s.northM-e.northM,upM:s.upM-e.upM});if(!r)return;const o=Ke.normalized({eastM:r.northM,northM:-r.eastM,upM:0})??{eastM:1,northM:0,upM:0},c=Ke.cross(o,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},v=Ke.dot(p,r);if(v<=0)return;const m=Math.atan2(Ke.dot(p,o),v),g=Math.atan2(Ke.dot(p,c),v);l=Math.min(l,m),h=Math.max(h,m),u=Math.min(u,g),d=Math.max(d,g)}return{aim:{azimuthDeg:(Math.atan2(r.eastM,r.northM)*ao+360)%360,altitudeDeg:Math.asin(Math.max(-1,Math.min(1,r.upM)))*ao},angular:{widthDeg:(h-l)*ao,heightDeg:(d-u)*ao}}}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*sa,n=e.altitudeDeg*sa,s=Math.sin(i)*Math.sin(n)+Math.cos(i)*Math.cos(n)*Math.cos((t.azimuthDeg-e.azimuthDeg)*sa);return Math.acos(Math.max(-1,Math.min(1,s)))*ao}static withinSize(t){return t<=Ke.SIZE_TOLERANCE&&t>=1/Ke.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"&&R1.includes(r))for(let u=0;u<=Ke.RINGS;u++){const d=u/Ke.RINGS*Math.PI;for(let f=0;f<Ke.SEGMENTS;f++){const p=f/Ke.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*sa,l=t.attitude.pitchDeg*sa,h=t.attitude.rollDeg*sa;return s.map(([u,d,f])=>{const p=u*Math.cos(h)+f*Math.sin(h),v=-u*Math.sin(h)+f*Math.cos(h),m=d*Math.cos(l)-v*Math.sin(l),g=d*Math.sin(l)+v*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+g}})}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}}ag();const DE={sun:{en:"Sun",fr:"Soleil"},moon:{en:"Moon",fr:"Lune"},Venus:{en:"Venus",fr:"Vénus"},Mars:{en:"Mars",fr:"Mars"},Jupiter:{en:"Jupiter",fr:"Jupiter"},Saturn:{en:"Saturn",fr:"Saturne"}},CE=["en","fr"],IE={en:"{name} — mag {mag}, {alt}° above the horizon",fr:"{name} — mag {mag}, {alt}° au-dessus de l'horizon"},PE={en:"{name} — satellite, mag {mag}, {height} km up",fr:"{name} — satellite, mag {mag}, à {height} km d'altitude"},LE="satellites-change",OE="rr0-confrontation",NE={en:"{name} — mag {mag}, {alt}° below the horizontal",fr:"{name} — mag {mag}, {alt}° sous l'horizontale"},Gm="comet:",Vm="nova:",FE={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},shrub:{en:"Shrub",fr:"Buisson"},bridge:{en:"Bridge",fr:"Pont"},crop:{en:"Crop row",fr:"Rang de culture"},mound:{en:"Stone heap",fr:"Tas de pierres"},streetlight:{en:"Streetlight",fr:"Lampadaire"},vehicle:{en:"Vehicle",fr:"Véhicule"},observer:{en:"Observer",fr:"Observateur"},aircraft:{en:"Aircraft",fr:"Aéronef"},entity:{en:"Being",fr:"Être"}},UE=new URL(""+new URL("stars-mag7.5-B43R6Wvg.bin",import.meta.url).href,import.meta.url).href,kE=new URL(""+new URL("stars-mag7.5-9-BLV2tFmZ.bin",import.meta.url).href,import.meta.url).href,zE=-18,BE={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},mu={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class I0 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",pa,ma]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;distanceHypotheses=new Map;depths=new Map;directionScratch=new R;meteorScheduleFor;lightningScheduleFor;lightningFlashes=[];lastLightningT;lastTimeMs=0;interpretationShown;confrontationReadings=[];confrontationSignature="";comparing=!1;inTheRound=!0;lastSkyKey;starCatalog;starCatalogRequest=0;static tleArchive=new Ti;satellitesFor;satelliteRequest=0;satelliteStatus="none";satellites;satellitePassesMemo;starCatalogDepth=0;weatherAudio=new bE;vehicleAudio=new H1;vehicleHearing=new al;animateWhilePausedValue=!1;set animateWhilePaused(t){t!==this.animateWhilePausedValue&&(this.animateWhilePausedValue=t,this.syncAnimationsToPlayback())}get animateWhilePaused(){return this.animateWhilePausedValue}thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=t=>{this.sceneRenderer.setCompassHovered(!0);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,o=-((t.clientY-i.top)/i.height*2-1),c=ll(po.preferencesFor(this),CE),l=this.sceneRenderer.pickBodyAt(r,o);if(l){this.showHoverTooltip(t,this.bodyName(l,c));return}const h=this.sceneRenderer.pickDecorAt(r,o),u=h?this.ufoElement.sighting.decor.find(p=>p.id===h):void 0;if(u){this.showHoverTooltip(t,this.said.read(u.title)||FE[u.kind][c]);return}const d=this.sceneRenderer.pickSatelliteAt(r,o);if(d){this.showHoverTooltip(t,PE[c].replace("{name}",d.name).replace("{mag}",d.magnitude.toLocaleString(void 0,{maximumFractionDigits:1})).replace("{height}",Math.round(d.heightKm).toLocaleString()));return}const f=this.sceneRenderer.pickStarAt(r,o);if(f){const p=f.star.mag,v=f.altitudeDeg,m=(v<0?NE:IE)[c];this.showHoverTooltip(t,m.replace("{name}",f.star.name[c]).replace("{mag}",p.toLocaleString(void 0,{maximumFractionDigits:Math.abs(p)<1?2:1})).replace("{alt}",String(Math.round(Math.abs(v)))));return}this.hoverTooltip.hidden=!0};bodyName(t,e){const i=t.startsWith(Gm)?t.slice(Gm.length):void 0,n=i?I1.find(r=>r.id===i):void 0,s=t.startsWith(Vm)?zm.byId(t.slice(Vm.length)):void 0;return n?.name[e]??s?.name[e]??DE[t]?.[e]??t}showHoverTooltip(t,e){this.hoverTooltip.textContent=e,this.hoverTooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${t.clientX-i.left+12}px`,this.hoverTooltip.style.top=`${t.clientY-i.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash(t){clearTimeout(this.thunderTimeoutId),this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),hi.thunderDelayMs(t))}handleFirstInteraction=()=>{this.removeEventListener("pointerdown",this.handleFirstInteraction,!0),this.removeEventListener("keydown",this.handleFirstInteraction,!0),this.weatherAudio.resume(),this.vehicleAudio.resume(),this.setWeather(K0(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=t=>{this.lastTimeMs=t.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.playbackState==="playing"&&this.sceneRenderer.frame(performance.now())};syncAnimationsToPlayback(){const t=this.ufoElement.playbackState==="playing",e=t||this.animateWhilePaused;this.sceneRenderer.setAnimationsRunning(e,t),this.weatherAudio.setPaused(!e),this.vehicleAudio.setPaused(!e),e||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${q1}</style>${X1}`,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 ke(this.sceneCanvas);const e=this.shadow.getElementById("scene-loader");this.sceneRenderer.onFirstFrameHold=r=>{e.hidden=!r},this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(Mu),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.paintsShapes=!1,this.forwardPlayerAttributes(),this.ufoElement.addEventListener("lookat",r=>this.lookToward(r.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",r=>{r.newState==="open"&&Wn.fill(n,this)});const s=ll(po.preferencesFor(this),["en","fr"])==="fr"?"Crédits":"Credits";this.creditsButton.title=s,this.creditsButton.setAttribute("aria-label",s),this.sceneRenderer.onMapSubjectBounds=r=>this.ufoElement.setMapSubjectBounds(r),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.addEventListener("referenceview",r=>this.applyReferenceView(r.detail)),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave),this.addEventListener("pointerdown",this.handleFirstInteraction,!0),this.addEventListener("keydown",this.handleFirstInteraction,!0)}get said(){return this.saidTexts??=new Vs(po.preferencesFor(this))}saidTexts;connectedCallback(){this.saidTexts=void 0,this.sceneRenderer.restoreContext(),this.resizeToStage(),this.updateAstronomy(this.lastTimeMs),this.loadStars(),this.resizeObserver=new ResizeObserver(()=>this.resizeToStage()),this.resizeObserver.observe(this.frameElement),document.addEventListener("fullscreenchange",this.handleFullscreenChange);const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose(),this.vehicleAudio.dispose(),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===pa||t===ma)&&i!==e&&this.forwardPlayerAttributes()}forwardPlayerAttributes(){for(const t of[pa,ma]){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=oi(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}=ci(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)}bodyScreenBox(t){return this.sceneRenderer.bodyScreenBox(t)}pickPlacedBodyAt(t,e){return this.sceneRenderer.pickPlacedBodyAt(t,e)}resumeWeatherAudio(){this.weatherAudio.resume(),this.vehicleAudio.resume()}async loadFromSrc(t){const e=await Km.json(t);this.documentUrl=new URL(t,location.href).href,this.sightingData=e}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.interpretationShown=this.inTheRound?this.ufoElement.sighting.interpretation:void 0,this.applyFrameFormat(),this.lastTimeMs=0,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(0)}referenceAspect(t){return this.sceneRenderer.referenceAspect(t)}screenPointOf(t){return this.sceneRenderer.screenPointOf(t)}directionAt(t,e){return this.sceneRenderer.directionAt(t,e)}referenceFailedToLoad(t){return this.sceneRenderer.referenceFailedToLoad(t)}applyReferenceView(t){this.sceneRenderer.setReferencesShown(t.shown);for(const e of this.ufoElement.sighting.references)this.sceneRenderer.setReferenceView(e.id,{opacity:t.opacity})}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}get currentRoadAttribution(){return this.sceneRenderer.currentRoadAttribution}setTerrainProviders(t){this.sceneRenderer.setTerrainProviders(t)}setDecorModelProvider(t){this.sceneRenderer.setDecorModelProvider(t)}get decorModelCredits(){return this.sceneRenderer.currentDecorModelCredits}applyFrameFormat(){const t=this.ufoElement.sighting.instrument,e=Pe.CANVAS_HEIGHT_PX,i=li.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:hu,url:this.getAttribute("star-catalog-src")??UE},{magnitudeLimit:uu,url:this.getAttribute("deep-star-catalog-src")??kE}],e=this.instrumentReach(),i=++this.starCatalogRequest;this.starCatalogDepth=e>hu?uu:hu;const n=await Vn.upTo(t,e);i===this.starCatalogRequest&&(this.starCatalog=n,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=uu||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const t=this.ufoElement.sighting,e=Fi.gainFor(t.instrument,{fNumber:oi(t,0)?.fNumber,fieldOfViewDeg:Ki.fovOf(t,0),exposureSeconds:t.exposure});return il(zE,e)}updateAstronomy(t){this.ensureStarsDeepEnough(),this.applySceneAt(t);const e=Tn.windowEndingAt(t,this.exposureSeconds()),i=e.seconds,n=this.degreesPerPixelAt(t),s=Tr.instants(i,n),r=Math.max(s,this.ufoElement.exposureTimes(t).length,Tn.instants(this.ufoElement.sighting.decor,oi(this.ufoElement.sighting,t)?.elevationM??0,e.fromMs,i,n));if(r<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(r,o=>this.applySceneAt(e.fromMs+e.ms*o/(r-1),{sky:Math.floor(o*s/r)!==Math.floor((o-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:Ki.fovOf(this.ufoElement.sighting,t)/e}applySceneAt(t,e){const i=this.ufoElement.sighting;this.setWeather(K0(i,t)),this.sceneRenderer.setInstrument(i.instrument),e||this.vehicleAudio.setVoices(this.vehicleHearing.at(i,t)),this.updateMeteorShower(i,t),this.updateLightning(i,t,e!==void 0),this.sceneRenderer.setDecor(i.decor),this.sceneRenderer.setReferences(i.references);const n=oi(i,t),s=oi(i,0),r=Na(i,0),o=Object.fromEntries(ol(Na(i,t)).map(S=>[S.id,W0(t,i.weatherTrack,r,s,n,S.id)]));this.sceneRenderer.setCloudOffset(W0(t,i.weatherTrack,r,s,n),o),this.sceneRenderer.setObserverPose(n??mu),this.sceneRenderer.setLensOptics(this.lensOpticsAt(t)),this.sceneRenderer.setInstrumentGain(Fi.gainFor(i.instrument,{fNumber:n?.fNumber,fieldOfViewDeg:Ki.fovOf(i,t),exposureSeconds:i.exposure}),i.instrument.detailUm!==void 0),this.sceneRenderer.setGait(xe.bodyAt(i,t,this.ufoElement.steadyObserver)),this.sceneRenderer.updateDecorAnchoring(oi(i,0),n,t),this.placeBodiesAt(t,e===void 0),this.sceneRenderer.updateDecorLitState(t,e?.stepMs??0),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng,()=>{this.placeBodiesAt(this.lastTimeMs,!0),this.sceneRenderer.render()}),this.sceneRenderer.setStatedRoads(i.roads),this.pushPhenomenaAt(t);const c=n?.lat??mu.lat,l=n?.lng??mu.lng,h=Lc(i.event.time??{},l,i.event.utcOffsetHours),u={lat:c,lng:l,elevationM:n?.elevationM??0};if(this.pushSatellitesAt(h,t,u),e&&!e.sky)return;if(!h){this.sceneRenderer.setAstronomy(BE);return}const d=new Date(h.getTime()+t),f=Math.max(1,Math.round(.25*this.degreesPerPixelAt(t)/Tr.DEG_PER_SECOND*1e3)),p=Math.max(1e-8,this.degreesPerPixelAt(t)*.1),v=`${Math.floor(d.getTime()/f)}|${Math.round(c/p)}|${Math.round(l/p)}|${Math.round(u.elevationM)}|${this.starCatalog?this.starCatalogDepth:0}`;if(v===this.lastSkyKey){this.sceneRenderer.render();return}this.lastSkyKey=v;const m={...Hh("Sun",d,u),magnitude:Gh("Sun",d)},g={...Hh("Moon",d,u),phase:x5(d),magnitude:Gh("Moon",d)},_=M5.map(S=>({body:S,position:Hh(S,d,u),magnitude:Gh(S,d)}));this.sceneRenderer.setAstronomy({sun:m,moon:g,planets:_,comet:this.cometAt(d,u),novae:zm.appearancesAt(d,u).map(({outburst:S,position:M,magnitude:b})=>({id:S.id,position:M,magnitude:b})),stars:this.starCatalog?{catalog:this.starCatalog,date:d,observer:u}:void 0,frame:{date:d,observer:u}}),this.ufoElement.setSunAltitude(m.altitudeDeg)}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)}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(LE)))},s=I0.tleArchive;(async()=>{if(!await s.covers(t))return n("outside");const[r,o]=await Promise.all([s.at(t),sl(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(i===this.satelliteRequest){if(!r)return n("unavailable");this.satellites={snapshot:r,passes:new o.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}}satellitePassesDuring(t){const e=this.satellites,i=this.ufoElement.sighting,n=oi(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,o=n?.lng??s?.lng;if(!e||r===void 0||o===void 0)return[];const c=Lc(i.event.time??{},o,i.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(t,0),4*36e5),h={lat:r,lng:o,elevationM:n?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),r,o,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=wE.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),o=new Map,c=new Map,l=new Set;for(const p of i.sourceIds){const v=i.getInterpolatedShapeAt(t,p);if(!v)continue;const m={...v,bounds:{...v.bounds,x:v.bounds.x+s.x,y:v.bounds.y+s.y}};o.set(p,m);const g=v.aim?this.sceneRenderer.screenPointOf(An.directionOf(v.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)},_=g!==void 0&&Math.abs(g.ndcX)<=1&&Math.abs(g.ndcY)<=1,S=_?this.sceneRenderer.decorDistancesAt(g.ndcX,g.ndcY,p):{};l.add(p),(_||v.aim)&&l.delete(p);const M=v.angular?.widthDeg??r.pxToDeg(v.bounds.width),b=this.sizeEstimateOf(p);b.add(M,S);const w=So.of(e,p);c.set(p,Ni.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:w&&M>0?Pe.distanceMAt(w.widthM,M):void 0,range:b.distanceRangeAt(M),crossing:S}))}for(const[p,v]of o)for(const[m,g]of o){if(m===p||g.transparency>=1||g.bounds.width*g.bounds.height<=v.bounds.width*v.bounds.height||!(v.bounds.x>=g.bounds.x&&v.bounds.y>=g.bounds.y&&v.bounds.x+v.bounds.width<=g.bounds.x+g.bounds.width&&v.bounds.y+v.bounds.height<=g.bounds.y+g.bounds.height))continue;const S=c.get(m);S&&c.set(p,{distanceM:S.distanceM*.999,basis:S.basis});break}this.depths=c;const h=i.sourceIds,u=[];for(const[p,v]of o)u.push({sourceId:p,shape:v,distanceM:c.get(p).distanceM,renderOrder:h.indexOf(p),aim:v.aim,hidden:l.has(p)||this.interpretationShown!==void 0&&!this.comparing,ghost:this.interpretationShown!==void 0&&this.comparing});const f=(oi(e,t)?.rollDeg??0)+xe.bodyAt(e,t,this.ufoElement.steadyObserver).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:li.starPointsOf(e.instrument),rollRad:f*Math.PI/180})}get interpretation(){return this.interpretationShown}set interpretation(t){this.interpretationShown=t,this.updateAstronomy(this.lastTimeMs)}get accountInTheRound(){return this.inTheRound}set accountInTheRound(t){this.inTheRound=t}get compareAccount(){return this.comparing}set compareAccount(t){this.comparing=t,this.updateAstronomy(this.lastTimeMs)}get confrontation(){return this.confrontationReadings}groundAlong(t,e,i){const n=this.sceneRenderer.bodyGround,s=Qt.eyeOf(this.ufoElement.sighting,i,n);return s?Qt.lineOfSightMeetsGround(s,t,e,n):void 0}bodyReading(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=d=>Qt.eyeOf(n,d,i),r=new Qt(t,i,s).at(e),o=s(e);if(!r||!o)return;const c=r.eastM-o.eastM,l=r.northM-o.northM,h=r.upM-o.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}}directionToBody(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=p=>Qt.eyeOf(n,p,i),r=new Qt(t,i,s),o=r.at(e)?e:t.track[0]?.t,c=o===void 0?void 0:r.at(o),l=o===void 0?void 0:s(o);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 o=this.sceneRenderer.bodyGround,c=p=>Qt.eyeOf(n,p,o);i&&(s=i.bodies.map(p=>new Qt(p,o,c).at(t)).filter(p=>p!==void 0));const l=Na(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 Ke(n.timeline).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(OE,{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&&Na(t,s.t).storm&&this.handleLightningFlash(s)}ensureLightningSchedule(t){const e=Na(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?Lc(n,s?.lng??0,t.event.utcOffsetHours):void 0,o=(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=hi.schedule({durationMs:o,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?Lc(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,o=Math.round(n.getTime()/1e3)+Math.round(e.lat*1e3),c=$e.schedule({ratePerHour:$e.observedRatePerHour($e.apexPosition(n,s).altitudeDeg),durationMs:r,velocityKmS:$e.TYPICAL_VELOCITY_KM_S,seed:o}),l=fu.activeAt(n).map(u=>{const d=fu.radiantPosition(u.shower,n,s);return{entry:u,position:d,rate:fu.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=Er.schedule({ratePerHour:l.rate,durationMs:r,velocityKmS:l.entry.shower.velocityKmS,seed:o+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}meteorByRank(t){this.ensureMeteorSchedule(this.ufoElement.sighting);const e=[...this.sceneRenderer.meteorSchedule].filter(s=>s.t+s.durationMs<=this.ufoElement.seekableDuration).sort((s,r)=>r.brightness-s.brightness);if(e.length===0)return;const i=e[t%e.length],n=this.sceneRenderer.meteorMidpoint(i);if(n)return{t:Math.round(i.t+i.durationMs*.45),...n}}lensOpticsAt(t){const e=this.ufoElement.sighting,i=e.instrument,n=i.frame,s=oi(e,t),r=s?.fNumber??i.fNumber;if(!n||r===void 0)return;const o=li.focalLengthMmFor(i,Ki.fovOf(e,t));if(o!==void 0)return{focalLengthMm:o,fNumber:r,focusDistance:s?.focusDistanceM??0,frameHeightMm:n.heightMm}}projectionAt(t){const e=this.ufoElement.sighting;return vs.of(e.instrument,Pe.CANVAS_HEIGHT_PX,Ki.fovOf(e,t))}sizeEstimateOf(t){let e=this.sizeEstimates.get(t);return e||(e=new AE,this.sizeEstimates.set(t,e)),e}}const Wm="rr0-scene";function HE(){ag(),customElements.get(Wm)||customElements.define(Wm,I0)}HE();export{gM as $,qE as A,ee as B,st as C,sp as D,Rt as E,ZE as F,KE as G,Dg as H,YE as I,$E as J,ps as K,Ho as L,RM as M,Jo as N,Fe as O,zg as P,Zi as Q,Io as R,ki as S,GE as T,Re as U,Mt as V,Yi as W,XE as X,Ln as Y,Rg as Z,jf as _,WE as a,dl as a0,sd as a1,xl as a2,yi as a3,Ug as a4,h0 as a5,u0 as a6,re as a7,Js as a8,Bo as a9,zi as aa,bs as ab,VE as b,QE as c,ml as d,jE as e,Zt as f,R as g,Hf as h,JE as i,tA as j,dM as k,xr as l,th as m,m2 as n,ae as o,Ee as p,Tu as q,_i as r,Cg as s,ws as t,SM as u,fr as v,$i as w,Mn as x,Se as y,oe as z};
7171
+ `);let s=Vn.cache.get(n);return s||(s=Promise.all(i.map(r=>Vn.load(r.url))).then(r=>r.reduce((o,c)=>Vn.concat(o,c))),Vn.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)}}}const mE="“Thunder” by Jerimee",gE="https://creativecommons.org/licenses/by/3.0/",vE="CC BY 3.0";class Wn{static fill(t,e){t.innerHTML="";const i=l=>t.appendChild(l),n=e.currentTerrainAttribution;n&&i(Wn.text(n));const s=e.currentRoadAttribution;s&&i(Wn.text(s));const r=e.ufoElement.observerMapCredit;r&&!n?.includes(r)&&i(Wn.text(r));for(const l of e.decorModelCredits){const h=l.author?` — ${l.author}`:"",u=document.createElement("li");l.sourceUrl?u.append(Wn.link(l.sourceUrl,l.title),document.createTextNode(`${h} (${l.license})`)):u.textContent=`${l.title}${h} (${l.license})`,i(u)}for(const l of e.ufoElement.sighting.references){if(!l.credit)continue;const h=document.createElement("li");l.creditUrl?h.appendChild(Wn.link(l.creditUrl,l.credit)):h.textContent=l.credit,i(h)}const o=e.satelliteState;if(o.status==="ready"&&o.credit){const l=document.createElement("li");l.appendChild(Wn.link(o.creditUrl??"",o.credit)),i(l)}const c=Wn.text(`${mE} (`);c.append(Wn.link(gE,vE),document.createTextNode(")")),i(c)}static text(t){const e=document.createElement("li");return e.textContent=t,e}static link(t,e){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener",i.textContent=e,i}}const ME=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,xE=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,yE=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,_E=20,SE=1;class bE{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};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}}this.context.state==="suspended"&&this.context.resume()}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(ME,this.ambientVolume).then(o=>this.applyIfCurrent(o,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/_E,1);const s=i>SE;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(xE,this.windVolume).then(o=>this.applyIfCurrent(o,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(yE,.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.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(i.destination),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(i.destination),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 fs{constructor(t){this.elements=t;const{eccentricity:e,perihelionAu:i}=t,[n,s]=this.perifocalAxes(),r=Math.sqrt(fs.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*fs.stumpffC(n),o=e-i*i*i/Math.sqrt(fs.SUN_GM_AU3_PER_DAY2)*fs.stumpffS(n);return{x:r*this.perihelionPosition.x+o*this.perihelionVelocity.x,y:r*this.perihelionPosition.y+o*this.perihelionVelocity.y,z:r*this.perihelionPosition.z+o*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(fs.SUN_GM_AU3_PER_DAY2)*Math.abs(t),n=o=>{const c=this.inverseSemiMajorAxis*o*o,l=this.elements.perihelionAu;return(1-this.inverseSemiMajorAxis*l)*o*o*o*fs.stumpffS(c)+l*o};let s=Math.max(1,i/this.elements.perihelionAu);for(;n(s)<i;)s*=2;let r=0;for(let o=0;o<fs.MAX_ITERATIONS&&s-r>1e-13*Math.max(1,s);o++){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),o=Math.sin(e),c=Math.cos(i),l=Math.sin(i);return[{x:n*r-s*o*c,y:s*r+n*o*c,z:o*l},{x:-n*o-s*r*c,y:-s*o+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 I1=[{id:"halley-1910",designation:"1P/Halley",name:{en:"Halley's Comet",fr:"comète de Halley"},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:{en:"Comet Brooks",fr:"comète 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:{en:"Comet Skjellerup-Maristany",fr:"comète 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:{en:"Comet de Kock-Paraskevopoulos",fr:"comète 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:{en:"the Southern Comet",fr:"comète australe"},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:{en:"the Eclipse Comet",fr:"comète de l'éclipse"},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:{en:"Comet Arend-Roland",fr:"comète 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:{en:"Comet Mrkos",fr:"comète 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:{en:"Comet Seki-Lines",fr:"comète 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:{en:"Comet Ikeya-Seki",fr:"comète 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:{en:"Comet Bennett",fr:"comète 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:{en:"Comet White-Ortiz-Bolelli",fr:"comète 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:{en:"Comet Kohoutek",fr:"comète 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:{en:"Comet West",fr:"comète 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:{en:"Comet IRAS-Araki-Alcock",fr:"comète 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:{en:"Halley's Comet",fr:"comète de Halley"},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:{en:"Comet Hyakutake",fr:"comète 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:{en:"Comet Hale-Bopp",fr:"comète 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:{en:"Comet McNaught",fr:"comète 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:{en:"Comet Lovejoy",fr:"comète 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:{en:"Comet PANSTARRS",fr:"comète 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:{en:"Comet NEOWISE",fr:"comète 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:{en:"Comet Tsuchinshan-ATLAS",fr:"comète 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 wE{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 I1.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=Ve(e),s=this.earthPositionAt(n),r=this.apparentPositionOf(t,2451545+n.tt,s),o=this.subtract(r,s),c=this.length(r),l=this.length(o),h=this.tailEndAt(t,r,s,c,n,e,i),u=this.horizontalOf(o,n,e,i);return{apparition:t,position:u,...h,heliocentricDistanceAu:c,earthDistanceAu:l,elongationDeg:this.angleBetween(o,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,o){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,o),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 o=this.length(this.subtract(s,i))/this.LIGHT_SPEED_AU_PER_DAY;s=n.positionAt(e-o)}return s}static horizontalOf(t,e,i,n){const s=wa(m5(),new Le(t.x,t.y,t.z,e)),r=wa(v1(e),s),o=Kb(e,new E0(n.lat,n.lng,n.elevationM)),c=new Le(r.x-o.x,r.y-o.y,r.z-o.z,e),l=T0(c);return R0(l.ra,l.dec,i,n)}static earthPositionAt(t){return wa(p5(),Zs(bt.Earth,t))}static julianDayOf(t){return 2451545+Ve(t).tt}static orbitOf(t){const e=this.orbits.get(t.id);if(e)return e;const i=new fs(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 du=[{id:"sn-1006",kind:"supernova",designation:"SN 1006",name:{en:"Supernova of 1006",fr:"supernova de 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:{en:"Supernova of 1054",fr:"supernova de 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:{en:"Supernova of 1181",fr:"supernova de 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:{en:"Tycho's Supernova",fr:"supernova de Tycho"},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:{en:"Kepler's Supernova",fr:"supernova de Kepler"},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:{en:"Nova Coronae Borealis 1866",fr:"nova de la Couronne boréale 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:{en:"Nova Aurigae 1891",fr:"nova du Cocher 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:{en:"Nova Persei 1901",fr:"nova de Persée 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:{en:"Nova Geminorum 1912",fr:"nova des Gémeaux 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:{en:"Nova Aquilae 1918",fr:"nova de l'Aigle 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:{en:"Nova Cygni 1920",fr:"nova du Cygne 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:{en:"Nova Pictoris 1925",fr:"nova du Peintre 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:{en:"Nova Herculis 1934",fr:"nova d'Hercule 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:{en:"Nova Lacertae 1936",fr:"nova du Lézard 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:{en:"Nova Puppis 1942",fr:"nova de la Poupe 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:{en:"Nova Coronae Borealis 1946",fr:"nova de la Couronne boréale 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:{en:"Nova Herculis 1960",fr:"nova d'Hercule 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:{en:"Nova Herculis 1963",fr:"nova d'Hercule 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:{en:"Nova Delphini 1967",fr:"nova du Dauphin 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:{en:"Nova Vulpeculae 1968",fr:"nova du Petit Renard 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:{en:"Nova Serpentis 1970",fr:"nova du Serpent 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:{en:"Nova Cygni 1975",fr:"nova du Cygne 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:{en:"Nova Centauri 1986",fr:"nova du Centaure 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:{en:"Supernova 1987A",fr:"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:{en:"Nova Cygni 1992",fr:"nova du Cygne 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:{en:"Nova Velorum 1999",fr:"nova des Voiles 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:{en:"Nova Aquilae 1999",fr:"nova de l'Aigle 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:{en:"Nova Sagittarii 2002",fr:"nova du Sagittaire 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:{en:"Nova Ophiuchi 2006",fr:"nova d'Ophiuchus 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:{en:"Nova Scorpii 2007",fr:"nova du Scorpion 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:{en:"Nova Delphini 2013",fr:"nova du Dauphin 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:{en:"Nova Centauri 2013",fr:"nova du Centaure 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:{en:"Nova Ophiuchi 2021",fr:"nova d'Ophiuchus 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 zm{static UNIX_EPOCH_JD=24405875e-1;static aroundDate(t){const e=this.julianDayOf(t);return du.filter(i=>this.magnitudeAt(i,e)!==void 0)}static appearancesAt(t,e){const i=this.julianDayOf(t),n=[];for(const s of du){const r=this.magnitudeAt(s,i);r!==void 0&&n.push({outburst:s,position:Rn.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 du.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,o]=i[s-1]??i[0],[c,l]=i[s]??i[0];if(c===r)return o;const h=Math.min(1,Math.max(0,(n-r)/(c-r)));return o+h*(l-o)}static julianDayOf(t){return t.getTime()/864e5+this.UNIX_EPOCH_JD}}const EE=[{id:"quadrantids",code:"QUA",name:{en:"Quadrantids",fr:"Quadrantides"},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:{en:"April Lyrids",fr:"Lyrides d'avril"},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:{en:"eta Aquariids",fr:"Êta Aquarides"},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:{en:"alpha Capricornids",fr:"Alpha Capricornides"},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:{en:"Southern delta Aquariids",fr:"Delta Aquarides du Sud"},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:{en:"Perseids",fr:"Perséides"},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:{en:"Southern Taurids",fr:"Taurides du Sud"},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:{en:"October Draconids",fr:"Draconides d'octobre"},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:{en:"Orionids",fr:"Orionides"},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:{en:"Northern Taurids",fr:"Taurides du Nord"},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:{en:"Leonids",fr:"Léonides"},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:{en:"Geminids",fr:"Géminides"},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:{en:"Ursids",fr:"Ursides"},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}],Il=6.5;class fu{static activeAt(t){return EE.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)),o=this.wrappedDelta(i,s),c=this.wrappedDelta(s,n),l=this.wrappedDelta(r,s);return o<0?o<-c?0:1+o/c:o>0?o>l?0:1-o/l:1}static observedRatePerHour(t,e,i,n=Il){if(e<=0)return 0;const s=Il-n;return t*Math.sin(e*Math.PI/180)/Math.pow(i,s)}static radiantPosition(t,e,i){return Rn.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 $e{static QUIET_RATE_PER_HOUR=2;static APEX_RATE_PER_HOUR=8;static POPULATION_INDEX=3;static apexPosition(t,e){const i=Ve(t),n=new Wl(0,qb(t).elon-90,1),s=wa(v5(i),A0(n,i)),r=T0(s);return R0(r.ra,r.dec,t,e)}static observedRatePerHour(t,e=Il){const i=$e.APEX_RATE_PER_HOUR*Math.max(0,Math.sin(t*Math.PI/180)),n=Il-e;return($e.QUIET_RATE_PER_HOUR+i)/Math.pow($e.POPULATION_INDEX,n)}static schedule(t){const e=new Yl(t.seed^1542469173);return Er.schedule(t).map(i=>{const n=$e.toCartesian({altitudeDeg:Math.asin(e.next())*180/Math.PI,azimuthDeg:e.between(0,360)}),s=i.fromRadiantDeg*Math.PI/180,r=$e.turnAround(n,e.between(0,360)),o={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:$e.toHorizontal(o),bearingDeg:$e.bearingFrom(o,n)}})}static turnAround(t,e){const[i,n]=$e.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]=$e.basisAround(t),s=t.x*e.x+t.y*e.y+t.z*e.z,r=$e.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=$e.normalise($e.cross(t,e));return[i,$e.normalise($e.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=$e.toCartesian(t.radiant??{altitudeDeg:90,azimuthDeg:0}),i=$e.turnAround(e,t.bearingDeg),n=t.fromRadiantDeg*Math.PI/180;return $e.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 Bm="https://ufoathome.org/tle/index.json";class Ti{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??Ti.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(Bm)||t.push(Bm),t}static FIRST_SNAPSHOT="2021-02-22";async covers(t){const e=Date.parse(`${Ti.FIRST_SNAPSHOT}T00:00:00Z`)-Ti.MAX_ELEMENT_AGE_DAYS*Ti.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)-Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS&&t.getTime()<=Date.parse(n.to)+Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS):!1}async at(t){const e=await this.loadIndex();if(!e)return;const{index:i,base:n}=e,s=[],r=[];for(const o of Object.keys(i.kinds)){const c=await this.kindAt(o,t,i,n);s.push(...c),r.push(this.coverageOf(o,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*Ti.DAY_MS,o=Math.floor(s/r),c=s-o*r<r/2?o-1:o+1,l=new Set(i.kinds[t].bins),h=[o,c].map(v=>new Date(v*r).toISOString().slice(0,10)).filter(v=>l.has(v));if(h.length===0)return[];const[u,...d]=await Promise.all([this.json(new URL(`objects-${t}.json`,n).href),...h.map(v=>this.binary(new URL(`${t}/${v}.bin`,n).href))]),f=new Map;for(const v of d)for(const m of Ti.decode(v,i.recordBytes)){const g=f.get(m.norad);(!g||Math.abs(m.epochMs-s)<Math.abs(g.epochMs-s))&&f.set(m.norad,m)}const p=[];for(const v of f.values()){const m=Math.abs(v.epochMs-s)/Ti.DAY_MS;if(m>Ti.MAX_ELEMENT_AGE_DAYS)continue;const g=u[v.norad]??{name:String(v.norad)};g.launch&&Date.parse(`${g.launch}T00:00:00Z`)>s||p.push({norad:v.norad,name:g.name,kind:t,launch:g.launch,stdMag:g.stdMag,elements:v,ageDays:m})}return p}coverageOf(t,e,i,n){const{from:s,to:r}=i.kinds[t],o=e.getTime(),c=Ti.MAX_ELEMENT_AGE_DAYS*Ti.DAY_MS,l=n?"covered":o<Date.parse(s)-c?"before":o>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 AE{lowerM;upperM;add(t,e){if(!(t<=0)){if(e.behindM!==void 0){const i=Pe.sizeMAt(e.behindM,t);this.lowerM=this.lowerM===void 0?i:Math.max(this.lowerM,i)}if(e.inFrontM!==void 0){const i=Pe.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:Pe.distanceMAt(this.lowerM,t),maxM:this.upperM===void 0?void 0:Pe.distanceMAt(this.upperM,t)}}clear(){this.lowerM=void 0,this.upperM=void 0}}class Tr{static DEG_PER_SECOND=360/86164.0905;static degOver(t){return Math.max(0,t)*Tr.DEG_PER_SECOND}static instants(t,e){if(!(e>0))return 1;const i=Tr.degOver(t)/e;return i<1?1:Math.min(Tr.MAX_INSTANTS,Math.max(2,Math.ceil(i)))}static MAX_INSTANTS=64}class Fi{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 Tr.DEG_PER_SECOND*3600}static graspOf(t,e={}){const i=e.exposureSeconds??t.exposureSeconds,n=e.fNumber??t.fNumber;if(i===void 0||n===void 0||!(i>0)||!(n>0))return Fi.EYE;const s=e.focalLengthMm??t.frame?.focalLengthMm??Fi.UNKNOWN_CAMERA_FOCAL_MM,r=s/n,o=Fi.resolutionArcsec(t,s,r);return{apertureMm:r,exposureSeconds:Math.min(i,Fi.trailLimitedSeconds(o)),resolutionArcsec:o}}static resolutionArcsec(t,e,i){const s=(t.detailUm??Fi.UNKNOWN_CAMERA_DETAIL_UM)/1e3/e*Fi.ARCSEC_PER_RADIAN,r=1.22*Fi.WAVELENGTH_M/(i/1e3)*Fi.ARCSEC_PER_RADIAN;return Math.max(s,r)}static trailLimitedSeconds(t){return t/Fi.skyDriftArcsecPerSecond}static gainOverEye(t,e={}){const i=Fi.graspOf(t,e),n=Fi.EYE,s=(i.apertureMm/n.apertureMm)**2,r=i.exposureSeconds/n.exposureSeconds,o=(n.resolutionArcsec/i.resolutionArcsec)**2;return 1.25*Math.log10(s*r*o)}static gainFor(t,e){const i=e.fieldOfViewDeg===void 0?void 0:li.focalLengthMmFor(t,e.fieldOfViewDeg);return Fi.gainOverEye(t,{fNumber:e.fNumber,focalLengthMm:i,exposureSeconds:e.exposureSeconds})}}const Hm=111320,ro=Math.PI/180,TE=1.02,RE=1;class So{static of(t,e){const i=So.sightings(t,e);if(i.length<2)return;const n=So.baseline(i);if(!n)return;const{near:s,far:r,closedM:o}=n,c=Math.tan(r.widthDeg/2*ro)===0?0:Math.tan(s.widthDeg/2*ro)/Math.tan(r.widthDeg/2*ro);if(c<TE)return;const l=o/(c-1),h=Pe.sizeMAt(l,s.widthDeg),u=i.map(d=>({t:d.t,m:Pe.distanceMAt(h,d.widthDeg)}));return{widthM:h,distanceM:u,nearestM:Math.min(...u.map(d=>d.m)),fromT:r.t,toT:s.t,closedM:o}}static sightings(t,e){return t.timeline.allKeyframes.flatMap(i=>{const n=i.shapes.find(o=>o.sourceId===e)?.shape,s=n?.angular?.widthDeg,r=oi(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=So.closedAlongSight(i,n),[r,o,c]=s>=0?[n,i,s]:[i,n,-s];c<RE||r.widthDeg<=o.widthDeg||(!e||c>e.closedM)&&(e={near:r,far:o,closedM:c})}return e}static closedAlongSight(t,e){const i=(e.lat-t.lat)*Hm,n=(e.lng-t.lng)*Hm*Math.cos(t.lat*ro),s=(t.sightAzimuthDeg??0)*ro;return i*Math.cos(s)+n*Math.sin(s)}}class Ni{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:Ni.atLeastNearest(t.statedM),basis:"stated"};if(t.hypothesisM!==void 0&&t.hypothesisM>0)return{distanceM:Ni.atLeastNearest(t.hypothesisM),basis:"hypothesis"};if(t.derivedM!==void 0&&t.derivedM>0)return{distanceM:Ni.atLeastNearest(t.derivedM),basis:"derived"};const e=Ni.largest(t.range?.minM,t.crossing?.behindM),i=Ni.smallest(t.range?.maxM,t.crossing?.inFrontM),n=e===void 0?void 0:e*Ni.MARGIN,s=i===void 0?void 0:i/Ni.MARGIN;return n!==void 0&&s!==void 0?{distanceM:Ni.atLeastNearest(n<=s?Math.sqrt(n*s):n),basis:"bounded"}:n!==void 0?{distanceM:Ni.atLeastNearest(n),basis:"bounded"}:s!==void 0&&s<Ni.CONVENTIONAL_M?{distanceM:Ni.atLeastNearest(s),basis:"bounded"}:{distanceM:Ni.CONVENTIONAL_M,basis:"conventional"}}static atLeastNearest(t){return Math.max(Ni.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 pu=Math.PI/180;class Qt{constructor(t,e,i){this.body=t,this.ground=e;const n=[...t.track].sort((s,r)=>s.t-r.t);this.keys=this.place(n,i);for(const s of n)Qt.collect(this.motionKeys,s.t,s.motions),Qt.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};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 Qt.channelsAt(this.motionKeys,t,0)}lightsAt(t){return this.lightKeys.size>0?Qt.channelsAt(this.lightKeys,t,void 0):void 0}static channelsAt(t,e,i){const n={};for(const[s,r]of t){let o=r.length-1;for(;o>=0&&r[o].t>e;)o--;if(o<0){i!==void 0&&(n[s]=i);continue}const c=r[o],l=r[Math.min(o+1,r.length-1)],h=l===c||l.t===c.t?0:Math.min(1,(e-c.t)/(l.t-c.t));n[s]=Qt.lerp(c.value,l.value,h)}return n}static eyeOf(t,e,i){const n=oi(t,0),s=oi(t,e),o=n?.lat!==void 0&&n.lng!==void 0&&s?.lat!==void 0&&s.lng!==void 0?ci(s.lat,s.lng,n.lat,n.lng):void 0,c=o?o.x:0,l=o?-o.z:0;return{eastM:c,northM:l,upM:i.heightAt(c,l)+Qt.EYE_HEIGHT_M+(s?.elevationM??0),headingDeg:s?.headingDeg}}static lineOfSightMeetsGround(t,e,i,n){const s=Qt.directionOf(e,i),r=l=>t.upM+s.upM*l-n.heightAt(t.eastM+s.eastM*l,t.northM+s.northM*l);let o=0,c=0;for(;c<Qt.MAX_RANGE_M;){if(c=o+Math.max(.5,o*.01),r(c)<=0){for(let l=0;l<30;l++){const h=(o+c)/2;r(h)<=0?c=h:o=h}return c}o=c}}static directionOf(t,e){const i=t*pu,n=e*pu;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=e.length-1;for(;i>0&&e[i].t>t;)i--;const n=e[i];if(!n.present)return;const s=e[Math.min(i+1,e.length-1)],r=s===n||s.t===n.t?0:Math.min(1,(t-n.t)/(s.t-n.t)),o=Qt.lerp(n.eastM,s.eastM,r),c=Qt.lerp(n.northM,s.northM,r),l={widthM:Qt.lerp(n.sizeM.widthM,s.sizeM.widthM,r),lengthM:Qt.lerp(n.sizeM.lengthM,s.sizeM.lengthM,r),heightM:Qt.lerp(n.sizeM.heightM,s.sizeM.heightM,r)},h={headingDeg:Qt.lerpAngle(n.attitude.headingDeg,s.attitude.headingDeg,r),pitchDeg:Qt.lerp(n.attitude.pitchDeg,s.attitude.pitchDeg,r),rollDeg:Qt.lerp(n.attitude.rollDeg,s.attitude.rollDeg,r)};let u;if("aboveGroundM"in n.vertical&&"aboveGroundM"in s.vertical){const d=Qt.lerp(n.vertical.aboveGroundM,s.vertical.aboveGroundM,r);u=this.groundUnderFootprint(o,c,l,h.headingDeg)+d+l.heightM/2}else u=Qt.lerp(this.centreUpOf(n),this.centreUpOf(s),r);return{id:this.body.id,model:this.body.model,explains:this.body.explains??[],outlineNode:this.body.outlineNode,eastM:o,northM:c,upM:u,sizeM:l,attitude:h,appearance:{color:(r<1?n:s).appearance.color,albedo:Qt.lerp(n.appearance.albedo,s.appearance.albedo,r),luminanceCdM2:Qt.lerp(n.appearance.luminanceCdM2,s.appearance.luminanceCdM2,r)},flame:Qt.flameBetween(n.flame,s.flame,r),motions:this.motionsAt(t),lights:this.lightsAt(t),throwsFlame:this.body.track.some(d=>d.flame!==void 0&&d.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:Qt.lerp(n.lengthM,s.lengthM,i),widthM:Qt.lerp(n.widthM,s.widthM,i),luminanceCdM2:Qt.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*pu,r={eastM:Math.cos(s),northM:-Math.sin(s)},o={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+o.eastM*d,e+r.northM*u+o.northM*d))}return c}place(t,e){const i=[];let n;for(const s of t){const r=s.sizeM??n?.sizeM??Qt.DEFAULT_SIZE,o={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??Qt.DEFAULT_APPEARANCE.color,albedo:s.appearance?.albedo??n?.appearance.albedo??Qt.DEFAULT_APPEARANCE.albedo,luminanceCdM2:s.appearance?.luminanceCdM2??n?.appearance.luminanceCdM2??Qt.DEFAULT_APPEARANCE.luminanceCdM2},l=this.positionOf(s,e)??(n&&{eastM:n.eastM,northM:n.northM,vertical:this.verticalOf(s)??n.vertical});if(!l)continue;const h=s.flame??n?.flame,u=s.present??n?.present??!0;n={t:s.t,...l,sizeM:r,attitude:o,appearance:c,flame:h,present:u},i.push(n)}return i}verticalOf(t){if(t.onGround)return{aboveGroundM:0};if(t.altitudeAboveGroundM!==void 0)return{aboveGroundM:t.altitudeAboveGroundM}}positionOf(t,e){if(t.eastM!==void 0&&t.northM!==void 0)return{eastM:t.eastM,northM:t.northM,vertical:this.verticalOf(t)??{aboveGroundM:0}};if(t.azimuthDeg===void 0||t.altitudeDeg===void 0)return;const i=e(t.t);if(!i)return;const n=t.distanceM??(t.onGround?Qt.lineOfSightMeetsGround(i,t.azimuthDeg,t.altitudeDeg,this.ground):void 0);if(n===void 0)return;const s=Qt.directionOf(t.azimuthDeg,t.altitudeDeg),r=i.eastM+s.eastM*n,o=i.northM+s.northM*n;return{eastM:r,northM:o,vertical:this.verticalOf(t)??{upM:i.upM+s.upM*n}}}static lerp(t,e,i){return t+(e-t)*i}static lerpAngle(t,e,i){const n=((e-t)%360+540)%360-180;return((t+n*i)%360+360)%360}}const sa=Math.PI/180,ao=180/Math.PI;class Ke{constructor(t){this.timeline=t}static DIRECTION_TOLERANCE_DEG=1;static SIZE_TOLERANCE=1.5;static RINGS=12;static SEGMENTS=24;at(t,e,i,n){const s=[];for(const r of e){const o=Ke.projectionOf(r,i,n?.(r));if(o)for(const c of r.explains){const l=this.timeline.getInterpolatedShapeAt(t,c);!l||l.transparency>=1||s.push({...Ke.compare(c,r.id,{aim:l.aim,angular:l.angular},o),title:l.title})}}return s}static compare(t,e,i,n){const s=[],r=i.aim?Ke.separationDeg(i.aim,n.aim):void 0;if(r!==void 0){const l=Math.max(i.angular?.widthDeg??0,n.angular.widthDeg)/2;r>Math.max(Ke.DIRECTION_TOLERANCE_DEG,l)&&s.push("direction")}const o=i.angular&&i.angular.widthDeg>0?n.angular.widthDeg/i.angular.widthDeg:void 0,c=i.angular&&i.angular.heightDeg>0?n.angular.heightDeg/i.angular.heightDeg:void 0;return o!==void 0&&!Ke.withinSize(o)&&s.push("width"),c!==void 0&&!Ke.withinSize(c)&&s.push("height"),{sourceId:t,bodyId:e,stated:i,predicted:n,separationDeg:r,widthRatio:o,heightRatio:c,disagreements:s}}static projectionOf(t,e,i){const n=i&&i.length>0?i:Ke.outlineOf(t),s=i&&i.length>0?Ke.centreOf(i):t,r=Ke.normalized({eastM:s.eastM-e.eastM,northM:s.northM-e.northM,upM:s.upM-e.upM});if(!r)return;const o=Ke.normalized({eastM:r.northM,northM:-r.eastM,upM:0})??{eastM:1,northM:0,upM:0},c=Ke.cross(o,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},v=Ke.dot(p,r);if(v<=0)return;const m=Math.atan2(Ke.dot(p,o),v),g=Math.atan2(Ke.dot(p,c),v);l=Math.min(l,m),h=Math.max(h,m),u=Math.min(u,g),d=Math.max(d,g)}return{aim:{azimuthDeg:(Math.atan2(r.eastM,r.northM)*ao+360)%360,altitudeDeg:Math.asin(Math.max(-1,Math.min(1,r.upM)))*ao},angular:{widthDeg:(h-l)*ao,heightDeg:(d-u)*ao}}}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*sa,n=e.altitudeDeg*sa,s=Math.sin(i)*Math.sin(n)+Math.cos(i)*Math.cos(n)*Math.cos((t.azimuthDeg-e.azimuthDeg)*sa);return Math.acos(Math.max(-1,Math.min(1,s)))*ao}static withinSize(t){return t<=Ke.SIZE_TOLERANCE&&t>=1/Ke.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"&&R1.includes(r))for(let u=0;u<=Ke.RINGS;u++){const d=u/Ke.RINGS*Math.PI;for(let f=0;f<Ke.SEGMENTS;f++){const p=f/Ke.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*sa,l=t.attitude.pitchDeg*sa,h=t.attitude.rollDeg*sa;return s.map(([u,d,f])=>{const p=u*Math.cos(h)+f*Math.sin(h),v=-u*Math.sin(h)+f*Math.cos(h),m=d*Math.cos(l)-v*Math.sin(l),g=d*Math.sin(l)+v*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+g}})}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}}ag();const DE={sun:{en:"Sun",fr:"Soleil"},moon:{en:"Moon",fr:"Lune"},Venus:{en:"Venus",fr:"Vénus"},Mars:{en:"Mars",fr:"Mars"},Jupiter:{en:"Jupiter",fr:"Jupiter"},Saturn:{en:"Saturn",fr:"Saturne"}},CE=["en","fr"],IE={en:"{name} — mag {mag}, {alt}° above the horizon",fr:"{name} — mag {mag}, {alt}° au-dessus de l'horizon"},PE={en:"{name} — satellite, mag {mag}, {height} km up",fr:"{name} — satellite, mag {mag}, à {height} km d'altitude"},LE="satellites-change",OE="rr0-confrontation",NE={en:"{name} — mag {mag}, {alt}° below the horizontal",fr:"{name} — mag {mag}, {alt}° sous l'horizontale"},Gm="comet:",Vm="nova:",FE={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},shrub:{en:"Shrub",fr:"Buisson"},bridge:{en:"Bridge",fr:"Pont"},crop:{en:"Crop row",fr:"Rang de culture"},mound:{en:"Stone heap",fr:"Tas de pierres"},streetlight:{en:"Streetlight",fr:"Lampadaire"},vehicle:{en:"Vehicle",fr:"Véhicule"},observer:{en:"Observer",fr:"Observateur"},aircraft:{en:"Aircraft",fr:"Aéronef"},entity:{en:"Being",fr:"Être"}},UE=new URL(""+new URL("stars-mag7.5-B43R6Wvg.bin",import.meta.url).href,import.meta.url).href,kE=new URL(""+new URL("stars-mag7.5-9-BLV2tFmZ.bin",import.meta.url).href,import.meta.url).href,zE=-18,BE={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},mu={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class I0 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",pa,ma]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;distanceHypotheses=new Map;depths=new Map;directionScratch=new R;meteorScheduleFor;lightningScheduleFor;lightningFlashes=[];lastLightningT;lastTimeMs=0;interpretationShown;confrontationReadings=[];confrontationSignature="";comparing=!1;inTheRound=!0;lastSkyKey;starCatalog;starCatalogRequest=0;static tleArchive=new Ti;satellitesFor;satelliteRequest=0;satelliteStatus="none";satellites;satellitePassesMemo;starCatalogDepth=0;weatherAudio=new bE;vehicleAudio=new H1;vehicleHearing=new al;animateWhilePausedValue=!1;set animateWhilePaused(t){t!==this.animateWhilePausedValue&&(this.animateWhilePausedValue=t,this.syncAnimationsToPlayback())}get animateWhilePaused(){return this.animateWhilePausedValue}thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=t=>{this.sceneRenderer.setCompassHovered(!0);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,o=-((t.clientY-i.top)/i.height*2-1),c=ll(po.preferencesFor(this),CE),l=this.sceneRenderer.pickBodyAt(r,o);if(l){this.showHoverTooltip(t,this.bodyName(l,c));return}const h=this.sceneRenderer.pickDecorAt(r,o),u=h?this.ufoElement.sighting.decor.find(p=>p.id===h):void 0;if(u){this.showHoverTooltip(t,this.said.read(u.title)||FE[u.kind][c]);return}const d=this.sceneRenderer.pickSatelliteAt(r,o);if(d){this.showHoverTooltip(t,PE[c].replace("{name}",d.name).replace("{mag}",d.magnitude.toLocaleString(void 0,{maximumFractionDigits:1})).replace("{height}",Math.round(d.heightKm).toLocaleString()));return}const f=this.sceneRenderer.pickStarAt(r,o);if(f){const p=f.star.mag,v=f.altitudeDeg,m=(v<0?NE:IE)[c];this.showHoverTooltip(t,m.replace("{name}",f.star.name[c]).replace("{mag}",p.toLocaleString(void 0,{maximumFractionDigits:Math.abs(p)<1?2:1})).replace("{alt}",String(Math.round(Math.abs(v)))));return}this.hoverTooltip.hidden=!0};bodyName(t,e){const i=t.startsWith(Gm)?t.slice(Gm.length):void 0,n=i?I1.find(r=>r.id===i):void 0,s=t.startsWith(Vm)?zm.byId(t.slice(Vm.length)):void 0;return n?.name[e]??s?.name[e]??DE[t]?.[e]??t}showHoverTooltip(t,e){this.hoverTooltip.textContent=e,this.hoverTooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${t.clientX-i.left+12}px`,this.hoverTooltip.style.top=`${t.clientY-i.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash(t){clearTimeout(this.thunderTimeoutId),this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),hi.thunderDelayMs(t))}handleFirstInteraction=()=>{this.removeEventListener("pointerdown",this.handleFirstInteraction,!0),this.removeEventListener("keydown",this.handleFirstInteraction,!0),this.weatherAudio.resume(),this.vehicleAudio.resume(),this.setWeather(K0(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=t=>{this.lastTimeMs=t.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.playbackState==="playing"&&this.sceneRenderer.frame(performance.now())};syncAnimationsToPlayback(){const t=this.ufoElement.playbackState==="playing",e=t||this.animateWhilePaused;this.sceneRenderer.setAnimationsRunning(e,t),this.weatherAudio.setPaused(!e),this.vehicleAudio.setPaused(!e),e||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${q1}</style>${X1}`,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 ke(this.sceneCanvas);const e=this.shadow.getElementById("scene-loader");this.sceneRenderer.onFirstFrameHold=r=>{e.hidden=!r},this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(Mu),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.paintsShapes=!1,this.forwardPlayerAttributes(),this.ufoElement.addEventListener("lookat",r=>this.lookToward(r.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",r=>{r.newState==="open"&&Wn.fill(n,this)});const s=ll(po.preferencesFor(this),["en","fr"])==="fr"?"Crédits":"Credits";this.creditsButton.title=s,this.creditsButton.setAttribute("aria-label",s),this.sceneRenderer.onMapSubjectBounds=r=>this.ufoElement.setMapSubjectBounds(r),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.addEventListener("referenceview",r=>this.applyReferenceView(r.detail)),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave),this.addEventListener("pointerdown",this.handleFirstInteraction,!0),this.addEventListener("keydown",this.handleFirstInteraction,!0)}get said(){return this.saidTexts??=new Vs(po.preferencesFor(this))}saidTexts;connectedCallback(){this.saidTexts=void 0,this.sceneRenderer.restoreContext(),this.resizeToStage(),this.updateAstronomy(this.lastTimeMs),this.loadStars(),this.resizeObserver=new ResizeObserver(()=>this.resizeToStage()),this.resizeObserver.observe(this.frameElement),document.addEventListener("fullscreenchange",this.handleFullscreenChange);const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose(),this.vehicleAudio.dispose(),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===pa||t===ma)&&i!==e&&this.forwardPlayerAttributes()}forwardPlayerAttributes(){for(const t of[pa,ma]){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=oi(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}=ci(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)}bodyScreenBox(t){return this.sceneRenderer.bodyScreenBox(t)}pickPlacedBodyAt(t,e){return this.sceneRenderer.pickPlacedBodyAt(t,e)}resumeWeatherAudio(){this.weatherAudio.resume(),this.vehicleAudio.resume()}async loadFromSrc(t){const e=await Km.json(t);this.documentUrl=new URL(t,location.href).href,this.sightingData=e}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.interpretationShown=this.inTheRound?this.ufoElement.sighting.interpretation:void 0,this.applyFrameFormat(),this.lastTimeMs=0,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(0)}referenceAspect(t){return this.sceneRenderer.referenceAspect(t)}screenPointOf(t){return this.sceneRenderer.screenPointOf(t)}directionAt(t,e){return this.sceneRenderer.directionAt(t,e)}referenceFailedToLoad(t){return this.sceneRenderer.referenceFailedToLoad(t)}applyReferenceView(t){this.sceneRenderer.setReferencesShown(t.shown);for(const e of this.ufoElement.sighting.references)this.sceneRenderer.setReferenceView(e.id,{opacity:t.opacity})}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}get currentRoadAttribution(){return this.sceneRenderer.currentRoadAttribution}setTerrainProviders(t){this.sceneRenderer.setTerrainProviders(t)}setDecorModelProvider(t){this.sceneRenderer.setDecorModelProvider(t)}get decorModelCredits(){return this.sceneRenderer.currentDecorModelCredits}applyFrameFormat(){const t=this.ufoElement.sighting.instrument,e=Pe.CANVAS_HEIGHT_PX,i=li.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:hu,url:this.getAttribute("star-catalog-src")??UE},{magnitudeLimit:uu,url:this.getAttribute("deep-star-catalog-src")??kE}],e=this.instrumentReach(),i=++this.starCatalogRequest;this.starCatalogDepth=e>hu?uu:hu;const n=await Vn.upTo(t,e);i===this.starCatalogRequest&&(this.starCatalog=n,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=uu||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const t=this.ufoElement.sighting,e=Fi.gainFor(t.instrument,{fNumber:oi(t,0)?.fNumber,fieldOfViewDeg:Ki.fovOf(t,0),exposureSeconds:t.exposure});return il(zE,e)}updateAstronomy(t){this.ensureStarsDeepEnough(),this.applySceneAt(t);const e=Tn.windowEndingAt(t,this.exposureSeconds()),i=e.seconds,n=this.degreesPerPixelAt(t),s=Tr.instants(i,n),r=Math.max(s,this.ufoElement.exposureTimes(t).length,Tn.instants(this.ufoElement.sighting.decor,oi(this.ufoElement.sighting,t)?.elevationM??0,e.fromMs,i,n));if(r<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(r,o=>this.applySceneAt(e.fromMs+e.ms*o/(r-1),{sky:Math.floor(o*s/r)!==Math.floor((o-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:Ki.fovOf(this.ufoElement.sighting,t)/e}applySceneAt(t,e){const i=this.ufoElement.sighting;this.setWeather(K0(i,t)),this.sceneRenderer.setInstrument(i.instrument),e||this.vehicleAudio.setVoices(this.vehicleHearing.at(i,t)),this.updateMeteorShower(i,t),this.updateLightning(i,t,e!==void 0),this.sceneRenderer.setDecor(i.decor),this.sceneRenderer.setReferences(i.references);const n=oi(i,t),s=oi(i,0),r=Na(i,0),o=Object.fromEntries(ol(Na(i,t)).map(S=>[S.id,W0(t,i.weatherTrack,r,s,n,S.id)]));this.sceneRenderer.setCloudOffset(W0(t,i.weatherTrack,r,s,n),o),this.sceneRenderer.setObserverPose(n??mu),this.sceneRenderer.setLensOptics(this.lensOpticsAt(t)),this.sceneRenderer.setInstrumentGain(Fi.gainFor(i.instrument,{fNumber:n?.fNumber,fieldOfViewDeg:Ki.fovOf(i,t),exposureSeconds:i.exposure}),i.instrument.detailUm!==void 0),this.sceneRenderer.setGait(xe.bodyAt(i,t,this.ufoElement.steadyObserver)),this.sceneRenderer.updateDecorAnchoring(oi(i,0),n,t),this.placeBodiesAt(t,e===void 0),this.sceneRenderer.updateDecorLitState(t,e?.stepMs??0),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng,()=>{this.placeBodiesAt(this.lastTimeMs,!0),this.sceneRenderer.render()}),this.sceneRenderer.setStatedRoads(i.roads),this.pushPhenomenaAt(t);const c=n?.lat??mu.lat,l=n?.lng??mu.lng,h=Lc(i.event.time??{},l,i.event.utcOffsetHours),u={lat:c,lng:l,elevationM:n?.elevationM??0};if(this.pushSatellitesAt(h,t,u),e&&!e.sky)return;if(!h){this.sceneRenderer.setAstronomy(BE);return}const d=new Date(h.getTime()+t),f=Math.max(1,Math.round(.25*this.degreesPerPixelAt(t)/Tr.DEG_PER_SECOND*1e3)),p=Math.max(1e-8,this.degreesPerPixelAt(t)*.1),v=`${Math.floor(d.getTime()/f)}|${Math.round(c/p)}|${Math.round(l/p)}|${Math.round(u.elevationM)}|${this.starCatalog?this.starCatalogDepth:0}`;if(v===this.lastSkyKey){this.sceneRenderer.render();return}this.lastSkyKey=v;const m={...Hh("Sun",d,u),magnitude:Gh("Sun",d)},g={...Hh("Moon",d,u),phase:x5(d),magnitude:Gh("Moon",d)},_=M5.map(S=>({body:S,position:Hh(S,d,u),magnitude:Gh(S,d)}));this.sceneRenderer.setAstronomy({sun:m,moon:g,planets:_,comet:this.cometAt(d,u),novae:zm.appearancesAt(d,u).map(({outburst:S,position:M,magnitude:b})=>({id:S.id,position:M,magnitude:b})),stars:this.starCatalog?{catalog:this.starCatalog,date:d,observer:u}:void 0,frame:{date:d,observer:u}}),this.ufoElement.setSunAltitude(m.altitudeDeg)}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)}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(LE)))},s=I0.tleArchive;(async()=>{if(!await s.covers(t))return n("outside");const[r,o]=await Promise.all([s.at(t),sl(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(i===this.satelliteRequest){if(!r)return n("unavailable");this.satellites={snapshot:r,passes:new o.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}}satellitePassesDuring(t){const e=this.satellites,i=this.ufoElement.sighting,n=oi(i,0),s=i.event.place?.[0],r=n?.lat??s?.lat,o=n?.lng??s?.lng;if(!e||r===void 0||o===void 0)return[];const c=Lc(i.event.time??{},o,i.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(t,0),4*36e5),h={lat:r,lng:o,elevationM:n?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),r,o,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=wE.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),o=new Map,c=new Map,l=new Set;for(const p of i.sourceIds){const v=i.getInterpolatedShapeAt(t,p);if(!v)continue;const m={...v,bounds:{...v.bounds,x:v.bounds.x+s.x,y:v.bounds.y+s.y}};o.set(p,m);const g=v.aim?this.sceneRenderer.screenPointOf(An.directionOf(v.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)},_=g!==void 0&&Math.abs(g.ndcX)<=1&&Math.abs(g.ndcY)<=1,S=_?this.sceneRenderer.decorDistancesAt(g.ndcX,g.ndcY,p):{};l.add(p),(_||v.aim)&&l.delete(p);const M=v.angular?.widthDeg??r.pxToDeg(v.bounds.width),b=this.sizeEstimateOf(p);b.add(M,S);const w=So.of(e,p);c.set(p,Ni.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:w&&M>0?Pe.distanceMAt(w.widthM,M):void 0,range:b.distanceRangeAt(M),crossing:S}))}for(const[p,v]of o)for(const[m,g]of o){if(m===p||g.transparency>=1||g.bounds.width*g.bounds.height<=v.bounds.width*v.bounds.height||!(v.bounds.x>=g.bounds.x&&v.bounds.y>=g.bounds.y&&v.bounds.x+v.bounds.width<=g.bounds.x+g.bounds.width&&v.bounds.y+v.bounds.height<=g.bounds.y+g.bounds.height))continue;const S=c.get(m);S&&c.set(p,{distanceM:S.distanceM*.999,basis:S.basis});break}this.depths=c;const h=i.sourceIds,u=[];for(const[p,v]of o)u.push({sourceId:p,shape:v,distanceM:c.get(p).distanceM,renderOrder:h.indexOf(p),aim:v.aim,hidden:l.has(p)||this.interpretationShown!==void 0&&(!this.comparing||v.transparency>=1),ghost:this.interpretationShown!==void 0&&this.comparing});const f=(oi(e,t)?.rollDeg??0)+xe.bodyAt(e,t,this.ufoElement.steadyObserver).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:li.starPointsOf(e.instrument),rollRad:f*Math.PI/180})}get interpretation(){return this.interpretationShown}set interpretation(t){this.interpretationShown=t,this.updateAstronomy(this.lastTimeMs)}get accountInTheRound(){return this.inTheRound}set accountInTheRound(t){this.inTheRound=t}get compareAccount(){return this.comparing}set compareAccount(t){this.comparing=t,this.updateAstronomy(this.lastTimeMs)}get confrontation(){return this.confrontationReadings}groundAlong(t,e,i){const n=this.sceneRenderer.bodyGround,s=Qt.eyeOf(this.ufoElement.sighting,i,n);return s?Qt.lineOfSightMeetsGround(s,t,e,n):void 0}bodyReading(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=d=>Qt.eyeOf(n,d,i),r=new Qt(t,i,s).at(e),o=s(e);if(!r||!o)return;const c=r.eastM-o.eastM,l=r.northM-o.northM,h=r.upM-o.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}}directionToBody(t,e){const i=this.sceneRenderer.bodyGround,n=this.ufoElement.sighting,s=p=>Qt.eyeOf(n,p,i),r=new Qt(t,i,s),o=r.at(e)?e:t.track[0]?.t,c=o===void 0?void 0:r.at(o),l=o===void 0?void 0:s(o);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 o=this.sceneRenderer.bodyGround,c=p=>Qt.eyeOf(n,p,o);i&&(s=i.bodies.map(p=>new Qt(p,o,c).at(t)).filter(p=>p!==void 0));const l=Na(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 Ke(n.timeline).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(OE,{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&&Na(t,s.t).storm&&this.handleLightningFlash(s)}ensureLightningSchedule(t){const e=Na(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?Lc(n,s?.lng??0,t.event.utcOffsetHours):void 0,o=(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=hi.schedule({durationMs:o,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?Lc(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,o=Math.round(n.getTime()/1e3)+Math.round(e.lat*1e3),c=$e.schedule({ratePerHour:$e.observedRatePerHour($e.apexPosition(n,s).altitudeDeg),durationMs:r,velocityKmS:$e.TYPICAL_VELOCITY_KM_S,seed:o}),l=fu.activeAt(n).map(u=>{const d=fu.radiantPosition(u.shower,n,s);return{entry:u,position:d,rate:fu.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=Er.schedule({ratePerHour:l.rate,durationMs:r,velocityKmS:l.entry.shower.velocityKmS,seed:o+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}meteorByRank(t){this.ensureMeteorSchedule(this.ufoElement.sighting);const e=[...this.sceneRenderer.meteorSchedule].filter(s=>s.t+s.durationMs<=this.ufoElement.seekableDuration).sort((s,r)=>r.brightness-s.brightness);if(e.length===0)return;const i=e[t%e.length],n=this.sceneRenderer.meteorMidpoint(i);if(n)return{t:Math.round(i.t+i.durationMs*.45),...n}}lensOpticsAt(t){const e=this.ufoElement.sighting,i=e.instrument,n=i.frame,s=oi(e,t),r=s?.fNumber??i.fNumber;if(!n||r===void 0)return;const o=li.focalLengthMmFor(i,Ki.fovOf(e,t));if(o!==void 0)return{focalLengthMm:o,fNumber:r,focusDistance:s?.focusDistanceM??0,frameHeightMm:n.heightMm}}projectionAt(t){const e=this.ufoElement.sighting;return vs.of(e.instrument,Pe.CANVAS_HEIGHT_PX,Ki.fovOf(e,t))}sizeEstimateOf(t){let e=this.sizeEstimates.get(t);return e||(e=new AE,this.sizeEstimates.set(t,e)),e}}const Wm="rr0-scene";function HE(){ag(),customElements.get(Wm)||customElements.define(Wm,I0)}HE();export{gM as $,qE as A,ee as B,st as C,sp as D,Rt as E,ZE as F,KE as G,Dg as H,YE as I,$E as J,ps as K,Ho as L,RM as M,Jo as N,Fe as O,zg as P,Zi as Q,Io as R,ki as S,GE as T,Re as U,Mt as V,Yi as W,XE as X,Ln as Y,Rg as Z,jf as _,WE as a,dl as a0,sd as a1,xl as a2,yi as a3,Ug as a4,h0 as a5,u0 as a6,re as a7,Js as a8,Bo as a9,zi as aa,bs as ab,VE as b,QE as c,ml as d,jE as e,Zt as f,R as g,Hf as h,JE as i,tA as j,dM as k,xr as l,th as m,m2 as n,ae as o,Ee as p,Tu as q,_i as r,Cg as s,ws as t,SM as u,fr as v,$i as w,Mn as x,Se as y,oe as z};