@rr0/ufoathome 0.57.6 → 0.57.7

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.
@@ -507,7 +507,7 @@ input[type=range] {
507
507
  pointer-events: none;
508
508
  white-space: nowrap;
509
509
  }
510
- `,Na=[{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 Ht{static get default(){return Na[0]}static byId(e){return Na.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:Ht.UNAIDED_FIELD_DEG}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Ht.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Ht.aspectOf(e))}static availableAt(e){return e===void 0?Na:Na.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??Ht.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class ma{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 ma(t)}get moved(){return this.spanM>ma.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:Li(0,-r,n,i).lat,south:Li(0,r,n,i).lat,east:Li(r,0,n,i).lng,west:Li(-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 Bt{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=ma.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=Bt.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 Bt(n,1-(e.instrument.stabilization??0))}static stepHzFor(e){return e<Bt.SLOWEST_WALK_M_PER_S||e>Bt.FASTEST_WALK_M_PER_S?0:Bt.REFERENCE_STEP_HZ*Math.pow(e/Bt.REFERENCE_SPEED_M_PER_S,Bt.CADENCE_EXPONENT)}offsetAt(e){const t=this.stretches.find(c=>e>=c.startMs&&e<=c.endMs);if(!t||t.stepHz===0)return Bt.STILL;const n=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,i=2*Math.PI*n,r=this.amplitudeAt(t,e),a=Bt.SWAY_M*r*Math.cos(i/2),o=r*this.rotationPassed*t.speedMPerS/Bt.REFERENCE_SPEED_M_PER_S;return{eastM:a*t.northUnit,northM:-a*t.eastUnit,upM:Bt.RISE_M_PER_M_PER_S*t.speedMPerS*r*Math.cos(i),rollDeg:Bt.HEAD_ROLL_DEG*o*Math.cos(i/2),pitchDeg:-1.25*o*Math.cos(i),yawDeg:Bt.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 Jm(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 Qm(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 _n(s,e,t){return s+(e-s)*t}function sd(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 jm(s){return`#${s.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function eg(s,e,t){const n=sd(s),i=sd(e);return!n||!i?t<1?s:e:jm([_n(n[0],i[0],t),_n(n[1],i[1],t),_n(n[2],i[2],t)])}function tg(s,e,t){const n={x:_n(s.bounds.x,e.bounds.x,t),y:_n(s.bounds.y,e.bounds.y,t),width:_n(s.bounds.width,e.bounds.width,t),height:_n(s.bounds.height,e.bounds.height,t)},i=_n(s.angle,e.angle,t),r=_n(s.transparency,e.transparency,t),a=_n(s.haloScale,e.haloScale,t),o=_n(s.blur??0,e.blur??0,t),c=_n(s.brightness??0,e.brightness??0,t),l=eg(s.color,e.color,t),h=mt.lerpAngular(s.angular,e.angular,t),u=Jm(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:_n(d.x,e.points[f].x,t),y:_n(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 pc{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?tg(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&&Qm(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 pc;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 ng(s,e,t){return Math.max(e,Math.min(t,s))}function ig(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function ks(s,e,t){return s+(e-s)*t}function sg(s,e,t){return{lat:s.lat===void 0||e.lat===void 0?void 0:ks(s.lat,e.lat,t),lng:s.lng===void 0||e.lng===void 0?void 0:ks(s.lng,e.lng,t),elevationM:ks(s.elevationM,e.elevationM,t),headingDeg:s.headingDeg===void 0||e.headingDeg===void 0?void 0:ig(s.headingDeg,e.headingDeg,t),pitchDeg:ks(s.pitchDeg,e.pitchDeg,t),rollDeg:ks(s.rollDeg??0,e.rollDeg??0,t),fovDeg:ks(s.fovDeg,e.fovDeg,t),fNumber:s.fNumber,focusDistanceM:s.focusDistanceM}}class ga{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?sg(n.pose,i.pose,ng((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 ga;for(const n of e.keyframes)t.addKeyframe(n.t,n.pose);return t}}function Mt(s,e,t){return s+(e-s)*t}function mu(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function rg(s,e,t){return Math.max(e,Math.min(t,s))}function ag(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:Mt(a.eastM,o.eastM,t),northM:Mt(a.northM,o.northM,t),baseM:Mt(a.baseM,o.baseM,t),thicknessM:Mt(a.thicknessM,o.thicknessM,t),widthM:Mt(a.widthM,o.widthM,t),depthM:Mt(a.depthM,o.depthM,t),rotationDeg:mu(a.rotationDeg,o.rotationDeg,t),density:Mt(a.density,o.density,t),darkness:Mt(a.darkness??0,o.darkness??0,t)}})}function og(s,e,t){if(s.cloudLayers===void 0&&e.cloudLayers===void 0)return;const n=qo(s),i=qo(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:ag(o?.instances,c?.instances,t),baseM:Mt(l.baseM,h.baseM,t),thicknessM:Mt(l.thicknessM,h.thicknessM,t),coverage:Mt(l.coverage,h.coverage,t),sizeM:Mt(l.sizeM,h.sizeM,t),density:Mt(l.density,h.density,t),darkness:Mt(l.darkness??s.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Mt(l.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:Mt(l.windSpeed??s.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:mu(l.windDirectionDeg??s.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function cg(s,e,t){return{cloudLayers:og(s,e,t),cloudCover:Mt(s.cloudCover,e.cloudCover,t),cloudDarkness:Mt(s.cloudDarkness,e.cloudDarkness,t),highCloudCover:s.highCloudCover===void 0||e.highCloudCover===void 0?void 0:Mt(s.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:s.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:Mt(s.iceCrystalAlignment,e.iceCrystalAlignment,t),lowerCloudCover:s.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:Mt(s.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:s.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:Mt(s.cloudBaseM,e.cloudBaseM,t),precipitationType:t<1?s.precipitationType:e.precipitationType,precipitationIntensity:Mt(s.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:mu(s.windDirectionDeg,e.windDirectionDeg,t),windSpeed:Mt(s.windSpeed,e.windSpeed,t),storm:t<1?s.storm:e.storm}}class va{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?cg(n.weather,i.weather,rg((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 va;for(const n of e.keyframes)t.addKeyframe(n.t,n.weather);return t}}class xa{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 xa;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,hg={kind:"none",volume:0,pitchHz:lg};class Fn{constructor(e){this.entries=e}static empty(){return new Fn(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 Fn(new Map);return{recording:Fn.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=Fn.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 Fn.isWrapper(e)?(n.set(t.join("."),{basis:e.basis??"stated",...e.rationale===void 0?{}:{rationale:e.rationale},of:e.value}),Fn.stripValue(e.value,t,n)):Array.isArray(e)?e.map((i,r)=>Fn.stripValue(i,[...t,String(r)],n)):typeof e=="object"&&e!==null?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,Fn.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 Vl(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 rd(s){return(((s.day??0)*24+(s.hour??0))*60+(s.minute??0))*6e4+(s.second??0)*1e3}const ug=["year","month","day","hour","minute"],dg=["day","hour","minute"];function ad(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?ug:dg,n=ad(s.time,t);if(!(n===""||n!==ad(s.endTime,t)))return e?Vl(s.endTime)-Vl(s.time):rd(s.endTime)-rd(s.time)}class mc{constructor(e,t,n,i,r,a,o,c,l=[],h,u,d,f=[]){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}provenance=Fn.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 Ht.byId(this.instrumentId)}static create(e,t,n){return new mc({eventType:"sighting",time:e,place:t},new pc,new ga,new va,new xa,n)}}const pg=0,mg=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:pg,headingDeg:void 0,pitchDeg:mg,fovDeg:Ht.fieldOfViewDeg(s.instrument)}}function Oa(s,e){return s.weatherTrack.getInterpolatedWeatherAt(e)??s.weather??ip}function gg(s,e){return s.soundTrack.getInterpolatedSoundAt(e)??hg}class vg{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 ap=["nw","n","ne","e","se","s","sw","w"],xg=24,Ua=8,Mg=3,_g=8;function Fa(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 Ur(s){return{x:s.x+s.width/2,y:s.y+s.height/2}}const yg={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 Dn{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-xg}},o=Ur(e.bounds),c={};for(const l of Object.keys(a))c[l]=Fa(a[l],o,e.angle);return c}static hitTestHandle(e,t,n=8,i=[...ap,"rotate"]){const r=Dn.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=((Dn.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=Ur(e),a=Fa(i,r,-t),{x:o,y:c,width:l,height:h}=e,u=yg[n];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(a.x,p-Ua)),u.right&&(p=Math.max(a.x,d+Ua)),u.top&&(f=Math.min(a.y,v-Ua)),u.bottom&&(v=Math.max(a.y,f+Ua)),{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=Dn.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=Ur(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=Ur(e.bounds);return e.points.map(n=>Fa({x:e.bounds.x+n.x,y:e.bounds.y+n.y},t,e.angle))}static hitTestVertex(e,t,n=_g){const i=Dn.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=Ur(e.bounds),i=Fa(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?Dn.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=Dn.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=Dn.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<=Mg?e:{...e,points:e.points.filter((n,i)=>i!==t)}}}const Wl=6,za=Wl/2,od=20,cd=24,ld=9,hd=6,ud=7,dd=6,fd=4;class Xl{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+ld*f),dd*f)-d:0,v=f>0?d*(1+ud*f)-d:0,g=3*cd*(e.blur??0)+1.5*od*e.haloScale,m=Math.max(p,v,0)+g+2;return{x:a-h-m,y:o-u-m,width:2*(h+m),height:2*(u+m)}}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(${(cd*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+ld*t),dd*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<=hd;d++){const f=d/hd,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+ud*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,g=c+Math.sin(p)*d,m=this.ctx.createLinearGradient(o,c,v,g);m.addColorStop(0,this.withAlpha(e.color,t*.55)),m.addColorStop(.35,this.withAlpha(e.color,t*.22)),m.addColorStop(1,this.withAlpha(e.color,0)),this.ctx.strokeStyle=m,this.ctx.beginPath(),this.ctx.moveTo(o,c),this.ctx.lineTo(v,g),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=od*e.haloScale,this.paintBase(e),this.ctx.restore()}paintSelectionHandles(e){this.paintHandleFrame(Dn.handlePointsFor(e),{includeRotate:!0}),e.kind==="polygon"&&this.paintVertexHandles(e)}paintVertexHandles(e){this.ctx.fillStyle="#39f";for(const t of Dn.vertexPointsFor(e))this.ctx.beginPath(),this.ctx.ellipse(t.x,t.y,fd,fd,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(e){this.paintOutline(Dn.handlePointsFor(e))}paintSelectionOnly(e){this.paintSelectionHandles(e)}paintGroupHandles(e){this.paintHandleFrame(Dn.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 ap){const i=e[n];this.ctx.fillRect(i.x-za,i.y-za,Wl,Wl)}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,za+1,za+1,0,0,2*Math.PI),this.ctx.fill())}}const pd=.05,md=.08,gd=2,vd=3,Sg=14,bg=.02;class Eg{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,pd);for(const{param:r,ratio:a}of e.pitch)r.setTargetAtTime(Math.min(t.pitchHz*a,n.sampleRate/2-1),i,pd)}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*gd),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*gd),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*vd),e.sampleRate),n=t.getChannelData(0),i=Math.max(1,Math.floor(bg*e.sampleRate)),r=Math.round(vd*Sg);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,md/3);const i=n+md;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 Ko(s){return[...s].sort((e,t)=>e.t-t.t)}function xd(s,e){let t;for(const n of Ko(s)){if(n.t>e)break;t=n}return t}const Tc=Math.PI/180,ka=180/Math.PI;class Ni{constructor(e,t,n){this.kind=e,this.canvasHeightPx=t,this.fovDeg=n;const i=n*Tc/2;this.focalPx=e==="equidistant"?t/2/i:t/2/Math.tan(i)}focalPx;static of(e,t,n){return new Ni(e.projection,t,n)}degToPx(e){const t=e*Tc;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*ka:2*Math.atan(e/(2*this.focalPx))*ka}angleDegToRadiusPx(e){const t=e*Tc;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*ka:Math.atan(e/this.focalPx)*ka}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 zn{static fovOf(e,t){return Qt(e,t)?.fovDeg??Ht.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=Ni.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:Ht.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)>=zn.OFF_CANVAS_DEG?Math.sign(t)*zn.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,n){const i=Ht.frameWidthPx(t,mt.CANVAS_HEIGHT_PX)/2,r=Ht.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=Ni.of(t,mt.CANVAS_HEIGHT_PX,l),u=Ni.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,g=Math.hypot(p,v),m=g===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(g))/g,E={...f,x:r+p*m-f.width/2,y:a+v*m-f.height/2};return{...d,shape:{...d.shape,bounds:E}}}))}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=Ni.of(e.instrument,mt.CANVAS_HEIGHT_PX,a);n.addKeyframe(i.t,i.shapes.map(c=>({...c,shape:t(c.shape,o,r)})))}}}function wg(s){return Fn.restore(Ag(s),s.provenance)}function Ag(s){return zn.toAngular(s),zn.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,weatherSource:s.weatherSource,instrument:s.instrumentId,exposureSeconds:s.exposureSeconds}}function Tg(s){const{recording:e,provenance:t}=Fn.strip(s),n=Rg(e);return n.provenance=t,n}function Rg(s){const e=new mc({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},pc.fromJSON(s.timeline),s.witnessTrack?ga.fromJSON(s.witnessTrack):new ga,s.weatherTrack?va.fromJSON(s.weatherTrack):new va,s.soundTrack?xa.fromJSON(s.soundTrack):new xa,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),Ko(s.milestones??[]));return e.testimony=s.testimony,zn.toBounds(e),zn.toPosition(e),e}function gu(s,e){for(const t of s){const n=t.toLowerCase().split("-")[0];if(e.includes(n))return n}return"en"}class $o{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 is{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[is.base(n)];if(i)return i}const t=new Set(this.preferences.map(n=>is.base(n)));for(const[n,i]of Object.entries(e))if(i&&t.has(is.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=>is.base(o)===is.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 Dg="modulepreload",Cg=function(s,e){return new URL(s,e).href},Md={},ql=function(e,t,n){let i=Promise.resolve();if(t&&t.length>0){let a=function(h){return Promise.all(h.map(u=>Promise.resolve(u).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const o=document.getElementsByTagName("link"),c=document.querySelector("meta[property=csp-nonce]"),l=c?.nonce||c?.getAttribute("nonce");i=a(t.map(h=>{if(h=Cg(h,n),h in Md)return;Md[h]=!0;const u=h.endsWith(".css"),d=u?'[rel="stylesheet"]':"";if(!!n)for(let v=o.length-1;v>=0;v--){const g=o[v];if(g.href===h&&(!u||g.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${d}`))return;const p=document.createElement("link");if(p.rel=u?"stylesheet":Dg,u||(p.as="script"),p.crossOrigin="",p.href=h,l&&p.setAttribute("nonce",l),document.head.appendChild(p),u)return new Promise((v,g)=>{p.addEventListener("load",v),p.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${h}`)))})}))}function r(a){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a}return i.then(a=>{for(const o of a||[])o.status==="rejected"&&r(o.reason);return e().catch(r)})},Pg=["en","fr"],Ig={en:()=>ql(()=>Promise.resolve().then(()=>Ng),void 0,import.meta.url).then(s=>s.ufoMessages_en),fr:()=>ql(()=>import("./UfoMessages_fr-BJPYHN17.js"),[],import.meta.url).then(s=>s.ufoMessages_fr)};function Lg(s){return Ig[s]()}const op={play:"Play",pause:"Pause",noDuration:"No observation duration",autoReplay:"Auto-replay",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",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",witnessHere:"The witness, here",decorHere:"Scenery"},Ng=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:op},Symbol.toStringTag,{value:"Module"})),_d=2;function cp(s){return s==="building"||s==="vehicle"}function Og(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 Ug(s,e){return s.pattern.kind==="steady"?!0:lp(s,e,e+1)>.5}function lp(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 vu(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 yd(t[0],s);const i=t[t.length-1];if(e>=i.t)return yd(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 yd(s,e){return{eastM:s.eastM,northM:s.northM,altitudeM:s.altitudeM??0,headingDeg:s.headingDeg??e.headingDeg}}const hp=Math.PI/180,Fg=180/Math.PI,zg=256,kg=19;function Bg(s,e){return 156543.03392*Math.cos(s*hp)/2**e}function Hg(s,e){return Bg(s,e)*zg}function up(s,e){let t=0;for(;t<kg&&Hg(s,t+1)>=e;)t++;return t}function Fo(s){const e=s*hp;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function dp(s,e,t){const n=2**t;return{x:(s+180)/360*n,y:Fo(e)*n}}function fp(s,e,t){const n=Fo(s.north),i=Fo(s.south);return{x:(e-s.west)/(s.east-s.west),y:(Fo(t)-n)/(i-n)}}function Gg(s,e,t){const{x:n,y:i}=dp(s,e,t);return{x:Math.floor(n),y:Math.floor(i),z:t}}function Vg(s){const e=2**s.z,t=s.x/e*360-180,n=(s.x+1)/e*360-180,i=Sd(s.y,e);return{south:Sd(s.y+1,e),north:i,west:t,east:n}}function Sd(s,e){const t=s/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*Fg}function pp(s,e,t,n){const i=Gg(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(Vg),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 ys{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=fp(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:ys.MARKER_RADIUS_PX}),t.beginPath(),t.arc(i.x,i.y,ys.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)<=ys.ON_MARKER_M});n.beginPath(),n.arc(i.x,i.y,r?ys.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=ys.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 Ln=256,bd=3,Wg=32768;class Xg{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=up(n,Math.max(r,a)),{tiles:c}=pp(i,n,o,bd),l=bd*Ln,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 g=e.west+(e.east-e.west)*(v/(t.width-1));d[f*t.width+v]=this.sampleAt(p,g,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=Ln,c.height=Ln;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,Ln,Ln),u=(e.x-t.x)*Ln,d=(e.y-t.y)*Ln;for(let f=0;f<Ln;f++)for(let p=0;p<Ln;p++){const v=(f*Ln+p)*4,g=h[v]*256+h[v+1]+h[v+2]/256-Wg,m=u+p,E=d+f;n[E*i+m]=g}}sampleAt(e,t,n,i,r,a){const{x:o,y:c}=dp(t,e,n),l=(o-i.x)*Ln,h=(c-i.y)*Ln,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,g=h-d,m=r[d*a+u],E=r[d*a+f],b=r[p*a+u],_=r[p*a+f],S=m+(E-m)*v,w=b+(_-b)*v;return S+(w-S)*g}}const Rc=256,Ed=3;async function qg(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=up(i,Math.max(a,o)/2),{tiles:l,bounds:h}=pp(r,i,c,Ed),u=Ed*Rc,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 m=>{const E=t(m),b=await n(E);if(!b.ok)throw new Error(`Imagery tile fetch failed (${b.status}): ${E}`);const _=await createImageBitmap(await b.blob());f.drawImage(_,(m.x-p.x)*Rc,(m.y-p.y)*Rc)}));const v=document.createElement("canvas");v.width=e.width,v.height=e.height;const g=v.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");return g.drawImage(d,0,0,u,u,0,0,e.width,e.height),{source:v,width:e.width,height:e.height,bounds:h}}class Yg{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 qg(e,t,n=>this.tileUrlTemplate.replace("{z}",String(n.z)).replace("{y}",String(n.y)).replace("{x}",String(n.x)),this.fetchImpl)}}function Kg(){return{elevation:new Xg,imagery:mp()}}function mp(){return new Yg}const $g=new Set,mr="show-witness-map",gr="hide-milestones";class On extends HTMLElement{static get observedAttributes(){return["src",mr,gr]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;loopButton;static WITNESS_MAP_MIN_SPAN_M=400;static WITNESS_MAP_MARGIN=.6;static WITNESS_MAP_IMAGERY_PX=768;fullscreenButton;cornerButtons;witnessMapButton;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=mc.create();sightingAudio=new Eg;soundPreview;player;loopEnabled=!0;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;enableClickToPlay=!0;fullscreenTarget;messages=op;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>${Zm}</style>${$m}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Xl(this.canvas.getContext("2d")),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.playPauseButton=this.shadow.getElementById("play-pause"),this.loopButton=this.shadow.getElementById("loop"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.witnessMapButton=this.shadow.getElementById("witness-map"),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 ys(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.loopButton.addEventListener("click",()=>this.toggleLoop()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.witnessMapButton.addEventListener("click",()=>this.toggleWitnessMap()),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(Number(this.seekInput.value))),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.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),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===mr&&this.applyWitnessMapDefault(),e===gr&&this.setMilestonesShown(!this.hasAttribute(gr))}async loadFromSrc(e){this.sightingData=await rp.json(e)}get sightingData(){return wg(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Tg(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.player.seek(this.player.time)}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Ko(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.addEventListener("click",()=>this.player.seek(n.t)),i}))}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?xd(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=(this.currentSighting.exposure??0)*1e3;if(t<On.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const n=Math.min(On.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t/On.SHORTEST_VISIBLE_EXPOSURE_MS))),i=Math.ceil(this.travelPxOver(e,t)/On.EXPOSURE_STEP_PX),r=Math.min(On.MAX_TRAVEL_STEPS,Math.max(n,i)),a=[];for(let o=0;o<r;o++)a.push(e+t*o/r);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=Ht.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:$g;this.canvasRenderer.setStarPoints(Ht.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)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(n.size>1){const o=Dn.groupBoundsFor([...t].filter(([c])=>n.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.keepWitnessMapClear(r[0].shapes),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(gg(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 vg(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.loopButton.setAttribute("aria-pressed",String(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(mr)&&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=ma.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(On.WITNESS_MAP_MIN_SPAN_M,On.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=mp(),t=this.witnessMapBounds;try{const n=await e.getImageryTexture(t,{width:On.WITNESS_MAP_IMAGERY_PX,height:On.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}keepWitnessMapClear(e){if(this.witnessMapPanel.hidden)return;const t=this.witnessMapBoxPx;if(!t)return;const n=(o,c,l)=>{for(const h of e.values())if(!(h.transparency>=1)&&!(h.bounds.x+h.bounds.width<o-l||h.bounds.x>c+l)&&!(h.bounds.y>t.bottom+l||h.bounds.y+h.bounds.height<t.top-l))return!0;return!1},i=[this.canvas.width-t.width,this.canvas.width],r=[0,t.width],a=On.WITNESS_MAP_CLEARANCE_PX;if(this.witnessMapPanel.classList.contains("on-the-left")){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?xd(this.currentSighting.milestones,e):void 0;for(const a of this.milestonesShown?Ko(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?Ni.of(n,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Ht.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=vu(n,e),{lat:r,lng:a}=Li(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=Ni.of(this.currentSighting.instrument,this.canvas.height,i?.fovDeg??60);return{x:-r.angleDegToRadiusPx(t),y:r.angleDegToRadiusPx(n)}}gaitAt(e){return Bt.of(this.currentSighting)?.offsetAt(e)??Bt.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 is($o.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=gu($o.preferencesFor(this),Pg);e!=="en"&&this.applyMessages(await Lg(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.loopButton.title=e.autoReplay,this.loopButton.setAttribute("aria-label",e.autoReplay),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),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?Vl(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 Ba(e);const t=this.currentSighting.timeline.duration,n=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?Ad(wd(this.realStartMs+n)):Ba(n)}formatEndOfTimeline(){return this.realDurationMs===void 0?Ba(this.currentSighting.timeline.duration):this.canShowClockTime?Ad(wd(this.realStartMs+this.realDurationMs)):Ba(this.realDurationMs)}}function wd(s){const e=new Date(s);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function Ad(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 Ba(s){const e=Math.round(s/1e3),t=Math.floor(e/60),n=e%60;return`${t}:${String(n).padStart(2,"0")}`}const Yl="rr0-ufo";function gp(){customElements.get(Yl)||customElements.define(Yl,On)}/**
510
+ `,Na=[{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 Ht{static get default(){return Na[0]}static byId(e){return Na.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:Ht.UNAIDED_FIELD_DEG}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Ht.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Ht.aspectOf(e))}static availableAt(e){return e===void 0?Na:Na.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??Ht.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class ma{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 ma(t)}get moved(){return this.spanM>ma.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:Li(0,-r,n,i).lat,south:Li(0,r,n,i).lat,east:Li(r,0,n,i).lng,west:Li(-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 Bt{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=ma.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=Bt.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 Bt(n,1-(e.instrument.stabilization??0))}static stepHzFor(e){return e<Bt.SLOWEST_WALK_M_PER_S||e>Bt.FASTEST_WALK_M_PER_S?0:Bt.REFERENCE_STEP_HZ*Math.pow(e/Bt.REFERENCE_SPEED_M_PER_S,Bt.CADENCE_EXPONENT)}offsetAt(e){const t=this.stretches.find(c=>e>=c.startMs&&e<=c.endMs);if(!t||t.stepHz===0)return Bt.STILL;const n=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,i=2*Math.PI*n,r=this.amplitudeAt(t,e),a=Bt.SWAY_M*r*Math.cos(i/2),o=r*this.rotationPassed*t.speedMPerS/Bt.REFERENCE_SPEED_M_PER_S;return{eastM:a*t.northUnit,northM:-a*t.eastUnit,upM:Bt.RISE_M_PER_M_PER_S*t.speedMPerS*r*Math.cos(i),rollDeg:Bt.HEAD_ROLL_DEG*o*Math.cos(i/2),pitchDeg:-1.25*o*Math.cos(i),yawDeg:Bt.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 Jm(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 Qm(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 _n(s,e,t){return s+(e-s)*t}function sd(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 jm(s){return`#${s.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function eg(s,e,t){const n=sd(s),i=sd(e);return!n||!i?t<1?s:e:jm([_n(n[0],i[0],t),_n(n[1],i[1],t),_n(n[2],i[2],t)])}function tg(s,e,t){const n={x:_n(s.bounds.x,e.bounds.x,t),y:_n(s.bounds.y,e.bounds.y,t),width:_n(s.bounds.width,e.bounds.width,t),height:_n(s.bounds.height,e.bounds.height,t)},i=_n(s.angle,e.angle,t),r=_n(s.transparency,e.transparency,t),a=_n(s.haloScale,e.haloScale,t),o=_n(s.blur??0,e.blur??0,t),c=_n(s.brightness??0,e.brightness??0,t),l=eg(s.color,e.color,t),h=mt.lerpAngular(s.angular,e.angular,t),u=Jm(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:_n(d.x,e.points[f].x,t),y:_n(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 pc{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?tg(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&&Qm(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 pc;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 ng(s,e,t){return Math.max(e,Math.min(t,s))}function ig(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function ks(s,e,t){return s+(e-s)*t}function sg(s,e,t){return{lat:s.lat===void 0||e.lat===void 0?void 0:ks(s.lat,e.lat,t),lng:s.lng===void 0||e.lng===void 0?void 0:ks(s.lng,e.lng,t),elevationM:ks(s.elevationM,e.elevationM,t),headingDeg:s.headingDeg===void 0||e.headingDeg===void 0?void 0:ig(s.headingDeg,e.headingDeg,t),pitchDeg:ks(s.pitchDeg,e.pitchDeg,t),rollDeg:ks(s.rollDeg??0,e.rollDeg??0,t),fovDeg:ks(s.fovDeg,e.fovDeg,t),fNumber:s.fNumber,focusDistanceM:s.focusDistanceM}}class ga{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?sg(n.pose,i.pose,ng((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 ga;for(const n of e.keyframes)t.addKeyframe(n.t,n.pose);return t}}function Mt(s,e,t){return s+(e-s)*t}function mu(s,e,t){const n=((e-s)%360+540)%360-180;return((s+n*t)%360+360)%360}function rg(s,e,t){return Math.max(e,Math.min(t,s))}function ag(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:Mt(a.eastM,o.eastM,t),northM:Mt(a.northM,o.northM,t),baseM:Mt(a.baseM,o.baseM,t),thicknessM:Mt(a.thicknessM,o.thicknessM,t),widthM:Mt(a.widthM,o.widthM,t),depthM:Mt(a.depthM,o.depthM,t),rotationDeg:mu(a.rotationDeg,o.rotationDeg,t),density:Mt(a.density,o.density,t),darkness:Mt(a.darkness??0,o.darkness??0,t)}})}function og(s,e,t){if(s.cloudLayers===void 0&&e.cloudLayers===void 0)return;const n=qo(s),i=qo(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:ag(o?.instances,c?.instances,t),baseM:Mt(l.baseM,h.baseM,t),thicknessM:Mt(l.thicknessM,h.thicknessM,t),coverage:Mt(l.coverage,h.coverage,t),sizeM:Mt(l.sizeM,h.sizeM,t),density:Mt(l.density,h.density,t),darkness:Mt(l.darkness??s.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:l.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:Mt(l.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:l.windSpeed===void 0&&h.windSpeed===void 0?void 0:Mt(l.windSpeed??s.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:l.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:mu(l.windDirectionDeg??s.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function cg(s,e,t){return{cloudLayers:og(s,e,t),cloudCover:Mt(s.cloudCover,e.cloudCover,t),cloudDarkness:Mt(s.cloudDarkness,e.cloudDarkness,t),highCloudCover:s.highCloudCover===void 0||e.highCloudCover===void 0?void 0:Mt(s.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:s.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:Mt(s.iceCrystalAlignment,e.iceCrystalAlignment,t),lowerCloudCover:s.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:Mt(s.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:s.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:Mt(s.cloudBaseM,e.cloudBaseM,t),precipitationType:t<1?s.precipitationType:e.precipitationType,precipitationIntensity:Mt(s.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:mu(s.windDirectionDeg,e.windDirectionDeg,t),windSpeed:Mt(s.windSpeed,e.windSpeed,t),storm:t<1?s.storm:e.storm}}class va{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?cg(n.weather,i.weather,rg((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 va;for(const n of e.keyframes)t.addKeyframe(n.t,n.weather);return t}}class xa{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 xa;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,hg={kind:"none",volume:0,pitchHz:lg};class Fn{constructor(e){this.entries=e}static empty(){return new Fn(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 Fn(new Map);return{recording:Fn.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=Fn.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 Fn.isWrapper(e)?(n.set(t.join("."),{basis:e.basis??"stated",...e.rationale===void 0?{}:{rationale:e.rationale},of:e.value}),Fn.stripValue(e.value,t,n)):Array.isArray(e)?e.map((i,r)=>Fn.stripValue(i,[...t,String(r)],n)):typeof e=="object"&&e!==null?Object.fromEntries(Object.entries(e).map(([i,r])=>[i,Fn.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 Vl(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 rd(s){return(((s.day??0)*24+(s.hour??0))*60+(s.minute??0))*6e4+(s.second??0)*1e3}const ug=["year","month","day","hour","minute"],dg=["day","hour","minute"];function ad(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?ug:dg,n=ad(s.time,t);if(!(n===""||n!==ad(s.endTime,t)))return e?Vl(s.endTime)-Vl(s.time):rd(s.endTime)-rd(s.time)}class mc{constructor(e,t,n,i,r,a,o,c,l=[],h,u,d,f=[]){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}provenance=Fn.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 Ht.byId(this.instrumentId)}static create(e,t,n){return new mc({eventType:"sighting",time:e,place:t},new pc,new ga,new va,new xa,n)}}const pg=0,mg=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:pg,headingDeg:void 0,pitchDeg:mg,fovDeg:Ht.fieldOfViewDeg(s.instrument)}}function Oa(s,e){return s.weatherTrack.getInterpolatedWeatherAt(e)??s.weather??ip}function gg(s,e){return s.soundTrack.getInterpolatedSoundAt(e)??hg}class vg{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 ap=["nw","n","ne","e","se","s","sw","w"],xg=24,Ua=8,Mg=3,_g=8;function Fa(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 Ur(s){return{x:s.x+s.width/2,y:s.y+s.height/2}}const yg={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 Dn{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-xg}},o=Ur(e.bounds),c={};for(const l of Object.keys(a))c[l]=Fa(a[l],o,e.angle);return c}static hitTestHandle(e,t,n=8,i=[...ap,"rotate"]){const r=Dn.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=((Dn.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=Ur(e),a=Fa(i,r,-t),{x:o,y:c,width:l,height:h}=e,u=yg[n];let d=o,f=c,p=o+l,v=c+h;return u.left&&(d=Math.min(a.x,p-Ua)),u.right&&(p=Math.max(a.x,d+Ua)),u.top&&(f=Math.min(a.y,v-Ua)),u.bottom&&(v=Math.max(a.y,f+Ua)),{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=Dn.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=Ur(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=Ur(e.bounds);return e.points.map(n=>Fa({x:e.bounds.x+n.x,y:e.bounds.y+n.y},t,e.angle))}static hitTestVertex(e,t,n=_g){const i=Dn.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=Ur(e.bounds),i=Fa(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?Dn.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=Dn.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=Dn.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<=Mg?e:{...e,points:e.points.filter((n,i)=>i!==t)}}}const Wl=6,za=Wl/2,od=20,cd=24,ld=9,hd=6,ud=7,dd=6,fd=4;class Xl{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+ld*f),dd*f)-d:0,v=f>0?d*(1+ud*f)-d:0,g=3*cd*(e.blur??0)+1.5*od*e.haloScale,m=Math.max(p,v,0)+g+2;return{x:a-h-m,y:o-u-m,width:2*(h+m),height:2*(u+m)}}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(${(cd*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+ld*t),dd*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<=hd;d++){const f=d/hd,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+ud*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,g=c+Math.sin(p)*d,m=this.ctx.createLinearGradient(o,c,v,g);m.addColorStop(0,this.withAlpha(e.color,t*.55)),m.addColorStop(.35,this.withAlpha(e.color,t*.22)),m.addColorStop(1,this.withAlpha(e.color,0)),this.ctx.strokeStyle=m,this.ctx.beginPath(),this.ctx.moveTo(o,c),this.ctx.lineTo(v,g),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=od*e.haloScale,this.paintBase(e),this.ctx.restore()}paintSelectionHandles(e){this.paintHandleFrame(Dn.handlePointsFor(e),{includeRotate:!0}),e.kind==="polygon"&&this.paintVertexHandles(e)}paintVertexHandles(e){this.ctx.fillStyle="#39f";for(const t of Dn.vertexPointsFor(e))this.ctx.beginPath(),this.ctx.ellipse(t.x,t.y,fd,fd,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(e){this.paintOutline(Dn.handlePointsFor(e))}paintSelectionOnly(e){this.paintSelectionHandles(e)}paintGroupHandles(e){this.paintHandleFrame(Dn.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 ap){const i=e[n];this.ctx.fillRect(i.x-za,i.y-za,Wl,Wl)}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,za+1,za+1,0,0,2*Math.PI),this.ctx.fill())}}const pd=.05,md=.08,gd=2,vd=3,Sg=14,bg=.02;class Eg{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,pd);for(const{param:r,ratio:a}of e.pitch)r.setTargetAtTime(Math.min(t.pitchHz*a,n.sampleRate/2-1),i,pd)}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*gd),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*gd),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*vd),e.sampleRate),n=t.getChannelData(0),i=Math.max(1,Math.floor(bg*e.sampleRate)),r=Math.round(vd*Sg);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,md/3);const i=n+md;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 Ko(s){return[...s].sort((e,t)=>e.t-t.t)}function xd(s,e){let t;for(const n of Ko(s)){if(n.t>e)break;t=n}return t}const Tc=Math.PI/180,ka=180/Math.PI;class Ni{constructor(e,t,n){this.kind=e,this.canvasHeightPx=t,this.fovDeg=n;const i=n*Tc/2;this.focalPx=e==="equidistant"?t/2/i:t/2/Math.tan(i)}focalPx;static of(e,t,n){return new Ni(e.projection,t,n)}degToPx(e){const t=e*Tc;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*ka:2*Math.atan(e/(2*this.focalPx))*ka}angleDegToRadiusPx(e){const t=e*Tc;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*ka:Math.atan(e/this.focalPx)*ka}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 zn{static fovOf(e,t){return Qt(e,t)?.fovDeg??Ht.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=Ni.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:Ht.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)>=zn.OFF_CANVAS_DEG?Math.sign(t)*zn.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,n){const i=Ht.frameWidthPx(t,mt.CANVAS_HEIGHT_PX)/2,r=Ht.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=Ni.of(t,mt.CANVAS_HEIGHT_PX,l),u=Ni.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,g=Math.hypot(p,v),m=g===0?1:u.angleDegToRadiusPx(h.radiusPxToAngleDeg(g))/g,E={...f,x:r+p*m-f.width/2,y:a+v*m-f.height/2};return{...d,shape:{...d.shape,bounds:E}}}))}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=Ni.of(e.instrument,mt.CANVAS_HEIGHT_PX,a);n.addKeyframe(i.t,i.shapes.map(c=>({...c,shape:t(c.shape,o,r)})))}}}function wg(s){return Fn.restore(Ag(s),s.provenance)}function Ag(s){return zn.toAngular(s),zn.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,weatherSource:s.weatherSource,instrument:s.instrumentId,exposureSeconds:s.exposureSeconds}}function Tg(s){const{recording:e,provenance:t}=Fn.strip(s),n=Rg(e);return n.provenance=t,n}function Rg(s){const e=new mc({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},pc.fromJSON(s.timeline),s.witnessTrack?ga.fromJSON(s.witnessTrack):new ga,s.weatherTrack?va.fromJSON(s.weatherTrack):new va,s.soundTrack?xa.fromJSON(s.soundTrack):new xa,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),Ko(s.milestones??[]));return e.testimony=s.testimony,zn.toBounds(e),zn.toPosition(e),e}function gu(s,e){for(const t of s){const n=t.toLowerCase().split("-")[0];if(e.includes(n))return n}return"en"}class $o{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 is{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[is.base(n)];if(i)return i}const t=new Set(this.preferences.map(n=>is.base(n)));for(const[n,i]of Object.entries(e))if(i&&t.has(is.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=>is.base(o)===is.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 Dg="modulepreload",Cg=function(s,e){return new URL(s,e).href},Md={},ql=function(e,t,n){let i=Promise.resolve();if(t&&t.length>0){let a=function(h){return Promise.all(h.map(u=>Promise.resolve(u).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const o=document.getElementsByTagName("link"),c=document.querySelector("meta[property=csp-nonce]"),l=c?.nonce||c?.getAttribute("nonce");i=a(t.map(h=>{if(h=Cg(h,n),h in Md)return;Md[h]=!0;const u=h.endsWith(".css"),d=u?'[rel="stylesheet"]':"";if(!!n)for(let v=o.length-1;v>=0;v--){const g=o[v];if(g.href===h&&(!u||g.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${d}`))return;const p=document.createElement("link");if(p.rel=u?"stylesheet":Dg,u||(p.as="script"),p.crossOrigin="",p.href=h,l&&p.setAttribute("nonce",l),document.head.appendChild(p),u)return new Promise((v,g)=>{p.addEventListener("load",v),p.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${h}`)))})}))}function r(a){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a}return i.then(a=>{for(const o of a||[])o.status==="rejected"&&r(o.reason);return e().catch(r)})},Pg=["en","fr"],Ig={en:()=>ql(()=>Promise.resolve().then(()=>Ng),void 0,import.meta.url).then(s=>s.ufoMessages_en),fr:()=>ql(()=>import("./UfoMessages_fr-BJPYHN17.js"),[],import.meta.url).then(s=>s.ufoMessages_fr)};function Lg(s){return Ig[s]()}const op={play:"Play",pause:"Pause",noDuration:"No observation duration",autoReplay:"Auto-replay",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",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",witnessHere:"The witness, here",decorHere:"Scenery"},Ng=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:op},Symbol.toStringTag,{value:"Module"})),_d=2;function cp(s){return s==="building"||s==="vehicle"}function Og(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 Ug(s,e){return s.pattern.kind==="steady"?!0:lp(s,e,e+1)>.5}function lp(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 vu(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 yd(t[0],s);const i=t[t.length-1];if(e>=i.t)return yd(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 yd(s,e){return{eastM:s.eastM,northM:s.northM,altitudeM:s.altitudeM??0,headingDeg:s.headingDeg??e.headingDeg}}const hp=Math.PI/180,Fg=180/Math.PI,zg=256,kg=19;function Bg(s,e){return 156543.03392*Math.cos(s*hp)/2**e}function Hg(s,e){return Bg(s,e)*zg}function up(s,e){let t=0;for(;t<kg&&Hg(s,t+1)>=e;)t++;return t}function Fo(s){const e=s*hp;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function dp(s,e,t){const n=2**t;return{x:(s+180)/360*n,y:Fo(e)*n}}function fp(s,e,t){const n=Fo(s.north),i=Fo(s.south);return{x:(e-s.west)/(s.east-s.west),y:(Fo(t)-n)/(i-n)}}function Gg(s,e,t){const{x:n,y:i}=dp(s,e,t);return{x:Math.floor(n),y:Math.floor(i),z:t}}function Vg(s){const e=2**s.z,t=s.x/e*360-180,n=(s.x+1)/e*360-180,i=Sd(s.y,e);return{south:Sd(s.y+1,e),north:i,west:t,east:n}}function Sd(s,e){const t=s/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*Fg}function pp(s,e,t,n){const i=Gg(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(Vg),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 ys{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=fp(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:ys.MARKER_RADIUS_PX}),t.beginPath(),t.arc(i.x,i.y,ys.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)<=ys.ON_MARKER_M});n.beginPath(),n.arc(i.x,i.y,r?ys.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=ys.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 Ln=256,bd=3,Wg=32768;class Xg{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=up(n,Math.max(r,a)),{tiles:c}=pp(i,n,o,bd),l=bd*Ln,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 g=e.west+(e.east-e.west)*(v/(t.width-1));d[f*t.width+v]=this.sampleAt(p,g,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=Ln,c.height=Ln;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,Ln,Ln),u=(e.x-t.x)*Ln,d=(e.y-t.y)*Ln;for(let f=0;f<Ln;f++)for(let p=0;p<Ln;p++){const v=(f*Ln+p)*4,g=h[v]*256+h[v+1]+h[v+2]/256-Wg,m=u+p,E=d+f;n[E*i+m]=g}}sampleAt(e,t,n,i,r,a){const{x:o,y:c}=dp(t,e,n),l=(o-i.x)*Ln,h=(c-i.y)*Ln,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,g=h-d,m=r[d*a+u],E=r[d*a+f],b=r[p*a+u],_=r[p*a+f],S=m+(E-m)*v,w=b+(_-b)*v;return S+(w-S)*g}}const Rc=256,Ed=3;async function qg(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=up(i,Math.max(a,o)/2),{tiles:l,bounds:h}=pp(r,i,c,Ed),u=Ed*Rc,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 m=>{const E=t(m),b=await n(E);if(!b.ok)throw new Error(`Imagery tile fetch failed (${b.status}): ${E}`);const _=await createImageBitmap(await b.blob());f.drawImage(_,(m.x-p.x)*Rc,(m.y-p.y)*Rc)}));const v=document.createElement("canvas");v.width=e.width,v.height=e.height;const g=v.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");return g.drawImage(d,0,0,u,u,0,0,e.width,e.height),{source:v,width:e.width,height:e.height,bounds:h}}class Yg{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 qg(e,t,n=>this.tileUrlTemplate.replace("{z}",String(n.z)).replace("{y}",String(n.y)).replace("{x}",String(n.x)),this.fetchImpl)}}function Kg(){return{elevation:new Xg,imagery:mp()}}function mp(){return new Yg}const $g=new Set,mr="show-witness-map",gr="hide-milestones";class On extends HTMLElement{static get observedAttributes(){return["src",mr,gr]}shadow;stageElement;canvas;canvasRenderer;tooltip;toolbar;playPauseButton;loopButton;static WITNESS_MAP_MIN_SPAN_M=400;static WITNESS_MAP_MARGIN=.6;static WITNESS_MAP_IMAGERY_PX=768;fullscreenButton;cornerButtons;witnessMapButton;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=mc.create();sightingAudio=new Eg;soundPreview;player;loopEnabled=!0;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;enableClickToPlay=!0;fullscreenTarget;messages=op;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>${Zm}</style>${$m}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new Xl(this.canvas.getContext("2d")),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.playPauseButton=this.shadow.getElementById("play-pause"),this.loopButton=this.shadow.getElementById("loop"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.witnessMapButton=this.shadow.getElementById("witness-map"),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 ys(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.loopButton.addEventListener("click",()=>this.toggleLoop()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.witnessMapButton.addEventListener("click",()=>this.toggleWitnessMap()),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(Number(this.seekInput.value))),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.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),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===mr&&this.applyWitnessMapDefault(),e===gr&&this.setMilestonesShown(!this.hasAttribute(gr))}async loadFromSrc(e){this.sightingData=await rp.json(e)}get sightingData(){return wg(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=Tg(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.player.seek(this.player.time)}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Ko(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.addEventListener("click",()=>this.player.seek(n.t)),i}))}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?xd(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=(this.currentSighting.exposure??0)*1e3;if(t<On.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const n=Math.min(On.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t/On.SHORTEST_VISIBLE_EXPOSURE_MS))),i=Math.ceil(this.travelPxOver(e,t)/On.EXPOSURE_STEP_PX),r=Math.min(On.MAX_TRAVEL_STEPS,Math.max(n,i)),a=[];for(let o=0;o<r;o++)a.push(e+t*o/r);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=Ht.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:$g;this.canvasRenderer.setStarPoints(Ht.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)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(n.size>1){const o=Dn.groupBoundsFor([...t].filter(([c])=>n.has(c)).map(([,c])=>c.bounds));this.canvasRenderer.paintGroupHandles(o)}this.keepWitnessMapClear(r[0].shapes),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(gg(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 vg(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.loopButton.setAttribute("aria-pressed",String(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(mr)&&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=ma.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(On.WITNESS_MAP_MIN_SPAN_M,On.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=mp(),t=this.witnessMapBounds;try{const n=await e.getImageryTexture(t,{width:On.WITNESS_MAP_IMAGERY_PX,height:On.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}keepWitnessMapClear(e){if(this.witnessMapPanel.hidden)return;const t=this.witnessMapBoxPx;if(!t)return;const n=(o,c,l)=>{for(const h of e.values())if(!(h.transparency>=1)&&!(h.bounds.x+h.bounds.width<o-l||h.bounds.x>c+l)&&!(h.bounds.y>t.bottom+l||h.bounds.y+h.bounds.height<t.top-l))return!0;return!1},i=[this.canvas.width-t.width,this.canvas.width],r=[0,t.width],a=On.WITNESS_MAP_CLEARANCE_PX;if(this.witnessMapPanel.classList.contains("on-the-left")){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?xd(this.currentSighting.milestones,e):void 0;for(const a of this.milestonesShown?Ko(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?Ni.of(n,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Ht.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=vu(n,e),{lat:r,lng:a}=Li(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=Ni.of(this.currentSighting.instrument,this.canvas.height,i?.fovDeg??60);return{x:-r.angleDegToRadiusPx(t),y:r.angleDegToRadiusPx(n)}}gaitAt(e){return Bt.of(this.currentSighting)?.offsetAt(e)??Bt.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 is($o.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=gu($o.preferencesFor(this),Pg);e!=="en"&&this.applyMessages(await Lg(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.loopButton.title=e.autoReplay,this.loopButton.setAttribute("aria-label",e.autoReplay),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateWitnessMapButton(),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?Vl(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 Ba(e);const t=this.currentSighting.timeline.duration,n=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?Ad(wd(this.realStartMs+n)):Ba(n)}formatEndOfTimeline(){return this.realDurationMs===void 0?Ba(this.currentSighting.timeline.duration):this.canShowClockTime?Ad(wd(this.realStartMs+this.realDurationMs)):Ba(this.realDurationMs)}}function wd(s){const e=new Date(s);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function Ad(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 Ba(s){const e=Math.round(s/1e3),t=Math.floor(e/60),n=e%60;return`${t}:${String(n).padStart(2,"0")}`}const Yl="rr0-ufo";function gp(){customElements.get(Yl)||customElements.define(Yl,On)}/**
511
511
  * @license
