@rr0/ufoathome 0.61.0 → 0.61.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.
|
@@ -600,7 +600,7 @@ input[type=range] {
|
|
|
600
600
|
pointer-events: none;
|
|
601
601
|
white-space: nowrap;
|
|
602
602
|
}
|
|
603
|
-
`,Ja=[{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 Vt{static get default(){return Ja[0]}static byId(e){return Ja.find(t=>t.id===e)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(e){const t=e.frame;return t?2*Math.atan(t.heightMm/(2*t.focalLengthMm))*180/Math.PI:Vt.UNAIDED_FIELD_DEG}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Vt.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Vt.aspectOf(e))}static availableAt(e){return e===void 0?Ja:Ja.filter(t=>!t.years||e>=t.years.from&&(t.years.to===void 0||e<=t.years.to))}static fieldOfViewDegAt(e,t){const n=e.frame;if(!(!n||t<=0))return 2*Math.atan(n.heightMm/(2*t))*180/Math.PI}static focalLengthMmFor(e,t){const n=e.frame;if(!(!n||t<=0||t>=180))return n.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){const n=t??e.fNumber;if(n===void 0||e.apertureBlades===void 0)return 0;const i=e.fNumberRange;return!i||i.max<=i.min?1:Math.max(0,Math.min(1,(n-i.min)/(i.max-i.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(e){return e.flare??Vt.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class Ca{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const n of e.witnessTrack.allKeyframes){const{lat:i,lng:r,headingDeg:a}=n.pose;i===void 0||r===void 0||t.push({t:n.t,lat:i,lng:r,headingDeg:a})}if(t.length===0){const n=e.event.place?.[0];if(!n)return;t.push({t:0,lat:n.lat,lng:n.lng})}return new Ca(t)}get moved(){return this.spanM>Ca.STATIONARY_M}get spanM(){const e=this.box,t=(e.south+e.north)/2,n=(e.west+e.east)/2;return Math.max(Math.abs(rn(t,e.east,t,e.west).x),Math.abs(rn(e.north,n,e.south,n).z))}get center(){const e=this.box;return{lat:(e.south+e.north)/2,lng:(e.west+e.east)/2}}boundsAround(e,t){const{lat:n,lng:i}=this.center,r=Math.max(this.spanM*(1+t),e)/2;return{north:Bi(0,-r,n,i).lat,south:Bi(0,r,n,i).lat,east:Bi(r,0,n,i).lng,west:Bi(-r,0,n,i).lng}}get box(){const e=this.points.map(n=>n.lat),t=this.points.map(n=>n.lng);return{south:Math.min(...e),north:Math.max(...e),west:Math.min(...t),east:Math.max(...t)}}}class Gt{constructor(e,t){this.stretches=e,this.rotationPassed=t}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(e){const t=Ca.of(e);if(!t||t.points.length<2)return;const n=[];let i=0;for(let r=1;r<t.points.length;r++){const a=t.points[r-1],o=t.points[r],c=(o.t-a.t)/1e3;if(c<=0)continue;const l=rn(o.lat,o.lng,a.lat,a.lng),h=l.x,u=-l.z,d=Math.hypot(h,u),f=d/c,p=Gt.stepHzFor(f);n.push({startMs:a.t,endMs:o.t,speedMPerS:f,eastUnit:d>0?h/d:0,northUnit:d>0?u/d:0,stepHz:p,stepsBefore:i,rampsIn:!0,rampsOut:!0}),i+=p*c}for(let r=0;r<n.length;r++){const a=n[r-1],o=n[r+1];n[r].rampsIn=a===void 0||a.stepHz===0,n[r].rampsOut=o===void 0||o.stepHz===0}if(n.some(r=>r.stepHz>0))return new Gt(n,1-(e.instrument.stabilization??0))}static stepHzFor(e){return e<Gt.SLOWEST_WALK_M_PER_S||e>Gt.FASTEST_WALK_M_PER_S?0:Gt.REFERENCE_STEP_HZ*Math.pow(e/Gt.REFERENCE_SPEED_M_PER_S,Gt.CADENCE_EXPONENT)}offsetAt(e){const t=this.stretches.find(c=>e>=c.startMs&&e<=c.endMs);if(!t||t.stepHz===0)return Gt.STILL;const n=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,i=2*Math.PI*n,r=this.amplitudeAt(t,e),a=Gt.SWAY_M*r*Math.cos(i/2),o=r*this.rotationPassed*t.speedMPerS/Gt.REFERENCE_SPEED_M_PER_S;return{eastM:a*t.northUnit,northM:-a*t.eastUnit,upM:Gt.RISE_M_PER_M_PER_S*t.speedMPerS*r*Math.cos(i),rollDeg:Gt.HEAD_ROLL_DEG*o*Math.cos(i/2),pitchDeg:-1.25*o*Math.cos(i),yawDeg:Gt.HEAD_YAW_DEG*o*Math.cos(i/2)}}amplitudeAt(e,t){const n=1e3/e.stepHz,i=Math.min(n,(e.endMs-e.startMs)/2);if(i<=0)return 1;const r=t-e.startMs,a=e.endMs-t,o=Math.min(e.rampsIn?r/i:1,e.rampsOut?a/i:1,1);return(1-Math.cos(Math.PI*Math.max(o,0)))/2}}class mt{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(e){return 2*Math.atan(e.sizeM/(2*e.distanceM))*180/Math.PI}static inMoons(e){return e/mt.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(e,t,n){if(!(!e||!t))return{widthDeg:e.widthDeg+(t.widthDeg-e.widthDeg)*n,heightDeg:e.heightDeg+(t.heightDeg-e.heightDeg)*n}}static sizeMAt(e,t){return 2*e*Math.tan(t*Math.PI/360)}static distanceMAt(e,t){return e/(2*Math.tan(t*Math.PI/360))}}function yg(s,e,t){if(!s||!e)return t<1?s:e;const n=((e.azimuthDeg-s.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((s.azimuthDeg+n*t)%360+360)%360,altitudeDeg:s.altitudeDeg+(e.altitudeDeg-s.altitudeDeg)*t}}function Sg(s,e,t){const{bounds:n}=s;return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height}function wn(s,e,t){return s+(e-s)*t}function Ed(s){const e=/^#([0-9a-f]{6})$/i.exec(s);if(!e)return;const t=parseInt(e[1],16);return[t>>16&255,t>>8&255,t&255]}function bg(s){return`#${s.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function wg(s,e,t){const n=Ed(s),i=Ed(e);return!n||!i?t<1?s:e:bg([wn(n[0],i[0],t),wn(n[1],i[1],t),wn(n[2],i[2],t)])}function Eg(s,e,t){const n={x:wn(s.bounds.x,e.bounds.x,t),y:wn(s.bounds.y,e.bounds.y,t),width:wn(s.bounds.width,e.bounds.width,t),height:wn(s.bounds.height,e.bounds.height,t)},i=wn(s.angle,e.angle,t),r=wn(s.transparency,e.transparency,t),a=wn(s.haloScale,e.haloScale,t),o=wn(s.blur??0,e.blur??0,t),c=wn(s.brightness??0,e.brightness??0,t),l=wg(s.color,e.color,t),h=mt.lerpAngular(s.angular,e.angular,t),u=yg(s.aim,e.aim,t);return s.kind==="polygon"&&e.kind==="polygon"&&s.points.length===e.points.length?{...s,bounds:n,angle:i,transparency:r,haloScale:a,blur:o,brightness:c,color:l,angular:h,aim:u,points:s.points.map((d,f)=>({x:wn(d.x,e.points[f].x,t),y:wn(d.y,e.points[f].y,t)}))}:{...t<1?s:e,bounds:n,angle:i,transparency:r,haloScale:a,blur:o,brightness:c,color:l,angular:h,aim:u}}class Nc{keyframes=[];order=[];groups=[];addKeyframe(e,t){const n=this.findInsertIndex(e);if(this.keyframes[n]?.t===e){const i=new Set(t.map(r=>r.sourceId));this.keyframes[n]={t:e,shapes:[...this.keyframes[n].shapes.filter(r=>!i.has(r.sourceId)),...t]}}else this.keyframes.splice(n,0,{t:e,shapes:[...t]});for(const i of t)this.order.includes(i.sourceId)||this.order.push(i.sourceId)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getKeyframeAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t];return n?.t===e?n:void 0}getShapeAt(e,t){return this.getKeyframeAt(e)?.shapes.find(n=>n.sourceId===t)?.shape}getLatestShapeAt(e,t){let n=this.findInsertIndex(e);for(this.keyframes[n]?.t!==e&&(n-=1);n>=0;n--){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return i.shape}}getInterpolatedShapeAt(e,t){const n=this.findShapeAtOrBefore(e,t);if(n?.t===e)return n.shape;const i=this.findShapeAtOrAfter(e,t);return n?i?Eg(n.shape,i.shape,(e-n.t)/(i.t-n.t)):n.shape:i?.shape}findShapeAtOrBefore(e,t){let n=this.findInsertIndex(e);for(this.keyframes[n]?.t!==e&&(n-=1);n>=0;n--){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return{t:this.keyframes[n].t,shape:i.shape}}}findShapeAtOrAfter(e,t){for(let n=this.findInsertIndex(e);n<this.keyframes.length;n++){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return{t:this.keyframes[n].t,shape:i.shape}}}hitTest(e,t,n,i){const r=this.sourceIds;for(let a=r.length-1;a>=0;a--){if(i?.has(r[a]))continue;const o=this.getInterpolatedShapeAt(e,r[a]);if(o&&Sg(o,t,n))return{sourceId:r[a],shape:o}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const n=this.keyframes[t].shapes.filter(i=>i.sourceId!==e);n.length===0?this.keyframes.splice(t,1):n.length!==this.keyframes[t].shapes.length&&(this.keyframes[t]={t:this.keyframes[t].t,shapes:n})}this.order=this.order.filter(t=>t!==e),this.removeFromGroup(e)}group(e){if(!(e.length<2)){for(const t of e)this.removeFromGroup(t);this.groups.push([...e])}}ungroup(e){const t=this.groups.findIndex(n=>n.includes(e));t!==-1&&this.groups.splice(t,1)}groupMembers(e){return this.groups.find(t=>t.includes(e))}removeFromGroup(e){const t=this.groups.findIndex(i=>i.includes(e));if(t===-1)return;const n=this.groups[t].filter(i=>i!==e);n.length<2?this.groups.splice(t,1):this.groups[t]=n}bringToFront(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.push(e))}sendToBack(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.unshift(e))}get duration(){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(e){const t=new Nc;for(const n of e.keyframes)t.addKeyframe(n.t,n.shapes);if(e.order){const n=t.order.filter(i=>!e.order.includes(i));t.order=[...e.order,...n]}return e.groups&&(t.groups=e.groups.map(n=>n.filter(i=>t.order.includes(i))).filter(n=>n.length>=2)),t}}function Ag(s,e,t){return Math.max(e,Math.min(t,s))}function Tg(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function Zs(s,e,t){return s+(e-s)*t}function Rg(s,e,t){return{lat:s.lat===void 0||e.lat===void 0?void 0:Zs(s.lat,e.lat,t),lng:s.lng===void 0||e.lng===void 0?void 0:Zs(s.lng,e.lng,t),elevationM:Zs(s.elevationM,e.elevationM,t),headingDeg:s.headingDeg===void 0||e.headingDeg===void 0?void 0:Tg(s.headingDeg,e.headingDeg,t),pitchDeg:Zs(s.pitchDeg,e.pitchDeg,t),rollDeg:Zs(s.rollDeg??0,e.rollDeg??0,t),fovDeg:Zs(s.fovDeg,e.fovDeg,t),fNumber:s.fNumber,focusDistanceM:s.focusDistanceM}}class Pa{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,pose:t}:this.keyframes.splice(n,0,{t:e,pose:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getLatestPoseAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].pose:void 0}getInterpolatedPoseAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.pose;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return n?i?Rg(n.pose,i.pose,Ag((e-n.t)/(i.t-n.t),0,1)):n.pose:i?.pose}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Pa;for(const n of e.keyframes)t.addKeyframe(n.t,n.pose);return t}}function bt(s,e,t){return s+(e-s)*t}function Nu(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function Dg(s,e,t){return Math.max(e,Math.min(t,s))}function Cg(s=[],e=[],t){if(!(!s.length&&!e.length))return[...new Set([...s.map(n=>n.id),...e.map(n=>n.id)])].map(n=>{const i=s.find(c=>c.id===n),r=e.find(c=>c.id===n),a=i??{...r,density:0},o=r??{...i,density:0};return{...a,eastM:bt(a.eastM,o.eastM,t),northM:bt(a.northM,o.northM,t),baseM:bt(a.baseM,o.baseM,t),thicknessM:bt(a.thicknessM,o.thicknessM,t),widthM:bt(a.widthM,o.widthM,t),depthM:bt(a.depthM,o.depthM,t),rotationDeg:Nu(a.rotationDeg,o.rotationDeg,t),density:bt(a.density,o.density,t),darkness:bt(a.darkness??0,o.darkness??0,t)}})}function Pg(s,e,t){if(s.cloudLayers===void 0&&e.cloudLayers===void 0)return;const n=hc(s),i=hc(e);return t>=1?i.map(a=>({...a})):[...new Set([...n.map(a=>a.id),...i.map(a=>a.id)])].map(a=>{const o=n.find(u=>u.id===a),c=i.find(u=>u.id===a),l=o??{...c,coverage:0},h=c??{...o,coverage:0};return{...l,instances:Cg(o?.instances,c?.instances,t),baseM:bt(l.baseM,h.baseM,t),thicknessM:bt(l.thicknessM,h.thicknessM,t),coverage:bt(l.coverage,h.coverage,t),sizeM:bt(l.sizeM,h.sizeM,t),density:bt(l.density,h.density,t),darkness:bt(l.darkness??s.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:bt(l.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:l.windSpeed===void 0&&h.windSpeed===void 0?void 0:bt(l.windSpeed??s.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:l.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Nu(l.windDirectionDeg??s.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function Ig(s,e,t){return{cloudLayers:Pg(s,e,t),cloudCover:bt(s.cloudCover,e.cloudCover,t),cloudDarkness:bt(s.cloudDarkness,e.cloudDarkness,t),highCloudCover:s.highCloudCover===void 0||e.highCloudCover===void 0?void 0:bt(s.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:s.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:bt(s.iceCrystalAlignment,e.iceCrystalAlignment,t),lowerCloudCover:s.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:bt(s.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:s.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:bt(s.cloudBaseM,e.cloudBaseM,t),precipitationType:t<1?s.precipitationType:e.precipitationType,precipitationIntensity:bt(s.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Nu(s.windDirectionDeg,e.windDirectionDeg,t),windSpeed:bt(s.windSpeed,e.windSpeed,t),storm:t<1?s.storm:e.storm}}class Ia{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,weather:t}:this.keyframes.splice(n,0,{t:e,weather:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getLatestWeatherAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].weather:void 0}getInterpolatedWeatherAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.weather;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return n?i?Ig(n.weather,i.weather,Dg((e-n.t)/(i.t-n.t),0,1)):n.weather:i?.weather}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Ia;for(const n of e.keyframes)t.addKeyframe(n.t,n.weather);return t}}class La{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,sound:t}:this.keyframes.splice(n,0,{t:e,sound:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}getLatestSoundAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].sound:void 0}getInterpolatedSoundAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.sound;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!n)return i?.sound;if(!i)return n.sound;const r=(e-n.t)/(i.t-n.t);return this.lerp(n.sound,i.sound,Math.max(0,Math.min(1,r)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new La;for(const n of e.keyframes)t.addKeyframe(n.t,n.sound);return t}lerp(e,t,n){return{kind:n<1?e.kind:t.kind,volume:e.volume+(t.volume-e.volume)*n,pitchHz:e.pitchHz+(t.pitchHz-e.pitchHz)*n,src:n<1?e.src:t.src}}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}}const Lg=100,Ng={kind:"none",volume:0,pitchHz:Lg};class Gn{constructor(e){this.entries=e}static empty(){return new Gn(new Map)}get size(){return this.entries.size}at(e){return this.entries.get(e)}paths(){return[...this.entries.keys()]}set(e,t){t.basis==="stated"&&t.rationale===void 0?this.entries.delete(e):this.entries.set(e,t)}clear(e){for(const t of this.entries.keys())(t===e||t.startsWith(`${e}.`))&&this.entries.delete(t)}static strip(e){const t=new Gn(new Map);return{recording:Gn.stripValue(e,[],t),provenance:t}}static restore(e,t){if(t.size===0)return e;const n=structuredClone(e);for(const i of t.paths()){const r=t.at(i),a=i.split("."),o=Gn.holderOf(n,a);if(!o)continue;const c=a[a.length-1],l=o[c];l!==void 0&&(r.of!==void 0&&JSON.stringify(r.of)!==JSON.stringify(l)||(o[c]={value:l,...r.basis==="stated"?{}:{basis:r.basis},...r.rationale===void 0?{}:{rationale:r.rationale}}))}return n}static isWrapper(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&"value"in e}static stripValue(e,t,n){return Gn.isWrapper(e)?(n.set(t.join("."),{basis:e.basis??"stated",...e.rationale===void 0?{}:{rationale:e.rationale},of:e.value}),Gn.stripValue(e.value,t,n)):Array.isArray(e)?e.map((i,r)=>Gn.stripValue(i,[...t,String(r)],n)):typeof e=="object"&&e!==null?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,Gn.stripValue(r,[...t,i],n)])):e}static holderOf(e,t){let n=e;for(const i of t.slice(0,-1)){if(typeof n!="object"||n===null)return;n=n[i]}return typeof n=="object"&&n!==null?n:void 0}}function lh(s){if(s.year!==void 0)return Date.UTC(s.year,(s.month??1)-1,s.day??1,s.hour??0,s.minute??0,s.second??0)}function Ad(s){return(((s.day??0)*24+(s.hour??0))*60+(s.minute??0))*6e4+(s.second??0)*1e3}const Og=["year","month","day","hour","minute"],Ug=["day","hour","minute"];function Td(s,e){return e.filter(t=>s[t]!==void 0).join(",")}function Fg(s){if(s.durationSeconds!==void 0)return s.durationSeconds*1e3;if(!s.time||!s.endTime)return;const e=s.time.year!==void 0&&s.endTime.year!==void 0,t=e?Og:Ug,n=Td(s.time,t);if(!(n===""||n!==Td(s.endTime,t)))return e?lh(s.endTime)-lh(s.time):Ad(s.endTime)-Ad(s.time)}class Oc{constructor(e,t,n,i,r,a,o,c,l=[],h,u,d,f=[],p=[]){this.event=e,this.timeline=t,this.witnessTrack=n,this.weatherTrack=i,this.soundTrack=r,this.witness=a,this.caseId=o,this.weather=c,this.decor=l,this.weatherSource=h,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p}provenance=Gn.empty();testimony;get witnessCount(){return 1+this.decor.filter(e=>e.kind==="witness").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Vt.byId(this.instrumentId)}static create(e,t,n){return new Oc({eventType:"sighting",time:e,place:t},new Nc,new Pa,new Ia,new La,n)}}const kg=0,zg=0;function Qt(s,e){const t=s.witnessTrack.getInterpolatedPoseAt(e);if(t)return t;const n=s.event.place?.[0];if(n)return{lat:n.lat,lng:n.lng,elevationM:kg,headingDeg:void 0,pitchDeg:zg,fovDeg:Vt.fieldOfViewDeg(s.instrument)}}function Js(s,e){return s.weatherTrack.getInterpolatedWeatherAt(e)??s.weather??Ap}function Bg(s,e){return s.soundTrack.getInterpolatedSoundAt(e)??Ng}class Hg{constructor(e,t){this.timeline=e,this.onFrame=t}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const e=()=>{if(this.state!=="playing")return;const t=performance.now();if(this.currentT+=(t-this.lastWallTime)*this.playbackRate,this.lastWallTime=t,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(e){this.currentT=Math.max(0,Math.min(e,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(e){const t=new Map;for(const n of this.timeline.sourceIds){const i=this.timeline.getInterpolatedShapeAt(e,n);i&&t.set(n,i)}this.onFrame(e,t)}}const Dp=["nw","n","ne","e","se","s","sw","w"],Gg=24,ja=8,Vg=3,Wg=8;function Qa(s,e,t){const n=s.x-e.x,i=s.y-e.y,r=Math.cos(t),a=Math.sin(t);return{x:e.x+n*r-i*a,y:e.y+n*a+i*r}}function Kr(s){return{x:s.x+s.width/2,y:s.y+s.height/2}}const Xg={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 Nn{static handlePointsFor(e){const{x:t,y:n,width:i,height:r}=e.bounds,a={nw:{x:t,y:n},n:{x:t+i/2,y:n},ne:{x:t+i,y:n},e:{x:t+i,y:n+r/2},se:{x:t+i,y:n+r},s:{x:t+i/2,y:n+r},sw:{x:t,y:n+r},w:{x:t,y:n+r/2},rotate:{x:t+i/2,y:n-Gg}},o=Kr(e.bounds),c={};for(const l of Object.keys(a))c[l]=Qa(a[l],o,e.angle);return c}static hitTestHandle(e,t,n=8,i=[...Dp,"rotate"]){const r=Nn.handlePointsFor(e);for(const a of i)if(Math.hypot(t.x-r[a].x,t.y-r[a].y)<=n)return a}static HANDLE_DIRECTION_DEG={e:0,se:45,s:90,sw:135,w:180,nw:225,n:270,ne:315};static resizeAxisFor(e,t){const i=((Nn.HANDLE_DIRECTION_DEG[e]+t*180/Math.PI)%180+180)%180/45,r=["ew","nwse","ns","nesw"];return r[Math.round(i)%r.length]}static resizeBounds(e,t,n,i){const r=Kr(e),a=Qa(i,r,-t),{x:o,y:c,width:l,height:h}=e,u=Xg[n];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(a.x,p-ja)),u.right&&(p=Math.max(a.x,d+ja)),u.top&&(f=Math.min(a.y,v-ja)),u.bottom&&(v=Math.max(a.y,f+ja)),{x:d,y:f,width:p-d,height:v-f}}static resizeShape(e,t,n){if(t==="rotate")throw new Error("resizeShape does not accept the rotate handle");const{width:i,height:r}=e.bounds,a=Nn.resizeBounds(e.bounds,e.angle,t,n);if(e.kind==="oval")return{...e,bounds:a};const o=i===0?1:a.width/i,c=r===0?1:a.height/r;return{...e,bounds:a,points:e.points.map(l=>({x:l.x*o,y:l.y*c}))}}static rotateShape(e,t){const n=Kr(e.bounds),i=Math.atan2(t.y-n.y,t.x-n.x)+Math.PI/2;return{...e,angle:i}}static groupBoundsFor(e){const t=Math.min(...e.map(a=>a.x)),n=Math.min(...e.map(a=>a.y)),i=Math.max(...e.map(a=>a.x+a.width)),r=Math.max(...e.map(a=>a.y+a.height));return{x:t,y:n,width:i-t,height:r-n}}static vertexPointsFor(e){const t=Kr(e.bounds);return e.points.map(n=>Qa({x:e.bounds.x+n.x,y:e.bounds.y+n.y},t,e.angle))}static hitTestVertex(e,t,n=Wg){const i=Nn.vertexPointsFor(e);let r,a=n;return i.forEach((o,c)=>{const l=Math.hypot(t.x-o.x,t.y-o.y);l<=a&&(a=l,r=c)}),r}static toLocalPoint(e,t){const n=Kr(e.bounds),i=Qa(t,n,-e.angle);return{x:i.x-e.bounds.x,y:i.y-e.bounds.y}}static moveVertex(e,t,n){const i=e.points.map((u,d)=>d===t?Nn.toLocalPoint(e,n):u),r=Math.min(...i.map(u=>u.x)),a=Math.min(...i.map(u=>u.y)),o=Math.max(...i.map(u=>u.x)),c=Math.max(...i.map(u=>u.y)),l={x:e.bounds.x+r,y:e.bounds.y+a,width:o-r,height:c-a},h=i.map(u=>({x:u.x-r,y:u.y-a}));return{...e,bounds:l,points:h}}static insertVertexNear(e,t){const n=Nn.toLocalPoint(e,t),{points:i}=e;let r=i.length-1,a=1/0;for(let c=0;c<i.length;c++){const l=i[c],h=i[(c+1)%i.length],u=Nn.distanceToSegment(n,l,h);u<a&&(a=u,r=c)}const o=[...i.slice(0,r+1),n,...i.slice(r+1)];return{...e,points:o}}static distanceToSegment(e,t,n){const i=n.x-t.x,r=n.y-t.y,a=i*i+r*r,o=a===0?0:Math.max(0,Math.min(1,((e.x-t.x)*i+(e.y-t.y)*r)/a)),c=t.x+o*i,l=t.y+o*r;return Math.hypot(e.x-c,e.y-l)}static deleteVertex(e,t){return e.points.length<=Vg?e:{...e,points:e.points.filter((n,i)=>i!==t)}}}const hh=6,eo=hh/2,Rd=20,Dd=24,Cd=9,Pd=6,Id=7,Ld=6,hi=4;class Na{constructor(e){this.ctx=e}starPoints=0;roll=0;clear(e,t){this.ctx.clearRect(0,0,e,t)}static paintExtent(e){const{x:t,y:n,width:i,height:r}=e.bounds,a=t+i/2,o=n+r/2,c=e.angle%(2*Math.PI)!==0,l=Math.hypot(i,r)/2,h=c?l:i/2,u=c?l:r/2,d=Math.max(i,r)/2,f=e.brightness??0,p=f>0?Math.max(d*(1+Cd*f),Ld*f)-d:0,v=f>0?d*(1+Id*f)-d:0,m=3*Dd*(e.blur??0)+1.5*Rd*e.haloScale,g=Math.max(p,v,0)+m+2;return{x:a-h-g,y:o-u-g,width:2*(h+g),height:2*(u+g)}}paintInto(e,t,n){this.ctx.save(),this.ctx.scale(n,n),this.ctx.translate(-t.x,-t.y),this.paintShape(e.selected?{...e,selected:!1}:e),this.ctx.restore()}paintShape(e){this.ctx.save(),this.ctx.globalAlpha=1-e.transparency;const t=e.blur??0;t>0&&(this.ctx.filter=`blur(${(Dd*t).toFixed(2)}px)`);const n=e.brightness??0;n>0&&this.paintDazzle(e,n),e.haloScale>0&&this.paintHalo(e),this.paintBase(e),this.ctx.restore(),e.selected&&this.paintSelectionHandles(e)}setStarPoints(e){this.starPoints=Math.max(0,Math.floor(e))}setRoll(e){this.roll=e}paintDazzle(e,t){const{x:n,y:i,width:r,height:a}=e.bounds,o=n+r/2,c=i+a/2,l=Math.max(r,a)/2,h=Math.max(l*(1+Cd*t),Ld*t);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<=Pd;d++){const f=d/Pd,p=1/(1+24*f*f);this.ctx.globalAlpha=1,u.addColorStop(f,this.withAlpha(e.color,p*t*.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+Id*t);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(e.color,t*.55)),g.addColorStop(.35,this.withAlpha(e.color,t*.22)),g.addColorStop(1,this.withAlpha(e.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(e,t){if(t<=0)return e.color;const n=/^#([0-9a-f]{6})$/i.exec(e.color.trim());if(!n)return e.color;const i=Number.parseInt(n[1],16),r=a=>Math.round(a+(255-a)*t);return`rgb(${r(i>>16&255)}, ${r(i>>8&255)}, ${r(i&255)})`}withAlpha(e,t){const n=Math.max(0,Math.min(1,t)),i=/^#([0-9a-f]{6})$/i.exec(e.trim());if(!i)return e;const r=Number.parseInt(i[1],16);return`rgba(${r>>16&255}, ${r>>8&255}, ${r&255}, ${n.toFixed(3)})`}paintBase(e){if(this.ctx.fillStyle=this.dazzledFill(e,e.brightness??0),this.ctx.beginPath(),e.kind==="oval"){const{x:t,y:n,width:i,height:r}=e.bounds,a=i/2,o=r/2;this.ctx.ellipse(t+a,n+o,a,o,e.angle,0,2*Math.PI)}else{const{x:t,y:n,width:i,height:r}=e.bounds;this.ctx.save(),this.ctx.translate(t+i/2,n+r/2),this.ctx.rotate(e.angle),this.ctx.translate(-i/2,-r/2),e.points.forEach((a,o)=>{o===0?this.ctx.moveTo(a.x,a.y):this.ctx.lineTo(a.x,a.y)}),this.ctx.closePath(),this.ctx.restore()}this.ctx.fill()}paintHalo(e){this.ctx.save(),this.ctx.shadowColor=e.color,this.ctx.shadowBlur=Rd*e.haloScale,this.paintBase(e),this.ctx.restore()}paintSelectionHandles(e){this.paintHandleFrame(Nn.handlePointsFor(e),{includeRotate:!0}),e.kind==="polygon"&&this.paintVertexHandles(e)}paintVertexHandles(e){this.ctx.fillStyle="#39f";for(const t of Nn.vertexPointsFor(e))this.ctx.beginPath(),this.ctx.ellipse(t.x,t.y,hi,hi,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(e){this.paintOutline(Nn.handlePointsFor(e))}paintSelectionOnly(e){this.paintSelectionHandles(e)}paintPictureFrame(e,t,n){const i=this.ctx;if(i.save(),e&&e.length===4){i.strokeStyle="#39f",i.lineWidth=1.5,i.setLineDash([6,4]),i.beginPath(),i.moveTo(e[0].x,e[0].y);for(const r of e.slice(1))i.lineTo(r.x,r.y);i.closePath(),i.stroke(),i.setLineDash([])}for(const r of t){const a=Na.landmarkColour(r.residualDeg),o=r.selected?3:2;r.selected&&(i.strokeStyle="#fff",i.lineWidth=o+3,i.beginPath(),i.ellipse(r.picture.x,r.picture.y,hi+2,hi+2,0,0,2*Math.PI),i.stroke()),r.scene&&(i.strokeStyle=a,i.lineWidth=1,i.beginPath(),i.moveTo(r.picture.x,r.picture.y),i.lineTo(r.scene.x,r.scene.y),i.stroke(),i.fillStyle=a,i.beginPath(),i.ellipse(r.scene.x,r.scene.y,hi,hi,0,0,2*Math.PI),i.fill()),i.strokeStyle=a,i.lineWidth=o,i.beginPath(),i.ellipse(r.picture.x,r.picture.y,hi+2,hi+2,0,0,2*Math.PI),i.stroke(),this.paintLabel(r.label,r.picture.x+hi+5,r.picture.y-hi-2,a)}n&&this.paintLabel(n,8,8,"#fff",13),i.restore()}static landmarkColour(e){return e===void 0?"#ffb000":e<=1?"#3c3":e<=3?"#ffb000":"#f33"}paintLabel(e,t,n,i,r=11){const a=this.ctx;a.save(),a.font=`${r}px system-ui, sans-serif`,a.textBaseline="top";const o=a.measureText(e).width;a.fillStyle="rgba(0, 0, 0, 0.6)",a.fillRect(t-3,n-2,o+6,r+4),a.fillStyle=i,a.fillText(e,t,n),a.restore()}paintGroupHandles(e){this.paintHandleFrame(Nn.handlePointsFor({bounds:e,angle:0}),{includeRotate:!0})}paintOutline(e){this.ctx.strokeStyle="lightgray",this.ctx.beginPath(),this.ctx.moveTo(e.nw.x,e.nw.y),this.ctx.lineTo(e.ne.x,e.ne.y),this.ctx.lineTo(e.se.x,e.se.y),this.ctx.lineTo(e.sw.x,e.sw.y),this.ctx.closePath(),this.ctx.stroke()}paintHandleFrame(e,{includeRotate:t}){this.paintOutline(e),this.ctx.fillStyle="lightgray";for(const n of Dp){const i=e[n];this.ctx.fillRect(i.x-eo,i.y-eo,hh,hh)}t&&(this.ctx.beginPath(),this.ctx.moveTo(e.n.x,e.n.y),this.ctx.lineTo(e.rotate.x,e.rotate.y),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.ellipse(e.rotate.x,e.rotate.y,eo+1,eo+1,0,0,2*Math.PI),this.ctx.fill())}}const Nd=.05,Od=.08,Ud=2,Fd=3,qg=14,Yg=.02;class Kg{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(e){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",e);return}}this.context.state==="suspended"&&this.context.resume()}setSound(e){if(this.requested=e,!this.context)return;const t=this.keyFor(e);if(!t){this.silence();return}if(this.voice?.key!==t){this.stopVoice();const n=++this.voiceToken;t.startsWith("src:")?this.buildRecordedVoice(e.src,t,n):this.voice=this.buildSynthesizedVoice(e,t)}this.applyTo(this.voice,e)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(e){if(!(e.volume<=0))return e.src?`src:${e.src}`:e.kind==="none"?void 0:e.kind}applyTo(e,t){const n=this.context;if(!e||!n)return;const i=n.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,i,Nd);for(const{param:r,ratio:a}of e.pitch)r.setTargetAtTime(Math.min(t.pitchHz*a,n.sampleRate/2-1),i,Nd)}buildSynthesizedVoice(e,t){const n=this.context;if(n)switch(e.kind){case"hum":return this.buildHum(n,t);case"whistle":return this.buildWhistle(n,t);case"rumble":return this.buildRumble(n,t);case"crackle":return this.buildCrackle(n,t);default:return}}buildHum(e,t){const n=e.createOscillator();n.type="sawtooth";const i=e.createOscillator();i.type="sawtooth";const r=e.createBiquadFilter();r.type="lowpass",r.Q.value=1;const a=e.createGain();return a.gain.value=0,n.connect(r),i.connect(r),r.connect(a).connect(e.destination),n.start(),i.start(),{key:t,nodes:[r,a],sources:[n,i],volumeParam:a.gain,gainScale:.16,pitch:[{param:n.frequency,ratio:1},{param:i.frequency,ratio:1.006},{param:r.frequency,ratio:6}]}}buildWhistle(e,t){const n=e.createOscillator();n.type="sine";const i=e.createOscillator();i.type="sine",i.frequency.value=5;const r=e.createGain(),a=e.createGain();return a.gain.value=0,i.connect(r).connect(n.frequency),n.connect(a).connect(e.destination),n.start(),i.start(),{key:t,nodes:[r,a],sources:[n,i],volumeParam:a.gain,gainScale:.22,pitch:[{param:n.frequency,ratio:1},{param:r.gain,ratio:.012}]}}buildRumble(e,t){const n=e.createBufferSource();n.buffer=this.brownNoise(e),n.loop=!0;const i=e.createBiquadFilter();i.type="lowpass",i.Q.value=.8;const r=e.createGain();return r.gain.value=0,n.connect(i).connect(r).connect(e.destination),n.start(),{key:t,nodes:[i,r],sources:[n],volumeParam:r.gain,gainScale:1.4,pitch:[{param:i.frequency,ratio:1}]}}buildCrackle(e,t){const n=e.createBufferSource();n.buffer=this.whiteNoise(e),n.loop=!0;const i=e.createBiquadFilter();i.type="bandpass",i.Q.value=1.2;const r=e.createGain();r.gain.value=0;const a=e.createBufferSource();a.buffer=this.crackleEnvelope(e),a.loop=!0;const o=e.createGain();return o.gain.value=0,a.connect(o).connect(r.gain),n.connect(i).connect(r).connect(e.destination),n.start(),a.start(),{key:t,nodes:[i,r,o],sources:[n,a],volumeParam:o.gain,gainScale:.9,pitch:[{param:i.frequency,ratio:4}]}}async buildRecordedVoice(e,t,n){const i=this.context;if(!i)return;let r;try{r=await this.getBuffer(e)}catch(c){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",c);return}if(n!==this.voiceToken||!this.context)return;const a=i.createBufferSource();a.buffer=r,a.loop=!0;const o=i.createGain();o.gain.value=0,a.connect(o).connect(i.destination),a.start(),this.voice={key:t,nodes:[o],sources:[a],volumeParam:o.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(e){const t=this.context;if(!t)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(i=>{if(!i.ok)throw new Error(`Audio fetch failed (${i.status}): ${e}`);return i.arrayBuffer()}).then(i=>t.decodeAudioData(i)),this.buffers.set(e,n)),n}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*Ud),e.sampleRate),n=t.getChannelData(0);for(let i=0;i<n.length;i++)n[i]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*Ud),e.sampleRate),n=t.getChannelData(0);let i=0,r=0;for(let a=0;a<n.length;a++)i=(i+.02*(Math.random()*2-1))/1.02,n[a]=i,r=Math.max(r,Math.abs(i));if(r>0)for(let a=0;a<n.length;a++)n[a]/=r;return t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*Fd),e.sampleRate),n=t.getChannelData(0),i=Math.max(1,Math.floor(Yg*e.sampleRate)),r=Math.round(Fd*qg);for(let a=0;a<r;a++){const o=Math.floor(Math.random()*n.length),c=.4+Math.random()*.6;for(let l=0;l<i&&o+l<n.length;l++)n[o+l]=Math.max(n[o+l],c*(1-l/i))}this.crackleBuffer=t}return this.crackleBuffer}stopVoice(){const e=this.voice,t=this.context;if(this.voice=void 0,!e||!t)return;const n=t.currentTime;e.volumeParam.cancelScheduledValues(n),e.volumeParam.setTargetAtTime(0,n,Od/3);const i=n+Od;for(const r of e.sources){r.onended=()=>{r.disconnect();for(const a of e.nodes)a.disconnect()};try{r.stop(i)}catch{r.disconnect();for(const a of e.nodes)a.disconnect()}}}}function dc(s){return[...s].sort((e,t)=>e.t-t.t)}function kd(s,e){let t;for(const n of dc(s)){if(n.t>e)break;t=n}return t}const $c=Math.PI/180,to=180/Math.PI;class Hi{constructor(e,t,n){this.kind=e,this.canvasHeightPx=t,this.fovDeg=n;const i=n*$c/2;this.focalPx=e==="equidistant"?t/2/i:t/2/Math.tan(i)}focalPx;static of(e,t,n){return new Hi(e.projection,t,n)}degToPx(e){const t=e*$c;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*to:2*Math.atan(e/(2*this.focalPx))*to}angleDegToRadiusPx(e){const t=e*$c;return this.kind==="equidistant"?this.focalPx*t:this.focalPx*Math.tan(t)}halfWidthAngleDeg(e){return this.radiusPxToAngleDeg(this.canvasHeightPx*e/2)}radiusPxToAngleDeg(e){return this.kind==="equidistant"?e/this.focalPx*to:Math.atan(e/this.focalPx)*to}ofBounds(e){return{widthDeg:this.pxToDeg(e.width),heightDeg:this.pxToDeg(e.height)}}toBoundsSize(e){return{width:this.degToPx(e.widthDeg),height:this.degToPx(e.heightDeg)}}widthPx(e){return this.degToPx(mt.angularWidthDeg(e))}}class Vn{static fovOf(e,t){return Qt(e,t)?.fovDeg??Vt.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,n)=>({...t,angular:n.ofBounds(t.bounds)}))}static toBounds(e){this.eachKeyframe(e,(t,n)=>{if(!t.angular)return t;const{width:i,height:r}=n.toBoundsSize(t.angular),a={x:t.bounds.x+(t.bounds.width-i)/2,y:t.bounds.y+(t.bounds.height-r)/2,width:i,height:r};if(t.kind!=="polygon")return{...t,bounds:a};const o=t.bounds.width===0?1:i/t.bounds.width,c=t.bounds.height===0?1:r/t.bounds.height;return{...t,bounds:a,points:t.points.map(l=>({x:l.x*o,y:l.y*c}))}})}static toAim(e){this.eachKeyframe(e,(t,n,i)=>{const r=this.aimFrom(e,n,i,t.bounds);return r?{...t,aim:r}:t})}static aimOf(e,t,n){const i=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,i,Qt(e,t),n)}static aimFrom(e,t,n,i){if(n?.headingDeg===void 0)return;const r=this.frameCentre(e),a=t.radiusPxToAngleDeg(i.x+i.width/2-r.x),o=t.radiusPxToAngleDeg(r.y-(i.y+i.height/2));return{azimuthDeg:((n.headingDeg+a)%360+360)%360,altitudeDeg:n.pitchDeg+o}}static toPosition(e){this.eachKeyframe(e,(t,n,i)=>{if(!t.aim||i?.headingDeg===void 0)return t;const r=this.frameCentre(e),a=this.shortestArc(t.aim.azimuthDeg-i.headingDeg),o=t.aim.altitudeDeg-i.pitchDeg,c=r.x+this.offAxisPx(n,a)-t.bounds.width/2,l=r.y-this.offAxisPx(n,o)-t.bounds.height/2;return{...t,bounds:{...t.bounds,x:c,y:l}}})}static frameCentre(e){return{x:Vt.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,y:mt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=Vn.OFF_CANVAS_DEG?Math.sign(t)*Vn.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,n){const i=Vt.frameWidthPx(t,mt.CANVAS_HEIGHT_PX)/2,r=Vt.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,a=mt.CANVAS_HEIGHT_PX/2;for(const o of[...e.timeline.allKeyframes]){const c=this.fovOf(e,o.t),l=n?.get(o.t)??c,h=Hi.of(t,mt.CANVAS_HEIGHT_PX,l),u=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,c);e.timeline.addKeyframe(o.t,o.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-i,v=f.y+f.height/2-a,m=Math.hypot(p,v),g=m===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,S={...f,x:r+p*g-f.width/2,y:a+v*g-f.height/2};return{...d,shape:{...d.shape,bounds:S}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:n}=e;for(const i of[...n.allKeyframes]){const r=Qt(e,i.t),a=this.fovOf(e,i.t),o=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,a);n.addKeyframe(i.t,i.shapes.map(c=>({...c,shape:t(c.shape,o,r)})))}}}function $g(s){return Gn.restore(Zg(s),s.provenance)}function Zg(s){return Vn.toAngular(s),Vn.toAim(s),{version:1,time:s.event.time,endTime:s.event.endTime,durationSeconds:s.event.durationSeconds,utcOffsetHours:s.event.utcOffsetHours,timeZone:s.event.timeZone,place:s.event.place,witness:s.witness,testimony:s.testimony,caseId:s.caseId,description:s.event.description,tags:s.event.tags,timeline:s.timeline.toJSON(),witnessTrack:s.witnessTrack.toJSON(),weatherTrack:s.weatherTrack.toJSON(),soundTrack:s.soundTrack.toJSON(),weather:s.weather,decor:s.decor,milestones:s.milestones.length>0?s.milestones:void 0,references:s.references.length>0?s.references:void 0,weatherSource:s.weatherSource,instrument:s.instrumentId,exposureSeconds:s.exposureSeconds}}function Jg(s){const{recording:e,provenance:t}=Gn.strip(s),n=jg(e);return n.provenance=t,n}function jg(s){const e=new Oc({eventType:"sighting",time:s.time,endTime:s.endTime,durationSeconds:s.durationSeconds,utcOffsetHours:s.utcOffsetHours,timeZone:s.timeZone,place:s.place,description:s.description,tags:s.tags},Nc.fromJSON(s.timeline),s.witnessTrack?Pa.fromJSON(s.witnessTrack):new Pa,s.weatherTrack?Ia.fromJSON(s.weatherTrack):new Ia,s.soundTrack?La.fromJSON(s.soundTrack):new La,s.witness,s.caseId,s.weather,s.decor??[],s.weatherSource,s.instrument,s.exposureSeconds??s.witnessTrack?.keyframes.map(t=>t.pose.exposureSeconds).find(t=>t!==void 0),dc(s.milestones??[]),s.references??[]);return e.testimony=s.testimony,Vn.toBounds(e),Vn.toPosition(e),e}const zd=2;function Cp(s){return s==="building"||s==="vehicle"}function Qg(s,e){const t=s.litKeyframes;if(!t||t.length===0)return s.lit??!1;let n=t[0];for(const i of t){if(i.t>e)break;n=i}return n.lit}function e1(s,e){return s.pattern.kind==="steady"?!0:Pp(s,e,e+1)>.5}function Pp(s,e,t){if(s.pattern.kind==="steady")return 1;const{perMinute:n,dutyCycle:i,phase:r=0}=s.pattern,a=Math.min(Math.max(i,0),1);if(a===0||n<=0)return 0;const o=6e4/n,c=e/o+r,l=t/o+r;if(l<=c)return Math.min(Math.max(c-Math.floor(c),0),a)<a?1:0;const h=u=>Math.floor(u)*a+Math.min(u-Math.floor(u),a);return(h(l)-h(c))/(l-c)}function Ou(s,e){const t=s.track,n={eastM:s.eastM,northM:s.northM,altitudeM:0,headingDeg:s.headingDeg};if(!t||t.length===0)return n;if(t.length===1||e<=t[0].t)return Bd(t[0],s);const i=t[t.length-1];if(e>=i.t)return Bd(i,s);for(let r=0;r<t.length-1;r++){const a=t[r],o=t[r+1];if(e<a.t||e>o.t)continue;const c=o.t-a.t,l=c===0?0:(e-a.t)/c;return{eastM:a.eastM+(o.eastM-a.eastM)*l,northM:a.northM+(o.northM-a.northM)*l,altitudeM:(a.altitudeM??0)+((o.altitudeM??0)-(a.altitudeM??0))*l,headingDeg:a.headingDeg??s.headingDeg}}return n}function Bd(s,e){return{eastM:s.eastM,northM:s.northM,altitudeM:s.altitudeM??0,headingDeg:s.headingDeg??e.headingDeg}}class Qn{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(e,t){const n=Number.isFinite(t)?Math.max(0,t):0,i=Math.max(0,e-n*1e3),r=Math.max(0,e-i);return{fromMs:i,toMs:e,ms:r,seconds:r/1e3}}static instants(e,t,n,i,r){if(!(i>0))return 1;const a=r>0?Qn.travelDegOver(e,t,n,n+i*1e3)/r/Qn.PIXELS_PER_INSTANT:0,o=Qn.flashesOver(e,i)*Qn.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(a,o));return c<2?1:Math.min(Qn.MAX_INSTANTS,c)}static travelDegOver(e,t,n,i){let r=0;for(const a of e){if(!a.track||a.track.length<2)continue;const o=Qn.directionAt(a,t,n),c=Qn.directionAt(a,t,i),l=Math.min(1,Math.max(-1,o.x*c.x+o.y*c.y+o.z*c.z));r=Math.max(r,Math.acos(l)*180/Math.PI)}return r}static flashesOver(e,t){let n=0;for(const i of e)for(const r of i.lights??[])r.pattern.kind==="flash"&&(n=Math.max(n,r.pattern.perMinute));return n/60*t}static directionAt(e,t,n){const i=Ou(e,n),r=i.eastM,a=i.altitudeM-t,o=i.northM,c=Math.hypot(r,a,o);return c===0?{x:0,y:1,z:0}:{x:r/c,y:a/c,z:o/c}}}function Uu(s,e){for(const t of s){const n=t.toLowerCase().split("-")[0];if(e.includes(n))return n}return"en"}class fc{static preferencesFor(e){const t=navigator.languages??[],n=this.declaredFor(e);return n?[n,...t]:t}static declaredFor(e){for(let t=e;t;){const n=t.closest("[lang]")?.getAttribute("lang")?.trim();if(n)return n;const i=t.getRootNode();t=i instanceof ShadowRoot?i.host:void 0}}}class hs{constructor(e){this.preferences=e}read(e){if(e===void 0||typeof e=="string")return e===""?void 0:e;for(const n of this.preferences){const i=e[n]??e[hs.base(n)];if(i)return i}const t=new Set(this.preferences.map(n=>hs.base(n)));for(const[n,i]of Object.entries(e))if(i&&t.has(hs.base(n)))return i;return Object.values(e).find(n=>n)??void 0}write(e,t,n){const i=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return i;const r={...e},a=Object.keys(r).find(o=>o===n)??Object.keys(r).find(o=>hs.base(o)===hs.base(n))??n;return i===void 0?delete r[a]:r[a]=i,Object.keys(r).length===0?void 0:r}static base(e){return e.toLowerCase().split("-")[0]}}const t1=["en","fr"],n1={en:()=>lc(()=>Promise.resolve().then(()=>s1),void 0,import.meta.url).then(s=>s.ufoMessages_en),fr:()=>lc(()=>import("./UfoMessages_fr-CnenjNH2.js"),[],import.meta.url).then(s=>s.ufoMessages_fr)};function i1(s){return n1[s]()}const Ip={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",showWitnessMap:"Show where the witness was",hideWitnessMap:"Hide where the witness 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",witnessHere:"The witness, here",decorHere:"Scenery"},s1=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Ip},Symbol.toStringTag,{value:"Module"})),Lp=Math.PI/180,r1=180/Math.PI,a1=256,o1=19;function c1(s,e){return 156543.03392*Math.cos(s*Lp)/2**e}function l1(s,e){return c1(s,e)*a1}function Np(s,e){let t=0;for(;t<o1&&l1(s,t+1)>=e;)t++;return t}function Qo(s){const e=s*Lp;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function Op(s,e,t){const n=2**t;return{x:(s+180)/360*n,y:Qo(e)*n}}function Up(s,e,t){const n=Qo(s.north),i=Qo(s.south);return{x:(e-s.west)/(s.east-s.west),y:(Qo(t)-n)/(i-n)}}function h1(s,e,t){const{x:n,y:i}=Op(s,e,t);return{x:Math.floor(n),y:Math.floor(i),z:t}}function u1(s){const e=2**s.z,t=s.x/e*360-180,n=(s.x+1)/e*360-180,i=Hd(s.y,e);return{south:Hd(s.y+1,e),north:i,west:t,east:n}}function Hd(s,e){const t=s/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*r1}function Fp(s,e,t,n){const i=h1(s,e,t),r=Math.floor(n/2),a=[];for(let l=-r;l<=r;l++)for(let h=-r;h<=r;h++)a.push({x:i.x+h,y:i.y+l,z:t});const o=a.map(u1),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:a,bounds:c}}class Rs{constructor(e){this.ctx=e}static SCALE_STEPS_M=[5e3,2e3,1e3,500,200,100,50,20,10,5];static MARKER_RADIUS_PX=8.5;static ON_MARKER_M=3;targets=[];hitTest(e,t){let n,i=1/0;for(const r of this.targets){const a=Math.hypot(r.x-e,r.y-t);a>r.radius||a>i||(n=r,i=a)}return n}get width(){return this.ctx.canvas.width}get height(){return this.ctx.canvas.height}paint(e){const{ctx:t}=this;t.save(),this.targets=[],t.clearRect(0,0,this.width,this.height),this.paintGround(e),this.paintNight(e.nightFraction),this.paintPath(e),e.position?(this.paintCone(e,e.position),this.paintDecor(e),this.paintMarkers(e),this.paintWitness(e,e.position)):(this.paintDecor(e),this.paintMarkers(e)),this.paintNorth(),this.paintFooter(e.bounds,e.attribution),t.restore()}toCanvas(e,t,n){const i=Up(e,n,t);return{x:i.x*this.width,y:i.y*this.height}}paintGround(e){const{ctx:t}=this;t.fillStyle="#1d2321",t.fillRect(0,0,this.width,this.height);const n=e.imagery;if(!n)return;const i=this.toCanvas(e.bounds,n.bounds.north,n.bounds.west),r=this.toCanvas(e.bounds,n.bounds.south,n.bounds.east);t.drawImage(n.source,i.x,i.y,r.x-i.x,r.y-i.y)}paintNight(e=0){if(e<=0)return;const{ctx:t}=this;t.save(),t.fillStyle=`rgba(6, 12, 30, ${Math.min(e,1)*.78})`,t.fillRect(0,0,this.width,this.height),t.restore()}paintDecor(e){const{ctx:t}=this;for(const n of e.decor){const i=this.toCanvas(e.bounds,n.lat,n.lng);if(n.label&&this.targets.push({kind:"decor",label:n.label,lat:n.lat,lng:n.lng,x:i.x,y:i.y,radius:7}),t.beginPath(),t.rect(i.x-3.5,i.y-3.5,7,7),t.fillStyle="rgba(120, 220, 255, 0.85)",t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.7)",t.stroke(),n.headingDeg===void 0)continue;const r=(n.headingDeg-90)*Math.PI/180;t.beginPath(),t.moveTo(i.x,i.y),t.lineTo(i.x+Math.cos(r)*10,i.y+Math.sin(r)*10),t.lineWidth=3,t.strokeStyle="rgba(0, 0, 0, 0.6)",t.stroke(),t.lineWidth=1.5,t.strokeStyle="rgba(120, 220, 255, 0.9)",t.stroke()}}paintPath(e){if(!e.path.moved)return;const{ctx:t}=this,n=e.path.points.map(i=>this.toCanvas(e.bounds,i.lat,i.lng));t.beginPath(),t.moveTo(n[0].x,n[0].y);for(const i of n.slice(1))t.lineTo(i.x,i.y);t.lineJoin="round",t.lineCap="round",t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=5,t.stroke(),t.strokeStyle="rgba(255, 255, 255, 0.9)",t.lineWidth=2,t.stroke()}paintCone(e,t){const{headingDeg:n,coneHalfAngleDeg:i}=e;if(n===void 0||i===void 0)return;const{ctx:r}=this,a=this.toCanvas(e.bounds,t.lat,t.lng),o=Math.hypot(this.width,this.height),c=(n-90)*Math.PI/180,l=i*Math.PI/180;r.save(),r.beginPath(),r.moveTo(a.x,a.y),r.arc(a.x,a.y,o,c-l,c+l),r.closePath();const h=r.createRadialGradient(a.x,a.y,0,a.x,a.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)"),r.fillStyle=h,r.fill(),r.restore()}paintMarkers(e){const{ctx:t}=this;t.textAlign="center",t.textBaseline="middle",t.font="bold 10px sans-serif";for(const n of[...e.markers].sort((i,r)=>Number(i.current)-Number(r.current))){const i=this.toCanvas(e.bounds,n.lat,n.lng);this.targets.push({kind:"milestone",label:n.note?`${n.label} — ${n.note}`:n.label,lat:n.lat,lng:n.lng,t:n.t,x:i.x,y:i.y,radius:Rs.MARKER_RADIUS_PX}),t.beginPath(),t.arc(i.x,i.y,Rs.MARKER_RADIUS_PX,0,Math.PI*2),t.fillStyle=n.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",t.fill(),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.9)",t.stroke(),t.fillStyle=n.current?"#1d2321":"#fff",t.fillText(n.label,i.x,i.y)}}paintWitness(e,t){const{ctx:n}=this,i=this.toCanvas(e.bounds,t.lat,t.lng);e.witnessLabel&&this.targets.push({kind:"witness",label:e.witnessLabel,lat:t.lat,lng:t.lng,x:i.x,y:i.y,radius:8});const r=e.markers.some(a=>{if(!a.current)return!1;const o=rn(a.lat,a.lng,t.lat,t.lng);return Math.hypot(o.x,o.z)<=Rs.ON_MARKER_M});n.beginPath(),n.arc(i.x,i.y,r?Rs.MARKER_RADIUS_PX+2.5:5.5,0,Math.PI*2),r||(n.fillStyle="#ff5a3c",n.fill()),n.lineWidth=4,n.strokeStyle="rgba(0, 0, 0, 0.5)",n.stroke(),n.lineWidth=r?3:2.5,n.strokeStyle=r?"#ff5a3c":"#fff",n.stroke()}paintNorth(){const{ctx:e}=this,t=this.width-14,n=16;e.beginPath(),e.moveTo(t,n-9),e.lineTo(t-4.5,n+5),e.lineTo(t,n+2),e.lineTo(t+4.5,n+5),e.closePath(),e.fillStyle="rgba(255, 255, 255, 0.92)",e.strokeStyle="rgba(0, 0, 0, 0.6)",e.lineWidth=1,e.fill(),e.stroke(),e.font="bold 9px sans-serif",e.textAlign="center",e.textBaseline="top",e.strokeText("N",t,n+6),e.fillText("N",t,n+6)}paintFooter(e,t){const{ctx:n}=this;n.font="9px sans-serif",n.textBaseline="bottom";const i=t?this.wrap(t,this.width-20):[];let r=this.height-4;n.textAlign="right";for(const f of i.slice().reverse())this.paintOutlinedText(f,this.width-6,r),r-=11;const a=(e.south+e.north)/2,c=Math.abs(rn(a,e.east,a,e.west).x)/this.width,l=Rs.SCALE_STEPS_M.find(f=>f/c<=this.width/3);if(l===void 0)return;const h=l/c,u=8,d=r-3;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.6)",n.beginPath(),n.moveTo(u,d),n.lineTo(u+h,d),n.stroke(),n.lineWidth=1.5,n.strokeStyle="rgba(255, 255, 255, 0.95)",n.stroke(),n.textAlign="left",this.paintOutlinedText(l>=1e3?`${l/1e3} km`:`${l} m`,u,d-3)}paintOutlinedText(e,t,n){const{ctx:i}=this;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.75)",i.strokeText(e,t,n),i.fillStyle="#fff",i.fillText(e,t,n)}wrap(e,t){const n=[];let i="";for(const r of e.split(" ")){const a=i?`${i} ${r}`:r;i&&this.ctx.measureText(a).width>t?(n.push(i),i=r):i=a}return i&&n.push(i),n}}const kn=256,Gd=3,d1=32768;class f1{fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(e,t){const n=(e.south+e.north)/2,i=(e.west+e.east)/2,r=Math.abs(rn(n,e.east,n,e.west).x),a=Math.abs(rn(e.north,i,e.south,i).z),o=Np(n,Math.max(r,a)),{tiles:c}=Fp(i,n,o,Gd),l=Gd*kn,h=new Float32Array(l*l),u=c[0];await Promise.all(c.map(f=>this.decodeTileInto(f,u,h,l)));const d=new Float32Array(t.width*t.height);for(let f=0;f<t.height;f++){const p=e.north+(e.south-e.north)*(f/(t.height-1));for(let v=0;v<t.width;v++){const m=e.west+(e.east-e.west)*(v/(t.width-1));d[f*t.width+v]=this.sampleAt(p,m,o,u,h,l)}}return{heights:d,width:t.width,height:t.height,bounds:e}}async decodeTileInto(e,t,n,i){const r=this.tileUrlTemplate.replace("{z}",String(e.z)).replace("{x}",String(e.x)).replace("{y}",String(e.y)),a=await this.fetchImpl(r);if(!a.ok)throw new Error(`Elevation tile fetch failed (${a.status}): ${r}`);const o=await createImageBitmap(await a.blob()),c=document.createElement("canvas");c.width=kn,c.height=kn;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,kn,kn),u=(e.x-t.x)*kn,d=(e.y-t.y)*kn;for(let f=0;f<kn;f++)for(let p=0;p<kn;p++){const v=(f*kn+p)*4,m=h[v]*256+h[v+1]+h[v+2]/256-d1,g=u+p,S=d+f;n[S*i+g]=m}}sampleAt(e,t,n,i,r,a){const{x:o,y:c}=Op(t,e,n),l=(o-i.x)*kn,h=(c-i.y)*kn,u=Math.max(0,Math.min(a-1,Math.floor(l))),d=Math.max(0,Math.min(a-1,Math.floor(h))),f=Math.min(a-1,u+1),p=Math.min(a-1,d+1),v=l-u,m=h-d,g=r[d*a+u],S=r[d*a+f],w=r[p*a+u],_=r[p*a+f],b=g+(S-g)*v,E=w+(_-w)*v;return b+(E-b)*m}}const Zc=256,Vd=3;async function p1(s,e,t,n){const i=(s.south+s.north)/2,r=(s.west+s.east)/2,a=Math.abs(rn(i,s.east,i,s.west).x),o=Math.abs(rn(s.north,r,s.south,r).z),c=Np(i,Math.max(a,o)/2),{tiles:l,bounds:h}=Fp(r,i,c,Vd),u=Vd*Zc,d=document.createElement("canvas");d.width=u,d.height=u;const f=d.getContext("2d");if(!f)throw new Error("2D canvas context unavailable");const p=l[0];await Promise.all(l.map(async g=>{const S=t(g),w=await n(S);if(!w.ok)throw new Error(`Imagery tile fetch failed (${w.status}): ${S}`);const _=await createImageBitmap(await w.blob());f.drawImage(_,(g.x-p.x)*Zc,(g.y-p.y)*Zc)}));const v=document.createElement("canvas");v.width=e.width,v.height=e.height;const m=v.getContext("2d");if(!m)throw new Error("2D canvas context unavailable");return m.drawImage(d,0,0,u,u,0,0,e.width,e.height),{source:v,width:e.width,height:e.height,bounds:h}}class m1{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(e,t){return p1(e,t,n=>this.tileUrlTemplate.replace("{z}",String(n.z)).replace("{y}",String(n.y)).replace("{x}",String(n.x)),this.fetchImpl)}}function g1(){return{elevation:new f1,imagery:kp()}}function kp(){return new m1}const v1=new Set,Cr="show-witness-map",Pr="hide-milestones";class In extends HTMLElement{static get observedAttributes(){return["src",Cr,Pr]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;static WITNESS_MAP_MIN_SPAN_M=400;static WITNESS_MAP_MARGIN=.6;static WITNESS_MAP_IMAGERY_PX=768;fullscreenButton;cornerButtons;witnessMapButton;referencesButton;referenceOpacityInput;referencesShownState=!0;referenceOpacityTouched=!1;milestonesButton;witnessMapPanel;witnessMapCanvas;witnessMapRenderer;seekInput;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;witnessPath;witnessMapBounds;witnessMapImagery;witnessMapImageryRequested=!1;witnessMapImageryCredit;witnessMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Oc.create();sightingAudio=new Kg;soundPreview;player;loopEnabled=!0;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Ip;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.resizeWitnessMap()};witnessMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeWitnessMap());resizeWitnessMap(){this.witnessMapPanel.hidden||(this.sizeWitnessMapCanvas(),this.paintWitnessMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),n=t&&this.shapeAt(t.x,t.y),i=this.said.read(n?.shape.title);if(!i){this.tooltip.hidden=!0;return}this.tooltip.textContent=i,this.tooltip.hidden=!1;const r=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-r.left+12}px`,this.tooltip.style.top=`${e.clientY-r.top+12}px`};handleWitnessMapPointerMove=e=>{const t=this.witnessMapTargetFrom(e);if(!t){this.tooltip.hidden=!0,this.witnessMapCanvas.style.cursor="default";return}this.witnessMapCanvas.style.cursor="pointer",this.tooltip.textContent=t.label,this.tooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-n.left+12}px`,this.tooltip.style.top=`${e.clientY-n.top+12}px`};handleWitnessMapClick=e=>{const t=this.witnessMapTargetFrom(e);if(t){if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))}};witnessMapTargetFrom(e){const t=this.witnessMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.witnessMapRenderer.hitTest((e.clientX-t.left)/t.width*this.witnessMapCanvas.width,(e.clientY-t.top)/t.height*this.witnessMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${_g}</style>${xg}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Na(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.cornerButtons=this.shadow.getElementById("corner-buttons"),this.witnessMapButton=this.shadow.getElementById("witness-map"),this.referencesButton=this.shadow.getElementById("references"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.milestonesButton=this.shadow.getElementById("milestones"),this.witnessMapPanel=this.shadow.getElementById("witness-map-panel"),this.witnessMapCanvas=this.shadow.getElementById("witness-map-canvas"),this.witnessMapRenderer=new Rs(this.witnessMapCanvas.getContext("2d")),this.seekInput=this.shadow.getElementById("seek"),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 t of[this.timeStartLabel,this.timeEndLabel])t.addEventListener("click",()=>this.toggleTimeDisplay()),t.addEventListener("keydown",n=>{n.key!=="Enter"&&n.key!==" "||(n.preventDefault(),this.toggleTimeDisplay())});this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.witnessMapButton.addEventListener("click",()=>this.toggleWitnessMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.witnessMapCanvas.addEventListener("pointermove",this.handleWitnessMapPointerMove),this.witnessMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.witnessMapCanvas.addEventListener("click",this.handleWitnessMapClick),this.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",t=>{this.seekSnapArmed=!0,this.nameMarkUnder(t)}),this.seekInput.addEventListener("pointerup",()=>{this.seekSnapArmed=!1}),this.seekInput.addEventListener("pointermove",t=>this.nameMarkUnder(t)),this.seekInput.addEventListener("pointerleave",()=>this.seekInput.removeAttribute("title")),this.canvas.addEventListener("click",t=>{this.enableClickToPlay&&(t.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause())}),this.canvas.addEventListener("dblclick",t=>{this.enableClickToPlay&&(t.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),this.witnessMapResizeObserver?.observe(this.witnessMapPanel),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),this.updateReferencesButton(),this.updateMilestonesButton(),this.refresh(),this.loadLocaleMessages()}connectedCallback(){this.saidTexts=void 0;const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.witnessMapResizeObserver?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(e,t,n){e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),e===Cr&&this.applyWitnessMapDefault(),e===Pr&&this.setMilestonesShown(!this.hasAttribute(Pr))}async loadFromSrc(e){this.sightingData=await Rp.json(e)}get sightingData(){return $g(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Jg(e),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyWitnessMapDefault()}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){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(e){this.toolbar.classList.toggle("hidden",!e)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(i=>this.highlightedSourceIds.has(i))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==void 0}refresh(){this.applyFrameFormat(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateWitnessMap(),this.updateReferences(),this.player.seek(this.player.time)}hostControls(e){const t=[this.milestonesButton,this.referenceOpacityInput,this.referencesButton,this.witnessMapButton];if(e)for(const n of t)e.appendChild(n);else for(const n of t)this.toolbar.appendChild(n)}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}toggleReferences(){this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity)),this.updateReferencesButton()}updateReferencesButton(){const e=this.currentSighting.references.length>0;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState,this.referencesButton.setAttribute("aria-pressed",String(this.referencesShownState));const t=this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=t,this.referencesButton.setAttribute("aria-label",t),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 e=this.player.seekableDuration,t=e>0?dc(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(n=>{const i=document.createElement("button");i.type="button",i.className="milestone-mark",i.style.left=`${Math.min(Math.max(n.t/e,0),1)*100}%`;const r=this.said.read(n.label)??"",a=this.said.read(n.note),o=a?`${r} — ${a}`:r;return i.title=o,i.setAttribute("aria-label",o),i.dataset.t=String(n.t),i.addEventListener("click",()=>this.player.seek(n.t)),i}))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,n=this.seekInput.getBoundingClientRect().width;if(t<=0||n<=0)return;const i=In.MARK_SNAP_PX/n*t;let r;for(const a of this.milestoneMarks.children){const o=Number(a.dataset.t);Math.abs(o-e)>i||(!r||Math.abs(o-e)<Math.abs(r.t-e))&&(r={t:o,name:a.title})}return r}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),n=this.player.seekableDuration;if(t.width<=0||n<=0)return;const i=(e.clientX-t.left)/t.width*n,r=this.markNear(i);r?this.seekInput.title=r.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?kd(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,!t)return;const n=document.createElement("b");n.textContent=this.said.read(t.label)??"";const i=this.said.read(t.note),r=i?` — ${i}`:"";this.milestoneCaption.replaceChildren(n,document.createTextNode(r))}exposureInstants(e){const t=this.exposureTimes(e),n=1/t.length;return t.map(i=>({shapes:this.shapesAt(i),share:n}))}exposureTimes(e=this.currentTime){const t=Qn.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<In.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const n=Math.min(In.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/In.SHORTEST_VISIBLE_EXPOSURE_MS))),i=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/In.EXPOSURE_STEP_PX),r=Math.min(In.MAX_TRAVEL_STEPS,Math.max(n,i)),a=[];for(let o=0;o<r;o++)a.push(t.fromMs+t.ms*o/(r-1));return a}travelPxOver(e,t){const n=this.shapesAt(e),i=this.shapesAt(e+t);let r=0;for(const[a,o]of n){const c=i.get(a);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);r=Math.max(r,Math.hypot(l,h))}return r}shapeAt(e,t,n){for(const i of this.exposureTimes()){const r=this.currentSighting.timeline.hitTest(i,e,t,n);if(r)return r}}shapesAt(e){const t=new Map;for(const n of this.currentSighting.timeline.sourceIds){const i=this.currentSighting.timeline.getInterpolatedShapeAt(e,n);i&&t.set(n,i)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Vt.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const n=this.playbackState!=="playing"?this.highlightedSourceIds:v1;this.canvasRenderer.setStarPoints(Vt.starPointsOf(this.sighting.instrument));const i=(Qt(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(i*Math.PI/180);const r=this.exposureInstants(e),a=this.frameShift;if(this.paintsShapes)for(const o of r)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,a))}for(const[o,c]of r[0].shapes)!this.selectionShown||!n.has(o)||(this.paintsShapes?n.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,a)));if(this.selectionShown&&n.size>1){const o=Nn.groupBoundsFor([...t].filter(([c])=>n.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.overlayPainter?.(this.canvasRenderer),this.mapShapeBounds=r.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,a).bounds)),this.keepWitnessMapClear(),this.seekInput.value=String(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintWitnessMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(Bg(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new Hg(this.currentSighting.timeline,(t,n)=>this.onFrame(t,n));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}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())}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.playPauseButton.textContent=e?"⏸":"▶";const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const n=t?e?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=n,this.playPauseButton.setAttribute("aria-label",n),this.toolbar.classList.toggle("auto-hide",e),this.cornerButtons.classList.toggle("auto-hide",e)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton()}toggleWitnessMap(){this.setWitnessMapOpen(this.witnessMapPanel.hidden)}applyWitnessMapDefault(){this.setWitnessMapOpen(this.hasAttribute(Cr)&&this.witnessPath!==void 0)}setWitnessMapOpen(e){this.witnessMapPanel.hidden=!e,this.witnessMapPanel.removeAttribute("title"),this.witnessMapButton.setAttribute("aria-pressed",String(e)),this.updateWitnessMapButton(),e&&(this.sizeWitnessMapCanvas(),this.loadWitnessMapImagery(),this.paintWitnessMap(this.currentTime))}updateWitnessMapButton(){const t=!this.witnessMapPanel.hidden?this.messages.hideWitnessMap:this.messages.showWitnessMap;this.witnessMapButton.title=t,this.witnessMapButton.setAttribute("aria-label",t)}updateWitnessMap(){const e=this.witnessPath!==void 0;if(this.witnessPath=Ca.of(this.currentSighting),this.witnessMapButton.hidden=this.witnessPath===void 0,!e&&this.witnessPath&&this.applyWitnessMapDefault(),!this.witnessPath){this.setWitnessMapOpen(!1),this.witnessMapBounds=void 0;return}const t=this.witnessPath.boundsAround(In.WITNESS_MAP_MIN_SPAN_M,In.WITNESS_MAP_MARGIN);(!this.witnessMapBounds||!this.sameGround(this.witnessMapBounds,t))&&(this.witnessMapBounds=t,this.witnessMapImagery=void 0,this.witnessMapImageryCredit=void 0,this.witnessMapImageryFailed=!1,this.witnessMapImageryRequested=!1,this.witnessMapPanel.hidden||this.loadWitnessMapImagery())}sameGround(e,t){const n=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<n&&Math.abs(e.south-t.south)<n&&Math.abs(e.west-t.west)<n&&Math.abs(e.east-t.east)<n}async loadWitnessMapImagery(){if(this.witnessMapImageryRequested||!this.witnessMapBounds)return;this.witnessMapImageryRequested=!0;const e=kp(),t=this.witnessMapBounds;try{const n=await e.getImageryTexture(t,{width:In.WITNESS_MAP_IMAGERY_PX,height:In.WITNESS_MAP_IMAGERY_PX});if(this.witnessMapBounds!==t)return;this.witnessMapImagery=n,this.witnessMapImageryCredit=e.attribution}catch{this.witnessMapImageryFailed=!0}this.paintWitnessMap(this.currentTime)}get witnessMapCredit(){return this.witnessMapImageryCredit}get witnessMapFooterLine(){return this.witnessMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.witnessMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepWitnessMapClear()}keepWitnessMapClear(){if(this.witnessMapPanel.hidden)return;const e=this.witnessMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],n=(l,h,u)=>{for(const d of t)if(!(d.x+d.width<l-u||d.x>h+u)&&!(d.y>e.bottom+u||d.y+d.height<e.top-u))return!0;return!1},i=[this.canvas.width-e.width,this.canvas.width],r=[0,e.width],a=In.WITNESS_MAP_CLEARANCE_PX,o=n(...i,0),c=n(...r,0);if(this.witnessMapPanel.classList.toggle("subject-overlap",o&&c),this.witnessMapPanel.classList.contains("on-the-left")){!o&&(c||!n(i[0],i[1],a))&&this.witnessMapPanel.classList.remove("on-the-left");return}n(i[0],i[1],0)&&!n(r[0],r[1],0)&&this.witnessMapPanel.classList.add("on-the-left")}witnessMapBoxPx;static WITNESS_MAP_CLEARANCE_PX=24;sizeWitnessMapCanvas(){const e=this.witnessMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureWitnessMapBox(),this.witnessMapCanvas.width!==t&&(this.witnessMapCanvas.width=t,this.witnessMapCanvas.height=t)}measureWitnessMapBox(){const e=this.witnessMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const n=this.canvas.width/t.width,i=this.canvas.height/t.height;this.witnessMapBoxPx={width:e.width*n,top:(e.top-t.top)*i,bottom:(e.bottom-t.top)*i}}paintWitnessMap(e){if(this.witnessMapPanel.hidden||!this.witnessPath||!this.witnessMapBounds)return;const t=Qt(this.currentSighting,e),n=this.currentSighting.instrument,i=[],r=this.currentSighting.milestones.length>0?kd(this.currentSighting.milestones,e):void 0;for(const a of this.milestonesShown?dc(this.currentSighting.milestones):[]){const o=Qt(this.currentSighting,a.t);o?.lat===void 0||o.lng===void 0||i.push({label:this.said.read(a.label)??"",note:this.said.read(a.note),t:a.t,lat:o.lat,lng:o.lng,current:a===r})}this.witnessMapRenderer.paint({bounds:this.witnessMapBounds,imagery:this.witnessMapImagery,path:this.witnessPath,position:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?Hi.of(n,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Vt.aspectOf(n)):void 0,markers:i,decor:this.witnessMapDecorAt(e),witnessLabel:this.said.read(this.currentSighting.witness?.title)??this.messages.witnessHere,nightFraction:this.witnessMapNightFraction,attribution:this.witnessMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.milestonesButton.setAttribute("aria-pressed",String(e)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintWitnessMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0;const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}witnessMapDecorAt(e){const t=Qt(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(n=>n.kind!=="crop").map(n=>{const i=Ou(n,e),{lat:r,lng:a}=Bi(i.eastM,-i.northM,t.lat,t.lng);return{lat:r,lng:a,headingDeg:i.headingDeg,label:this.said.read(n.title)??this.messages.decorHere}})}witnessMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.witnessMapNightFraction&&(this.witnessMapNightFraction=t,this.paintWitnessMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,n=this.lookPitchDeg+e.pitchDeg;if(t===0&&n===0)return{x:0,y:0};const i=Qt(this.currentSighting,this.currentTime),r=Hi.of(this.currentSighting.instrument,this.canvas.height,i?.fovDeg??60);return{x:-r.angleDegToRadiusPx(t),y:r.angleDegToRadiusPx(n)}}gaitAt(e){return Gt.of(this.currentSighting)?.offsetAt(e)??Gt.STILL}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new hs(fc.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=Uu(fc.preferencesFor(this),t1);e!=="en"&&this.applyMessages(await i1(e))}updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t;for(const n of[this.timeStartLabel,this.timeEndLabel])n.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(n.setAttribute("role","button"),n.setAttribute("tabindex","0")):(n.removeAttribute("role"),n.removeAttribute("tabindex"))}applyMessages(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),this.updateReferencesButton(),this.updateMilestonesButton()}updateTimeLabels(){const e=this.currentSighting.event,t=Fg(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?lh(e.time):void 0;const n=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&n>0?n/this.realDurationMs:1,this.player.durationOverrideMs=n>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return no(e);const t=this.currentSighting.timeline.duration,n=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?Xd(Wd(this.realStartMs+n)):no(n)}formatEndOfTimeline(){return this.realDurationMs===void 0?no(this.currentSighting.timeline.duration):this.canShowClockTime?Xd(Wd(this.realStartMs+this.realDurationMs)):no(this.realDurationMs)}}function Wd(s){const e=new Date(s);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function Xd(s){if(s.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return s.second?`${e(s.hour)}:${e(s.minute??0)}:${e(s.second)}`:`${e(s.hour)}:${e(s.minute??0)}`}function no(s){const e=Math.round(s/1e3),t=Math.floor(e/60),n=e%60;return`${t}:${String(n).padStart(2,"0")}`}const uh="rr0-ufo";function zp(){customElements.get(uh)||customElements.define(uh,In)}/**
|
|
603
|
+
`,Ja=[{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 Vt{static get default(){return Ja[0]}static byId(e){return Ja.find(t=>t.id===e)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(e){const t=e.frame;return t?2*Math.atan(t.heightMm/(2*t.focalLengthMm))*180/Math.PI:Vt.UNAIDED_FIELD_DEG}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Vt.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Vt.aspectOf(e))}static availableAt(e){return e===void 0?Ja:Ja.filter(t=>!t.years||e>=t.years.from&&(t.years.to===void 0||e<=t.years.to))}static fieldOfViewDegAt(e,t){const n=e.frame;if(!(!n||t<=0))return 2*Math.atan(n.heightMm/(2*t))*180/Math.PI}static focalLengthMmFor(e,t){const n=e.frame;if(!(!n||t<=0||t>=180))return n.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){const n=t??e.fNumber;if(n===void 0||e.apertureBlades===void 0)return 0;const i=e.fNumberRange;return!i||i.max<=i.min?1:Math.max(0,Math.min(1,(n-i.min)/(i.max-i.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(e){return e.flare??Vt.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class Ca{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const n of e.witnessTrack.allKeyframes){const{lat:i,lng:r,headingDeg:a}=n.pose;i===void 0||r===void 0||t.push({t:n.t,lat:i,lng:r,headingDeg:a})}if(t.length===0){const n=e.event.place?.[0];if(!n)return;t.push({t:0,lat:n.lat,lng:n.lng})}return new Ca(t)}get moved(){return this.spanM>Ca.STATIONARY_M}get spanM(){const e=this.box,t=(e.south+e.north)/2,n=(e.west+e.east)/2;return Math.max(Math.abs(rn(t,e.east,t,e.west).x),Math.abs(rn(e.north,n,e.south,n).z))}get center(){const e=this.box;return{lat:(e.south+e.north)/2,lng:(e.west+e.east)/2}}boundsAround(e,t){const{lat:n,lng:i}=this.center,r=Math.max(this.spanM*(1+t),e)/2;return{north:Bi(0,-r,n,i).lat,south:Bi(0,r,n,i).lat,east:Bi(r,0,n,i).lng,west:Bi(-r,0,n,i).lng}}get box(){const e=this.points.map(n=>n.lat),t=this.points.map(n=>n.lng);return{south:Math.min(...e),north:Math.max(...e),west:Math.min(...t),east:Math.max(...t)}}}class Gt{constructor(e,t){this.stretches=e,this.rotationPassed=t}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(e){const t=Ca.of(e);if(!t||t.points.length<2)return;const n=[];let i=0;for(let r=1;r<t.points.length;r++){const a=t.points[r-1],o=t.points[r],c=(o.t-a.t)/1e3;if(c<=0)continue;const l=rn(o.lat,o.lng,a.lat,a.lng),h=l.x,u=-l.z,d=Math.hypot(h,u),f=d/c,p=Gt.stepHzFor(f);n.push({startMs:a.t,endMs:o.t,speedMPerS:f,eastUnit:d>0?h/d:0,northUnit:d>0?u/d:0,stepHz:p,stepsBefore:i,rampsIn:!0,rampsOut:!0}),i+=p*c}for(let r=0;r<n.length;r++){const a=n[r-1],o=n[r+1];n[r].rampsIn=a===void 0||a.stepHz===0,n[r].rampsOut=o===void 0||o.stepHz===0}if(n.some(r=>r.stepHz>0))return new Gt(n,1-(e.instrument.stabilization??0))}static stepHzFor(e){return e<Gt.SLOWEST_WALK_M_PER_S||e>Gt.FASTEST_WALK_M_PER_S?0:Gt.REFERENCE_STEP_HZ*Math.pow(e/Gt.REFERENCE_SPEED_M_PER_S,Gt.CADENCE_EXPONENT)}offsetAt(e){const t=this.stretches.find(c=>e>=c.startMs&&e<=c.endMs);if(!t||t.stepHz===0)return Gt.STILL;const n=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,i=2*Math.PI*n,r=this.amplitudeAt(t,e),a=Gt.SWAY_M*r*Math.cos(i/2),o=r*this.rotationPassed*t.speedMPerS/Gt.REFERENCE_SPEED_M_PER_S;return{eastM:a*t.northUnit,northM:-a*t.eastUnit,upM:Gt.RISE_M_PER_M_PER_S*t.speedMPerS*r*Math.cos(i),rollDeg:Gt.HEAD_ROLL_DEG*o*Math.cos(i/2),pitchDeg:-1.25*o*Math.cos(i),yawDeg:Gt.HEAD_YAW_DEG*o*Math.cos(i/2)}}amplitudeAt(e,t){const n=1e3/e.stepHz,i=Math.min(n,(e.endMs-e.startMs)/2);if(i<=0)return 1;const r=t-e.startMs,a=e.endMs-t,o=Math.min(e.rampsIn?r/i:1,e.rampsOut?a/i:1,1);return(1-Math.cos(Math.PI*Math.max(o,0)))/2}}class mt{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(e){return 2*Math.atan(e.sizeM/(2*e.distanceM))*180/Math.PI}static inMoons(e){return e/mt.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(e,t,n){if(!(!e||!t))return{widthDeg:e.widthDeg+(t.widthDeg-e.widthDeg)*n,heightDeg:e.heightDeg+(t.heightDeg-e.heightDeg)*n}}static sizeMAt(e,t){return 2*e*Math.tan(t*Math.PI/360)}static distanceMAt(e,t){return e/(2*Math.tan(t*Math.PI/360))}}function yg(s,e,t){if(!s||!e)return t<1?s:e;const n=((e.azimuthDeg-s.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((s.azimuthDeg+n*t)%360+360)%360,altitudeDeg:s.altitudeDeg+(e.altitudeDeg-s.altitudeDeg)*t}}function Sg(s,e,t){const{bounds:n}=s;return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height}function wn(s,e,t){return s+(e-s)*t}function Ed(s){const e=/^#([0-9a-f]{6})$/i.exec(s);if(!e)return;const t=parseInt(e[1],16);return[t>>16&255,t>>8&255,t&255]}function bg(s){return`#${s.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function wg(s,e,t){const n=Ed(s),i=Ed(e);return!n||!i?t<1?s:e:bg([wn(n[0],i[0],t),wn(n[1],i[1],t),wn(n[2],i[2],t)])}function Eg(s,e,t){const n={x:wn(s.bounds.x,e.bounds.x,t),y:wn(s.bounds.y,e.bounds.y,t),width:wn(s.bounds.width,e.bounds.width,t),height:wn(s.bounds.height,e.bounds.height,t)},i=wn(s.angle,e.angle,t),r=wn(s.transparency,e.transparency,t),a=wn(s.haloScale,e.haloScale,t),o=wn(s.blur??0,e.blur??0,t),c=wn(s.brightness??0,e.brightness??0,t),l=wg(s.color,e.color,t),h=mt.lerpAngular(s.angular,e.angular,t),u=yg(s.aim,e.aim,t);return s.kind==="polygon"&&e.kind==="polygon"&&s.points.length===e.points.length?{...s,bounds:n,angle:i,transparency:r,haloScale:a,blur:o,brightness:c,color:l,angular:h,aim:u,points:s.points.map((d,f)=>({x:wn(d.x,e.points[f].x,t),y:wn(d.y,e.points[f].y,t)}))}:{...t<1?s:e,bounds:n,angle:i,transparency:r,haloScale:a,blur:o,brightness:c,color:l,angular:h,aim:u}}class Nc{keyframes=[];order=[];groups=[];addKeyframe(e,t){const n=this.findInsertIndex(e);if(this.keyframes[n]?.t===e){const i=new Set(t.map(r=>r.sourceId));this.keyframes[n]={t:e,shapes:[...this.keyframes[n].shapes.filter(r=>!i.has(r.sourceId)),...t]}}else this.keyframes.splice(n,0,{t:e,shapes:[...t]});for(const i of t)this.order.includes(i.sourceId)||this.order.push(i.sourceId)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getKeyframeAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t];return n?.t===e?n:void 0}getShapeAt(e,t){return this.getKeyframeAt(e)?.shapes.find(n=>n.sourceId===t)?.shape}getLatestShapeAt(e,t){let n=this.findInsertIndex(e);for(this.keyframes[n]?.t!==e&&(n-=1);n>=0;n--){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return i.shape}}getInterpolatedShapeAt(e,t){const n=this.findShapeAtOrBefore(e,t);if(n?.t===e)return n.shape;const i=this.findShapeAtOrAfter(e,t);return n?i?Eg(n.shape,i.shape,(e-n.t)/(i.t-n.t)):n.shape:i?.shape}findShapeAtOrBefore(e,t){let n=this.findInsertIndex(e);for(this.keyframes[n]?.t!==e&&(n-=1);n>=0;n--){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return{t:this.keyframes[n].t,shape:i.shape}}}findShapeAtOrAfter(e,t){for(let n=this.findInsertIndex(e);n<this.keyframes.length;n++){const i=this.keyframes[n].shapes.find(r=>r.sourceId===t);if(i)return{t:this.keyframes[n].t,shape:i.shape}}}hitTest(e,t,n,i){const r=this.sourceIds;for(let a=r.length-1;a>=0;a--){if(i?.has(r[a]))continue;const o=this.getInterpolatedShapeAt(e,r[a]);if(o&&Sg(o,t,n))return{sourceId:r[a],shape:o}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const n=this.keyframes[t].shapes.filter(i=>i.sourceId!==e);n.length===0?this.keyframes.splice(t,1):n.length!==this.keyframes[t].shapes.length&&(this.keyframes[t]={t:this.keyframes[t].t,shapes:n})}this.order=this.order.filter(t=>t!==e),this.removeFromGroup(e)}group(e){if(!(e.length<2)){for(const t of e)this.removeFromGroup(t);this.groups.push([...e])}}ungroup(e){const t=this.groups.findIndex(n=>n.includes(e));t!==-1&&this.groups.splice(t,1)}groupMembers(e){return this.groups.find(t=>t.includes(e))}removeFromGroup(e){const t=this.groups.findIndex(i=>i.includes(e));if(t===-1)return;const n=this.groups[t].filter(i=>i!==e);n.length<2?this.groups.splice(t,1):this.groups[t]=n}bringToFront(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.push(e))}sendToBack(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.unshift(e))}get duration(){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(e){const t=new Nc;for(const n of e.keyframes)t.addKeyframe(n.t,n.shapes);if(e.order){const n=t.order.filter(i=>!e.order.includes(i));t.order=[...e.order,...n]}return e.groups&&(t.groups=e.groups.map(n=>n.filter(i=>t.order.includes(i))).filter(n=>n.length>=2)),t}}function Ag(s,e,t){return Math.max(e,Math.min(t,s))}function Tg(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function Zs(s,e,t){return s+(e-s)*t}function Rg(s,e,t){return{lat:s.lat===void 0||e.lat===void 0?void 0:Zs(s.lat,e.lat,t),lng:s.lng===void 0||e.lng===void 0?void 0:Zs(s.lng,e.lng,t),elevationM:Zs(s.elevationM,e.elevationM,t),headingDeg:s.headingDeg===void 0||e.headingDeg===void 0?void 0:Tg(s.headingDeg,e.headingDeg,t),pitchDeg:Zs(s.pitchDeg,e.pitchDeg,t),rollDeg:Zs(s.rollDeg??0,e.rollDeg??0,t),fovDeg:Zs(s.fovDeg,e.fovDeg,t),fNumber:s.fNumber,focusDistanceM:s.focusDistanceM}}class Pa{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,pose:t}:this.keyframes.splice(n,0,{t:e,pose:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getLatestPoseAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].pose:void 0}getInterpolatedPoseAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.pose;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return n?i?Rg(n.pose,i.pose,Ag((e-n.t)/(i.t-n.t),0,1)):n.pose:i?.pose}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Pa;for(const n of e.keyframes)t.addKeyframe(n.t,n.pose);return t}}function bt(s,e,t){return s+(e-s)*t}function Nu(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function Dg(s,e,t){return Math.max(e,Math.min(t,s))}function Cg(s=[],e=[],t){if(!(!s.length&&!e.length))return[...new Set([...s.map(n=>n.id),...e.map(n=>n.id)])].map(n=>{const i=s.find(c=>c.id===n),r=e.find(c=>c.id===n),a=i??{...r,density:0},o=r??{...i,density:0};return{...a,eastM:bt(a.eastM,o.eastM,t),northM:bt(a.northM,o.northM,t),baseM:bt(a.baseM,o.baseM,t),thicknessM:bt(a.thicknessM,o.thicknessM,t),widthM:bt(a.widthM,o.widthM,t),depthM:bt(a.depthM,o.depthM,t),rotationDeg:Nu(a.rotationDeg,o.rotationDeg,t),density:bt(a.density,o.density,t),darkness:bt(a.darkness??0,o.darkness??0,t)}})}function Pg(s,e,t){if(s.cloudLayers===void 0&&e.cloudLayers===void 0)return;const n=hc(s),i=hc(e);return t>=1?i.map(a=>({...a})):[...new Set([...n.map(a=>a.id),...i.map(a=>a.id)])].map(a=>{const o=n.find(u=>u.id===a),c=i.find(u=>u.id===a),l=o??{...c,coverage:0},h=c??{...o,coverage:0};return{...l,instances:Cg(o?.instances,c?.instances,t),baseM:bt(l.baseM,h.baseM,t),thicknessM:bt(l.thicknessM,h.thicknessM,t),coverage:bt(l.coverage,h.coverage,t),sizeM:bt(l.sizeM,h.sizeM,t),density:bt(l.density,h.density,t),darkness:bt(l.darkness??s.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:bt(l.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:l.windSpeed===void 0&&h.windSpeed===void 0?void 0:bt(l.windSpeed??s.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:l.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:Nu(l.windDirectionDeg??s.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function Ig(s,e,t){return{cloudLayers:Pg(s,e,t),cloudCover:bt(s.cloudCover,e.cloudCover,t),cloudDarkness:bt(s.cloudDarkness,e.cloudDarkness,t),highCloudCover:s.highCloudCover===void 0||e.highCloudCover===void 0?void 0:bt(s.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:s.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:bt(s.iceCrystalAlignment,e.iceCrystalAlignment,t),lowerCloudCover:s.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:bt(s.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:s.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:bt(s.cloudBaseM,e.cloudBaseM,t),precipitationType:t<1?s.precipitationType:e.precipitationType,precipitationIntensity:bt(s.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:Nu(s.windDirectionDeg,e.windDirectionDeg,t),windSpeed:bt(s.windSpeed,e.windSpeed,t),storm:t<1?s.storm:e.storm}}class Ia{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,weather:t}:this.keyframes.splice(n,0,{t:e,weather:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}getLatestWeatherAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].weather:void 0}getInterpolatedWeatherAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.weather;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return n?i?Ig(n.weather,i.weather,Dg((e-n.t)/(i.t-n.t),0,1)):n.weather:i?.weather}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new Ia;for(const n of e.keyframes)t.addKeyframe(n.t,n.weather);return t}}class La{keyframes=[];addKeyframe(e,t){const n=this.findInsertIndex(e);this.keyframes[n]?.t===e?this.keyframes[n]={t:e,sound:t}:this.keyframes.splice(n,0,{t:e,sound:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}getLatestSoundAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].sound:void 0}getInterpolatedSoundAt(e){const t=this.findInsertIndex(e),n=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(n?.t===e)return n.sound;const i=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!n)return i?.sound;if(!i)return n.sound;const r=(e-n.t)/(i.t-n.t);return this.lerp(n.sound,i.sound,Math.max(0,Math.min(1,r)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(e){const t=new La;for(const n of e.keyframes)t.addKeyframe(n.t,n.sound);return t}lerp(e,t,n){return{kind:n<1?e.kind:t.kind,volume:e.volume+(t.volume-e.volume)*n,pitchHz:e.pitchHz+(t.pitchHz-e.pitchHz)*n,src:n<1?e.src:t.src}}findInsertIndex(e){let t=0,n=this.keyframes.length;for(;t<n;){const i=t+n>>>1;this.keyframes[i].t<e?t=i+1:n=i}return t}}const Lg=100,Ng={kind:"none",volume:0,pitchHz:Lg};class Gn{constructor(e){this.entries=e}static empty(){return new Gn(new Map)}get size(){return this.entries.size}at(e){return this.entries.get(e)}paths(){return[...this.entries.keys()]}set(e,t){t.basis==="stated"&&t.rationale===void 0?this.entries.delete(e):this.entries.set(e,t)}clear(e){for(const t of this.entries.keys())(t===e||t.startsWith(`${e}.`))&&this.entries.delete(t)}static strip(e){const t=new Gn(new Map);return{recording:Gn.stripValue(e,[],t),provenance:t}}static restore(e,t){if(t.size===0)return e;const n=structuredClone(e);for(const i of t.paths()){const r=t.at(i),a=i.split("."),o=Gn.holderOf(n,a);if(!o)continue;const c=a[a.length-1],l=o[c];l!==void 0&&(r.of!==void 0&&JSON.stringify(r.of)!==JSON.stringify(l)||(o[c]={value:l,...r.basis==="stated"?{}:{basis:r.basis},...r.rationale===void 0?{}:{rationale:r.rationale}}))}return n}static isWrapper(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&"value"in e}static stripValue(e,t,n){return Gn.isWrapper(e)?(n.set(t.join("."),{basis:e.basis??"stated",...e.rationale===void 0?{}:{rationale:e.rationale},of:e.value}),Gn.stripValue(e.value,t,n)):Array.isArray(e)?e.map((i,r)=>Gn.stripValue(i,[...t,String(r)],n)):typeof e=="object"&&e!==null?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,Gn.stripValue(r,[...t,i],n)])):e}static holderOf(e,t){let n=e;for(const i of t.slice(0,-1)){if(typeof n!="object"||n===null)return;n=n[i]}return typeof n=="object"&&n!==null?n:void 0}}function lh(s){if(s.year!==void 0)return Date.UTC(s.year,(s.month??1)-1,s.day??1,s.hour??0,s.minute??0,s.second??0)}function Ad(s){return(((s.day??0)*24+(s.hour??0))*60+(s.minute??0))*6e4+(s.second??0)*1e3}const Og=["year","month","day","hour","minute"],Ug=["day","hour","minute"];function Td(s,e){return e.filter(t=>s[t]!==void 0).join(",")}function Fg(s){if(s.durationSeconds!==void 0)return s.durationSeconds*1e3;if(!s.time||!s.endTime)return;const e=s.time.year!==void 0&&s.endTime.year!==void 0,t=e?Og:Ug,n=Td(s.time,t);if(!(n===""||n!==Td(s.endTime,t)))return e?lh(s.endTime)-lh(s.time):Ad(s.endTime)-Ad(s.time)}class Oc{constructor(e,t,n,i,r,a,o,c,l=[],h,u,d,f=[],p=[]){this.event=e,this.timeline=t,this.witnessTrack=n,this.weatherTrack=i,this.soundTrack=r,this.witness=a,this.caseId=o,this.weather=c,this.decor=l,this.weatherSource=h,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p}provenance=Gn.empty();testimony;get witnessCount(){return 1+this.decor.filter(e=>e.kind==="witness").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Vt.byId(this.instrumentId)}static create(e,t,n){return new Oc({eventType:"sighting",time:e,place:t},new Nc,new Pa,new Ia,new La,n)}}const kg=0,zg=0;function Qt(s,e){const t=s.witnessTrack.getInterpolatedPoseAt(e);if(t)return t;const n=s.event.place?.[0];if(n)return{lat:n.lat,lng:n.lng,elevationM:kg,headingDeg:void 0,pitchDeg:zg,fovDeg:Vt.fieldOfViewDeg(s.instrument)}}function Js(s,e){return s.weatherTrack.getInterpolatedWeatherAt(e)??s.weather??Ap}function Bg(s,e){return s.soundTrack.getInterpolatedSoundAt(e)??Ng}class Hg{constructor(e,t){this.timeline=e,this.onFrame=t}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const e=()=>{if(this.state!=="playing")return;const t=performance.now();if(this.currentT+=(t-this.lastWallTime)*this.playbackRate,this.lastWallTime=t,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(e){this.currentT=Math.max(0,Math.min(e,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(e){const t=new Map;for(const n of this.timeline.sourceIds){const i=this.timeline.getInterpolatedShapeAt(e,n);i&&t.set(n,i)}this.onFrame(e,t)}}const Dp=["nw","n","ne","e","se","s","sw","w"],Gg=24,ja=8,Vg=3,Wg=8;function Qa(s,e,t){const n=s.x-e.x,i=s.y-e.y,r=Math.cos(t),a=Math.sin(t);return{x:e.x+n*r-i*a,y:e.y+n*a+i*r}}function Kr(s){return{x:s.x+s.width/2,y:s.y+s.height/2}}const Xg={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 Nn{static handlePointsFor(e){const{x:t,y:n,width:i,height:r}=e.bounds,a={nw:{x:t,y:n},n:{x:t+i/2,y:n},ne:{x:t+i,y:n},e:{x:t+i,y:n+r/2},se:{x:t+i,y:n+r},s:{x:t+i/2,y:n+r},sw:{x:t,y:n+r},w:{x:t,y:n+r/2},rotate:{x:t+i/2,y:n-Gg}},o=Kr(e.bounds),c={};for(const l of Object.keys(a))c[l]=Qa(a[l],o,e.angle);return c}static hitTestHandle(e,t,n=8,i=[...Dp,"rotate"]){const r=Nn.handlePointsFor(e);for(const a of i)if(Math.hypot(t.x-r[a].x,t.y-r[a].y)<=n)return a}static HANDLE_DIRECTION_DEG={e:0,se:45,s:90,sw:135,w:180,nw:225,n:270,ne:315};static resizeAxisFor(e,t){const i=((Nn.HANDLE_DIRECTION_DEG[e]+t*180/Math.PI)%180+180)%180/45,r=["ew","nwse","ns","nesw"];return r[Math.round(i)%r.length]}static resizeBounds(e,t,n,i){const r=Kr(e),a=Qa(i,r,-t),{x:o,y:c,width:l,height:h}=e,u=Xg[n];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(a.x,p-ja)),u.right&&(p=Math.max(a.x,d+ja)),u.top&&(f=Math.min(a.y,v-ja)),u.bottom&&(v=Math.max(a.y,f+ja)),{x:d,y:f,width:p-d,height:v-f}}static resizeShape(e,t,n){if(t==="rotate")throw new Error("resizeShape does not accept the rotate handle");const{width:i,height:r}=e.bounds,a=Nn.resizeBounds(e.bounds,e.angle,t,n);if(e.kind==="oval")return{...e,bounds:a};const o=i===0?1:a.width/i,c=r===0?1:a.height/r;return{...e,bounds:a,points:e.points.map(l=>({x:l.x*o,y:l.y*c}))}}static rotateShape(e,t){const n=Kr(e.bounds),i=Math.atan2(t.y-n.y,t.x-n.x)+Math.PI/2;return{...e,angle:i}}static groupBoundsFor(e){const t=Math.min(...e.map(a=>a.x)),n=Math.min(...e.map(a=>a.y)),i=Math.max(...e.map(a=>a.x+a.width)),r=Math.max(...e.map(a=>a.y+a.height));return{x:t,y:n,width:i-t,height:r-n}}static vertexPointsFor(e){const t=Kr(e.bounds);return e.points.map(n=>Qa({x:e.bounds.x+n.x,y:e.bounds.y+n.y},t,e.angle))}static hitTestVertex(e,t,n=Wg){const i=Nn.vertexPointsFor(e);let r,a=n;return i.forEach((o,c)=>{const l=Math.hypot(t.x-o.x,t.y-o.y);l<=a&&(a=l,r=c)}),r}static toLocalPoint(e,t){const n=Kr(e.bounds),i=Qa(t,n,-e.angle);return{x:i.x-e.bounds.x,y:i.y-e.bounds.y}}static moveVertex(e,t,n){const i=e.points.map((u,d)=>d===t?Nn.toLocalPoint(e,n):u),r=Math.min(...i.map(u=>u.x)),a=Math.min(...i.map(u=>u.y)),o=Math.max(...i.map(u=>u.x)),c=Math.max(...i.map(u=>u.y)),l={x:e.bounds.x+r,y:e.bounds.y+a,width:o-r,height:c-a},h=i.map(u=>({x:u.x-r,y:u.y-a}));return{...e,bounds:l,points:h}}static insertVertexNear(e,t){const n=Nn.toLocalPoint(e,t),{points:i}=e;let r=i.length-1,a=1/0;for(let c=0;c<i.length;c++){const l=i[c],h=i[(c+1)%i.length],u=Nn.distanceToSegment(n,l,h);u<a&&(a=u,r=c)}const o=[...i.slice(0,r+1),n,...i.slice(r+1)];return{...e,points:o}}static distanceToSegment(e,t,n){const i=n.x-t.x,r=n.y-t.y,a=i*i+r*r,o=a===0?0:Math.max(0,Math.min(1,((e.x-t.x)*i+(e.y-t.y)*r)/a)),c=t.x+o*i,l=t.y+o*r;return Math.hypot(e.x-c,e.y-l)}static deleteVertex(e,t){return e.points.length<=Vg?e:{...e,points:e.points.filter((n,i)=>i!==t)}}}const hh=6,eo=hh/2,Rd=20,Dd=24,Cd=9,Pd=6,Id=7,Ld=6,hi=4;class Na{constructor(e){this.ctx=e}starPoints=0;roll=0;clear(e,t){this.ctx.clearRect(0,0,e,t)}static paintExtent(e){const{x:t,y:n,width:i,height:r}=e.bounds,a=t+i/2,o=n+r/2,c=e.angle%(2*Math.PI)!==0,l=Math.hypot(i,r)/2,h=c?l:i/2,u=c?l:r/2,d=Math.max(i,r)/2,f=e.brightness??0,p=f>0?Math.max(d*(1+Cd*f),Ld*f)-d:0,v=f>0?d*(1+Id*f)-d:0,m=3*Dd*(e.blur??0)+1.5*Rd*e.haloScale,g=Math.max(p,v,0)+m+2;return{x:a-h-g,y:o-u-g,width:2*(h+g),height:2*(u+g)}}paintInto(e,t,n){this.ctx.save(),this.ctx.scale(n,n),this.ctx.translate(-t.x,-t.y),this.paintShape(e.selected?{...e,selected:!1}:e),this.ctx.restore()}paintShape(e){this.ctx.save(),this.ctx.globalAlpha=1-e.transparency;const t=e.blur??0;t>0&&(this.ctx.filter=`blur(${(Dd*t).toFixed(2)}px)`);const n=e.brightness??0;n>0&&this.paintDazzle(e,n),e.haloScale>0&&this.paintHalo(e),this.paintBase(e),this.ctx.restore(),e.selected&&this.paintSelectionHandles(e)}setStarPoints(e){this.starPoints=Math.max(0,Math.floor(e))}setRoll(e){this.roll=e}paintDazzle(e,t){const{x:n,y:i,width:r,height:a}=e.bounds,o=n+r/2,c=i+a/2,l=Math.max(r,a)/2,h=Math.max(l*(1+Cd*t),Ld*t);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<=Pd;d++){const f=d/Pd,p=1/(1+24*f*f);this.ctx.globalAlpha=1,u.addColorStop(f,this.withAlpha(e.color,p*t*.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+Id*t);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(e.color,t*.55)),g.addColorStop(.35,this.withAlpha(e.color,t*.22)),g.addColorStop(1,this.withAlpha(e.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(e,t){if(t<=0)return e.color;const n=/^#([0-9a-f]{6})$/i.exec(e.color.trim());if(!n)return e.color;const i=Number.parseInt(n[1],16),r=a=>Math.round(a+(255-a)*t);return`rgb(${r(i>>16&255)}, ${r(i>>8&255)}, ${r(i&255)})`}withAlpha(e,t){const n=Math.max(0,Math.min(1,t)),i=/^#([0-9a-f]{6})$/i.exec(e.trim());if(!i)return e;const r=Number.parseInt(i[1],16);return`rgba(${r>>16&255}, ${r>>8&255}, ${r&255}, ${n.toFixed(3)})`}paintBase(e){if(this.ctx.fillStyle=this.dazzledFill(e,e.brightness??0),this.ctx.beginPath(),e.kind==="oval"){const{x:t,y:n,width:i,height:r}=e.bounds,a=i/2,o=r/2;this.ctx.ellipse(t+a,n+o,a,o,e.angle,0,2*Math.PI)}else{const{x:t,y:n,width:i,height:r}=e.bounds;this.ctx.save(),this.ctx.translate(t+i/2,n+r/2),this.ctx.rotate(e.angle),this.ctx.translate(-i/2,-r/2),e.points.forEach((a,o)=>{o===0?this.ctx.moveTo(a.x,a.y):this.ctx.lineTo(a.x,a.y)}),this.ctx.closePath(),this.ctx.restore()}this.ctx.fill()}paintHalo(e){this.ctx.save(),this.ctx.shadowColor=e.color,this.ctx.shadowBlur=Rd*e.haloScale,this.paintBase(e),this.ctx.restore()}paintSelectionHandles(e){this.paintHandleFrame(Nn.handlePointsFor(e),{includeRotate:!0}),e.kind==="polygon"&&this.paintVertexHandles(e)}paintVertexHandles(e){this.ctx.fillStyle="#39f";for(const t of Nn.vertexPointsFor(e))this.ctx.beginPath(),this.ctx.ellipse(t.x,t.y,hi,hi,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(e){this.paintOutline(Nn.handlePointsFor(e))}paintSelectionOnly(e){this.paintSelectionHandles(e)}paintPictureFrame(e,t,n){const i=this.ctx;if(i.save(),e&&e.length===4){i.strokeStyle="#39f",i.lineWidth=1.5,i.setLineDash([6,4]),i.beginPath(),i.moveTo(e[0].x,e[0].y);for(const r of e.slice(1))i.lineTo(r.x,r.y);i.closePath(),i.stroke(),i.setLineDash([])}for(const r of t){const a=Na.landmarkColour(r.residualDeg),o=r.selected?3:2;r.selected&&(i.strokeStyle="#fff",i.lineWidth=o+3,i.beginPath(),i.ellipse(r.picture.x,r.picture.y,hi+2,hi+2,0,0,2*Math.PI),i.stroke()),r.scene&&(i.strokeStyle=a,i.lineWidth=1,i.beginPath(),i.moveTo(r.picture.x,r.picture.y),i.lineTo(r.scene.x,r.scene.y),i.stroke(),i.fillStyle=a,i.beginPath(),i.ellipse(r.scene.x,r.scene.y,hi,hi,0,0,2*Math.PI),i.fill()),i.strokeStyle=a,i.lineWidth=o,i.beginPath(),i.ellipse(r.picture.x,r.picture.y,hi+2,hi+2,0,0,2*Math.PI),i.stroke(),this.paintLabel(r.label,r.picture.x+hi+5,r.picture.y-hi-2,a)}n&&this.paintLabel(n,8,8,"#fff",13),i.restore()}static landmarkColour(e){return e===void 0?"#ffb000":e<=1?"#3c3":e<=3?"#ffb000":"#f33"}paintLabel(e,t,n,i,r=11){const a=this.ctx;a.save(),a.font=`${r}px system-ui, sans-serif`,a.textBaseline="top";const o=a.measureText(e).width;a.fillStyle="rgba(0, 0, 0, 0.6)",a.fillRect(t-3,n-2,o+6,r+4),a.fillStyle=i,a.fillText(e,t,n),a.restore()}paintGroupHandles(e){this.paintHandleFrame(Nn.handlePointsFor({bounds:e,angle:0}),{includeRotate:!0})}paintOutline(e){this.ctx.strokeStyle="lightgray",this.ctx.beginPath(),this.ctx.moveTo(e.nw.x,e.nw.y),this.ctx.lineTo(e.ne.x,e.ne.y),this.ctx.lineTo(e.se.x,e.se.y),this.ctx.lineTo(e.sw.x,e.sw.y),this.ctx.closePath(),this.ctx.stroke()}paintHandleFrame(e,{includeRotate:t}){this.paintOutline(e),this.ctx.fillStyle="lightgray";for(const n of Dp){const i=e[n];this.ctx.fillRect(i.x-eo,i.y-eo,hh,hh)}t&&(this.ctx.beginPath(),this.ctx.moveTo(e.n.x,e.n.y),this.ctx.lineTo(e.rotate.x,e.rotate.y),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.ellipse(e.rotate.x,e.rotate.y,eo+1,eo+1,0,0,2*Math.PI),this.ctx.fill())}}const Nd=.05,Od=.08,Ud=2,Fd=3,qg=14,Yg=.02;class Kg{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(e){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",e);return}}this.context.state==="suspended"&&this.context.resume()}setSound(e){if(this.requested=e,!this.context)return;const t=this.keyFor(e);if(!t){this.silence();return}if(this.voice?.key!==t){this.stopVoice();const n=++this.voiceToken;t.startsWith("src:")?this.buildRecordedVoice(e.src,t,n):this.voice=this.buildSynthesizedVoice(e,t)}this.applyTo(this.voice,e)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(e){if(!(e.volume<=0))return e.src?`src:${e.src}`:e.kind==="none"?void 0:e.kind}applyTo(e,t){const n=this.context;if(!e||!n)return;const i=n.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,i,Nd);for(const{param:r,ratio:a}of e.pitch)r.setTargetAtTime(Math.min(t.pitchHz*a,n.sampleRate/2-1),i,Nd)}buildSynthesizedVoice(e,t){const n=this.context;if(n)switch(e.kind){case"hum":return this.buildHum(n,t);case"whistle":return this.buildWhistle(n,t);case"rumble":return this.buildRumble(n,t);case"crackle":return this.buildCrackle(n,t);default:return}}buildHum(e,t){const n=e.createOscillator();n.type="sawtooth";const i=e.createOscillator();i.type="sawtooth";const r=e.createBiquadFilter();r.type="lowpass",r.Q.value=1;const a=e.createGain();return a.gain.value=0,n.connect(r),i.connect(r),r.connect(a).connect(e.destination),n.start(),i.start(),{key:t,nodes:[r,a],sources:[n,i],volumeParam:a.gain,gainScale:.16,pitch:[{param:n.frequency,ratio:1},{param:i.frequency,ratio:1.006},{param:r.frequency,ratio:6}]}}buildWhistle(e,t){const n=e.createOscillator();n.type="sine";const i=e.createOscillator();i.type="sine",i.frequency.value=5;const r=e.createGain(),a=e.createGain();return a.gain.value=0,i.connect(r).connect(n.frequency),n.connect(a).connect(e.destination),n.start(),i.start(),{key:t,nodes:[r,a],sources:[n,i],volumeParam:a.gain,gainScale:.22,pitch:[{param:n.frequency,ratio:1},{param:r.gain,ratio:.012}]}}buildRumble(e,t){const n=e.createBufferSource();n.buffer=this.brownNoise(e),n.loop=!0;const i=e.createBiquadFilter();i.type="lowpass",i.Q.value=.8;const r=e.createGain();return r.gain.value=0,n.connect(i).connect(r).connect(e.destination),n.start(),{key:t,nodes:[i,r],sources:[n],volumeParam:r.gain,gainScale:1.4,pitch:[{param:i.frequency,ratio:1}]}}buildCrackle(e,t){const n=e.createBufferSource();n.buffer=this.whiteNoise(e),n.loop=!0;const i=e.createBiquadFilter();i.type="bandpass",i.Q.value=1.2;const r=e.createGain();r.gain.value=0;const a=e.createBufferSource();a.buffer=this.crackleEnvelope(e),a.loop=!0;const o=e.createGain();return o.gain.value=0,a.connect(o).connect(r.gain),n.connect(i).connect(r).connect(e.destination),n.start(),a.start(),{key:t,nodes:[i,r,o],sources:[n,a],volumeParam:o.gain,gainScale:.9,pitch:[{param:i.frequency,ratio:4}]}}async buildRecordedVoice(e,t,n){const i=this.context;if(!i)return;let r;try{r=await this.getBuffer(e)}catch(c){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",c);return}if(n!==this.voiceToken||!this.context)return;const a=i.createBufferSource();a.buffer=r,a.loop=!0;const o=i.createGain();o.gain.value=0,a.connect(o).connect(i.destination),a.start(),this.voice={key:t,nodes:[o],sources:[a],volumeParam:o.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(e){const t=this.context;if(!t)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(i=>{if(!i.ok)throw new Error(`Audio fetch failed (${i.status}): ${e}`);return i.arrayBuffer()}).then(i=>t.decodeAudioData(i)),this.buffers.set(e,n)),n}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*Ud),e.sampleRate),n=t.getChannelData(0);for(let i=0;i<n.length;i++)n[i]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*Ud),e.sampleRate),n=t.getChannelData(0);let i=0,r=0;for(let a=0;a<n.length;a++)i=(i+.02*(Math.random()*2-1))/1.02,n[a]=i,r=Math.max(r,Math.abs(i));if(r>0)for(let a=0;a<n.length;a++)n[a]/=r;return t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*Fd),e.sampleRate),n=t.getChannelData(0),i=Math.max(1,Math.floor(Yg*e.sampleRate)),r=Math.round(Fd*qg);for(let a=0;a<r;a++){const o=Math.floor(Math.random()*n.length),c=.4+Math.random()*.6;for(let l=0;l<i&&o+l<n.length;l++)n[o+l]=Math.max(n[o+l],c*(1-l/i))}this.crackleBuffer=t}return this.crackleBuffer}stopVoice(){const e=this.voice,t=this.context;if(this.voice=void 0,!e||!t)return;const n=t.currentTime;e.volumeParam.cancelScheduledValues(n),e.volumeParam.setTargetAtTime(0,n,Od/3);const i=n+Od;for(const r of e.sources){r.onended=()=>{r.disconnect();for(const a of e.nodes)a.disconnect()};try{r.stop(i)}catch{r.disconnect();for(const a of e.nodes)a.disconnect()}}}}function dc(s){return[...s].sort((e,t)=>e.t-t.t)}function kd(s,e){let t;for(const n of dc(s)){if(n.t>e)break;t=n}return t}const $c=Math.PI/180,to=180/Math.PI;class Hi{constructor(e,t,n){this.kind=e,this.canvasHeightPx=t,this.fovDeg=n;const i=n*$c/2;this.focalPx=e==="equidistant"?t/2/i:t/2/Math.tan(i)}focalPx;static of(e,t,n){return new Hi(e.projection,t,n)}degToPx(e){const t=e*$c;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*to:2*Math.atan(e/(2*this.focalPx))*to}angleDegToRadiusPx(e){const t=e*$c;return this.kind==="equidistant"?this.focalPx*t:this.focalPx*Math.tan(t)}halfWidthAngleDeg(e){return this.radiusPxToAngleDeg(this.canvasHeightPx*e/2)}radiusPxToAngleDeg(e){return this.kind==="equidistant"?e/this.focalPx*to:Math.atan(e/this.focalPx)*to}ofBounds(e){return{widthDeg:this.pxToDeg(e.width),heightDeg:this.pxToDeg(e.height)}}toBoundsSize(e){return{width:this.degToPx(e.widthDeg),height:this.degToPx(e.heightDeg)}}widthPx(e){return this.degToPx(mt.angularWidthDeg(e))}}class Vn{static fovOf(e,t){return Qt(e,t)?.fovDeg??Vt.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,n)=>({...t,angular:n.ofBounds(t.bounds)}))}static toBounds(e){this.eachKeyframe(e,(t,n)=>{if(!t.angular)return t;const{width:i,height:r}=n.toBoundsSize(t.angular),a={x:t.bounds.x+(t.bounds.width-i)/2,y:t.bounds.y+(t.bounds.height-r)/2,width:i,height:r};if(t.kind!=="polygon")return{...t,bounds:a};const o=t.bounds.width===0?1:i/t.bounds.width,c=t.bounds.height===0?1:r/t.bounds.height;return{...t,bounds:a,points:t.points.map(l=>({x:l.x*o,y:l.y*c}))}})}static toAim(e){this.eachKeyframe(e,(t,n,i)=>{const r=this.aimFrom(e,n,i,t.bounds);return r?{...t,aim:r}:t})}static aimOf(e,t,n){const i=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,i,Qt(e,t),n)}static aimFrom(e,t,n,i){if(n?.headingDeg===void 0)return;const r=this.frameCentre(e),a=t.radiusPxToAngleDeg(i.x+i.width/2-r.x),o=t.radiusPxToAngleDeg(r.y-(i.y+i.height/2));return{azimuthDeg:((n.headingDeg+a)%360+360)%360,altitudeDeg:n.pitchDeg+o}}static toPosition(e){this.eachKeyframe(e,(t,n,i)=>{if(!t.aim||i?.headingDeg===void 0)return t;const r=this.frameCentre(e),a=this.shortestArc(t.aim.azimuthDeg-i.headingDeg),o=t.aim.altitudeDeg-i.pitchDeg,c=r.x+this.offAxisPx(n,a)-t.bounds.width/2,l=r.y-this.offAxisPx(n,o)-t.bounds.height/2;return{...t,bounds:{...t.bounds,x:c,y:l}}})}static frameCentre(e){return{x:Vt.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,y:mt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=Vn.OFF_CANVAS_DEG?Math.sign(t)*Vn.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,n){const i=Vt.frameWidthPx(t,mt.CANVAS_HEIGHT_PX)/2,r=Vt.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,a=mt.CANVAS_HEIGHT_PX/2;for(const o of[...e.timeline.allKeyframes]){const c=this.fovOf(e,o.t),l=n?.get(o.t)??c,h=Hi.of(t,mt.CANVAS_HEIGHT_PX,l),u=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,c);e.timeline.addKeyframe(o.t,o.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-i,v=f.y+f.height/2-a,m=Math.hypot(p,v),g=m===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,S={...f,x:r+p*g-f.width/2,y:a+v*g-f.height/2};return{...d,shape:{...d.shape,bounds:S}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:n}=e;for(const i of[...n.allKeyframes]){const r=Qt(e,i.t),a=this.fovOf(e,i.t),o=Hi.of(e.instrument,mt.CANVAS_HEIGHT_PX,a);n.addKeyframe(i.t,i.shapes.map(c=>({...c,shape:t(c.shape,o,r)})))}}}function $g(s){return Gn.restore(Zg(s),s.provenance)}function Zg(s){return Vn.toAngular(s),Vn.toAim(s),{version:1,time:s.event.time,endTime:s.event.endTime,durationSeconds:s.event.durationSeconds,utcOffsetHours:s.event.utcOffsetHours,timeZone:s.event.timeZone,place:s.event.place,witness:s.witness,testimony:s.testimony,caseId:s.caseId,description:s.event.description,tags:s.event.tags,timeline:s.timeline.toJSON(),witnessTrack:s.witnessTrack.toJSON(),weatherTrack:s.weatherTrack.toJSON(),soundTrack:s.soundTrack.toJSON(),weather:s.weather,decor:s.decor,milestones:s.milestones.length>0?s.milestones:void 0,references:s.references.length>0?s.references:void 0,weatherSource:s.weatherSource,instrument:s.instrumentId,exposureSeconds:s.exposureSeconds}}function Jg(s){const{recording:e,provenance:t}=Gn.strip(s),n=jg(e);return n.provenance=t,n}function jg(s){const e=new Oc({eventType:"sighting",time:s.time,endTime:s.endTime,durationSeconds:s.durationSeconds,utcOffsetHours:s.utcOffsetHours,timeZone:s.timeZone,place:s.place,description:s.description,tags:s.tags},Nc.fromJSON(s.timeline),s.witnessTrack?Pa.fromJSON(s.witnessTrack):new Pa,s.weatherTrack?Ia.fromJSON(s.weatherTrack):new Ia,s.soundTrack?La.fromJSON(s.soundTrack):new La,s.witness,s.caseId,s.weather,s.decor??[],s.weatherSource,s.instrument,s.exposureSeconds??s.witnessTrack?.keyframes.map(t=>t.pose.exposureSeconds).find(t=>t!==void 0),dc(s.milestones??[]),s.references??[]);return e.testimony=s.testimony,Vn.toBounds(e),Vn.toPosition(e),e}const zd=2;function Cp(s){return s==="building"||s==="vehicle"}function Qg(s,e){const t=s.litKeyframes;if(!t||t.length===0)return s.lit??!1;let n=t[0];for(const i of t){if(i.t>e)break;n=i}return n.lit}function e1(s,e){return s.pattern.kind==="steady"?!0:Pp(s,e,e+1)>.5}function Pp(s,e,t){if(s.pattern.kind==="steady")return 1;const{perMinute:n,dutyCycle:i,phase:r=0}=s.pattern,a=Math.min(Math.max(i,0),1);if(a===0||n<=0)return 0;const o=6e4/n,c=e/o+r,l=t/o+r;if(l<=c)return Math.min(Math.max(c-Math.floor(c),0),a)<a?1:0;const h=u=>Math.floor(u)*a+Math.min(u-Math.floor(u),a);return(h(l)-h(c))/(l-c)}function Ou(s,e){const t=s.track,n={eastM:s.eastM,northM:s.northM,altitudeM:0,headingDeg:s.headingDeg};if(!t||t.length===0)return n;if(t.length===1||e<=t[0].t)return Bd(t[0],s);const i=t[t.length-1];if(e>=i.t)return Bd(i,s);for(let r=0;r<t.length-1;r++){const a=t[r],o=t[r+1];if(e<a.t||e>o.t)continue;const c=o.t-a.t,l=c===0?0:(e-a.t)/c;return{eastM:a.eastM+(o.eastM-a.eastM)*l,northM:a.northM+(o.northM-a.northM)*l,altitudeM:(a.altitudeM??0)+((o.altitudeM??0)-(a.altitudeM??0))*l,headingDeg:a.headingDeg??s.headingDeg}}return n}function Bd(s,e){return{eastM:s.eastM,northM:s.northM,altitudeM:s.altitudeM??0,headingDeg:s.headingDeg??e.headingDeg}}class Qn{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(e,t){const n=Number.isFinite(t)?Math.max(0,t):0,i=Math.max(0,e-n*1e3),r=Math.max(0,e-i);return{fromMs:i,toMs:e,ms:r,seconds:r/1e3}}static instants(e,t,n,i,r){if(!(i>0))return 1;const a=r>0?Qn.travelDegOver(e,t,n,n+i*1e3)/r/Qn.PIXELS_PER_INSTANT:0,o=Qn.flashesOver(e,i)*Qn.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(a,o));return c<2?1:Math.min(Qn.MAX_INSTANTS,c)}static travelDegOver(e,t,n,i){let r=0;for(const a of e){if(!a.track||a.track.length<2)continue;const o=Qn.directionAt(a,t,n),c=Qn.directionAt(a,t,i),l=Math.min(1,Math.max(-1,o.x*c.x+o.y*c.y+o.z*c.z));r=Math.max(r,Math.acos(l)*180/Math.PI)}return r}static flashesOver(e,t){let n=0;for(const i of e)for(const r of i.lights??[])r.pattern.kind==="flash"&&(n=Math.max(n,r.pattern.perMinute));return n/60*t}static directionAt(e,t,n){const i=Ou(e,n),r=i.eastM,a=i.altitudeM-t,o=i.northM,c=Math.hypot(r,a,o);return c===0?{x:0,y:1,z:0}:{x:r/c,y:a/c,z:o/c}}}function Uu(s,e){for(const t of s){const n=t.toLowerCase().split("-")[0];if(e.includes(n))return n}return"en"}class fc{static preferencesFor(e){const t=navigator.languages??[],n=this.declaredFor(e);return n?[n,...t]:t}static declaredFor(e){for(let t=e;t;){const n=t.closest("[lang]")?.getAttribute("lang")?.trim();if(n)return n;const i=t.getRootNode();t=i instanceof ShadowRoot?i.host:void 0}}}class hs{constructor(e){this.preferences=e}read(e){if(e===void 0||typeof e=="string")return e===""?void 0:e;for(const n of this.preferences){const i=e[n]??e[hs.base(n)];if(i)return i}const t=new Set(this.preferences.map(n=>hs.base(n)));for(const[n,i]of Object.entries(e))if(i&&t.has(hs.base(n)))return i;return Object.values(e).find(n=>n)??void 0}write(e,t,n){const i=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return i;const r={...e},a=Object.keys(r).find(o=>o===n)??Object.keys(r).find(o=>hs.base(o)===hs.base(n))??n;return i===void 0?delete r[a]:r[a]=i,Object.keys(r).length===0?void 0:r}static base(e){return e.toLowerCase().split("-")[0]}}const t1=["en","fr"],n1={en:()=>lc(()=>Promise.resolve().then(()=>s1),void 0,import.meta.url).then(s=>s.ufoMessages_en),fr:()=>lc(()=>import("./UfoMessages_fr-CnenjNH2.js"),[],import.meta.url).then(s=>s.ufoMessages_fr)};function i1(s){return n1[s]()}const Ip={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",showWitnessMap:"Show where the witness was",hideWitnessMap:"Hide where the witness 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",witnessHere:"The witness, here",decorHere:"Scenery"},s1=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:Ip},Symbol.toStringTag,{value:"Module"})),Lp=Math.PI/180,r1=180/Math.PI,a1=256,o1=19;function c1(s,e){return 156543.03392*Math.cos(s*Lp)/2**e}function l1(s,e){return c1(s,e)*a1}function Np(s,e){let t=0;for(;t<o1&&l1(s,t+1)>=e;)t++;return t}function Qo(s){const e=s*Lp;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function Op(s,e,t){const n=2**t;return{x:(s+180)/360*n,y:Qo(e)*n}}function Up(s,e,t){const n=Qo(s.north),i=Qo(s.south);return{x:(e-s.west)/(s.east-s.west),y:(Qo(t)-n)/(i-n)}}function h1(s,e,t){const{x:n,y:i}=Op(s,e,t);return{x:Math.floor(n),y:Math.floor(i),z:t}}function u1(s){const e=2**s.z,t=s.x/e*360-180,n=(s.x+1)/e*360-180,i=Hd(s.y,e);return{south:Hd(s.y+1,e),north:i,west:t,east:n}}function Hd(s,e){const t=s/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*r1}function Fp(s,e,t,n){const i=h1(s,e,t),r=Math.floor(n/2),a=[];for(let l=-r;l<=r;l++)for(let h=-r;h<=r;h++)a.push({x:i.x+h,y:i.y+l,z:t});const o=a.map(u1),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:a,bounds:c}}class Rs{constructor(e){this.ctx=e}static SCALE_STEPS_M=[5e3,2e3,1e3,500,200,100,50,20,10,5];static MARKER_RADIUS_PX=8.5;static ON_MARKER_M=3;targets=[];hitTest(e,t){let n,i=1/0;for(const r of this.targets){const a=Math.hypot(r.x-e,r.y-t);a>r.radius||a>i||(n=r,i=a)}return n}get width(){return this.ctx.canvas.width}get height(){return this.ctx.canvas.height}paint(e){const{ctx:t}=this;t.save(),this.targets=[],t.clearRect(0,0,this.width,this.height),this.paintGround(e),this.paintNight(e.nightFraction),this.paintPath(e),e.position?(this.paintCone(e,e.position),this.paintDecor(e),this.paintMarkers(e),this.paintWitness(e,e.position)):(this.paintDecor(e),this.paintMarkers(e)),this.paintNorth(),this.paintFooter(e.bounds,e.attribution),t.restore()}toCanvas(e,t,n){const i=Up(e,n,t);return{x:i.x*this.width,y:i.y*this.height}}paintGround(e){const{ctx:t}=this;t.fillStyle="#1d2321",t.fillRect(0,0,this.width,this.height);const n=e.imagery;if(!n)return;const i=this.toCanvas(e.bounds,n.bounds.north,n.bounds.west),r=this.toCanvas(e.bounds,n.bounds.south,n.bounds.east);t.drawImage(n.source,i.x,i.y,r.x-i.x,r.y-i.y)}paintNight(e=0){if(e<=0)return;const{ctx:t}=this;t.save(),t.fillStyle=`rgba(6, 12, 30, ${Math.min(e,1)*.78})`,t.fillRect(0,0,this.width,this.height),t.restore()}paintDecor(e){const{ctx:t}=this;for(const n of e.decor){const i=this.toCanvas(e.bounds,n.lat,n.lng);if(n.label&&this.targets.push({kind:"decor",label:n.label,lat:n.lat,lng:n.lng,x:i.x,y:i.y,radius:7}),t.beginPath(),t.rect(i.x-3.5,i.y-3.5,7,7),t.fillStyle="rgba(120, 220, 255, 0.85)",t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.7)",t.stroke(),n.headingDeg===void 0)continue;const r=(n.headingDeg-90)*Math.PI/180;t.beginPath(),t.moveTo(i.x,i.y),t.lineTo(i.x+Math.cos(r)*10,i.y+Math.sin(r)*10),t.lineWidth=3,t.strokeStyle="rgba(0, 0, 0, 0.6)",t.stroke(),t.lineWidth=1.5,t.strokeStyle="rgba(120, 220, 255, 0.9)",t.stroke()}}paintPath(e){if(!e.path.moved)return;const{ctx:t}=this,n=e.path.points.map(i=>this.toCanvas(e.bounds,i.lat,i.lng));t.beginPath(),t.moveTo(n[0].x,n[0].y);for(const i of n.slice(1))t.lineTo(i.x,i.y);t.lineJoin="round",t.lineCap="round",t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=5,t.stroke(),t.strokeStyle="rgba(255, 255, 255, 0.9)",t.lineWidth=2,t.stroke()}paintCone(e,t){const{headingDeg:n,coneHalfAngleDeg:i}=e;if(n===void 0||i===void 0)return;const{ctx:r}=this,a=this.toCanvas(e.bounds,t.lat,t.lng),o=Math.hypot(this.width,this.height),c=(n-90)*Math.PI/180,l=i*Math.PI/180;r.save(),r.beginPath(),r.moveTo(a.x,a.y),r.arc(a.x,a.y,o,c-l,c+l),r.closePath();const h=r.createRadialGradient(a.x,a.y,0,a.x,a.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)"),r.fillStyle=h,r.fill(),r.restore()}paintMarkers(e){const{ctx:t}=this;t.textAlign="center",t.textBaseline="middle",t.font="bold 10px sans-serif";for(const n of[...e.markers].sort((i,r)=>Number(i.current)-Number(r.current))){const i=this.toCanvas(e.bounds,n.lat,n.lng);this.targets.push({kind:"milestone",label:n.note?`${n.label} — ${n.note}`:n.label,lat:n.lat,lng:n.lng,t:n.t,x:i.x,y:i.y,radius:Rs.MARKER_RADIUS_PX}),t.beginPath(),t.arc(i.x,i.y,Rs.MARKER_RADIUS_PX,0,Math.PI*2),t.fillStyle=n.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",t.fill(),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.9)",t.stroke(),t.fillStyle=n.current?"#1d2321":"#fff",t.fillText(n.label,i.x,i.y)}}paintWitness(e,t){const{ctx:n}=this,i=this.toCanvas(e.bounds,t.lat,t.lng);e.witnessLabel&&this.targets.push({kind:"witness",label:e.witnessLabel,lat:t.lat,lng:t.lng,x:i.x,y:i.y,radius:8});const r=e.markers.some(a=>{if(!a.current)return!1;const o=rn(a.lat,a.lng,t.lat,t.lng);return Math.hypot(o.x,o.z)<=Rs.ON_MARKER_M});n.beginPath(),n.arc(i.x,i.y,r?Rs.MARKER_RADIUS_PX+2.5:5.5,0,Math.PI*2),r||(n.fillStyle="#ff5a3c",n.fill()),n.lineWidth=4,n.strokeStyle="rgba(0, 0, 0, 0.5)",n.stroke(),n.lineWidth=r?3:2.5,n.strokeStyle=r?"#ff5a3c":"#fff",n.stroke()}paintNorth(){const{ctx:e}=this,t=this.width-14,n=16;e.beginPath(),e.moveTo(t,n-9),e.lineTo(t-4.5,n+5),e.lineTo(t,n+2),e.lineTo(t+4.5,n+5),e.closePath(),e.fillStyle="rgba(255, 255, 255, 0.92)",e.strokeStyle="rgba(0, 0, 0, 0.6)",e.lineWidth=1,e.fill(),e.stroke(),e.font="bold 9px sans-serif",e.textAlign="center",e.textBaseline="top",e.strokeText("N",t,n+6),e.fillText("N",t,n+6)}paintFooter(e,t){const{ctx:n}=this;n.font="9px sans-serif",n.textBaseline="bottom";const i=t?this.wrap(t,this.width-20):[];let r=this.height-4;n.textAlign="right";for(const f of i.slice().reverse())this.paintOutlinedText(f,this.width-6,r),r-=11;const a=(e.south+e.north)/2,c=Math.abs(rn(a,e.east,a,e.west).x)/this.width,l=Rs.SCALE_STEPS_M.find(f=>f/c<=this.width/3);if(l===void 0)return;const h=l/c,u=8,d=r-3;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.6)",n.beginPath(),n.moveTo(u,d),n.lineTo(u+h,d),n.stroke(),n.lineWidth=1.5,n.strokeStyle="rgba(255, 255, 255, 0.95)",n.stroke(),n.textAlign="left",this.paintOutlinedText(l>=1e3?`${l/1e3} km`:`${l} m`,u,d-3)}paintOutlinedText(e,t,n){const{ctx:i}=this;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.75)",i.strokeText(e,t,n),i.fillStyle="#fff",i.fillText(e,t,n)}wrap(e,t){const n=[];let i="";for(const r of e.split(" ")){const a=i?`${i} ${r}`:r;i&&this.ctx.measureText(a).width>t?(n.push(i),i=r):i=a}return i&&n.push(i),n}}const kn=256,Gd=3,d1=32768;class f1{fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(e,t){const n=(e.south+e.north)/2,i=(e.west+e.east)/2,r=Math.abs(rn(n,e.east,n,e.west).x),a=Math.abs(rn(e.north,i,e.south,i).z),o=Np(n,Math.max(r,a)),{tiles:c}=Fp(i,n,o,Gd),l=Gd*kn,h=new Float32Array(l*l),u=c[0];await Promise.all(c.map(f=>this.decodeTileInto(f,u,h,l)));const d=new Float32Array(t.width*t.height);for(let f=0;f<t.height;f++){const p=e.north+(e.south-e.north)*(f/(t.height-1));for(let v=0;v<t.width;v++){const m=e.west+(e.east-e.west)*(v/(t.width-1));d[f*t.width+v]=this.sampleAt(p,m,o,u,h,l)}}return{heights:d,width:t.width,height:t.height,bounds:e}}async decodeTileInto(e,t,n,i){const r=this.tileUrlTemplate.replace("{z}",String(e.z)).replace("{x}",String(e.x)).replace("{y}",String(e.y)),a=await this.fetchImpl(r);if(!a.ok)throw new Error(`Elevation tile fetch failed (${a.status}): ${r}`);const o=await createImageBitmap(await a.blob()),c=document.createElement("canvas");c.width=kn,c.height=kn;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,kn,kn),u=(e.x-t.x)*kn,d=(e.y-t.y)*kn;for(let f=0;f<kn;f++)for(let p=0;p<kn;p++){const v=(f*kn+p)*4,m=h[v]*256+h[v+1]+h[v+2]/256-d1,g=u+p,S=d+f;n[S*i+g]=m}}sampleAt(e,t,n,i,r,a){const{x:o,y:c}=Op(t,e,n),l=(o-i.x)*kn,h=(c-i.y)*kn,u=Math.max(0,Math.min(a-1,Math.floor(l))),d=Math.max(0,Math.min(a-1,Math.floor(h))),f=Math.min(a-1,u+1),p=Math.min(a-1,d+1),v=l-u,m=h-d,g=r[d*a+u],S=r[d*a+f],w=r[p*a+u],_=r[p*a+f],b=g+(S-g)*v,E=w+(_-w)*v;return b+(E-b)*m}}const Zc=256,Vd=3;async function p1(s,e,t,n){const i=(s.south+s.north)/2,r=(s.west+s.east)/2,a=Math.abs(rn(i,s.east,i,s.west).x),o=Math.abs(rn(s.north,r,s.south,r).z),c=Np(i,Math.max(a,o)/2),{tiles:l,bounds:h}=Fp(r,i,c,Vd),u=Vd*Zc,d=document.createElement("canvas");d.width=u,d.height=u;const f=d.getContext("2d");if(!f)throw new Error("2D canvas context unavailable");const p=l[0];await Promise.all(l.map(async g=>{const S=t(g),w=await n(S);if(!w.ok)throw new Error(`Imagery tile fetch failed (${w.status}): ${S}`);const _=await createImageBitmap(await w.blob());f.drawImage(_,(g.x-p.x)*Zc,(g.y-p.y)*Zc)}));const v=document.createElement("canvas");v.width=e.width,v.height=e.height;const m=v.getContext("2d");if(!m)throw new Error("2D canvas context unavailable");return m.drawImage(d,0,0,u,u,0,0,e.width,e.height),{source:v,width:e.width,height:e.height,bounds:h}}class m1{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(e,t){return p1(e,t,n=>this.tileUrlTemplate.replace("{z}",String(n.z)).replace("{y}",String(n.y)).replace("{x}",String(n.x)),this.fetchImpl)}}function g1(){return{elevation:new f1,imagery:kp()}}function kp(){return new m1}const v1=new Set,Cr="show-witness-map",Pr="hide-milestones";class In extends HTMLElement{static get observedAttributes(){return["src",Cr,Pr]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;static WITNESS_MAP_MIN_SPAN_M=400;static WITNESS_MAP_MARGIN=.6;static WITNESS_MAP_IMAGERY_PX=768;fullscreenButton;cornerButtons;witnessMapButton;referencesButton;referenceOpacityInput;referencesShownState=!0;referenceOpacityTouched=!1;milestonesButton;witnessMapPanel;witnessMapCanvas;witnessMapRenderer;seekInput;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;witnessPath;witnessMapBounds;witnessMapImagery;witnessMapImageryRequested=!1;witnessMapImageryCredit;witnessMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Oc.create();sightingAudio=new Kg;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=Ip;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.resizeWitnessMap()};witnessMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeWitnessMap());resizeWitnessMap(){this.witnessMapPanel.hidden||(this.sizeWitnessMapCanvas(),this.paintWitnessMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),n=t&&this.shapeAt(t.x,t.y),i=this.said.read(n?.shape.title);if(!i){this.tooltip.hidden=!0;return}this.tooltip.textContent=i,this.tooltip.hidden=!1;const r=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-r.left+12}px`,this.tooltip.style.top=`${e.clientY-r.top+12}px`};handleWitnessMapPointerMove=e=>{const t=this.witnessMapTargetFrom(e);if(!t){this.tooltip.hidden=!0,this.witnessMapCanvas.style.cursor="default";return}this.witnessMapCanvas.style.cursor="pointer",this.tooltip.textContent=t.label,this.tooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-n.left+12}px`,this.tooltip.style.top=`${e.clientY-n.top+12}px`};handleWitnessMapClick=e=>{const t=this.witnessMapTargetFrom(e);if(t){if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))}};witnessMapTargetFrom(e){const t=this.witnessMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.witnessMapRenderer.hitTest((e.clientX-t.left)/t.width*this.witnessMapCanvas.width,(e.clientY-t.top)/t.height*this.witnessMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${_g}</style>${xg}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Na(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.cornerButtons=this.shadow.getElementById("corner-buttons"),this.witnessMapButton=this.shadow.getElementById("witness-map"),this.referencesButton=this.shadow.getElementById("references"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.milestonesButton=this.shadow.getElementById("milestones"),this.witnessMapPanel=this.shadow.getElementById("witness-map-panel"),this.witnessMapCanvas=this.shadow.getElementById("witness-map-canvas"),this.witnessMapRenderer=new Rs(this.witnessMapCanvas.getContext("2d")),this.seekInput=this.shadow.getElementById("seek"),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 t of[this.timeStartLabel,this.timeEndLabel])t.addEventListener("click",()=>this.toggleTimeDisplay()),t.addEventListener("keydown",n=>{n.key!=="Enter"&&n.key!==" "||(n.preventDefault(),this.toggleTimeDisplay())});this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.witnessMapButton.addEventListener("click",()=>this.toggleWitnessMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.witnessMapCanvas.addEventListener("pointermove",this.handleWitnessMapPointerMove),this.witnessMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.witnessMapCanvas.addEventListener("click",this.handleWitnessMapClick),this.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",t=>{this.seekSnapArmed=!0,this.nameMarkUnder(t)}),this.seekInput.addEventListener("pointerup",()=>{this.seekSnapArmed=!1}),this.seekInput.addEventListener("pointermove",t=>this.nameMarkUnder(t)),this.seekInput.addEventListener("pointerleave",()=>this.seekInput.removeAttribute("title")),this.canvas.addEventListener("click",t=>{this.enableClickToPlay&&(t.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause())}),this.canvas.addEventListener("dblclick",t=>{this.enableClickToPlay&&(t.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),this.witnessMapResizeObserver?.observe(this.witnessMapPanel),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),this.updateReferencesButton(),this.updateMilestonesButton(),this.refresh(),this.loadLocaleMessages()}connectedCallback(){this.saidTexts=void 0;const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.witnessMapResizeObserver?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(e,t,n){e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),e===Cr&&this.applyWitnessMapDefault(),e===Pr&&this.setMilestonesShown(!this.hasAttribute(Pr))}async loadFromSrc(e){this.sightingData=await Rp.json(e)}get sightingData(){return $g(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Jg(e),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyWitnessMapDefault()}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){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(e){this.toolbar.classList.toggle("hidden",!e)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(i=>this.highlightedSourceIds.has(i))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==void 0}refresh(){this.applyFrameFormat(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateWitnessMap(),this.updateReferences(),this.player.seek(this.player.time)}hostControls(e){const t=[this.milestonesButton,this.referenceOpacityInput,this.referencesButton,this.witnessMapButton];if(e)for(const n of t)e.appendChild(n);else for(const n of t)this.toolbar.appendChild(n)}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}toggleReferences(){this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity)),this.updateReferencesButton()}updateReferencesButton(){const e=this.currentSighting.references.length>0;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState,this.referencesButton.setAttribute("aria-pressed",String(this.referencesShownState));const t=this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=t,this.referencesButton.setAttribute("aria-label",t),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 e=this.player.seekableDuration,t=e>0?dc(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(n=>{const i=document.createElement("button");i.type="button",i.className="milestone-mark",i.style.left=`${Math.min(Math.max(n.t/e,0),1)*100}%`;const r=this.said.read(n.label)??"",a=this.said.read(n.note),o=a?`${r} — ${a}`:r;return i.title=o,i.setAttribute("aria-label",o),i.dataset.t=String(n.t),i.addEventListener("click",()=>this.player.seek(n.t)),i}))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,n=this.seekInput.getBoundingClientRect().width;if(t<=0||n<=0)return;const i=In.MARK_SNAP_PX/n*t;let r;for(const a of this.milestoneMarks.children){const o=Number(a.dataset.t);Math.abs(o-e)>i||(!r||Math.abs(o-e)<Math.abs(r.t-e))&&(r={t:o,name:a.title})}return r}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),n=this.player.seekableDuration;if(t.width<=0||n<=0)return;const i=(e.clientX-t.left)/t.width*n,r=this.markNear(i);r?this.seekInput.title=r.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?kd(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,!t)return;const n=document.createElement("b");n.textContent=this.said.read(t.label)??"";const i=this.said.read(t.note),r=i?` — ${i}`:"";this.milestoneCaption.replaceChildren(n,document.createTextNode(r))}exposureInstants(e){const t=this.exposureTimes(e),n=1/t.length;return t.map(i=>({shapes:this.shapesAt(i),share:n}))}exposureTimes(e=this.currentTime){const t=Qn.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<In.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const n=Math.min(In.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/In.SHORTEST_VISIBLE_EXPOSURE_MS))),i=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/In.EXPOSURE_STEP_PX),r=Math.min(In.MAX_TRAVEL_STEPS,Math.max(n,i)),a=[];for(let o=0;o<r;o++)a.push(t.fromMs+t.ms*o/(r-1));return a}travelPxOver(e,t){const n=this.shapesAt(e),i=this.shapesAt(e+t);let r=0;for(const[a,o]of n){const c=i.get(a);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);r=Math.max(r,Math.hypot(l,h))}return r}shapeAt(e,t,n){for(const i of this.exposureTimes()){const r=this.currentSighting.timeline.hitTest(i,e,t,n);if(r)return r}}shapesAt(e){const t=new Map;for(const n of this.currentSighting.timeline.sourceIds){const i=this.currentSighting.timeline.getInterpolatedShapeAt(e,n);i&&t.set(n,i)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Vt.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const n=this.playbackState!=="playing"?this.highlightedSourceIds:v1;this.canvasRenderer.setStarPoints(Vt.starPointsOf(this.sighting.instrument));const i=(Qt(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(i*Math.PI/180);const r=this.exposureInstants(e),a=this.frameShift;if(this.paintsShapes)for(const o of r)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,a))}for(const[o,c]of r[0].shapes)!this.selectionShown||!n.has(o)||(this.paintsShapes?n.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,a)));if(this.selectionShown&&n.size>1){const o=Nn.groupBoundsFor([...t].filter(([c])=>n.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.overlayPainter?.(this.canvasRenderer),this.mapShapeBounds=r.flatMap(o=>[...o.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,a).bounds)),this.keepWitnessMapClear(),this.seekInput.value=String(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintWitnessMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(Bg(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new Hg(this.currentSighting.timeline,(t,n)=>this.onFrame(t,n));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}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())}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.playPauseButton.textContent=e?"⏸":"▶";const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const n=t?e?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=n,this.playPauseButton.setAttribute("aria-label",n),this.toolbar.classList.toggle("auto-hide",e),this.cornerButtons.classList.toggle("auto-hide",e)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton()}toggleWitnessMap(){this.setWitnessMapOpen(this.witnessMapPanel.hidden)}applyWitnessMapDefault(){this.setWitnessMapOpen(this.hasAttribute(Cr)&&this.witnessPath!==void 0)}setWitnessMapOpen(e){this.witnessMapPanel.hidden=!e,this.witnessMapPanel.removeAttribute("title"),this.witnessMapButton.setAttribute("aria-pressed",String(e)),this.updateWitnessMapButton(),e&&(this.sizeWitnessMapCanvas(),this.loadWitnessMapImagery(),this.paintWitnessMap(this.currentTime))}updateWitnessMapButton(){const t=!this.witnessMapPanel.hidden?this.messages.hideWitnessMap:this.messages.showWitnessMap;this.witnessMapButton.title=t,this.witnessMapButton.setAttribute("aria-label",t)}updateWitnessMap(){const e=this.witnessPath!==void 0;if(this.witnessPath=Ca.of(this.currentSighting),this.witnessMapButton.hidden=this.witnessPath===void 0,!e&&this.witnessPath&&this.applyWitnessMapDefault(),!this.witnessPath){this.setWitnessMapOpen(!1),this.witnessMapBounds=void 0;return}const t=this.witnessPath.boundsAround(In.WITNESS_MAP_MIN_SPAN_M,In.WITNESS_MAP_MARGIN);(!this.witnessMapBounds||!this.sameGround(this.witnessMapBounds,t))&&(this.witnessMapBounds=t,this.witnessMapImagery=void 0,this.witnessMapImageryCredit=void 0,this.witnessMapImageryFailed=!1,this.witnessMapImageryRequested=!1,this.witnessMapPanel.hidden||this.loadWitnessMapImagery())}sameGround(e,t){const n=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<n&&Math.abs(e.south-t.south)<n&&Math.abs(e.west-t.west)<n&&Math.abs(e.east-t.east)<n}async loadWitnessMapImagery(){if(this.witnessMapImageryRequested||!this.witnessMapBounds)return;this.witnessMapImageryRequested=!0;const e=kp(),t=this.witnessMapBounds;try{const n=await e.getImageryTexture(t,{width:In.WITNESS_MAP_IMAGERY_PX,height:In.WITNESS_MAP_IMAGERY_PX});if(this.witnessMapBounds!==t)return;this.witnessMapImagery=n,this.witnessMapImageryCredit=e.attribution}catch{this.witnessMapImageryFailed=!0}this.paintWitnessMap(this.currentTime)}get witnessMapCredit(){return this.witnessMapImageryCredit}get witnessMapFooterLine(){return this.witnessMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.witnessMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepWitnessMapClear()}keepWitnessMapClear(){if(this.witnessMapPanel.hidden)return;const e=this.witnessMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],n=(l,h,u)=>{for(const d of t)if(!(d.x+d.width<l-u||d.x>h+u)&&!(d.y>e.bottom+u||d.y+d.height<e.top-u))return!0;return!1},i=[this.canvas.width-e.width,this.canvas.width],r=[0,e.width],a=In.WITNESS_MAP_CLEARANCE_PX,o=n(...i,0),c=n(...r,0);if(this.witnessMapPanel.classList.toggle("subject-overlap",o&&c),this.witnessMapPanel.classList.contains("on-the-left")){!o&&(c||!n(i[0],i[1],a))&&this.witnessMapPanel.classList.remove("on-the-left");return}n(i[0],i[1],0)&&!n(r[0],r[1],0)&&this.witnessMapPanel.classList.add("on-the-left")}witnessMapBoxPx;static WITNESS_MAP_CLEARANCE_PX=24;sizeWitnessMapCanvas(){const e=this.witnessMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureWitnessMapBox(),this.witnessMapCanvas.width!==t&&(this.witnessMapCanvas.width=t,this.witnessMapCanvas.height=t)}measureWitnessMapBox(){const e=this.witnessMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const n=this.canvas.width/t.width,i=this.canvas.height/t.height;this.witnessMapBoxPx={width:e.width*n,top:(e.top-t.top)*i,bottom:(e.bottom-t.top)*i}}paintWitnessMap(e){if(this.witnessMapPanel.hidden||!this.witnessPath||!this.witnessMapBounds)return;const t=Qt(this.currentSighting,e),n=this.currentSighting.instrument,i=[],r=this.currentSighting.milestones.length>0?kd(this.currentSighting.milestones,e):void 0;for(const a of this.milestonesShown?dc(this.currentSighting.milestones):[]){const o=Qt(this.currentSighting,a.t);o?.lat===void 0||o.lng===void 0||i.push({label:this.said.read(a.label)??"",note:this.said.read(a.note),t:a.t,lat:o.lat,lng:o.lng,current:a===r})}this.witnessMapRenderer.paint({bounds:this.witnessMapBounds,imagery:this.witnessMapImagery,path:this.witnessPath,position:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?Hi.of(n,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Vt.aspectOf(n)):void 0,markers:i,decor:this.witnessMapDecorAt(e),witnessLabel:this.said.read(this.currentSighting.witness?.title)??this.messages.witnessHere,nightFraction:this.witnessMapNightFraction,attribution:this.witnessMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.milestonesButton.setAttribute("aria-pressed",String(e)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintWitnessMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0;const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}witnessMapDecorAt(e){const t=Qt(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(n=>n.kind!=="crop").map(n=>{const i=Ou(n,e),{lat:r,lng:a}=Bi(i.eastM,-i.northM,t.lat,t.lng);return{lat:r,lng:a,headingDeg:i.headingDeg,label:this.said.read(n.title)??this.messages.decorHere}})}witnessMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.witnessMapNightFraction&&(this.witnessMapNightFraction=t,this.paintWitnessMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,n=this.lookPitchDeg+e.pitchDeg;if(t===0&&n===0)return{x:0,y:0};const i=Qt(this.currentSighting,this.currentTime),r=Hi.of(this.currentSighting.instrument,this.canvas.height,i?.fovDeg??60);return{x:-r.angleDegToRadiusPx(t),y:r.angleDegToRadiusPx(n)}}gaitAt(e){return Gt.of(this.currentSighting)?.offsetAt(e)??Gt.STILL}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new hs(fc.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=Uu(fc.preferencesFor(this),t1);e!=="en"&&this.applyMessages(await i1(e))}updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t;for(const n of[this.timeStartLabel,this.timeEndLabel])n.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(n.setAttribute("role","button"),n.setAttribute("tabindex","0")):(n.removeAttribute("role"),n.removeAttribute("tabindex"))}applyMessages(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),this.updateReferencesButton(),this.updateMilestonesButton()}updateTimeLabels(){const e=this.currentSighting.event,t=Fg(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?lh(e.time):void 0;const n=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&n>0?n/this.realDurationMs:1,this.player.durationOverrideMs=n>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return no(e);const t=this.currentSighting.timeline.duration,n=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?Xd(Wd(this.realStartMs+n)):no(n)}formatEndOfTimeline(){return this.realDurationMs===void 0?no(this.currentSighting.timeline.duration):this.canShowClockTime?Xd(Wd(this.realStartMs+this.realDurationMs)):no(this.realDurationMs)}}function Wd(s){const e=new Date(s);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function Xd(s){if(s.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return s.second?`${e(s.hour)}:${e(s.minute??0)}:${e(s.second)}`:`${e(s.hour)}:${e(s.minute??0)}`}function no(s){const e=Math.round(s/1e3),t=Math.floor(e/60),n=e%60;return`${t}:${String(n).padStart(2,"0")}`}const uh="rr0-ufo";function zp(){customElements.get(uh)||customElements.define(uh,In)}/**
|
|
604
604
|
* @license
|
|
605
605
|
* Copyright 2010-2026 Three.js Authors
|
|
606
606
|
* SPDX-License-Identifier: MIT
|
|
@@ -6069,4 +6069,4 @@ void main() {
|
|
|
6069
6069
|
gl_FragColor = vec4(color, tex.a * uOpacity * (1.0 - blur * 0.5));
|
|
6070
6070
|
}
|
|
6071
6071
|
`;let jo;function $w(){if(jo)return jo;const s=128,e=document.createElement("canvas");e.width=s,e.height=s;const t=e.getContext("2d"),n=t.createRadialGradient(s/2,s/2,0,s/2,s/2,s/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.4,"rgba(255,255,255,0.35)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,s,s),jo=new Ti(e),jo}function yp(s){const t=document.createElement("canvas");t.width=128,t.height=128;const n=t.getContext("2d"),i=128/2-2,r=128/2,a=128/2,o="#2e2b26",c="#f4f1e2";n.fillStyle=o,n.beginPath(),n.arc(r,a,i,0,Math.PI*2),n.fill();const l=Ra(s.illuminatedFraction,0,1),h=s.phaseFraction<.5,u=i*Math.abs(1-2*l),d=l<.5;return n.save(),n.beginPath(),n.arc(r,a,i,0,Math.PI*2),n.clip(),n.fillStyle=c,n.beginPath(),h?(n.arc(r,a,i,-Math.PI/2,Math.PI/2,!1),n.ellipse(r,a,u,i,0,Math.PI/2,-Math.PI/2,d)):(n.arc(r,a,i,Math.PI/2,-Math.PI/2,!1),n.ellipse(r,a,u,i,0,-Math.PI/2,Math.PI/2,d)),n.fill(),n.restore(),new Ti(t)}function Zw(s){const e=document.createElement("canvas");e.width=128,e.height=128;const t=e.getContext("2d");return t.fillStyle="rgba(0, 0, 0, 0.55)",t.beginPath(),t.arc(64,64,60,0,Math.PI*2),t.fill(),t.fillStyle="#ffffff",t.font="bold 52px sans-serif",t.textAlign="center",t.textBaseline="middle",t.fillText(s,64,68),new Ti(e)}function sh(s){let e=s;return function(){e|=0,e=e+1831565813|0;let n=Math.imul(e^e>>>15,1|e);return n=n+Math.imul(n^n>>>7,61|n)^n,((n^n>>>14)>>>0)/4294967296}}const rh=7.5,ah=9;class gi{static cache=new Map;static load(e){let t=gi.cache.get(e);return t||(t=fetch(e).then(n=>n.arrayBuffer()).then(n=>gi.parse(n)),gi.cache.set(e,t)),t}static upTo(e,t){const n=e.filter((a,o)=>o===0||e[o-1].magnitudeLimit<t);if(n.length<=1)return gi.load(e[0].url);const i=n.map(a=>a.url).join(`
|
|
6072
|
-
`);let r=gi.cache.get(i);return r||(r=Promise.all(n.map(a=>gi.load(a.url))).then(a=>a.reduce((o,c)=>gi.concat(o,c))),gi.cache.set(i,r)),r}static parse(e){const t=e.byteLength/(4*Float32Array.BYTES_PER_ELEMENT),n=t*Float32Array.BYTES_PER_ELEMENT;return{count:t,ra:new Float32Array(e,0*n,t),dec:new Float32Array(e,1*n,t),mag:new Float32Array(e,2*n,t),ci:new Float32Array(e,3*n,t)}}static concat(e,t){const n=(i,r)=>{const a=new Float32Array(i.length+r.length);return a.set(i,0),a.set(r,i.length),a};return{count:e.count+t.count,ra:n(e.ra,t.ra),dec:n(e.dec,t.dec),mag:n(e.mag,t.mag),ci:n(e.ci,t.ci)}}}const Jw=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,jw=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,Qw=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,eE=20,tE=1;class nE{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(e){console.warn("WeatherAudio: Web Audio unavailable, weather sounds disabled:",e);return}}this.context.state==="suspended"&&this.context.resume()}setAmbient(e,t,n){if(this.requested={type:e,intensity:t,windSpeed:n},!this.context)return;this.paused&&(e="none",t=0,n=0);const i=e==="rain"||e==="hail"?e:"none";if(this.ambientVolume=i==="hail"?Math.min(1,t*1.3+.2):i==="rain"?t:0,i!==this.ambientKey){this.ambientKey=i;const a=++this.ambientToken;this.stopSource(this.ambientSource,this.ambientGain),this.ambientSource=void 0,this.ambientGain=void 0,i!=="none"&&this.startLoop(Jw,this.ambientVolume).then(o=>this.applyIfCurrent(o,a,()=>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(n/eE,1);const r=n>tE;if(r!==this.windActive){this.windActive=r;const a=++this.windToken;this.stopSource(this.windSource,this.windGain),this.windSource=void 0,this.windGain=void 0,r&&this.startLoop(jw,this.windVolume).then(o=>this.applyIfCurrent(o,a,()=>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(e){if(e===this.paused)return;this.paused=e;const{type:t,intensity:n,windSpeed:i}=this.requested;this.setAmbient(t,n,i)}playThunder(){!this.context||this.paused||this.playOneShot(Qw,.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(e,t,n,i){if(t!==n()){e?.source.stop();return}i(e)}async startLoop(e,t){const n=this.context;if(n)try{const i=await this.getBuffer(e),r=n.createBufferSource();r.buffer=i,r.loop=!0;const a=n.createGain();return a.gain.value=t,r.connect(a).connect(n.destination),r.start(),{source:r,gain:a}}catch(i){console.warn("Weather ambient sound failed to load, staying silent:",i);return}}async playOneShot(e,t){const n=this.context;if(n)try{const i=await this.getBuffer(e),r=n.createBufferSource();r.buffer=i;const a=n.createGain();a.gain.value=t,r.connect(a).connect(n.destination),r.start()}catch(i){console.warn("Thunder sound failed to load:",i)}}async getBuffer(e){const t=this.context;if(!t)throw new Error("WeatherAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(i=>{if(!i.ok)throw new Error(`Audio fetch failed (${i.status}): ${e}`);return i.arrayBuffer()}).then(i=>t.decodeAudioData(i)),this.buffers.set(e,n)),n}stopSource(e,t){try{e?.stop()}catch{}e?.disconnect(),t?.disconnect()}}class ki{constructor(e){this.elements=e;const{eccentricity:t,perihelionAu:n}=e,[i,r]=this.perifocalAxes(),a=Math.sqrt(ki.SUN_GM_AU3_PER_DAY2*(1+t)/n);this.perihelionPosition=this.scale(i,n),this.perihelionVelocity=this.scale(r,a),this.inverseSemiMajorAxis=(1-t)/n}static SUN_GM_AU3_PER_DAY2=.0002959122082855911;static MAX_ITERATIONS=200;perihelionPosition;perihelionVelocity;inverseSemiMajorAxis;positionAt(e){const t=e-this.elements.perihelionJd,n=this.universalAnomaly(t),i=this.inverseSemiMajorAxis*n*n,r=this.elements.perihelionAu,a=1-n*n/r*ki.stumpffC(i),o=t-n*n*n/Math.sqrt(ki.SUN_GM_AU3_PER_DAY2)*ki.stumpffS(i);return{x:a*this.perihelionPosition.x+o*this.perihelionVelocity.x,y:a*this.perihelionPosition.y+o*this.perihelionVelocity.y,z:a*this.perihelionPosition.z+o*this.perihelionVelocity.z}}heliocentricDistanceAt(e){const t=this.positionAt(e);return Math.hypot(t.x,t.y,t.z)}universalAnomaly(e){if(e===0)return 0;const t=Math.sign(e),n=Math.sqrt(ki.SUN_GM_AU3_PER_DAY2)*Math.abs(e),i=o=>{const c=this.inverseSemiMajorAxis*o*o,l=this.elements.perihelionAu;return(1-this.inverseSemiMajorAxis*l)*o*o*o*ki.stumpffS(c)+l*o};let r=Math.max(1,n/this.elements.perihelionAu);for(;i(r)<n;)r*=2;let a=0;for(let o=0;o<ki.MAX_ITERATIONS&&r-a>1e-13*Math.max(1,r);o++){const c=(a+r)/2;i(c)<n?a=c:r=c}return t*(a+r)/2}perifocalAxes(){const e=this.elements.ascendingNodeDeg*Math.PI/180,t=this.elements.argumentOfPerihelionDeg*Math.PI/180,n=this.elements.inclinationDeg*Math.PI/180,i=Math.cos(e),r=Math.sin(e),a=Math.cos(t),o=Math.sin(t),c=Math.cos(n),l=Math.sin(n);return[{x:i*a-r*o*c,y:r*a+i*o*c,z:o*l},{x:-i*o-r*a*c,y:-r*o+i*a*c,z:a*l}]}scale(e,t){return{x:e.x*t,y:e.y*t,z:e.z*t}}static stumpffC(e){if(Math.abs(e)<1e-6)return 1/2-e/24+e*e/720;if(e>0)return(1-Math.cos(Math.sqrt(e)))/e;const t=Math.sqrt(-e);return(Math.cosh(t)-1)/-e}static stumpffS(e){if(Math.abs(e)<1e-6)return 1/6-e/120+e*e/5040;if(e>0){const n=Math.sqrt(e);return(n-Math.sin(n))/(n*n*n)}const t=Math.sqrt(-e);return(Math.sinh(t)-t)/(t*t*t)}}const og=[{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 iE{static WINDOW_DAYS=200;static TWILIGHT_ELONGATION_DEG=15;static LIGHT_SPEED_AU_PER_DAY=173.144632674;static orbits=new Map;static aroundDate(e){const t=this.julianDayOf(e);return og.filter(n=>Math.abs(t-n.orbit.perihelionJd)<=this.WINDOW_DAYS)}static brightestAt(e,t){return this.aroundDate(e).map(n=>this.appearanceOf(n,e,t)).sort((n,i)=>n.magnitude-i.magnitude)[0]}static appearanceOf(e,t,n){const i=zt(t),r=this.earthPositionAt(i),a=this.apparentPositionOf(e,2451545+i.tt,r),o=this.subtract(a,r),c=this.length(a),l=this.length(o),h=this.tailEndAt(e,a,r,c,i,t,n),u=this.horizontalOf(o,i,t,n);return{apparition:e,position:u,...h,heliocentricDistanceAu:c,earthDistanceAu:l,elongationDeg:this.angleBetween(o,this.subtract({x:0,y:0,z:0},r)),magnitude:this.magnitudeAt(e,c,l)}}static magnitudeAt(e,t,n){const i=e.absoluteMagnitude+5*Math.log10(n)+2.5*e.activityExponent*Math.log10(t);return Math.max(i,e.peakMagnitude)}static tailEndAt(e,t,n,i,r,a,o){if(e.tailLengthAu===void 0)return{};const c=1+e.tailLengthAu/i,l=this.subtract({x:t.x*c,y:t.y*c,z:t.z*c},n),h=this.subtract(t,n);return{tailEnd:this.horizontalOf(l,r,a,o),tailLengthDeg:this.angleBetween(h,l)}}static apparentPositionOf(e,t,n){const i=this.orbitOf(e);let r=i.positionAt(t);for(let a=0;a<2;a++){const o=this.length(this.subtract(r,n))/this.LIGHT_SPEED_AU_PER_DAY;r=i.positionAt(t-o)}return r}static horizontalOf(e,t,n,i){const r=cc(nb(),new Mt(e.x,e.y,e.z,t)),a=cc(ib(t),r),o=NS(t,new dd(i.lat,i.lng,i.elevationM)),c=new Mt(a.x-o.x,a.y-o.y,a.z-o.z,t),l=qm(c);return Xc(l.ra,l.dec,n,i)}static earthPositionAt(e){return cc(tb(),gs(Se.Earth,e))}static julianDayOf(e){return 2451545+zt(e).tt}static orbitOf(e){const t=this.orbits.get(e.id);if(t)return t;const n=new ki(e.orbit);return this.orbits.set(e.id,n),n}static subtract(e,t){return{x:e.x-t.x,y:e.y-t.y,z:e.z-t.z}}static length(e){return Math.hypot(e.x,e.y,e.z)}static angleBetween(e,t){const n=(e.x*t.x+e.y*t.y+e.z*t.z)/(this.length(e)*this.length(t)||1);return Math.acos(Math.min(1,Math.max(-1,n)))*180/Math.PI}}const sE=[{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}],Lc=6.5;class oh{static activeAt(e){return sE.flatMap(t=>{const n=this.nearness(t,e);return n<=0?[]:[{shower:t,zhr:t.peakZhr*n,nearness:n}]})}static nearness(e,t){const n=this.dayOfYear(t),i=this.dayOfYear(this.asDate(e.start)),r=this.dayOfYear(this.asDate(e.peak)),a=this.dayOfYear(this.asDate(e.end)),o=this.wrappedDelta(n,r),c=this.wrappedDelta(r,i),l=this.wrappedDelta(a,r);return o<0?o<-c?0:1+o/c:o>0?o>l?0:1-o/l:1}static observedRatePerHour(e,t,n,i=Lc){if(t<=0)return 0;const r=Lc-i;return e*Math.sin(t*Math.PI/180)/Math.pow(n,r)}static radiantPosition(e,t,n){return Xc(e.radiantRaHours,e.radiantDecDeg,t,n)}static dayOfYear(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return Math.floor((Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())-t)/864e5)+1}static asDate(e){return new Date(Date.UTC(2001,e.month-1,e.day))}static wrappedDelta(e,t){const n=e-t;return n>182?n-365:n<-182?n+365:n}}class It{static QUIET_RATE_PER_HOUR=2;static APEX_RATE_PER_HOUR=8;static POPULATION_INDEX=3;static apexPosition(e,t){const n=zt(e),i=new hd(0,IS(e).elon-90,1),r=cc(sb(n),Xm(i,n)),a=qm(r);return Xc(a.ra,a.dec,e,t)}static observedRatePerHour(e,t=Lc){const n=It.APEX_RATE_PER_HOUR*Math.max(0,Math.sin(e*Math.PI/180)),i=Lc-t;return(It.QUIET_RATE_PER_HOUR+n)/Math.pow(It.POPULATION_INDEX,i)}static schedule(e){const t=new qc(e.seed^1542469173);return ks.schedule(e).map(n=>{const i=It.toCartesian({altitudeDeg:Math.asin(t.next())*180/Math.PI,azimuthDeg:t.between(0,360)}),r=n.fromRadiantDeg*Math.PI/180,a=It.turnAround(i,t.between(0,360)),o={x:i.x*Math.cos(r)+a.x*Math.sin(r),y:i.y*Math.cos(r)+a.y*Math.sin(r),z:i.z*Math.cos(r)+a.z*Math.sin(r)};return{...n,radiant:It.toHorizontal(o),bearingDeg:It.bearingFrom(o,i)}})}static turnAround(e,t){const[n,i]=It.basisAround(e),r=t*Math.PI/180;return{x:n.x*Math.cos(r)+i.x*Math.sin(r),y:n.y*Math.cos(r)+i.y*Math.sin(r),z:n.z*Math.cos(r)+i.z*Math.sin(r)}}static bearingFrom(e,t){const[n,i]=It.basisAround(e),r=e.x*t.x+e.y*t.y+e.z*t.z,a=It.normalise({x:t.x-e.x*r,y:t.y-e.y*r,z:t.z-e.z*r});return(Math.atan2(a.x*i.x+a.y*i.y+a.z*i.z,a.x*n.x+a.y*n.y+a.z*n.z)*180/Math.PI%360+360)%360}static basisAround(e){const t=Math.abs(e.y)<.9?{x:0,y:1,z:0}:{x:1,y:0,z:0},n=It.normalise(It.cross(e,t));return[n,It.normalise(It.cross(e,n))]}static toHorizontal(e){const t=Math.hypot(e.x,e.y,e.z)||1;return{altitudeDeg:Math.asin(Math.min(1,Math.max(-1,e.y/t)))*180/Math.PI,azimuthDeg:(Math.atan2(e.x,-e.z)*180/Math.PI%360+360)%360}}static appearanceOf(e){const t=It.toCartesian(e.radiant??{altitudeDeg:90,azimuthDeg:0}),n=It.turnAround(t,e.bearingDeg),i=e.fromRadiantDeg*Math.PI/180;return It.toHorizontal({x:t.x*Math.cos(i)+n.x*Math.sin(i),y:t.y*Math.cos(i)+n.y*Math.sin(i),z:t.z*Math.cos(i)+n.z*Math.sin(i)})}static toCartesian(e){const t=e.altitudeDeg*Math.PI/180,n=e.azimuthDeg*Math.PI/180,i=Math.cos(t);return{x:i*Math.sin(n),y:Math.sin(t),z:-i*Math.cos(n)}}static cross(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}static normalise(e){const t=Math.hypot(e.x,e.y,e.z)||1;return{x:e.x/t,y:e.y/t,z:e.z/t}}static TYPICAL_VELOCITY_KM_S=40}const Sp="https://ufoathome.org/tle/index.json";class hn{static MAX_ELEMENT_AGE_DAYS=7;static DAY_MS=864e5;fetchImpl;indexUrls;index;files=new Map;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??hn.defaultIndexUrls()}static defaultIndexUrls(){const e=[];return typeof location<"u"&&/^https?:$/.test(location.protocol)&&e.push(new URL("/tle/index.json",location.href).href),e.includes(Sp)||e.push(Sp),e}static FIRST_SNAPSHOT="2021-02-22";async covers(e){const t=Date.parse(`${hn.FIRST_SNAPSHOT}T00:00:00Z`)-hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS;if(e.getTime()<t)return!1;const n=await this.loadIndex();return n?Object.values(n.index.kinds).some(i=>e.getTime()>=Date.parse(i.from)-hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS&&e.getTime()<=Date.parse(i.to)+hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS):!1}async at(e){const t=await this.loadIndex();if(!t)return;const{index:n,base:i}=t,r=[],a=[];for(const o of Object.keys(n.kinds)){const c=await this.kindAt(o,e,n,i);r.push(...c),a.push(this.coverageOf(o,e,n,c.length>0))}return{objects:r,coverage:a,credit:n.credit,creditUrl:n.source}}async kindAt(e,t,n,i){const r=t.getTime(),a=n.binDays*hn.DAY_MS,o=Math.floor(r/a),c=r-o*a<a/2?o-1:o+1,l=new Set(n.kinds[e].bins),h=[o,c].map(v=>new Date(v*a).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-${e}.json`,i).href),...h.map(v=>this.binary(new URL(`${e}/${v}.bin`,i).href))]),f=new Map;for(const v of d)for(const m of hn.decode(v,n.recordBytes)){const g=f.get(m.norad);(!g||Math.abs(m.epochMs-r)<Math.abs(g.epochMs-r))&&f.set(m.norad,m)}const p=[];for(const v of f.values()){const m=Math.abs(v.epochMs-r)/hn.DAY_MS;if(m>hn.MAX_ELEMENT_AGE_DAYS)continue;const g=u[v.norad]??{name:String(v.norad)};g.launch&&Date.parse(`${g.launch}T00:00:00Z`)>r||p.push({norad:v.norad,name:g.name,kind:e,launch:g.launch,stdMag:g.stdMag,elements:v,ageDays:m})}return p}coverageOf(e,t,n,i){const{from:r,to:a}=n.kinds[e],o=t.getTime(),c=hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS,l=i?"covered":o<Date.parse(r)-c?"before":o>Date.parse(a)+c?"after":"gap";return{kind:e,status:l,from:r,to:a}}static decode(e,t){const n=new DataView(e),i=[];for(let r=0;r+t<=e.byteLength;r+=t)i.push({norad:n.getUint32(r,!0),epochMs:n.getFloat64(r+4,!0),bstar:n.getFloat32(r+12,!0),inclinationDeg:n.getFloat32(r+16,!0),raanDeg:n.getFloat32(r+20,!0),eccentricity:n.getFloat32(r+24,!0),argOfPerigeeDeg:n.getFloat32(r+28,!0),meanAnomalyDeg:n.getFloat32(r+32,!0),meanMotion:n.getFloat64(r+36,!0)});return i}loadIndex(){return this.index??=(async()=>{for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;return{index:await t.json(),base:e}}catch{}})(),this.index}json(e){return this.cached(e,async t=>t.json())}binary(e){return this.cached(e,async t=>t.arrayBuffer())}cached(e,t){let n=this.files.get(e);return n||(n=this.fetchImpl(e).then(i=>{if(!i.ok)throw new Error(`${e}: ${i.status}`);return t(i)}),n.catch(()=>this.files.delete(e)),this.files.set(e,n)),n}}class rE{lowerM;upperM;add(e,t){if(!(e<=0)){if(t.behindM!==void 0){const n=mt.sizeMAt(t.behindM,e);this.lowerM=this.lowerM===void 0?n:Math.max(this.lowerM,n)}if(t.inFrontM!==void 0){const n=mt.sizeMAt(t.inFrontM,e);this.upperM=this.upperM===void 0?n:Math.min(this.upperM,n)}}}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(e){return e<=0?{}:{minM:this.lowerM===void 0?void 0:mt.distanceMAt(this.lowerM,e),maxM:this.upperM===void 0?void 0:mt.distanceMAt(this.upperM,e)}}clear(){this.lowerM=void 0,this.upperM=void 0}}class zs{static DEG_PER_SECOND=360/86164.0905;static degOver(e){return Math.max(0,e)*zs.DEG_PER_SECOND}static instants(e,t){if(!(t>0))return 1;const n=zs.degOver(e)/t;return n<1?1:Math.min(zs.MAX_INSTANTS,Math.max(2,Math.ceil(n)))}static MAX_INSTANTS=64}class gn{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 zs.DEG_PER_SECOND*3600}static graspOf(e,t={}){const n=t.exposureSeconds??e.exposureSeconds,i=t.fNumber??e.fNumber;if(n===void 0||i===void 0||!(n>0)||!(i>0))return gn.EYE;const r=t.focalLengthMm??e.frame?.focalLengthMm??gn.UNKNOWN_CAMERA_FOCAL_MM,a=r/i,o=gn.resolutionArcsec(e,r,a);return{apertureMm:a,exposureSeconds:Math.min(n,gn.trailLimitedSeconds(o)),resolutionArcsec:o}}static resolutionArcsec(e,t,n){const r=(e.detailUm??gn.UNKNOWN_CAMERA_DETAIL_UM)/1e3/t*gn.ARCSEC_PER_RADIAN,a=1.22*gn.WAVELENGTH_M/(n/1e3)*gn.ARCSEC_PER_RADIAN;return Math.max(r,a)}static trailLimitedSeconds(e){return e/gn.skyDriftArcsecPerSecond}static gainOverEye(e,t={}){const n=gn.graspOf(e,t),i=gn.EYE,r=(n.apertureMm/i.apertureMm)**2,a=n.exposureSeconds/i.exposureSeconds,o=(i.resolutionArcsec/n.resolutionArcsec)**2;return 1.25*Math.log10(r*a*o)}static gainFor(e,t){const n=t.fieldOfViewDeg===void 0?void 0:Vt.focalLengthMmFor(e,t.fieldOfViewDeg);return gn.gainOverEye(e,{fNumber:t.fNumber,focalLengthMm:n,exposureSeconds:t.exposureSeconds})}}const bp=111320,pa=Math.PI/180,aE=1.02,oE=1;class Da{static of(e,t){const n=Da.sightings(e,t);if(n.length<2)return;const i=Da.baseline(n);if(!i)return;const{near:r,far:a,closedM:o}=i,c=Math.tan(a.widthDeg/2*pa)===0?0:Math.tan(r.widthDeg/2*pa)/Math.tan(a.widthDeg/2*pa);if(c<aE)return;const l=o/(c-1),h=mt.sizeMAt(l,r.widthDeg),u=n.map(d=>({t:d.t,m:mt.distanceMAt(h,d.widthDeg)}));return{widthM:h,distanceM:u,nearestM:Math.min(...u.map(d=>d.m)),fromT:a.t,toT:r.t,closedM:o}}static sightings(e,t){return e.timeline.allKeyframes.flatMap(n=>{const i=n.shapes.find(o=>o.sourceId===t)?.shape,r=i?.angular?.widthDeg,a=Qt(e,n.t);return r===void 0||r<=0||a?.lat===void 0||a.lng===void 0?[]:[{t:n.t,widthDeg:r,lat:a.lat,lng:a.lng,sightAzimuthDeg:i?.aim?.azimuthDeg??a.headingDeg}]}).sort((n,i)=>n.t-i.t)}static baseline(e){let t;for(const n of e)for(const i of e){if(n.t>=i.t)continue;const r=Da.closedAlongSight(n,i),[a,o,c]=r>=0?[i,n,r]:[n,i,-r];c<oE||a.widthDeg<=o.widthDeg||(!t||c>t.closedM)&&(t={near:a,far:o,closedM:c})}return t}static closedAlongSight(e,t){const n=(t.lat-e.lat)*bp,i=(t.lng-e.lng)*bp*Math.cos(e.lat*pa),r=(e.sightAzimuthDeg??0)*pa;return n*Math.cos(r)+i*Math.sin(r)}}class mn{static CONVENTIONAL_M=5;static NEAREST_M=.2;static MARGIN=1.1;static resolve(e){if(e.statedM!==void 0&&e.statedM>0)return{distanceM:mn.atLeastNearest(e.statedM),basis:"stated"};if(e.hypothesisM!==void 0&&e.hypothesisM>0)return{distanceM:mn.atLeastNearest(e.hypothesisM),basis:"hypothesis"};if(e.derivedM!==void 0&&e.derivedM>0)return{distanceM:mn.atLeastNearest(e.derivedM),basis:"derived"};const t=mn.largest(e.range?.minM,e.crossing?.behindM),n=mn.smallest(e.range?.maxM,e.crossing?.inFrontM),i=t===void 0?void 0:t*mn.MARGIN,r=n===void 0?void 0:n/mn.MARGIN;return i!==void 0&&r!==void 0?{distanceM:mn.atLeastNearest(i<=r?Math.sqrt(i*r):i),basis:"bounded"}:i!==void 0?{distanceM:mn.atLeastNearest(i),basis:"bounded"}:r!==void 0&&r<mn.CONVENTIONAL_M?{distanceM:mn.atLeastNearest(r),basis:"bounded"}:{distanceM:mn.CONVENTIONAL_M,basis:"conventional"}}static atLeastNearest(e){return Math.max(mn.NEAREST_M,e)}static largest(...e){const t=e.filter(n=>n!==void 0&&n>0);return t.length===0?void 0:Math.max(...t)}static smallest(...e){const t=e.filter(n=>n!==void 0&&n>0);return t.length===0?void 0:Math.min(...t)}}zp();const cE={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"}},lE=["en","fr"],hE={en:"{name} — mag {mag}, {alt}° above the horizon",fr:"{name} — mag {mag}, {alt}° au-dessus de l'horizon"},uE={en:"{name} — satellite, mag {mag}, {height} km up",fr:"{name} — satellite, mag {mag}, à {height} km d'altitude"},dE="satellites-change",fE={en:"{name} — mag {mag}, {alt}° below the horizontal",fr:"{name} — mag {mag}, {alt}° sous l'horizontale"},wp="comet:",pE={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},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"},witness:{en:"Witness",fr:"Témoin"},aircraft:{en:"Aircraft",fr:"Aéronef"},entity:{en:"Being",fr:"Être"}},mE=new URL(""+new URL("stars-mag7.5-B43R6Wvg.bin",import.meta.url).href,import.meta.url).href,gE=new URL(""+new URL("stars-mag7.5-9-BLV2tFmZ.bin",import.meta.url).href,import.meta.url).href,vE=-18,ME={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},ch={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class fd extends HTMLElement{static get observedAttributes(){return["src","star-catalog-src","deep-star-catalog-src","show-compass","max-pixel-ratio",Cr,Pr]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;distanceHypotheses=new Map;depths=new Map;directionScratch=new C;meteorScheduleFor;lightningScheduleFor;lightningFlashes=[];lastLightningT;lastTimeMs=0;lastSkyKey;starCatalog;starCatalogRequest=0;static tleArchive=new hn;satellitesFor;satelliteRequest=0;satelliteStatus="none";satellites;satellitePassesMemo;starCatalogDepth=0;weatherAudio=new nE;animateWhilePausedValue=!1;set animateWhilePaused(e){e!==this.animateWhilePausedValue&&(this.animateWhilePausedValue=e,this.syncAnimationsToPlayback())}get animateWhilePaused(){return this.animateWhilePausedValue}thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=e=>{this.sceneRenderer.setCompassHovered(!0);const t=this.ufoElement.canvasElement,n=t.getBoundingClientRect();if(n.width===0||n.height===0)return;const i=(e.clientX-n.left)/n.width*t.width,r=(e.clientY-n.top)/n.height*t.height;if(this.ufoElement.hasVisibleShapeAt(i,r)){this.hoverTooltip.hidden=!0;return}const a=(e.clientX-n.left)/n.width*2-1,o=-((e.clientY-n.top)/n.height*2-1),c=Uu(fc.preferencesFor(this),lE),l=this.sceneRenderer.pickBodyAt(a,o);if(l){this.showHoverTooltip(e,this.bodyName(l,c));return}const h=this.sceneRenderer.pickDecorAt(a,o),u=h?this.ufoElement.sighting.decor.find(p=>p.id===h):void 0;if(u){this.showHoverTooltip(e,this.said.read(u.title)||pE[u.kind][c]);return}const d=this.sceneRenderer.pickSatelliteAt(a,o);if(d){this.showHoverTooltip(e,uE[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(a,o);if(f){const p=f.star.mag,v=f.altitudeDeg,m=(v<0?fE:hE)[c];this.showHoverTooltip(e,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(e,t){const n=e.startsWith(wp)?e.slice(wp.length):void 0;return(n?og.find(r=>r.id===n):void 0)?.name[t]??cE[e]?.[t]??e}showHoverTooltip(e,t){this.hoverTooltip.textContent=t,this.hoverTooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${e.clientX-n.left+12}px`,this.hoverTooltip.style.top=`${e.clientY-n.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash(e){clearTimeout(this.thunderTimeoutId),this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),Wt.thunderDelayMs(e))}handleFirstInteraction=()=>{this.weatherAudio.resume(),this.setWeather(Js(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=e=>{this.lastTimeMs=e.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.playbackState==="playing"&&this.sceneRenderer.frame(performance.now())};syncAnimationsToPlayback(){const e=this.ufoElement.playbackState==="playing",t=e||this.animateWhilePaused;this.sceneRenderer.setAnimationsRunning(t,e),this.weatherAudio.setPaused(!t),t||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${Mg}</style>${vg}`,this.shadow.appendChild(e.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 Hn(this.sceneCanvas),this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(uh),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.paintsShapes=!1,this.forwardPlayerAttributes(),this.ufoElement.addEventListener("lookat",t=>this.lookToward(t.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.sceneRenderer.onMapSubjectBounds=t=>this.ufoElement.setMapSubjectBounds(t),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.addEventListener("referenceview",t=>this.applyReferenceView(t.detail)),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave),this.ufoElement.canvasElement.addEventListener("pointerdown",this.handleFirstInteraction,{once:!0})}get said(){return this.saidTexts??=new hs(fc.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 e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose(),queueMicrotask(()=>{this.isConnected||this.sceneRenderer.releaseContext()})}attributeChangedCallback(e,t,n){if(e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),(e==="star-catalog-src"||e==="deep-star-catalog-src")&&n!==t&&this.isConnected&&this.loadStars(),e==="show-compass"&&n!==t&&this.sceneRenderer.setShowCompass(this.hasAttribute("show-compass")),e==="max-pixel-ratio"&&n!==t){const i=Number(n);this.sceneRenderer.setMaxPixelRatio(Number.isFinite(i)&&i>0?i:Math.min(window.devicePixelRatio||1,2))}(e===Cr||e===Pr)&&n!==t&&this.forwardPlayerAttributes()}forwardPlayerAttributes(){for(const e of[Cr,Pr])this.ufoElement.toggleAttribute(e,this.hasAttribute(e))}setCompassForced(e){this.sceneRenderer.setCompassForced(e)}lookToward(e){const t=Qt(this.ufoElement.sighting,this.lastTimeMs);if(e.kind==="witness"||t?.lat===void 0||t.lng===void 0||t.headingDeg===void 0){this.setLookOffset(0,0);return}const{x:n,z:i}=rn(e.lat,e.lng,t.lat,t.lng);if(Math.hypot(n,i)<1)return this.setLookOffset(0,0);const r=(Math.atan2(n,-i)*180/Math.PI+360)%360;this.setLookOffset(((r-t.headingDeg)%360+540)%360-180,-t.pitchDeg)}setLookOffset(e,t){this.sceneRenderer.setLookOffset(e,t),this.ufoElement.setLookOffset(e,t),this.updateAstronomy(this.lastTimeMs)}setIndoorLook(e,t){this.sceneRenderer.setIndoorLook(e,t)}setCloudRendering(e){this.sceneRenderer.setCloudRendering(e)}setWeather(e){this.sceneRenderer.setWeather(e),this.weatherAudio.setAmbient(e.precipitationType,e.precipitationIntensity,e.windSpeed)}pickCloudAt(e,t){return this.sceneRenderer.pickCloudAt(e,t)}cloudDirectionAt(e,t){return this.sceneRenderer.cloudDirectionAt(e,t)}pickDecorAt(e,t){return this.sceneRenderer.pickDecorAt(e,t)}resumeWeatherAudio(){this.weatherAudio.resume()}async loadFromSrc(e){this.sightingData=await Rp.json(e)}get sightingData(){return this.ufoElement.sightingData}set sightingData(e){this.ufoElement.sightingData=e,this.applyFrameFormat(),this.lastTimeMs=0,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(0)}referenceAspect(e){return this.sceneRenderer.referenceAspect(e)}screenPointOf(e){return this.sceneRenderer.screenPointOf(e)}directionAt(e,t){return this.sceneRenderer.directionAt(e,t)}referenceFailedToLoad(e){return this.sceneRenderer.referenceFailedToLoad(e)}applyReferenceView(e){this.sceneRenderer.setReferencesShown(e.shown);for(const t of this.ufoElement.sighting.references)this.sceneRenderer.setReferenceView(t.id,{opacity:e.opacity})}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}setTerrainProviders(e){this.sceneRenderer.setTerrainProviders(e)}setDecorModelProvider(e){this.sceneRenderer.setDecorModelProvider(e)}get decorModelCredits(){return this.sceneRenderer.currentDecorModelCredits}applyFrameFormat(){const e=this.ufoElement.sighting.instrument,t=mt.CANVAS_HEIGHT_PX,n=Vt.frameWidthPx(e,t);this.frameElement.style.setProperty("--frame-aspect",`${n} / ${t}`)}resizeToStage(){const e=this.frameElement.getBoundingClientRect(),t=Math.max(1,Math.round(e.width)),n=Math.max(1,Math.round(e.height));this.sceneCanvas.width=t,this.sceneCanvas.height=n,this.sceneRenderer.resize(t,n)}async loadStars(){const e=[{magnitudeLimit:rh,url:this.getAttribute("star-catalog-src")??mE},{magnitudeLimit:ah,url:this.getAttribute("deep-star-catalog-src")??gE}],t=this.instrumentReach(),n=++this.starCatalogRequest;this.starCatalogDepth=t>rh?ah:rh;const i=await gi.upTo(e,t);n===this.starCatalogRequest&&(this.starCatalog=i,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=ah||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const e=this.ufoElement.sighting,t=gn.gainFor(e.instrument,{fNumber:Qt(e,0)?.fNumber,fieldOfViewDeg:Vn.fovOf(e,0),exposureSeconds:e.exposure});return hu(vE,t)}updateAstronomy(e){this.ensureStarsDeepEnough(),this.applySceneAt(e);const t=Qn.windowEndingAt(e,this.exposureSeconds()),n=t.seconds,i=this.degreesPerPixelAt(e),r=zs.instants(n,i),a=Math.max(r,this.ufoElement.exposureTimes(e).length,Qn.instants(this.ufoElement.sighting.decor,Qt(this.ufoElement.sighting,e)?.elevationM??0,t.fromMs,n,i));if(a<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(a,o=>this.applySceneAt(t.fromMs+t.ms*o/(a-1),{sky:Math.floor(o*r/a)!==Math.floor((o-1)*r/a),stepMs:t.ms/a}))}exposureSeconds(){return this.ufoElement.sighting.exposure??0}degreesPerPixelAt(e){const t=this.sceneCanvas.height;return t<=0?0:Vn.fovOf(this.ufoElement.sighting,e)/t}applySceneAt(e,t){const n=this.ufoElement.sighting;this.setWeather(Js(n,e)),this.sceneRenderer.setInstrument(n.instrument),this.updateMeteorShower(n,e),this.updateLightning(n,e,t!==void 0),this.sceneRenderer.setDecor(n.decor),this.sceneRenderer.setReferences(n.references);const i=Qt(n,e),r=Qt(n,0),a=Js(n,0),o=Object.fromEntries(hc(Js(n,e)).map(w=>[w.id,wd(e,n.weatherTrack,a,r,i,w.id)]));this.sceneRenderer.setCloudOffset(wd(e,n.weatherTrack,a,r,i),o),this.sceneRenderer.setObserverPose(i??ch),this.sceneRenderer.setLensOptics(this.lensOpticsAt(e)),this.sceneRenderer.setInstrumentGain(gn.gainFor(n.instrument,{fNumber:i?.fNumber,fieldOfViewDeg:Vn.fovOf(n,e),exposureSeconds:n.exposure})),this.sceneRenderer.setGait(Gt.of(n)?.offsetAt(e)??Gt.STILL),this.sceneRenderer.updateDecorAnchoring(Qt(n,0),i,e),this.sceneRenderer.updateDecorLitState(e,t?.stepMs??0),this.sceneRenderer.setTerrainOrigin(i?.lat,i?.lng),this.pushPhenomenaAt(e);const c=i?.lat??ch.lat,l=i?.lng??ch.lng,h=Bo(n.event.time??{},l,n.event.utcOffsetHours),u={lat:c,lng:l,elevationM:i?.elevationM??0};if(this.pushSatellitesAt(h,e,u),t&&!t.sky)return;if(!h){this.sceneRenderer.setAstronomy(ME);return}const d=new Date(h.getTime()+e),f=Math.max(1,Math.round(.25*this.degreesPerPixelAt(e)/zs.DEG_PER_SECOND*1e3)),p=Math.max(1e-8,this.degreesPerPixelAt(e)*.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={...Bl("Sun",d,u),magnitude:Hl("Sun",d)},g={...Bl("Moon",d,u),phase:ab(d),magnitude:Hl("Moon",d)},S=rb.map(w=>({body:w,position:Bl(w,d,u),magnitude:Hl(w,d)}));this.sceneRenderer.setAstronomy({sun:m,moon:g,planets:S,comet:this.cometAt(d,u),stars:this.starCatalog?{catalog:this.starCatalog,date:d,observer:u}:void 0,frame:{date:d,observer:u}}),this.ufoElement.setSunAltitude(m.altitudeDeg)}pushSatellitesAt(e,t,n){if(this.ensureSatellites(e),!e||!this.satellites){this.sceneRenderer.setSatellites([]);return}const i=new Date(e.getTime()+t),r=[];for(const a of this.satellites.passes.positionsAt(i,n,-1))a.magnitude!==void 0&&r.push({norad:a.object.norad,name:a.object.name,position:{altitudeDeg:a.altitudeDeg,azimuthDeg:a.azimuthDeg},magnitude:a.magnitude,heightKm:a.heightKm});this.sceneRenderer.setSatellites(r)}ensureSatellites(e){const t=e?String(e.getTime()):"";if(t===this.satellitesFor)return;this.satellitesFor=t,this.satellites=void 0,this.satellitePassesMemo=void 0;const n=++this.satelliteRequest;if(!e){this.satelliteStatus="none";return}this.satelliteStatus="loading";const i=a=>{n===this.satelliteRequest&&(this.satelliteStatus=a,this.dispatchEvent(new CustomEvent(dE)))},r=fd.tleArchive;(async()=>{if(!await r.covers(e))return i("outside");const[a,o]=await Promise.all([r.at(e),lc(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(n===this.satelliteRequest){if(!a)return i("unavailable");this.satellites={snapshot:a,passes:new o.SatellitePasses(a.objects)},i("ready"),this.updateAstronomy(this.lastTimeMs)}})().catch(()=>i("unavailable"))}get satelliteState(){const e=this.satellites?.snapshot;return{status:this.satelliteStatus,coverage:e?.coverage,credit:e?.credit,creditUrl:e?.creditUrl}}satellitePassesDuring(e){const t=this.satellites,n=this.ufoElement.sighting,i=Qt(n,0),r=n.event.place?.[0],a=i?.lat??r?.lat,o=i?.lng??r?.lng;if(!t||a===void 0||o===void 0)return[];const c=Bo(n.event.time??{},o,n.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(e,0),4*36e5),h={lat:a,lng:o,elevationM:i?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),a,o,h.elevationM,l]);if(this.satellitePassesMemo?.key===u)return this.satellitePassesMemo.passes;const d=Math.max(10,Math.ceil(l/1e3/600)),f=t.passes.passesDuring(c,new Date(c.getTime()+l),h,d);return this.satellitePassesMemo={key:u,passes:f},f}cometAt(e,t){const n=iE.brightestAt(e,t);if(n)return{id:n.apparition.id,position:n.position,tailEnd:n.tailEnd,magnitude:n.magnitude}}pushPhenomenaAt(e){const t=this.ufoElement.sighting;t!==this.sizeEstimatesFor&&(this.sizeEstimates.clear(),this.distanceHypotheses.clear(),this.sizeEstimatesFor=t);const n=t.timeline,i=this.ufoElement.canvasElement,r=this.ufoElement.frameShiftPx,a=this.projectionAt(e),o=new Map,c=new Map,l=new Set;for(const p of n.sourceIds){const v=n.getInterpolatedShapeAt(e,p);if(!v)continue;const m={...v,bounds:{...v.bounds,x:v.bounds.x+r.x,y:v.bounds.y+r.y}};o.set(p,m);const g=v.aim?this.sceneRenderer.screenPointOf(jn.directionOf(v.aim,this.directionScratch)):{ndcX:(m.bounds.x+m.bounds.width/2)/i.width*2-1,ndcY:-((m.bounds.y+m.bounds.height/2)/i.height*2-1)},S=g!==void 0&&Math.abs(g.ndcX)<=1&&Math.abs(g.ndcY)<=1,w=S?this.sceneRenderer.decorDistancesAt(g.ndcX,g.ndcY,p):{};l.add(p),(S||v.aim)&&l.delete(p);const _=v.angular?.widthDeg??a.pxToDeg(v.bounds.width),b=this.sizeEstimateOf(p);b.add(_,w);const E=Da.of(t,p);c.set(p,mn.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:E&&_>0?mt.distanceMAt(E.widthM,_):void 0,range:b.distanceRangeAt(_),crossing:w}))}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 w=c.get(m);w&&c.set(p,{distanceM:w.distanceM*.999,basis:w.basis});break}this.depths=c;const h=n.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)});const f=(Qt(t,e)?.rollDeg??0)+(Gt.of(t)?.offsetAt(e)??Gt.STILL).rollDeg;this.sceneRenderer.setPhenomena(u,{projection:a,canvasWidthPx:i.width,canvasHeightPx:i.height,scale:Math.max(1,this.sceneCanvas.height/Math.max(1,i.height)),starPoints:Vt.starPointsOf(t.instrument),rollRad:f*Math.PI/180})}setDistanceHypothesis(e,t){t===void 0||!(t>0)?this.distanceHypotheses.delete(e):this.distanceHypotheses.set(e,t),this.updateAstronomy(this.lastTimeMs)}depthOf(e){return this.depths.get(e)}sizeRangeOf(e){return this.sizeEstimateOf(e).sizeRange}distanceRangeAt(e,t){const n=this.ufoElement.sighting.timeline.getInterpolatedShapeAt(t,e);if(!n)return{};const i=n.angular?.widthDeg??this.projectionAt(t).pxToDeg(n.bounds.width);return this.sizeEstimateOf(e).distanceRangeAt(i)}sizeContradictory(e){return this.sizeEstimateOf(e).contradictory}updateMeteorShower(e,t){this.ensureMeteorSchedule(e),this.sceneRenderer.updateMeteors(t)}updateLightning(e,t,n){if(this.ensureLightningSchedule(e),this.sceneRenderer.updateLightning(t),n)return;const i=this.lastLightningT;if(this.lastLightningT=t,i===void 0||t<i||this.ufoElement.playbackState!=="playing")return;const r=this.lightningFlashes.filter(a=>a.t>i&&a.t<=t).pop();r&&Js(e,r.t).storm&&this.handleLightningFlash(r)}ensureLightningSchedule(e){const t=Js(e,0).precipitationIntensity,n=`${this.meteorInputsOf(e)}|${t}`;if(n===this.lightningScheduleFor)return;this.lightningScheduleFor=n;const i=e.event.time,r=e.event.place?.[0],a=i?.year!==void 0?Bo(i,r?.lng??0,e.event.utcOffsetHours):void 0,o=(e.event.durationSeconds??0)*1e3||e.timeline.duration||2e4,c=Math.round((a?.getTime()??0)/1e3)+Math.round((r?.lat??0)*1e3)+7;this.lightningFlashes=Wt.schedule({durationMs:o,seed:c,intensity:t}),this.sceneRenderer.setLightning(this.lightningFlashes)}ensureMeteorSchedule(e){const t=this.meteorInputsOf(e);t!==this.meteorScheduleFor&&(this.meteorScheduleFor=t,this.scheduleMeteors(e))}meteorInputsOf(e){const t=e.event.place?.[0],n=e.event.time;return JSON.stringify([t?.lat,t?.lng,n?.year,n?.month,n?.day,n?.hour,n?.minute,n?.second,e.event.utcOffsetHours,e.event.durationSeconds,e.timeline.duration])}scheduleMeteors(e){const t=e.event.place?.[0],n=e.event.time,i=t?.lat!==void 0&&t.lng!==void 0&&n?.year!==void 0?Bo(n,t.lng,e.event.utcOffsetHours):void 0;if(!i||t?.lat===void 0||t.lng===void 0){this.sceneRenderer.setMeteorShower([],0,0);return}const r={lat:t.lat,lng:t.lng,elevationM:0},a=(e.event.durationSeconds??0)*1e3||e.timeline.duration||2e4,o=Math.round(i.getTime()/1e3)+Math.round(t.lat*1e3),c=It.schedule({ratePerHour:It.observedRatePerHour(It.apexPosition(i,r).altitudeDeg),durationMs:a,velocityKmS:It.TYPICAL_VELOCITY_KM_S,seed:o}),l=oh.activeAt(i).map(u=>{const d=oh.radiantPosition(u.shower,i,r);return{entry:u,position:d,rate:oh.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=ks.schedule({ratePerHour:l.rate,durationMs:a,velocityKmS:l.entry.shower.velocityKmS,seed:o+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}meteorByRank(e){this.ensureMeteorSchedule(this.ufoElement.sighting);const t=[...this.sceneRenderer.meteorSchedule].filter(r=>r.t+r.durationMs<=this.ufoElement.seekableDuration).sort((r,a)=>a.brightness-r.brightness);if(t.length===0)return;const n=t[e%t.length],i=this.sceneRenderer.meteorMidpoint(n);if(i)return{t:Math.round(n.t+n.durationMs*.45),...i}}lensOpticsAt(e){const t=this.ufoElement.sighting,n=t.instrument,i=n.frame,r=Qt(t,e),a=r?.fNumber??n.fNumber;if(!i||a===void 0)return;const o=Vt.focalLengthMmFor(n,Vn.fovOf(t,e));if(o!==void 0)return{focalLengthMm:o,fNumber:a,focusDistance:r?.focusDistanceM??0,frameHeightMm:i.heightMm}}projectionAt(e){const t=this.ufoElement.sighting;return Hi.of(t.instrument,mt.CANVAS_HEIGHT_PX,Vn.fovOf(t,e))}sizeEstimateOf(e){let t=this.sizeEstimates.get(e);return t||(t=new rE,this.sizeEstimates.set(e,t)),t}}const Ep="rr0-scene";function xE(){zp(),customElements.get(Ep)||customElements.define(Ep,fd)}xE();export{Hv as $,wE as A,tt as B,ce as C,H0 as D,Ge as E,CE as F,AE as G,om as H,EE as I,TE as J,wa as K,qa as L,RE as M,io as N,xt as O,x2 as P,xs as Q,Oa as R,An as S,_E as T,en as U,Pe as V,Tn as W,bE as X,qs as Y,am as Z,DE as _,SE as a,gc as a0,jh as a1,Sc as a2,nn as a3,dm as a4,ed as a5,td as a6,je as a7,vs as a8,Xa as a9,ri as aa,qi as ab,yE as b,LE as c,Mc as d,IE as e,Xe as f,C as g,E0 as h,PE as i,NE as j,Fv as k,Ns as l,Qc as m,G1 as n,gt as o,Xt as p,yh as q,Mn as r,ju as s,Yi as t,Yv as u,e2 as v,ei as w,qn as x,lt as y,vt as z};
|
|
6072
|
+
`);let r=gi.cache.get(i);return r||(r=Promise.all(n.map(a=>gi.load(a.url))).then(a=>a.reduce((o,c)=>gi.concat(o,c))),gi.cache.set(i,r)),r}static parse(e){const t=e.byteLength/(4*Float32Array.BYTES_PER_ELEMENT),n=t*Float32Array.BYTES_PER_ELEMENT;return{count:t,ra:new Float32Array(e,0*n,t),dec:new Float32Array(e,1*n,t),mag:new Float32Array(e,2*n,t),ci:new Float32Array(e,3*n,t)}}static concat(e,t){const n=(i,r)=>{const a=new Float32Array(i.length+r.length);return a.set(i,0),a.set(r,i.length),a};return{count:e.count+t.count,ra:n(e.ra,t.ra),dec:n(e.dec,t.dec),mag:n(e.mag,t.mag),ci:n(e.ci,t.ci)}}}const Jw=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,jw=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,Qw=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,eE=20,tE=1;class nE{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(e){console.warn("WeatherAudio: Web Audio unavailable, weather sounds disabled:",e);return}}this.context.state==="suspended"&&this.context.resume()}setAmbient(e,t,n){if(this.requested={type:e,intensity:t,windSpeed:n},!this.context)return;this.paused&&(e="none",t=0,n=0);const i=e==="rain"||e==="hail"?e:"none";if(this.ambientVolume=i==="hail"?Math.min(1,t*1.3+.2):i==="rain"?t:0,i!==this.ambientKey){this.ambientKey=i;const a=++this.ambientToken;this.stopSource(this.ambientSource,this.ambientGain),this.ambientSource=void 0,this.ambientGain=void 0,i!=="none"&&this.startLoop(Jw,this.ambientVolume).then(o=>this.applyIfCurrent(o,a,()=>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(n/eE,1);const r=n>tE;if(r!==this.windActive){this.windActive=r;const a=++this.windToken;this.stopSource(this.windSource,this.windGain),this.windSource=void 0,this.windGain=void 0,r&&this.startLoop(jw,this.windVolume).then(o=>this.applyIfCurrent(o,a,()=>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(e){if(e===this.paused)return;this.paused=e;const{type:t,intensity:n,windSpeed:i}=this.requested;this.setAmbient(t,n,i)}playThunder(){!this.context||this.paused||this.playOneShot(Qw,.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(e,t,n,i){if(t!==n()){e?.source.stop();return}i(e)}async startLoop(e,t){const n=this.context;if(n)try{const i=await this.getBuffer(e),r=n.createBufferSource();r.buffer=i,r.loop=!0;const a=n.createGain();return a.gain.value=t,r.connect(a).connect(n.destination),r.start(),{source:r,gain:a}}catch(i){console.warn("Weather ambient sound failed to load, staying silent:",i);return}}async playOneShot(e,t){const n=this.context;if(n)try{const i=await this.getBuffer(e),r=n.createBufferSource();r.buffer=i;const a=n.createGain();a.gain.value=t,r.connect(a).connect(n.destination),r.start()}catch(i){console.warn("Thunder sound failed to load:",i)}}async getBuffer(e){const t=this.context;if(!t)throw new Error("WeatherAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(i=>{if(!i.ok)throw new Error(`Audio fetch failed (${i.status}): ${e}`);return i.arrayBuffer()}).then(i=>t.decodeAudioData(i)),this.buffers.set(e,n)),n}stopSource(e,t){try{e?.stop()}catch{}e?.disconnect(),t?.disconnect()}}class ki{constructor(e){this.elements=e;const{eccentricity:t,perihelionAu:n}=e,[i,r]=this.perifocalAxes(),a=Math.sqrt(ki.SUN_GM_AU3_PER_DAY2*(1+t)/n);this.perihelionPosition=this.scale(i,n),this.perihelionVelocity=this.scale(r,a),this.inverseSemiMajorAxis=(1-t)/n}static SUN_GM_AU3_PER_DAY2=.0002959122082855911;static MAX_ITERATIONS=200;perihelionPosition;perihelionVelocity;inverseSemiMajorAxis;positionAt(e){const t=e-this.elements.perihelionJd,n=this.universalAnomaly(t),i=this.inverseSemiMajorAxis*n*n,r=this.elements.perihelionAu,a=1-n*n/r*ki.stumpffC(i),o=t-n*n*n/Math.sqrt(ki.SUN_GM_AU3_PER_DAY2)*ki.stumpffS(i);return{x:a*this.perihelionPosition.x+o*this.perihelionVelocity.x,y:a*this.perihelionPosition.y+o*this.perihelionVelocity.y,z:a*this.perihelionPosition.z+o*this.perihelionVelocity.z}}heliocentricDistanceAt(e){const t=this.positionAt(e);return Math.hypot(t.x,t.y,t.z)}universalAnomaly(e){if(e===0)return 0;const t=Math.sign(e),n=Math.sqrt(ki.SUN_GM_AU3_PER_DAY2)*Math.abs(e),i=o=>{const c=this.inverseSemiMajorAxis*o*o,l=this.elements.perihelionAu;return(1-this.inverseSemiMajorAxis*l)*o*o*o*ki.stumpffS(c)+l*o};let r=Math.max(1,n/this.elements.perihelionAu);for(;i(r)<n;)r*=2;let a=0;for(let o=0;o<ki.MAX_ITERATIONS&&r-a>1e-13*Math.max(1,r);o++){const c=(a+r)/2;i(c)<n?a=c:r=c}return t*(a+r)/2}perifocalAxes(){const e=this.elements.ascendingNodeDeg*Math.PI/180,t=this.elements.argumentOfPerihelionDeg*Math.PI/180,n=this.elements.inclinationDeg*Math.PI/180,i=Math.cos(e),r=Math.sin(e),a=Math.cos(t),o=Math.sin(t),c=Math.cos(n),l=Math.sin(n);return[{x:i*a-r*o*c,y:r*a+i*o*c,z:o*l},{x:-i*o-r*a*c,y:-r*o+i*a*c,z:a*l}]}scale(e,t){return{x:e.x*t,y:e.y*t,z:e.z*t}}static stumpffC(e){if(Math.abs(e)<1e-6)return 1/2-e/24+e*e/720;if(e>0)return(1-Math.cos(Math.sqrt(e)))/e;const t=Math.sqrt(-e);return(Math.cosh(t)-1)/-e}static stumpffS(e){if(Math.abs(e)<1e-6)return 1/6-e/120+e*e/5040;if(e>0){const n=Math.sqrt(e);return(n-Math.sin(n))/(n*n*n)}const t=Math.sqrt(-e);return(Math.sinh(t)-t)/(t*t*t)}}const og=[{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 iE{static WINDOW_DAYS=200;static TWILIGHT_ELONGATION_DEG=15;static LIGHT_SPEED_AU_PER_DAY=173.144632674;static orbits=new Map;static aroundDate(e){const t=this.julianDayOf(e);return og.filter(n=>Math.abs(t-n.orbit.perihelionJd)<=this.WINDOW_DAYS)}static brightestAt(e,t){return this.aroundDate(e).map(n=>this.appearanceOf(n,e,t)).sort((n,i)=>n.magnitude-i.magnitude)[0]}static appearanceOf(e,t,n){const i=zt(t),r=this.earthPositionAt(i),a=this.apparentPositionOf(e,2451545+i.tt,r),o=this.subtract(a,r),c=this.length(a),l=this.length(o),h=this.tailEndAt(e,a,r,c,i,t,n),u=this.horizontalOf(o,i,t,n);return{apparition:e,position:u,...h,heliocentricDistanceAu:c,earthDistanceAu:l,elongationDeg:this.angleBetween(o,this.subtract({x:0,y:0,z:0},r)),magnitude:this.magnitudeAt(e,c,l)}}static magnitudeAt(e,t,n){const i=e.absoluteMagnitude+5*Math.log10(n)+2.5*e.activityExponent*Math.log10(t);return Math.max(i,e.peakMagnitude)}static tailEndAt(e,t,n,i,r,a,o){if(e.tailLengthAu===void 0)return{};const c=1+e.tailLengthAu/i,l=this.subtract({x:t.x*c,y:t.y*c,z:t.z*c},n),h=this.subtract(t,n);return{tailEnd:this.horizontalOf(l,r,a,o),tailLengthDeg:this.angleBetween(h,l)}}static apparentPositionOf(e,t,n){const i=this.orbitOf(e);let r=i.positionAt(t);for(let a=0;a<2;a++){const o=this.length(this.subtract(r,n))/this.LIGHT_SPEED_AU_PER_DAY;r=i.positionAt(t-o)}return r}static horizontalOf(e,t,n,i){const r=cc(nb(),new Mt(e.x,e.y,e.z,t)),a=cc(ib(t),r),o=NS(t,new dd(i.lat,i.lng,i.elevationM)),c=new Mt(a.x-o.x,a.y-o.y,a.z-o.z,t),l=qm(c);return Xc(l.ra,l.dec,n,i)}static earthPositionAt(e){return cc(tb(),gs(Se.Earth,e))}static julianDayOf(e){return 2451545+zt(e).tt}static orbitOf(e){const t=this.orbits.get(e.id);if(t)return t;const n=new ki(e.orbit);return this.orbits.set(e.id,n),n}static subtract(e,t){return{x:e.x-t.x,y:e.y-t.y,z:e.z-t.z}}static length(e){return Math.hypot(e.x,e.y,e.z)}static angleBetween(e,t){const n=(e.x*t.x+e.y*t.y+e.z*t.z)/(this.length(e)*this.length(t)||1);return Math.acos(Math.min(1,Math.max(-1,n)))*180/Math.PI}}const sE=[{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}],Lc=6.5;class oh{static activeAt(e){return sE.flatMap(t=>{const n=this.nearness(t,e);return n<=0?[]:[{shower:t,zhr:t.peakZhr*n,nearness:n}]})}static nearness(e,t){const n=this.dayOfYear(t),i=this.dayOfYear(this.asDate(e.start)),r=this.dayOfYear(this.asDate(e.peak)),a=this.dayOfYear(this.asDate(e.end)),o=this.wrappedDelta(n,r),c=this.wrappedDelta(r,i),l=this.wrappedDelta(a,r);return o<0?o<-c?0:1+o/c:o>0?o>l?0:1-o/l:1}static observedRatePerHour(e,t,n,i=Lc){if(t<=0)return 0;const r=Lc-i;return e*Math.sin(t*Math.PI/180)/Math.pow(n,r)}static radiantPosition(e,t,n){return Xc(e.radiantRaHours,e.radiantDecDeg,t,n)}static dayOfYear(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return Math.floor((Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())-t)/864e5)+1}static asDate(e){return new Date(Date.UTC(2001,e.month-1,e.day))}static wrappedDelta(e,t){const n=e-t;return n>182?n-365:n<-182?n+365:n}}class It{static QUIET_RATE_PER_HOUR=2;static APEX_RATE_PER_HOUR=8;static POPULATION_INDEX=3;static apexPosition(e,t){const n=zt(e),i=new hd(0,IS(e).elon-90,1),r=cc(sb(n),Xm(i,n)),a=qm(r);return Xc(a.ra,a.dec,e,t)}static observedRatePerHour(e,t=Lc){const n=It.APEX_RATE_PER_HOUR*Math.max(0,Math.sin(e*Math.PI/180)),i=Lc-t;return(It.QUIET_RATE_PER_HOUR+n)/Math.pow(It.POPULATION_INDEX,i)}static schedule(e){const t=new qc(e.seed^1542469173);return ks.schedule(e).map(n=>{const i=It.toCartesian({altitudeDeg:Math.asin(t.next())*180/Math.PI,azimuthDeg:t.between(0,360)}),r=n.fromRadiantDeg*Math.PI/180,a=It.turnAround(i,t.between(0,360)),o={x:i.x*Math.cos(r)+a.x*Math.sin(r),y:i.y*Math.cos(r)+a.y*Math.sin(r),z:i.z*Math.cos(r)+a.z*Math.sin(r)};return{...n,radiant:It.toHorizontal(o),bearingDeg:It.bearingFrom(o,i)}})}static turnAround(e,t){const[n,i]=It.basisAround(e),r=t*Math.PI/180;return{x:n.x*Math.cos(r)+i.x*Math.sin(r),y:n.y*Math.cos(r)+i.y*Math.sin(r),z:n.z*Math.cos(r)+i.z*Math.sin(r)}}static bearingFrom(e,t){const[n,i]=It.basisAround(e),r=e.x*t.x+e.y*t.y+e.z*t.z,a=It.normalise({x:t.x-e.x*r,y:t.y-e.y*r,z:t.z-e.z*r});return(Math.atan2(a.x*i.x+a.y*i.y+a.z*i.z,a.x*n.x+a.y*n.y+a.z*n.z)*180/Math.PI%360+360)%360}static basisAround(e){const t=Math.abs(e.y)<.9?{x:0,y:1,z:0}:{x:1,y:0,z:0},n=It.normalise(It.cross(e,t));return[n,It.normalise(It.cross(e,n))]}static toHorizontal(e){const t=Math.hypot(e.x,e.y,e.z)||1;return{altitudeDeg:Math.asin(Math.min(1,Math.max(-1,e.y/t)))*180/Math.PI,azimuthDeg:(Math.atan2(e.x,-e.z)*180/Math.PI%360+360)%360}}static appearanceOf(e){const t=It.toCartesian(e.radiant??{altitudeDeg:90,azimuthDeg:0}),n=It.turnAround(t,e.bearingDeg),i=e.fromRadiantDeg*Math.PI/180;return It.toHorizontal({x:t.x*Math.cos(i)+n.x*Math.sin(i),y:t.y*Math.cos(i)+n.y*Math.sin(i),z:t.z*Math.cos(i)+n.z*Math.sin(i)})}static toCartesian(e){const t=e.altitudeDeg*Math.PI/180,n=e.azimuthDeg*Math.PI/180,i=Math.cos(t);return{x:i*Math.sin(n),y:Math.sin(t),z:-i*Math.cos(n)}}static cross(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}static normalise(e){const t=Math.hypot(e.x,e.y,e.z)||1;return{x:e.x/t,y:e.y/t,z:e.z/t}}static TYPICAL_VELOCITY_KM_S=40}const Sp="https://ufoathome.org/tle/index.json";class hn{static MAX_ELEMENT_AGE_DAYS=7;static DAY_MS=864e5;fetchImpl;indexUrls;index;files=new Map;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??hn.defaultIndexUrls()}static defaultIndexUrls(){const e=[];return typeof location<"u"&&/^https?:$/.test(location.protocol)&&e.push(new URL("/tle/index.json",location.href).href),e.includes(Sp)||e.push(Sp),e}static FIRST_SNAPSHOT="2021-02-22";async covers(e){const t=Date.parse(`${hn.FIRST_SNAPSHOT}T00:00:00Z`)-hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS;if(e.getTime()<t)return!1;const n=await this.loadIndex();return n?Object.values(n.index.kinds).some(i=>e.getTime()>=Date.parse(i.from)-hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS&&e.getTime()<=Date.parse(i.to)+hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS):!1}async at(e){const t=await this.loadIndex();if(!t)return;const{index:n,base:i}=t,r=[],a=[];for(const o of Object.keys(n.kinds)){const c=await this.kindAt(o,e,n,i);r.push(...c),a.push(this.coverageOf(o,e,n,c.length>0))}return{objects:r,coverage:a,credit:n.credit,creditUrl:n.source}}async kindAt(e,t,n,i){const r=t.getTime(),a=n.binDays*hn.DAY_MS,o=Math.floor(r/a),c=r-o*a<a/2?o-1:o+1,l=new Set(n.kinds[e].bins),h=[o,c].map(v=>new Date(v*a).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-${e}.json`,i).href),...h.map(v=>this.binary(new URL(`${e}/${v}.bin`,i).href))]),f=new Map;for(const v of d)for(const m of hn.decode(v,n.recordBytes)){const g=f.get(m.norad);(!g||Math.abs(m.epochMs-r)<Math.abs(g.epochMs-r))&&f.set(m.norad,m)}const p=[];for(const v of f.values()){const m=Math.abs(v.epochMs-r)/hn.DAY_MS;if(m>hn.MAX_ELEMENT_AGE_DAYS)continue;const g=u[v.norad]??{name:String(v.norad)};g.launch&&Date.parse(`${g.launch}T00:00:00Z`)>r||p.push({norad:v.norad,name:g.name,kind:e,launch:g.launch,stdMag:g.stdMag,elements:v,ageDays:m})}return p}coverageOf(e,t,n,i){const{from:r,to:a}=n.kinds[e],o=t.getTime(),c=hn.MAX_ELEMENT_AGE_DAYS*hn.DAY_MS,l=i?"covered":o<Date.parse(r)-c?"before":o>Date.parse(a)+c?"after":"gap";return{kind:e,status:l,from:r,to:a}}static decode(e,t){const n=new DataView(e),i=[];for(let r=0;r+t<=e.byteLength;r+=t)i.push({norad:n.getUint32(r,!0),epochMs:n.getFloat64(r+4,!0),bstar:n.getFloat32(r+12,!0),inclinationDeg:n.getFloat32(r+16,!0),raanDeg:n.getFloat32(r+20,!0),eccentricity:n.getFloat32(r+24,!0),argOfPerigeeDeg:n.getFloat32(r+28,!0),meanAnomalyDeg:n.getFloat32(r+32,!0),meanMotion:n.getFloat64(r+36,!0)});return i}loadIndex(){return this.index??=(async()=>{for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;return{index:await t.json(),base:e}}catch{}})(),this.index}json(e){return this.cached(e,async t=>t.json())}binary(e){return this.cached(e,async t=>t.arrayBuffer())}cached(e,t){let n=this.files.get(e);return n||(n=this.fetchImpl(e).then(i=>{if(!i.ok)throw new Error(`${e}: ${i.status}`);return t(i)}),n.catch(()=>this.files.delete(e)),this.files.set(e,n)),n}}class rE{lowerM;upperM;add(e,t){if(!(e<=0)){if(t.behindM!==void 0){const n=mt.sizeMAt(t.behindM,e);this.lowerM=this.lowerM===void 0?n:Math.max(this.lowerM,n)}if(t.inFrontM!==void 0){const n=mt.sizeMAt(t.inFrontM,e);this.upperM=this.upperM===void 0?n:Math.min(this.upperM,n)}}}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(e){return e<=0?{}:{minM:this.lowerM===void 0?void 0:mt.distanceMAt(this.lowerM,e),maxM:this.upperM===void 0?void 0:mt.distanceMAt(this.upperM,e)}}clear(){this.lowerM=void 0,this.upperM=void 0}}class zs{static DEG_PER_SECOND=360/86164.0905;static degOver(e){return Math.max(0,e)*zs.DEG_PER_SECOND}static instants(e,t){if(!(t>0))return 1;const n=zs.degOver(e)/t;return n<1?1:Math.min(zs.MAX_INSTANTS,Math.max(2,Math.ceil(n)))}static MAX_INSTANTS=64}class gn{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 zs.DEG_PER_SECOND*3600}static graspOf(e,t={}){const n=t.exposureSeconds??e.exposureSeconds,i=t.fNumber??e.fNumber;if(n===void 0||i===void 0||!(n>0)||!(i>0))return gn.EYE;const r=t.focalLengthMm??e.frame?.focalLengthMm??gn.UNKNOWN_CAMERA_FOCAL_MM,a=r/i,o=gn.resolutionArcsec(e,r,a);return{apertureMm:a,exposureSeconds:Math.min(n,gn.trailLimitedSeconds(o)),resolutionArcsec:o}}static resolutionArcsec(e,t,n){const r=(e.detailUm??gn.UNKNOWN_CAMERA_DETAIL_UM)/1e3/t*gn.ARCSEC_PER_RADIAN,a=1.22*gn.WAVELENGTH_M/(n/1e3)*gn.ARCSEC_PER_RADIAN;return Math.max(r,a)}static trailLimitedSeconds(e){return e/gn.skyDriftArcsecPerSecond}static gainOverEye(e,t={}){const n=gn.graspOf(e,t),i=gn.EYE,r=(n.apertureMm/i.apertureMm)**2,a=n.exposureSeconds/i.exposureSeconds,o=(i.resolutionArcsec/n.resolutionArcsec)**2;return 1.25*Math.log10(r*a*o)}static gainFor(e,t){const n=t.fieldOfViewDeg===void 0?void 0:Vt.focalLengthMmFor(e,t.fieldOfViewDeg);return gn.gainOverEye(e,{fNumber:t.fNumber,focalLengthMm:n,exposureSeconds:t.exposureSeconds})}}const bp=111320,pa=Math.PI/180,aE=1.02,oE=1;class Da{static of(e,t){const n=Da.sightings(e,t);if(n.length<2)return;const i=Da.baseline(n);if(!i)return;const{near:r,far:a,closedM:o}=i,c=Math.tan(a.widthDeg/2*pa)===0?0:Math.tan(r.widthDeg/2*pa)/Math.tan(a.widthDeg/2*pa);if(c<aE)return;const l=o/(c-1),h=mt.sizeMAt(l,r.widthDeg),u=n.map(d=>({t:d.t,m:mt.distanceMAt(h,d.widthDeg)}));return{widthM:h,distanceM:u,nearestM:Math.min(...u.map(d=>d.m)),fromT:a.t,toT:r.t,closedM:o}}static sightings(e,t){return e.timeline.allKeyframes.flatMap(n=>{const i=n.shapes.find(o=>o.sourceId===t)?.shape,r=i?.angular?.widthDeg,a=Qt(e,n.t);return r===void 0||r<=0||a?.lat===void 0||a.lng===void 0?[]:[{t:n.t,widthDeg:r,lat:a.lat,lng:a.lng,sightAzimuthDeg:i?.aim?.azimuthDeg??a.headingDeg}]}).sort((n,i)=>n.t-i.t)}static baseline(e){let t;for(const n of e)for(const i of e){if(n.t>=i.t)continue;const r=Da.closedAlongSight(n,i),[a,o,c]=r>=0?[i,n,r]:[n,i,-r];c<oE||a.widthDeg<=o.widthDeg||(!t||c>t.closedM)&&(t={near:a,far:o,closedM:c})}return t}static closedAlongSight(e,t){const n=(t.lat-e.lat)*bp,i=(t.lng-e.lng)*bp*Math.cos(e.lat*pa),r=(e.sightAzimuthDeg??0)*pa;return n*Math.cos(r)+i*Math.sin(r)}}class mn{static CONVENTIONAL_M=5;static NEAREST_M=.2;static MARGIN=1.1;static resolve(e){if(e.statedM!==void 0&&e.statedM>0)return{distanceM:mn.atLeastNearest(e.statedM),basis:"stated"};if(e.hypothesisM!==void 0&&e.hypothesisM>0)return{distanceM:mn.atLeastNearest(e.hypothesisM),basis:"hypothesis"};if(e.derivedM!==void 0&&e.derivedM>0)return{distanceM:mn.atLeastNearest(e.derivedM),basis:"derived"};const t=mn.largest(e.range?.minM,e.crossing?.behindM),n=mn.smallest(e.range?.maxM,e.crossing?.inFrontM),i=t===void 0?void 0:t*mn.MARGIN,r=n===void 0?void 0:n/mn.MARGIN;return i!==void 0&&r!==void 0?{distanceM:mn.atLeastNearest(i<=r?Math.sqrt(i*r):i),basis:"bounded"}:i!==void 0?{distanceM:mn.atLeastNearest(i),basis:"bounded"}:r!==void 0&&r<mn.CONVENTIONAL_M?{distanceM:mn.atLeastNearest(r),basis:"bounded"}:{distanceM:mn.CONVENTIONAL_M,basis:"conventional"}}static atLeastNearest(e){return Math.max(mn.NEAREST_M,e)}static largest(...e){const t=e.filter(n=>n!==void 0&&n>0);return t.length===0?void 0:Math.max(...t)}static smallest(...e){const t=e.filter(n=>n!==void 0&&n>0);return t.length===0?void 0:Math.min(...t)}}zp();const cE={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"}},lE=["en","fr"],hE={en:"{name} — mag {mag}, {alt}° above the horizon",fr:"{name} — mag {mag}, {alt}° au-dessus de l'horizon"},uE={en:"{name} — satellite, mag {mag}, {height} km up",fr:"{name} — satellite, mag {mag}, à {height} km d'altitude"},dE="satellites-change",fE={en:"{name} — mag {mag}, {alt}° below the horizontal",fr:"{name} — mag {mag}, {alt}° sous l'horizontale"},wp="comet:",pE={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},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"},witness:{en:"Witness",fr:"Témoin"},aircraft:{en:"Aircraft",fr:"Aéronef"},entity:{en:"Being",fr:"Être"}},mE=new URL(""+new URL("stars-mag7.5-B43R6Wvg.bin",import.meta.url).href,import.meta.url).href,gE=new URL(""+new URL("stars-mag7.5-9-BLV2tFmZ.bin",import.meta.url).href,import.meta.url).href,vE=-18,ME={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},ch={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class fd extends HTMLElement{static get observedAttributes(){return["src","star-catalog-src","deep-star-catalog-src","show-compass","max-pixel-ratio",Cr,Pr]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;distanceHypotheses=new Map;depths=new Map;directionScratch=new C;meteorScheduleFor;lightningScheduleFor;lightningFlashes=[];lastLightningT;lastTimeMs=0;lastSkyKey;starCatalog;starCatalogRequest=0;static tleArchive=new hn;satellitesFor;satelliteRequest=0;satelliteStatus="none";satellites;satellitePassesMemo;starCatalogDepth=0;weatherAudio=new nE;animateWhilePausedValue=!1;set animateWhilePaused(e){e!==this.animateWhilePausedValue&&(this.animateWhilePausedValue=e,this.syncAnimationsToPlayback())}get animateWhilePaused(){return this.animateWhilePausedValue}thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=e=>{this.sceneRenderer.setCompassHovered(!0);const t=this.ufoElement.canvasElement,n=t.getBoundingClientRect();if(n.width===0||n.height===0)return;const i=(e.clientX-n.left)/n.width*t.width,r=(e.clientY-n.top)/n.height*t.height;if(this.ufoElement.hasVisibleShapeAt(i,r)){this.hoverTooltip.hidden=!0;return}const a=(e.clientX-n.left)/n.width*2-1,o=-((e.clientY-n.top)/n.height*2-1),c=Uu(fc.preferencesFor(this),lE),l=this.sceneRenderer.pickBodyAt(a,o);if(l){this.showHoverTooltip(e,this.bodyName(l,c));return}const h=this.sceneRenderer.pickDecorAt(a,o),u=h?this.ufoElement.sighting.decor.find(p=>p.id===h):void 0;if(u){this.showHoverTooltip(e,this.said.read(u.title)||pE[u.kind][c]);return}const d=this.sceneRenderer.pickSatelliteAt(a,o);if(d){this.showHoverTooltip(e,uE[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(a,o);if(f){const p=f.star.mag,v=f.altitudeDeg,m=(v<0?fE:hE)[c];this.showHoverTooltip(e,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(e,t){const n=e.startsWith(wp)?e.slice(wp.length):void 0;return(n?og.find(r=>r.id===n):void 0)?.name[t]??cE[e]?.[t]??e}showHoverTooltip(e,t){this.hoverTooltip.textContent=t,this.hoverTooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${e.clientX-n.left+12}px`,this.hoverTooltip.style.top=`${e.clientY-n.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash(e){clearTimeout(this.thunderTimeoutId),this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),Wt.thunderDelayMs(e))}handleFirstInteraction=()=>{this.removeEventListener("pointerdown",this.handleFirstInteraction,!0),this.removeEventListener("keydown",this.handleFirstInteraction,!0),this.weatherAudio.resume(),this.setWeather(Js(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=e=>{this.lastTimeMs=e.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.ufoElement.playbackState==="playing"&&this.sceneRenderer.frame(performance.now())};syncAnimationsToPlayback(){const e=this.ufoElement.playbackState==="playing",t=e||this.animateWhilePaused;this.sceneRenderer.setAnimationsRunning(t,e),this.weatherAudio.setPaused(!t),t||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${Mg}</style>${vg}`,this.shadow.appendChild(e.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 Hn(this.sceneCanvas),this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(uh),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.paintsShapes=!1,this.forwardPlayerAttributes(),this.ufoElement.addEventListener("lookat",t=>this.lookToward(t.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.sceneRenderer.onMapSubjectBounds=t=>this.ufoElement.setMapSubjectBounds(t),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.addEventListener("referenceview",t=>this.applyReferenceView(t.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 hs(fc.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 e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose(),queueMicrotask(()=>{this.isConnected||this.sceneRenderer.releaseContext()})}attributeChangedCallback(e,t,n){if(e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),(e==="star-catalog-src"||e==="deep-star-catalog-src")&&n!==t&&this.isConnected&&this.loadStars(),e==="show-compass"&&n!==t&&this.sceneRenderer.setShowCompass(this.hasAttribute("show-compass")),e==="max-pixel-ratio"&&n!==t){const i=Number(n);this.sceneRenderer.setMaxPixelRatio(Number.isFinite(i)&&i>0?i:Math.min(window.devicePixelRatio||1,2))}(e===Cr||e===Pr)&&n!==t&&this.forwardPlayerAttributes()}forwardPlayerAttributes(){for(const e of[Cr,Pr])this.ufoElement.toggleAttribute(e,this.hasAttribute(e))}setCompassForced(e){this.sceneRenderer.setCompassForced(e)}lookToward(e){const t=Qt(this.ufoElement.sighting,this.lastTimeMs);if(e.kind==="witness"||t?.lat===void 0||t.lng===void 0||t.headingDeg===void 0){this.setLookOffset(0,0);return}const{x:n,z:i}=rn(e.lat,e.lng,t.lat,t.lng);if(Math.hypot(n,i)<1)return this.setLookOffset(0,0);const r=(Math.atan2(n,-i)*180/Math.PI+360)%360;this.setLookOffset(((r-t.headingDeg)%360+540)%360-180,-t.pitchDeg)}setLookOffset(e,t){this.sceneRenderer.setLookOffset(e,t),this.ufoElement.setLookOffset(e,t),this.updateAstronomy(this.lastTimeMs)}setIndoorLook(e,t){this.sceneRenderer.setIndoorLook(e,t)}setCloudRendering(e){this.sceneRenderer.setCloudRendering(e)}setWeather(e){this.sceneRenderer.setWeather(e),this.weatherAudio.setAmbient(e.precipitationType,e.precipitationIntensity,e.windSpeed)}pickCloudAt(e,t){return this.sceneRenderer.pickCloudAt(e,t)}cloudDirectionAt(e,t){return this.sceneRenderer.cloudDirectionAt(e,t)}pickDecorAt(e,t){return this.sceneRenderer.pickDecorAt(e,t)}resumeWeatherAudio(){this.weatherAudio.resume()}async loadFromSrc(e){this.sightingData=await Rp.json(e)}get sightingData(){return this.ufoElement.sightingData}set sightingData(e){this.ufoElement.sightingData=e,this.applyFrameFormat(),this.lastTimeMs=0,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(0)}referenceAspect(e){return this.sceneRenderer.referenceAspect(e)}screenPointOf(e){return this.sceneRenderer.screenPointOf(e)}directionAt(e,t){return this.sceneRenderer.directionAt(e,t)}referenceFailedToLoad(e){return this.sceneRenderer.referenceFailedToLoad(e)}applyReferenceView(e){this.sceneRenderer.setReferencesShown(e.shown);for(const t of this.ufoElement.sighting.references)this.sceneRenderer.setReferenceView(t.id,{opacity:e.opacity})}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}setTerrainProviders(e){this.sceneRenderer.setTerrainProviders(e)}setDecorModelProvider(e){this.sceneRenderer.setDecorModelProvider(e)}get decorModelCredits(){return this.sceneRenderer.currentDecorModelCredits}applyFrameFormat(){const e=this.ufoElement.sighting.instrument,t=mt.CANVAS_HEIGHT_PX,n=Vt.frameWidthPx(e,t);this.frameElement.style.setProperty("--frame-aspect",`${n} / ${t}`)}resizeToStage(){const e=this.frameElement.getBoundingClientRect(),t=Math.max(1,Math.round(e.width)),n=Math.max(1,Math.round(e.height));this.sceneCanvas.width=t,this.sceneCanvas.height=n,this.sceneRenderer.resize(t,n)}async loadStars(){const e=[{magnitudeLimit:rh,url:this.getAttribute("star-catalog-src")??mE},{magnitudeLimit:ah,url:this.getAttribute("deep-star-catalog-src")??gE}],t=this.instrumentReach(),n=++this.starCatalogRequest;this.starCatalogDepth=t>rh?ah:rh;const i=await gi.upTo(e,t);n===this.starCatalogRequest&&(this.starCatalog=i,this.sceneRenderer.compileNextFrameOffThread(),this.updateAstronomy(this.lastTimeMs))}ensureStarsDeepEnough(){!this.starCatalog||this.starCatalogDepth>=ah||this.instrumentReach()<=this.starCatalogDepth||this.loadStars()}instrumentReach(){const e=this.ufoElement.sighting,t=gn.gainFor(e.instrument,{fNumber:Qt(e,0)?.fNumber,fieldOfViewDeg:Vn.fovOf(e,0),exposureSeconds:e.exposure});return hu(vE,t)}updateAstronomy(e){this.ensureStarsDeepEnough(),this.applySceneAt(e);const t=Qn.windowEndingAt(e,this.exposureSeconds()),n=t.seconds,i=this.degreesPerPixelAt(e),r=zs.instants(n,i),a=Math.max(r,this.ufoElement.exposureTimes(e).length,Qn.instants(this.ufoElement.sighting.decor,Qt(this.ufoElement.sighting,e)?.elevationM??0,t.fromMs,n,i));if(a<=1){this.sceneRenderer.setExposure(1);return}this.sceneRenderer.setExposure(a,o=>this.applySceneAt(t.fromMs+t.ms*o/(a-1),{sky:Math.floor(o*r/a)!==Math.floor((o-1)*r/a),stepMs:t.ms/a}))}exposureSeconds(){return this.ufoElement.sighting.exposure??0}degreesPerPixelAt(e){const t=this.sceneCanvas.height;return t<=0?0:Vn.fovOf(this.ufoElement.sighting,e)/t}applySceneAt(e,t){const n=this.ufoElement.sighting;this.setWeather(Js(n,e)),this.sceneRenderer.setInstrument(n.instrument),this.updateMeteorShower(n,e),this.updateLightning(n,e,t!==void 0),this.sceneRenderer.setDecor(n.decor),this.sceneRenderer.setReferences(n.references);const i=Qt(n,e),r=Qt(n,0),a=Js(n,0),o=Object.fromEntries(hc(Js(n,e)).map(w=>[w.id,wd(e,n.weatherTrack,a,r,i,w.id)]));this.sceneRenderer.setCloudOffset(wd(e,n.weatherTrack,a,r,i),o),this.sceneRenderer.setObserverPose(i??ch),this.sceneRenderer.setLensOptics(this.lensOpticsAt(e)),this.sceneRenderer.setInstrumentGain(gn.gainFor(n.instrument,{fNumber:i?.fNumber,fieldOfViewDeg:Vn.fovOf(n,e),exposureSeconds:n.exposure})),this.sceneRenderer.setGait(Gt.of(n)?.offsetAt(e)??Gt.STILL),this.sceneRenderer.updateDecorAnchoring(Qt(n,0),i,e),this.sceneRenderer.updateDecorLitState(e,t?.stepMs??0),this.sceneRenderer.setTerrainOrigin(i?.lat,i?.lng),this.pushPhenomenaAt(e);const c=i?.lat??ch.lat,l=i?.lng??ch.lng,h=Bo(n.event.time??{},l,n.event.utcOffsetHours),u={lat:c,lng:l,elevationM:i?.elevationM??0};if(this.pushSatellitesAt(h,e,u),t&&!t.sky)return;if(!h){this.sceneRenderer.setAstronomy(ME);return}const d=new Date(h.getTime()+e),f=Math.max(1,Math.round(.25*this.degreesPerPixelAt(e)/zs.DEG_PER_SECOND*1e3)),p=Math.max(1e-8,this.degreesPerPixelAt(e)*.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={...Bl("Sun",d,u),magnitude:Hl("Sun",d)},g={...Bl("Moon",d,u),phase:ab(d),magnitude:Hl("Moon",d)},S=rb.map(w=>({body:w,position:Bl(w,d,u),magnitude:Hl(w,d)}));this.sceneRenderer.setAstronomy({sun:m,moon:g,planets:S,comet:this.cometAt(d,u),stars:this.starCatalog?{catalog:this.starCatalog,date:d,observer:u}:void 0,frame:{date:d,observer:u}}),this.ufoElement.setSunAltitude(m.altitudeDeg)}pushSatellitesAt(e,t,n){if(this.ensureSatellites(e),!e||!this.satellites){this.sceneRenderer.setSatellites([]);return}const i=new Date(e.getTime()+t),r=[];for(const a of this.satellites.passes.positionsAt(i,n,-1))a.magnitude!==void 0&&r.push({norad:a.object.norad,name:a.object.name,position:{altitudeDeg:a.altitudeDeg,azimuthDeg:a.azimuthDeg},magnitude:a.magnitude,heightKm:a.heightKm});this.sceneRenderer.setSatellites(r)}ensureSatellites(e){const t=e?String(e.getTime()):"";if(t===this.satellitesFor)return;this.satellitesFor=t,this.satellites=void 0,this.satellitePassesMemo=void 0;const n=++this.satelliteRequest;if(!e){this.satelliteStatus="none";return}this.satelliteStatus="loading";const i=a=>{n===this.satelliteRequest&&(this.satelliteStatus=a,this.dispatchEvent(new CustomEvent(dE)))},r=fd.tleArchive;(async()=>{if(!await r.covers(e))return i("outside");const[a,o]=await Promise.all([r.at(e),lc(()=>import("./SatellitePasses-Pfro2-0Z.js"),[],import.meta.url)]);if(n===this.satelliteRequest){if(!a)return i("unavailable");this.satellites={snapshot:a,passes:new o.SatellitePasses(a.objects)},i("ready"),this.updateAstronomy(this.lastTimeMs)}})().catch(()=>i("unavailable"))}get satelliteState(){const e=this.satellites?.snapshot;return{status:this.satelliteStatus,coverage:e?.coverage,credit:e?.credit,creditUrl:e?.creditUrl}}satellitePassesDuring(e){const t=this.satellites,n=this.ufoElement.sighting,i=Qt(n,0),r=n.event.place?.[0],a=i?.lat??r?.lat,o=i?.lng??r?.lng;if(!t||a===void 0||o===void 0)return[];const c=Bo(n.event.time??{},o,n.event.utcOffsetHours);if(!c)return[];const l=Math.min(Math.max(e,0),4*36e5),h={lat:a,lng:o,elevationM:i?.elevationM??0},u=JSON.stringify([this.satellitesFor,c.getTime(),a,o,h.elevationM,l]);if(this.satellitePassesMemo?.key===u)return this.satellitePassesMemo.passes;const d=Math.max(10,Math.ceil(l/1e3/600)),f=t.passes.passesDuring(c,new Date(c.getTime()+l),h,d);return this.satellitePassesMemo={key:u,passes:f},f}cometAt(e,t){const n=iE.brightestAt(e,t);if(n)return{id:n.apparition.id,position:n.position,tailEnd:n.tailEnd,magnitude:n.magnitude}}pushPhenomenaAt(e){const t=this.ufoElement.sighting;t!==this.sizeEstimatesFor&&(this.sizeEstimates.clear(),this.distanceHypotheses.clear(),this.sizeEstimatesFor=t);const n=t.timeline,i=this.ufoElement.canvasElement,r=this.ufoElement.frameShiftPx,a=this.projectionAt(e),o=new Map,c=new Map,l=new Set;for(const p of n.sourceIds){const v=n.getInterpolatedShapeAt(e,p);if(!v)continue;const m={...v,bounds:{...v.bounds,x:v.bounds.x+r.x,y:v.bounds.y+r.y}};o.set(p,m);const g=v.aim?this.sceneRenderer.screenPointOf(jn.directionOf(v.aim,this.directionScratch)):{ndcX:(m.bounds.x+m.bounds.width/2)/i.width*2-1,ndcY:-((m.bounds.y+m.bounds.height/2)/i.height*2-1)},S=g!==void 0&&Math.abs(g.ndcX)<=1&&Math.abs(g.ndcY)<=1,w=S?this.sceneRenderer.decorDistancesAt(g.ndcX,g.ndcY,p):{};l.add(p),(S||v.aim)&&l.delete(p);const _=v.angular?.widthDeg??a.pxToDeg(v.bounds.width),b=this.sizeEstimateOf(p);b.add(_,w);const E=Da.of(t,p);c.set(p,mn.resolve({hypothesisM:this.distanceHypotheses.get(p),derivedM:E&&_>0?mt.distanceMAt(E.widthM,_):void 0,range:b.distanceRangeAt(_),crossing:w}))}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 w=c.get(m);w&&c.set(p,{distanceM:w.distanceM*.999,basis:w.basis});break}this.depths=c;const h=n.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)});const f=(Qt(t,e)?.rollDeg??0)+(Gt.of(t)?.offsetAt(e)??Gt.STILL).rollDeg;this.sceneRenderer.setPhenomena(u,{projection:a,canvasWidthPx:i.width,canvasHeightPx:i.height,scale:Math.max(1,this.sceneCanvas.height/Math.max(1,i.height)),starPoints:Vt.starPointsOf(t.instrument),rollRad:f*Math.PI/180})}setDistanceHypothesis(e,t){t===void 0||!(t>0)?this.distanceHypotheses.delete(e):this.distanceHypotheses.set(e,t),this.updateAstronomy(this.lastTimeMs)}depthOf(e){return this.depths.get(e)}sizeRangeOf(e){return this.sizeEstimateOf(e).sizeRange}distanceRangeAt(e,t){const n=this.ufoElement.sighting.timeline.getInterpolatedShapeAt(t,e);if(!n)return{};const i=n.angular?.widthDeg??this.projectionAt(t).pxToDeg(n.bounds.width);return this.sizeEstimateOf(e).distanceRangeAt(i)}sizeContradictory(e){return this.sizeEstimateOf(e).contradictory}updateMeteorShower(e,t){this.ensureMeteorSchedule(e),this.sceneRenderer.updateMeteors(t)}updateLightning(e,t,n){if(this.ensureLightningSchedule(e),this.sceneRenderer.updateLightning(t),n)return;const i=this.lastLightningT;if(this.lastLightningT=t,i===void 0||t<i||this.ufoElement.playbackState!=="playing")return;const r=this.lightningFlashes.filter(a=>a.t>i&&a.t<=t).pop();r&&Js(e,r.t).storm&&this.handleLightningFlash(r)}ensureLightningSchedule(e){const t=Js(e,0).precipitationIntensity,n=`${this.meteorInputsOf(e)}|${t}`;if(n===this.lightningScheduleFor)return;this.lightningScheduleFor=n;const i=e.event.time,r=e.event.place?.[0],a=i?.year!==void 0?Bo(i,r?.lng??0,e.event.utcOffsetHours):void 0,o=(e.event.durationSeconds??0)*1e3||e.timeline.duration||2e4,c=Math.round((a?.getTime()??0)/1e3)+Math.round((r?.lat??0)*1e3)+7;this.lightningFlashes=Wt.schedule({durationMs:o,seed:c,intensity:t}),this.sceneRenderer.setLightning(this.lightningFlashes)}ensureMeteorSchedule(e){const t=this.meteorInputsOf(e);t!==this.meteorScheduleFor&&(this.meteorScheduleFor=t,this.scheduleMeteors(e))}meteorInputsOf(e){const t=e.event.place?.[0],n=e.event.time;return JSON.stringify([t?.lat,t?.lng,n?.year,n?.month,n?.day,n?.hour,n?.minute,n?.second,e.event.utcOffsetHours,e.event.durationSeconds,e.timeline.duration])}scheduleMeteors(e){const t=e.event.place?.[0],n=e.event.time,i=t?.lat!==void 0&&t.lng!==void 0&&n?.year!==void 0?Bo(n,t.lng,e.event.utcOffsetHours):void 0;if(!i||t?.lat===void 0||t.lng===void 0){this.sceneRenderer.setMeteorShower([],0,0);return}const r={lat:t.lat,lng:t.lng,elevationM:0},a=(e.event.durationSeconds??0)*1e3||e.timeline.duration||2e4,o=Math.round(i.getTime()/1e3)+Math.round(t.lat*1e3),c=It.schedule({ratePerHour:It.observedRatePerHour(It.apexPosition(i,r).altitudeDeg),durationMs:a,velocityKmS:It.TYPICAL_VELOCITY_KM_S,seed:o}),l=oh.activeAt(i).map(u=>{const d=oh.radiantPosition(u.shower,i,r);return{entry:u,position:d,rate:oh.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=ks.schedule({ratePerHour:l.rate,durationMs:a,velocityKmS:l.entry.shower.velocityKmS,seed:o+1});this.sceneRenderer.setMeteorShower([...h,...c],l.position.altitudeDeg,l.position.azimuthDeg)}meteorByRank(e){this.ensureMeteorSchedule(this.ufoElement.sighting);const t=[...this.sceneRenderer.meteorSchedule].filter(r=>r.t+r.durationMs<=this.ufoElement.seekableDuration).sort((r,a)=>a.brightness-r.brightness);if(t.length===0)return;const n=t[e%t.length],i=this.sceneRenderer.meteorMidpoint(n);if(i)return{t:Math.round(n.t+n.durationMs*.45),...i}}lensOpticsAt(e){const t=this.ufoElement.sighting,n=t.instrument,i=n.frame,r=Qt(t,e),a=r?.fNumber??n.fNumber;if(!i||a===void 0)return;const o=Vt.focalLengthMmFor(n,Vn.fovOf(t,e));if(o!==void 0)return{focalLengthMm:o,fNumber:a,focusDistance:r?.focusDistanceM??0,frameHeightMm:i.heightMm}}projectionAt(e){const t=this.ufoElement.sighting;return Hi.of(t.instrument,mt.CANVAS_HEIGHT_PX,Vn.fovOf(t,e))}sizeEstimateOf(e){let t=this.sizeEstimates.get(e);return t||(t=new rE,this.sizeEstimates.set(e,t)),t}}const Ep="rr0-scene";function xE(){zp(),customElements.get(Ep)||customElements.define(Ep,fd)}xE();export{Hv as $,wE as A,tt as B,ce as C,H0 as D,Ge as E,CE as F,AE as G,om as H,EE as I,TE as J,wa as K,qa as L,RE as M,io as N,xt as O,x2 as P,xs as Q,Oa as R,An as S,_E as T,en as U,Pe as V,Tn as W,bE as X,qs as Y,am as Z,DE as _,SE as a,gc as a0,jh as a1,Sc as a2,nn as a3,dm as a4,ed as a5,td as a6,je as a7,vs as a8,Xa as a9,ri as aa,qi as ab,yE as b,LE as c,Mc as d,IE as e,Xe as f,C as g,E0 as h,PE as i,NE as j,Fv as k,Ns as l,Qc as m,G1 as n,gt as o,Xt as p,yh as q,Mn as r,ju as s,Yi as t,Yv as u,e2 as v,ei as w,qn as x,lt as y,vt as z};
|