512
512
  * Copyright 2010-2026 Three.js Authors
513
513
  * SPDX-License-Identifier: MIT
@@ -0,0 +1 @@
1
+ const e={color:"Couleur",transparency:"Transparence",halo:"Halo",blur:"Flou",brightness:"Éclat",shapeTitle:"Nom",utcOffset:"Fuseau horaire",cloudBase:"Base des nuages",elevation:"Altitude",heightAboveGround:"Hauteur au-dessus du sol",duration:"Durée",placeName:"Lieu",latitude:"Latitude",longitude:"Longitude",heading:"Orientation",pitch:"Inclinaison",roll:"Roulis",observationTime:"Début de l'observation",observationEndTime:"Fin de l'observation",assessmentGroup:"Évaluation",assessmentNames:{coverage:"Infos du témoin"},assessmentVerdicts:{"hynek.nl":"NL — lumière nocturne","hynek.dd":"DD — disque diurne","hynek.rv":"RV — radar-visuel","hynek.ce1":"RR1 — rencontre rapprochée","hynek.ce2":"RR2 — avec trace physique","hynek.ce3":"RR3 — avec occupants"},witnessGroup:"Témoin",witnessId:"ID",witnessTitle:"Titre",witnessLastName:"Nom de famille",witnessFirstNames:"Prénoms",caseId:"ID de l'affaire",tags:"Mots-clés",cloudCover:"Couverture nuageuse",highCloudCover:"Nuages de glace (cirrus)",focalLength:"Focale",fieldOfView:"Champ de vision",aperture:"Diaphragme",exposure:"Temps de pose",focusDistance:"Mise au point à",iceCrystalAlignment:"Alignement des cristaux",cloudDarkness:"Obscurité des nuages",precipitationType:"Précipitations",precipitationNone:"Aucune",precipitationRain:"Pluie",precipitationSnow:"Neige",precipitationHail:"Grêle",precipitationIntensity:"Intensité",windDirection:"Direction du vent",windSpeed:"Force du vent",storm:"Orage",cloudsGroup:"Nuages",precipitationGroup:"Précipitations",windGroup:"Vent",soundKind:"Son",soundNone:"Aucun (silencieux)",soundHum:"Bourdonnement",soundWhistle:"Sifflement",soundRumble:"Grondement",soundCrackle:"Crépitement",soundVolume:"Intensité sonore",soundPitch:"Hauteur",soundSrc:"Enregistrement",instrument:"Observé avec",decorAircraft:"Aéronef",decorEntity:"Être",decorAltitude:"Altitude",decorLights:"Feux",decorLightsNone:"aucun",decor:"Environnement",decorBuilding:"Bâtiment",decorTree:"Arbre",decorCrop:"Rang de culture",decorMound:"Tas de pierres",decorStreetlight:"Lampadaire",decorVehicle:"Véhicule",decorWitness:"Autre témoin",decorEast:"Distance à l'est",decorNorth:"Distance au nord",decorHeading:"Orientation",decorColor:"Couleur",decorLit:"Allumé",decorTitle:"Nom",milestones:"Moments",milestoneLabel:"Repère",milestoneNote:"Ce qui se passe",addMilestone:"Nommer cet instant",deleteMilestone:"Supprimer le moment",confirmAccept:"Supprimer",confirmDecline:"Annuler",decorWidth:"Largeur",decorLength:"Longueur",decorHeight:"Hauteur",decorModel:"Modèle 3D",decorModelNone:"Forme intégrée",decorModelAdvanced:"Modèle depuis une adresse",decorModelUrl:"Adresse glTF/GLB",decorModelTitle:"Nom du modèle",decorModelAuthor:"Auteur",decorModelLicense:"Licence",decorModelSource:"Provenance",decorFloors:"Étages",decorOccupiedFloor:"Étage occupé",decorWitnessSide:"Emplacement du témoin",decorWitnessSideNone:"Non présent",decorWindows:"Fenêtres",decorSideFront:"Avant",decorSideBehind:"Arrière",decorSideLeft:"Gauche",decorSideRight:"Droite",decorSideFrontLeft:"Avant-gauche",decorSideFrontRight:"Avant-droit",decorSideBehindLeft:"Arrière-gauche",decorSideBehindRight:"Arrière-droit"},o={...e,testimonyBy:"Témoignage de",unnamedWitness:"Témoin {n}",about:"À propos",close:"Fermer",observation:"Observation",date:"Date",location:"Lieu",case:"Dossier",description:"Description",credits:"Crédits",editThisObservation:"Éditer cette observation",embed:"Intégrer",embedReplay:"Relecture",embedEdit:"Édition",embedCopy:"Copier",embedCopied:"Copié",showLabels:"Afficher ce qu'elle indique",hideLabels:"Masquer ce qu'elle indique"};export{o as sightingMessages_fr};