@rr0/ufoathome 0.152.0 → 0.152.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -664,7 +664,7 @@ ${x2.CSS}
|
|
|
664
664
|
margin: 0.4em 0 0;
|
|
665
665
|
padding-left: 1.2em;
|
|
666
666
|
}
|
|
667
|
-
`;class Gp{static NAMES=["weather","place","lightPollution","decor"];static KEYS={weather:["weatherTrack","weatherSource"],place:["place"],lightPollution:["lightPollution"],decor:["decor"]};static annexName(t,e){return`${t}.${e.replace(/[A-Z]/g,i=>`-${i.toLowerCase()}`)}.json`}static fromFile(t,e){return t?.[e]!==void 0&&t[e].live!==!0}}class Qc{static NAMES=["relief","imagery","roads","water","railways","upperAir","map"];static TERRAIN=["relief","imagery","roads","water","railways"];static held(t,e){if(!t||t.live)return;const i=t[e];return i&&!i.live&&!i.refresh&&i.src!==void 0?i:void 0}static isLive(t,e){return t?.live===!0||t?.[e]?.live===!0}static annexName(t,e){const i=e==="relief"||e==="imagery"||e==="map"?"zip":"json",n=e.replace(/[A-Z]/g,s=>`-${s.toLowerCase()}`);return`${t}.${n}.${i}`}static isEmpty(t){return!t||!t.live&&Qc.NAMES.every(e=>!t[e])&&Gp.NAMES.every(e=>!t[e])}}class sc extends Error{constructor(t,e,i){super(`${t}: ${e}${i===void 0?"":` (HTTP ${i})`}`),this.kind=t,this.url=e,this.status=i,this.name="SightingFetchError"}}class Ha{static async recording(t){const e=await Ha.json(t);for(const i of Gp.NAMES){const n=e?.frozen?.[i];if(!(!n?.src||n.live))try{const s=await Ha.json(new URL(n.src,new URL(t,location.href)).href);for(const r of Gp.KEYS[i])s[r]!==void 0&&(e[r]=s[r])}catch{}}return e}static async json(t){const e=new URL(t,location.href);if(location.protocol==="https:"&&e.protocol==="http:")throw new sc("mixed-content",t);let i;try{i=await fetch(t)}catch{throw await this.diagnose(t,e)}if(!i.ok)throw new sc("status",t,i.status);try{return await i.json()}catch{throw new sc("malformed",t)}}static async diagnose(t,e){if(e.origin===location.origin)return new sc("unreachable",t);try{return await fetch(t,{mode:"no-cors"}),new sc("cors",t)}catch{return new sc("unreachable",t)}}}class Kn{constructor(t){this.entries=t}static empty(){return new Kn(new Map)}get size(){return this.entries.size}at(t){return this.entries.get(t)}paths(){return[...this.entries.keys()]}set(t,e){e.basis==="stated"&&e.rationale===void 0&&e.how===void 0?this.entries.delete(t):this.entries.set(t,e)}clear(t){for(const e of this.entries.keys())(e===t||e.startsWith(`${t}.`))&&this.entries.delete(e)}static strip(t){const e=new Kn(new Map);return{recording:Kn.stripValue(t,[],e),provenance:e}}static restore(t,e){if(e.size===0)return t;const i={...t},n=new Set([i]);for(const s of e.paths()){const r=e.at(s),a=s.split("."),c=Kn.writableHolderOf(i,a,n);if(!c)continue;const h=a[a.length-1],l=c[h];l!==void 0&&(r.of!==void 0&&JSON.stringify(r.of)!==JSON.stringify(l)||(c[h]={value:l,...r.basis==="stated"?{}:{basis:r.basis},...r.rationale===void 0?{}:{rationale:r.rationale},...r.how===void 0?{}:{how:r.how}}))}return i}static isWrapper(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&"value"in t}static stripValue(t,e,i){return Kn.isWrapper(t)?(i.set(e.join("."),{basis:t.basis??"stated",...t.rationale===void 0?{}:{rationale:t.rationale},...t.how===void 0?{}:{how:t.how},of:t.value}),Kn.stripValue(t.value,e,i)):Array.isArray(t)?t.map((n,s)=>Kn.stripValue(n,[...e,String(s)],i)):typeof t=="object"&&t!==null?Object.fromEntries(Object.entries(t).map(([n,s])=>[n,Kn.stripValue(s,[...e,n],i)])):t}static writableHolderOf(t,e,i){let n=t;for(const s of e.slice(0,-1)){const r=n[s];if(typeof r!="object"||r===null)return;if(i.has(r)){n=r;continue}const a=Array.isArray(r)?[...r]:{...r};i.add(a),n[s]=a,n=a}return n}}class nw extends Error{constructor(t,e,i){super(typeof e=="number"&&Number.isInteger(e)&&e>i?`This ${t} file is in version ${e} of its format; this UFO@home reads up to version ${i}. Read it with a newer UFO@home.`:`This ${t} file states ${JSON.stringify(e)} as its format version, which is not a version.`),this.format=t,this.found=e,this.supported=i,this.name="FormatVersionError"}said(t){return t.replace("{found}",typeof this.found=="number"?String(this.found):JSON.stringify(this.found)).replace("{supported}",String(this.supported))}}class po{static CURRENT={sighting:1,case:1,interview:1};static SCHEMA_BASE="https://ufoathome.org/schema";static schemaUrl(t,e=po.CURRENT[t]){return`${po.SCHEMA_BASE}/${e}/${t}.schema.json`}static of(t){if(typeof t!="object"||t===null)return 1;const e=t.version;return e===void 0?1:typeof e=="object"&&e!==null&&"value"in e?e.value:e}static check(t,e){const i=po.of(t),n=po.CURRENT[e];if(typeof i!="number"||!Number.isInteger(i)||i<1||i>n)throw new nw(e,i,n);return t}}class sn{static SIGHTING_EVENT="sighting";static INTERPRETATION_EVENT="interpretation";static INTERVIEW_EVENT="interview";static check(t){return po.check(t,"case")}static isCase(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&Array.isArray(t.events)&&!("timeline"in t)}static sightingUrls(t,e){return(t.events??[]).filter(i=>i.eventType===sn.SIGHTING_EVENT&&!i.interpretationOf&&typeof i.url=="string"&&i.url!=="").map(i=>new URL(i.url,e).href)}static accountIds(t,e,i,n){const s=(t.events??[]).filter(r=>r.eventType===sn.SIGHTING_EVENT&&r.id!==void 0&&typeof r.url=="string"&&i!==void 0&&new URL(r.url,e).href===i).map(r=>r.id);return n!==void 0&&s.push(n),s}static interpretationEvents(t,e){const i=[e].flat().filter(n=>!!n);return i.length===0?[]:(t.events??[]).filter(n=>n.eventType===sn.INTERPRETATION_EVENT?n.sighting!==void 0&&i.includes(n.sighting):n.eventType!==sn.SIGHTING_EVENT||n.interpretationOf===void 0?!1:[n.interpretationOf].flat().some(s=>i.includes(s))).map(n=>n)}static problems(t,e){const i=t.events??[],n=new Set,s=new Set;for(const a of i)a.id!==void 0&&(n.has(a.id)&&s.add(a.id),n.add(a.id));const r=[];for(const a of i){const c=a.eventType===sn.SIGHTING_EVENT?a.interpretationOf:a.eventType===sn.INTERVIEW_EVENT?a.interviewOf:void 0;if(c!==void 0)for(const h of[c].flat())!n.has(h)&&!e.includes(h)&&r.push({reading:a.url??a.id??"",reference:h})}return{duplicateIds:[...s],unresolved:r}}static async interpretationOf(t,e,i){if(t.bodies)return sn.withModelsFrom(Kn.strip({title:t.title,bodies:t.bodies??[],smoke:t.smoke,flares:t.flares,lanterns:t.lanterns}).recording,e);if(!t.url)return{title:t.title,bodies:[]};const n=new URL(t.url,e).href,s=await i(n),r="timeline"in s&&s.interpretation?s.interpretation:s;return sn.withModelsFrom(Kn.strip({title:t.title??r.title,bodies:r.bodies??[],smoke:r.smoke,flares:r.flares,lanterns:r.lanterns}).recording,n)}static withModelsFrom(t,e){return{...t,bodies:t.bodies.map(i=>i.model?.url?{...i,model:{...i.model,url:new URL(i.model.url,e).href}}:i)}}}class th{static ISO=/^P(?:(\d+(?:[.,]\d+)?)W)?(?:(\d+(?:[.,]\d+)?)D)?(?:T(?:(\d+(?:[.,]\d+)?)H)?(?:(\d+(?:[.,]\d+)?)M)?(?:(\d+(?:[.,]\d+)?)S)?)?$/;static seconds(t){const e=t.trim().toUpperCase(),i=th.ISO.exec(e);if(!i||e==="P"||e.endsWith("T"))return;const[,n,s,r,a,c]=i,h=u=>u===void 0?0:Number(u.replace(",",".")),l=h(n)*604800+h(s)*86400+h(r)*3600+h(a)*60+h(c);return Number.isFinite(l)?l:void 0}static parse(t){let e=t.trim();if(e==="")return;const i=e.slice(-1),n="?~%".includes(i)?i:"";n!==""&&(e=e.slice(0,-1).trim());const s=e.split("/");if(s.length>2)return;const r=s.map(u=>th.seconds(u));if(r.some(u=>u===void 0))return;const[a,c]=r,h=Math.min(a,c??a),l=Math.max(a,c??a);return{doubt:n,minSeconds:h,maxSeconds:l,chosenSeconds:(h+l)/2}}static isExact(t){const e=th.parse(t);return e!==void 0&&e.doubt===""&&e.minSeconds===e.maxSeconds}static format(t){const e=Math.max(0,Math.round(t*10)/10),i=Math.floor(e/3600),n=Math.floor(e%3600/60),s=Math.round(e%60*10)/10;return`PT${`${i>0?`${i}H`:""}${n>0?`${n}M`:""}${s>0||i===0&&n===0?`${s}S`:""}`}`}static say(t){const e=Math.round(t*10)/10;if(e<60)return`${e} s`;const i=Math.floor(e/3600),n=Math.floor(e%3600/60),s=Math.round(e%60*10)/10,r=[];return i>0&&r.push(`${i} h`),n>0&&r.push(`${n} min`),s>0&&r.push(`${s} s`),r.join(" ")}}class Qe{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(t){return 2*Math.atan(t.sizeM/(2*t.distanceM))*180/Math.PI}static inMoons(t){return t/Qe.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(t,e,i){if(!(!t||!e))return{widthDeg:t.widthDeg+(e.widthDeg-t.widthDeg)*i,heightDeg:t.heightDeg+(e.heightDeg-t.heightDeg)*i}}static sizeMAt(t,e){return 2*t*Math.tan(e*Math.PI/360)}static distanceMAt(t,e){return t/(2*Math.tan(e*Math.PI/360))}}function sw(o,t,e){if(!o||!t)return e<1?o:t;const i=((t.azimuthDeg-o.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((o.azimuthDeg+i*e)%360+360)%360,altitudeDeg:o.altitudeDeg+(t.altitudeDeg-o.altitudeDeg)*e}}function rw(o,t,e){const{bounds:i}=o;return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}function ns(o,t,e){return o+(t-o)*e}function I1(o){const t=/^#([0-9a-f]{6})$/i.exec(o);if(!t)return;const e=parseInt(t[1],16);return[e>>16&255,e>>8&255,e&255]}function aw(o){return`#${o.map(t=>Math.round(t).toString(16).padStart(2,"0")).join("")}`}function ow(o,t,e){const i=I1(o),n=I1(t);return!i||!n?e<1?o:t:aw([ns(i[0],n[0],e),ns(i[1],n[1],e),ns(i[2],n[2],e)])}function cw(o,t,e){const i={x:ns(o.bounds.x,t.bounds.x,e),y:ns(o.bounds.y,t.bounds.y,e),width:ns(o.bounds.width,t.bounds.width,e),height:ns(o.bounds.height,t.bounds.height,e)},n=ns(o.angle,t.angle,e),s=ns(o.transparency,t.transparency,e),r=ns(o.haloScale,t.haloScale,e),a=ns(o.blur??0,t.blur??0,e),c=ns(o.brightness??0,t.brightness??0,e),h=ow(o.color,t.color,e),l=Qe.lerpAngular(o.angular,t.angular,e),u=sw(o.aim,t.aim,e);return o.kind==="polygon"&&t.kind==="polygon"&&o.points.length===t.points.length?{...o,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:c,color:h,angular:l,aim:u,points:o.points.map((d,f)=>({x:ns(d.x,t.points[f].x,e),y:ns(d.y,t.points[f].y,e)}))}:{...e<1?o:t,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:c,color:h,angular:l,aim:u}}class Ea{static DEFAULT_COLOR="#e8e6df";static complete(t,e=[]){const i=new Map;return t.map((n,s)=>({keyframe:n,index:s})).sort((n,s)=>n.keyframe.t-s.keyframe.t).map(({keyframe:n,index:s})=>({t:n.t,shapes:(n.shapes??[]).map((r,a)=>{const c=`timeline.keyframes.${s}.shapes.${a}.shape`,h=Ea.completed(r,i.get(r.sourceId),c,e);return i.set(r.sourceId,h),{sourceId:r.sourceId,shape:h}})}))}static thin(t,e){const i=new Map,n=new Set;return t.map((s,r)=>({t:s.t,shapes:s.shapes.map(a=>{const c=i.get(a.sourceId);if(i.set(a.sourceId,a.shape),!c)return{sourceId:a.sourceId,shape:a.shape};const h=Ea.thinned(a.shape,c);if(e){const l=h;e(r,a.sourceId)?(delete l.bounds,delete l.points,n.add(a.sourceId)):n.delete(a.sourceId)&&(l.bounds=a.shape.bounds,a.shape.kind==="polygon"&&(l.points=a.shape.points),a.shape.aim&&(l.aim=a.shape.aim),a.shape.angular&&(l.angular=a.shape.angular))}return{sourceId:a.sourceId,shape:h}})}))}static thinned(t,e){const i=e,n={};for(const[s,r]of Object.entries(t))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[s]&&JSON.stringify(r)!==JSON.stringify(i[s]))&&(n[s]=r);return"bounds"in n&&(t.aim&&(n.aim=t.aim),t.angular&&(n.angular=t.angular)),n}static completed(t,e,i,n){const s=t.shape??{},r=e??Ea.firstAppearance(s,i,n),a={...r};s.bounds&&e&&(e.aim||e.angular)&&!s.aim&&!s.angular&&n.push({kind:"pixels-over-angles",path:i}),s.bounds&&(s.aim||delete a.aim,s.angular||delete a.angular);const c=s.kind??r.kind??"oval",h={...a,...s,kind:c};if(c==="polygon"&&!h.points){n.push({kind:"defaulted",path:`${i}.points`,expected:"rectangle"});const{width:l,height:u}=h.bounds;return{...h,points:[{x:0,y:0},{x:l,y:0},{x:l,y:u},{x:0,y:u}]}}return h}static firstAppearance(t,e,i){return t.kind||i.push({kind:"defaulted",path:`${e}.kind`,expected:'"oval"'}),t.color||i.push({kind:"defaulted",path:`${e}.color`,expected:`"${Ea.DEFAULT_COLOR}"`}),!t.bounds&&!t.aim&&i.push({kind:"unplaced",path:e}),!t.bounds&&!t.angular&&i.push({kind:"unsized",path:e}),{kind:t.kind??"oval",bounds:{...Ea.NEUTRAL_BOUNDS},color:Ea.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:Qe.CANVAS_WIDTH_PX/2,y:Qe.CANVAS_HEIGHT_PX/2,width:1,height:1}}class Uf{keyframes=[];order=[];groups=[];span=0;addKeyframe(t,e){const i=this.findInsertIndex(t);if(this.keyframes[i]?.t===t){const n=new Set(e.map(s=>s.sourceId));this.keyframes[i]={t,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...e]}}else this.keyframes.splice(i,0,{t,shapes:[...e]});for(const n of e)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getKeyframeAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e];return i?.t===t?i:void 0}getShapeAt(t,e){return this.getKeyframeAt(t)?.shapes.find(i=>i.sourceId===e)?.shape}getLatestShapeAt(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return n.shape}}getInterpolatedShapeAt(t,e){const i=this.findShapeAtOrBefore(t,e);if(i?.t===t)return i.shape;const n=this.findShapeAtOrAfter(t,e);return i?n?cw(i.shape,n.shape,(t-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(t,e){for(let i=this.findInsertIndex(t);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(t,e,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const a=this.getInterpolatedShapeAt(t,s[r]);if(a&&rw(a,e,i))return{sourceId:s[r],shape:a}}}removeSource(t){for(let e=this.keyframes.length-1;e>=0;e--){const i=this.keyframes[e].shapes.filter(n=>n.sourceId!==t);i.length===0?this.keyframes.splice(e,1):i.length!==this.keyframes[e].shapes.length&&(this.keyframes[e]={t:this.keyframes[e].t,shapes:i})}this.order=this.order.filter(e=>e!==t),this.removeFromGroup(t)}removeShapeAt(t,e){const i=this.findInsertIndex(t),n=this.keyframes[i];if(n?.t!==t)return;const s=n.shapes.filter(r=>r.sourceId!==e);s.length===0?this.keyframes.splice(i,1):s.length!==n.shapes.length&&(this.keyframes[i]={t,shapes:s})}group(t){if(!(t.length<2)){for(const e of t)this.removeFromGroup(e);this.groups.push([...t])}}ungroup(t){const e=this.groups.findIndex(i=>i.includes(t));e!==-1&&this.groups.splice(e,1)}groupMembers(t){return this.groups.find(e=>e.includes(t))}removeFromGroup(t){const e=this.groups.findIndex(n=>n.includes(t));if(e===-1)return;const i=this.groups[e].filter(n=>n!==t);i.length<2?this.groups.splice(e,1):this.groups[e]=i}bringToFront(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.push(t))}sendToBack(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.unshift(t))}get duration(){const t=this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t;return Math.max(t,this.span)}get hasSpan(){return this.span>0}setSpan(t){this.span=Math.max(0,t)}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return this.span>0?{keyframes:this.keyframes,order:this.order,groups:this.groups,span:this.span}:{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(t,e){const i=new Uf;for(const n of Ea.complete(t.keyframes??[],e))i.addKeyframe(n.t,n.shapes);if(t.span!==void 0&&t.span>0&&(i.span=t.span),t.order){const n=i.order.filter(s=>!t.order.includes(s));i.order=[...t.order,...n]}return t.groups&&(i.groups=t.groups.map(n=>n.filter(s=>i.order.includes(s))).filter(n=>n.length>=2)),i}}function hw(o,t,e){return Math.max(t,Math.min(e,o))}function lw(o,t,e){const i=((t-o)%360+540)%360-180;return((o+i*e)%360+360)%360}function rc(o,t,e){return o+(t-o)*e}function uw(o,t,e){return{lat:o.lat===void 0||t.lat===void 0?void 0:rc(o.lat,t.lat,e),lng:o.lng===void 0||t.lng===void 0?void 0:rc(o.lng,t.lng,e),elevationM:rc(o.elevationM,t.elevationM,e),headingDeg:o.headingDeg===void 0||t.headingDeg===void 0?void 0:lw(o.headingDeg,t.headingDeg,e),pitchDeg:rc(o.pitchDeg,t.pitchDeg,e),rollDeg:rc(o.rollDeg??0,t.rollDeg??0,e),fovDeg:rc(o.fovDeg,t.fovDeg,e),fNumber:o.fNumber,focusDistanceM:o.focusDistanceM,filter:o.filter}}class Dn{static at(t,e,i,n,s){const r=t[i],c=t[i+1]-r;if(c<=0)return e[i];const h=Dn.tangent(t,e,i,s),l=Dn.tangent(t,e,i+1,s),u=(n-r)/c,d=u*u,f=d*u;return(2*f-3*d+1)*e[i]+(f-2*d+u)*c*h+(-2*f+3*d)*e[i+1]+(f-d)*c*l}static SETTLE_MS=120;static ARRIVAL=.5;static gaze(t,e,i,n){const s=t[i],a=t[i+1]-s;if(a<=0)return e[i];const c=l=>l+1<e.length?e[l+1]===e[l]:!0,h=e[i+1]!==e[i];if(h&&c(i+1)){const l=Dn.tangent(t,e,i,!0),u=Dn.ARRIVAL*(e[i+1]-e[i])/a;return Dn.hermite(e[i],l,e[i+1],u,a,(n-s)/a)}return!h&&i>0&&e[i-1]!==e[i]?e[i]+Dn.settle(t,e,i,n-s,a):Dn.at(t,e,i,n,!0)}static settle(t,e,i,n,s){const r=t[i]-t[i-1];if(r<=0||n<=0)return 0;const a=Dn.ARRIVAL*(e[i]-e[i-1])/r,c=Math.min(Dn.SETTLE_MS,.4*r),h=Number.isFinite(s)?(1-Math.min(1,n/s))**2:1;return a*n*Math.exp(-n/c)*h}static hermite(t,e,i,n,s,r){const a=r*r,c=a*r;return(2*c-3*a+1)*t+(c-2*a+r)*s*e+(-2*c+3*a)*i+(c-a)*s*n}static BRAKE_S=.8;static paced(t,e,i,n){if(!i&&!n)return t;const s=e>0?Math.min(.5,Dn.BRAKE_S/e):.5;if(i&&n){const a=1/(1-s);return t<=s?a*t*t/(2*s):t>=1-s?1-a*(1-t)*(1-t)/(2*s):a*(t-s/2)}const r=a=>{const c=1/(1-s/2);if(a<=1-s)return c*a;const h=a-(1-s);return c*(1-s)+c*(h-h*h/(2*s))};return n?r(t):1-r(1-t)}static tangent(t,e,i,n){const s=t.length-1,r=f=>(e[f+1]-e[f])/(t[f+1]-t[f]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-1);const a=r(i-1),c=r(i);if(a*c<=0)return 0;const h=t[i]-t[i-1],l=t[i+1]-t[i],u=2*l+h,d=l+2*h;return(u+d)/(u/a+d/c)}}class Cl{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,pose:e}:this.keyframes.splice(i,0,{t,pose:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestPoseAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].pose:void 0}getInterpolatedPoseAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.pose;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.pose;if(!n)return this.settledAfterEnd(e-1,t);const s=uw(i.pose,n.pose,hw((t-i.t)/(n.t-i.t),0,1));return this.humanly(e-1,t,s)}settledAfterEnd(t,e){const i=this.keyframes[t];if(t<1)return i.pose;const n=this.keyframes[t-1],s=[n.t,i.t],r=(l,u)=>l===void 0||u===void 0?0:Dn.settle(s,[l,u],1,e-i.t,1/0),a=n.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-n.pose.headingDeg)%360+540)%360-180,c=i.pose.headingDeg===void 0||a===void 0?i.pose.headingDeg:((i.pose.headingDeg+r(0,a))%360+360)%360,h=i.pose.pitchDeg+r(n.pose.pitchDeg,i.pose.pitchDeg);return c===i.pose.headingDeg&&h===i.pose.pitchDeg?i.pose:{...i.pose,headingDeg:c,pitchDeg:h}}humanly(t,e,i){const n=Math.max(0,t-1),s=Math.min(this.keyframes.length-1,t+2),r=this.keyframes.slice(n,s+1),a=t-n,c=r.map(M=>M.t),h=(M,b)=>{const S=r.map(_=>M(_.pose));if(!S.some(_=>_===void 0))return Dn.at(c,S,a,e,b)},l=M=>{const b=r.map(S=>M(S.pose));if(!b.some(S=>S===void 0))return Dn.gaze(c,b,a,e)},u=r.map(M=>M.pose.headingDeg);let d;if(u.every(M=>M!==void 0)){const M=[u[0]];for(let b=1;b<u.length;b++)M.push(M[b-1]+((u[b]-u[b-1])%360+540)%360-180);d=(Dn.gaze(c,M,a,e)%360+360)%360}const f=this.keyframes[t],p=this.keyframes[t+1],g=(M,b)=>M.lat===b.lat&&M.lng===b.lng&&M.elevationM===b.elevationM,m=!g(f.pose,p.pose),v=m&&t>0&&g(this.keyframes[t-1].pose,f.pose),y=m&&t+2<this.keyframes.length&&g(p.pose,this.keyframes[t+2].pose);let x;if(v||y){const M=Dn.paced((e-f.t)/(p.t-f.t),(p.t-f.t)/1e3,v,y),b=(S,_)=>S===void 0||_===void 0?void 0:S+(_-S)*M;x={lat:b(f.pose.lat,p.pose.lat),lng:b(f.pose.lng,p.pose.lng),elevationM:b(f.pose.elevationM,p.pose.elevationM)}}return{...i,lat:x?x.lat:h(M=>M.lat,!1)??i.lat,lng:x?x.lng:h(M=>M.lng,!1)??i.lng,elevationM:x?x.elevationM:h(M=>M.elevationM,!1)??i.elevationM,headingDeg:d??i.headingDeg,pitchDeg:l(M=>M.pitchDeg)??i.pitchDeg,rollDeg:h(M=>M.rollDeg??0,!0)??i.rollDeg,fovDeg:h(M=>M.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Cl;for(const i of t.keyframes)e.addKeyframe(i.t,i.pose);return e}}class Aa{static MAX_CHANGE_PER_S=.05;points;followed;constructor(t){let e="none",i=0;this.points=t.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(e=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:e,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(Aa.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.t)/1e3))}}at(t){if(this.points.length===0||t<this.points[0].t)return;let e=this.points.length-1;for(;e>0&&this.points[e].t>t;)e--;const i=this.points[e],n=this.points[e+1],s=n?Aa.follow(this.followed[e],i.intensity,n.intensity,(n.t-i.t)/1e3,(t-i.t)/1e3):Aa.follow(this.followed[e],i.intensity,i.intensity,1,(t-i.t)/1e3);return{type:Aa.typeBetween(i,n,t,s),intensity:s,character:Aa.characterBetween(i,n,t)}}static characterBetween(t,e,i){return t.type==="none"?e&&e.type!=="none"?e.intensity:t.lastFallingIntensity:!e||e.type==="none"?t.intensity:t.intensity+(e.intensity-t.intensity)*(i-t.t)/(e.t-t.t||1)}static typeBetween(t,e,i,n){return t.type==="none"?e&&e.type!=="none"&&i>t.t?e.type:n>0?t.lastFalling:"none":e&&e.type==="none"&&n<=0?"none":t.type}static follow(t,e,i,n,s){const r=Aa.MAX_CHANGE_PER_S,a=n>0?(i-e)/n:0,c=u=>e+a*Math.min(Math.max(u,0),n);let h=t,l=0;for(let u=0;u<8&&l<s;u++){const d=c(l)-h;if(Math.abs(d)<1e-9){const x=l<n?a:0;if(Math.abs(x)<=r){const b=l<n?Math.min(s,n):s;h=c(b),l=b;continue}const M=Math.min(s,n);h+=Math.sign(x)*r*(M-l),l=M;continue}const f=Math.sign(d),p=l<n?a:0,g=r-f*p,m=g>0?l+Math.abs(d)/g:1/0,v=l<n?n:1/0,y=Math.min(s,m,v);h+=f*r*(y-l),l=y,y===m&&(h=c(l))}return Math.min(1,Math.max(0,h))}}const xg=1e3,dw=.65,fw=.05,Ff={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function Cd(o){if(o.cloudLayers!==void 0)return o.cloudLayers;const t=[],e=o.lowerCloudCover??o.cloudCover;return e>0&&t.push({id:"lower",type:"cumulus",baseM:o.cloudBaseM??xg,thicknessM:650,coverage:e,sizeM:1400,density:1,darkness:o.cloudDarkness}),(o.highCloudCover??0)>0&&t.push({id:"cirrus",type:"cirrus",baseM:8e3,thicknessM:400,coverage:o.highCloudCover,sizeM:2200,density:.35,darkness:o.cloudDarkness,iceCrystalAlignment:o.iceCrystalAlignment}),t}function gi(o,t,e){return o+(t-o)*e}function bg(o,t,e){const i=((t-o)%360+540)%360-180;return((o+i*e)%360+360)%360}function pw(o,t,e){return Math.max(t,Math.min(e,o))}function mw(o=[],t=[],e){if(!(!o.length&&!t.length))return[...new Set([...o.map(i=>i.id),...t.map(i=>i.id)])].map(i=>{const n=o.find(c=>c.id===i),s=t.find(c=>c.id===i),r=n??{...s,density:0},a=s??{...n,density:0};return{...r,eastM:gi(r.eastM,a.eastM,e),northM:gi(r.northM,a.northM,e),baseM:gi(r.baseM,a.baseM,e),thicknessM:gi(r.thicknessM,a.thicknessM,e),widthM:gi(r.widthM,a.widthM,e),depthM:gi(r.depthM,a.depthM,e),rotationDeg:bg(r.rotationDeg,a.rotationDeg,e),density:gi(r.density,a.density,e),darkness:gi(r.darkness??0,a.darkness??0,e)}})}function gw(o,t,e){if(o.cloudLayers===void 0&&t.cloudLayers===void 0)return;const i=Cd(o),n=Cd(t);return e>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const a=i.find(u=>u.id===r),c=n.find(u=>u.id===r),h=a??{...c,coverage:0},l=c??{...a,coverage:0};return{...h,instances:mw(a?.instances,c?.instances,e),baseM:gi(h.baseM,l.baseM,e),thicknessM:gi(h.thicknessM,l.thicknessM,e),coverage:gi(h.coverage,l.coverage,e),sizeM:gi(h.sizeM,l.sizeM,e),density:gi(h.density,l.density,e),darkness:gi(h.darkness??o.cloudDarkness,l.darkness??t.cloudDarkness,e),iceCrystalAlignment:h.iceCrystalAlignment===void 0||l.iceCrystalAlignment===void 0?void 0:gi(h.iceCrystalAlignment,l.iceCrystalAlignment,e),windSpeed:h.windSpeed===void 0&&l.windSpeed===void 0?void 0:gi(h.windSpeed??o.windSpeed,l.windSpeed??t.windSpeed,e),windDirectionDeg:h.windDirectionDeg===void 0&&l.windDirectionDeg===void 0?void 0:bg(h.windDirectionDeg??o.windDirectionDeg,l.windDirectionDeg??t.windDirectionDeg,e)}})}function vw(o,t,e){return{cloudLayers:gw(o,t,e),cloudCover:gi(o.cloudCover,t.cloudCover,e),cloudDarkness:gi(o.cloudDarkness,t.cloudDarkness,e),highCloudCover:o.highCloudCover===void 0||t.highCloudCover===void 0?void 0:gi(o.highCloudCover,t.highCloudCover,e),iceCrystalAlignment:o.iceCrystalAlignment===void 0||t.iceCrystalAlignment===void 0?void 0:gi(o.iceCrystalAlignment,t.iceCrystalAlignment,e),rareIceCrystals:o.rareIceCrystals===void 0||t.rareIceCrystals===void 0?void 0:gi(o.rareIceCrystals,t.rareIceCrystals,e),lowerCloudCover:o.lowerCloudCover===void 0||t.lowerCloudCover===void 0?void 0:gi(o.lowerCloudCover,t.lowerCloudCover,e),cloudBaseM:o.cloudBaseM===void 0||t.cloudBaseM===void 0?void 0:gi(o.cloudBaseM,t.cloudBaseM,e),relativeHumidity:o.relativeHumidity===void 0||t.relativeHumidity===void 0?void 0:gi(o.relativeHumidity,t.relativeHumidity,e),precipitationType:e<1?o.precipitationType:t.precipitationType,precipitationIntensity:gi(o.precipitationIntensity,t.precipitationIntensity,e),windDirectionDeg:bg(o.windDirectionDeg,t.windDirectionDeg,e),windSpeed:gi(o.windSpeed,t.windSpeed,e),storm:e<1?o.storm:t.storm}}class Ol{keyframes=[];ramp;addKeyframe(t,e){this.ramp=void 0;const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,weather:e}:this.keyframes.splice(i,0,{t,weather:e})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(t){this.ramp=void 0;const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestWeatherAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].weather:void 0}getInterpolatedWeatherAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.weather;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];return i?n?vw(i.weather,n.weather,pw((t-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(t){const e=this.getInterpolatedWeatherAt(t);if(!e)return;const i=(this.ramp??=new Aa(this.keyframes)).at(t);if(!i)return e;const{type:n,intensity:s,character:r}=i,a=r>0?Math.min(1,s/r):n==="none"?0:1;return{...e,precipitationType:n,precipitationIntensity:r,precipitationAmount:a}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Ol;for(const i of t.keyframes)e.addKeyframe(i.t,{...Ff,...i.weather});return e}}class Pl{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,sound:e}:this.keyframes.splice(i,0,{t,sound:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}getLatestSoundAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].sound:void 0}getInterpolatedSoundAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.sound;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.sound;if(!n)return i.sound;const s=(t-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Pl;for(const i of t.keyframes)e.addKeyframe(i.t,i.sound);return e}lerp(t,e,i){return{kind:i<1?t.kind:e.kind,volume:t.volume+(e.volume-t.volume)*i,pitchHz:t.pitchHz+(e.pitchHz-t.pitchHz)*i,src:i<1?t.src:e.src}}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}}const Mw=100,yw={kind:"none",volume:0,pitchHz:Mw};class Uc{static DEFAULT_FOCAL_MM=50;static FOCAL_RANGE_MM={minMm:14,maxMm:135};static BODIES=[{id:"eos-450d",name:"Canon EOS 450D (APS-C)",widthMm:22.2,heightMm:14.8,pixelUm:5.2,year:2008},{id:"eos-60da",name:"Canon EOS 60Da (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.3,year:2012},{id:"eos-70d",name:"Canon EOS 70D (APS-C)",widthMm:22.5,heightMm:15,pixelUm:4.1,year:2013},{id:"eos-80d",name:"Canon EOS 80D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:3.7,year:2016},{id:"eos-7d",name:"Canon EOS 7D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.1,year:2009},{id:"eos-7d-ii",name:"Canon EOS 7D Mark II (APS-C)",widthMm:22.4,heightMm:15,pixelUm:4.1,year:2014},{id:"eos-5d",name:"Canon EOS 5D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:8.2,year:2005},{id:"eos-5d-ii",name:"Canon EOS 5D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:6.4,year:2008},{id:"eos-5d-iii",name:"Canon EOS 5D Mark III (full frame)",widthMm:36,heightMm:24,pixelUm:6.25,year:2012},{id:"eos-5d-iv",name:"Canon EOS 5D Mark IV (full frame)",widthMm:36,heightMm:24,pixelUm:5.36,year:2016},{id:"eos-6d",name:"Canon EOS 6D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:6.55,year:2012},{id:"eos-6d-ii",name:"Canon EOS 6D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:5.77,year:2017},{id:"nikon-d3",name:"Nikon D3 / D700 (full frame)",widthMm:36,heightMm:23.9,pixelUm:8.44,year:2007},{id:"nikon-d7000",name:"Nikon D7000 (DX)",widthMm:23.6,heightMm:15.6,pixelUm:4.78,year:2010},{id:"nikon-d7100",name:"Nikon D7100 / D7200 (DX)",widthMm:23.5,heightMm:15.6,pixelUm:3.9,year:2013},{id:"nikon-d500",name:"Nikon D500 / D7500 (DX)",widthMm:23.5,heightMm:15.7,pixelUm:4.2,year:2016}];static instruments(){return Uc.BODIES.map(t=>({id:t.id,category:"dslr",name:t.name,projection:"rectilinear",frame:{widthMm:t.widthMm,heightMm:t.heightMm,focalLengthMm:Uc.DEFAULT_FOCAL_MM,focalRangeMm:Uc.FOCAL_RANGE_MM},fNumber:8,fNumberRange:{min:1.4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/8e3,max:3600},years:{from:t.year},apertureBlades:7,detailUm:t.pixelUm,medium:{kind:"sensor",iso:100}}))}static names(){return Object.fromEntries(Uc.BODIES.map(t=>[t.id,t.name]))}}class Gs{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*Gs.DEFAULT_EYEPIECE_MM*Math.tan(Gs.DEFAULT_APPARENT_FIELD_DEG*Math.PI/360);static RANGE={min:26/40*.63,max:26/6*3};static BINOCULARS=[{id:"binoculars-zeiss-6x30",name:"Carl Zeiss 6x30",magnification:6,apertureMm:30,trueFieldDeg:5,fromYear:1960},{id:"binoculars-zeiss-dialyt-10x40",name:"Carl Zeiss Dialyt 10x40 B T*",magnification:10,apertureMm:40,trueFieldDeg:6.3,fromYear:1975},{id:"binoculars-jenoptem-10x50",name:"Jenoptem 10x50 W",magnification:10,apertureMm:50,trueFieldDeg:7.3,fromYear:1960},{id:"binoculars-swarovski-7x50-habicht",name:"Swarovski 7x50 SL Habicht",magnification:7,apertureMm:50,trueFieldDeg:6.6,fromYear:1960},{id:"binoculars-swarovski-7x50-slc",name:"Swarovski 7x50 SLC",magnification:7,apertureMm:50,trueFieldDeg:7.1,fromYear:1990},{id:"binoculars-nikon-10x42-edg",name:"Nikon 10x42 EDG",magnification:10,apertureMm:42,trueFieldDeg:6.5,fromYear:2011},{id:"binoculars-canon-15x50-is",name:"Canon 15x50 IS All Weather",magnification:15,apertureMm:50,trueFieldDeg:4.5,fromYear:2008},{id:"binoculars-celestron-15x70",name:"Celestron 15x70 SkyMaster",magnification:15,apertureMm:70,trueFieldDeg:4.4,fromYear:1990},{id:"binoculars-miyauchi-25x141",name:"Miyauchi BR-141 Galaxy 45 25x141",magnification:25,apertureMm:141,trueFieldDeg:2.6,fromYear:2e3}];static TELESCOPES=[{id:"telescope-generic-60-700",name:"Telescope 60/700",apertureMm:60,focalLengthMm:700},{id:"telescope-generic-60-1000",name:"Telescope 60/1000",apertureMm:60,focalLengthMm:1e3},{id:"telescope-celestron-onyx-80edf",name:"Celestron Onyx 80EDF",apertureMm:80,focalLengthMm:500,fromYear:2010},{id:"telescope-celestron-c5",name:"Celestron C5 f/10",apertureMm:125,focalLengthMm:1250,fromYear:1970},{id:"telescope-celestron-c8",name:"Celestron C8 f/10",apertureMm:203,focalLengthMm:2032,fromYear:1970},{id:"telescope-celestron-c11",name:"Celestron C11 f/10",apertureMm:280,focalLengthMm:2800,fromYear:1970},{id:"telescope-celestron-c14",name:"Celestron C14 f/11",apertureMm:355.6,focalLengthMm:3910,fromYear:1970},{id:"telescope-meade-etx-80",name:"Meade ETX 80 f/5",apertureMm:80,focalLengthMm:400,fromYear:1996},{id:"telescope-meade-etx-90",name:"Meade ETX 90 f/13.8",apertureMm:90,focalLengthMm:1242,fromYear:1996},{id:"telescope-meade-etx-125",name:"Meade ETX 125 f/15",apertureMm:127,focalLengthMm:1900,fromYear:1996},{id:"telescope-meade-lx200-8",name:"Meade LX200 8 in f/10",apertureMm:200,focalLengthMm:2e3,fromYear:1992},{id:"telescope-meade-lx200-10",name:"Meade LX200 10 in f/10",apertureMm:250,focalLengthMm:2500,fromYear:1992},{id:"telescope-meade-lx200-12",name:"Meade LX200 12 in f/10",apertureMm:305,focalLengthMm:3048,fromYear:1992},{id:"telescope-meade-lx200-14",name:"Meade LX200 14 in f/10",apertureMm:355,focalLengthMm:3556,fromYear:1992},{id:"telescope-meade-lx200-16",name:"Meade LX200 16 in f/10",apertureMm:406,focalLengthMm:4064,fromYear:1992}];static instruments(){const t=Gs.BINOCULARS.map(n=>({id:n.id,category:"binoculars",name:n.name,projection:"rectilinear",visualAid:{apertureMm:n.apertureMm,magnification:n.magnification,trueFieldDeg:n.trueFieldDeg},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}})),e=Gs.FIELD_STOP_MM,i=Gs.TELESCOPES.map(n=>({id:n.id,category:"telescope",name:n.name,projection:"rectilinear",frame:{widthMm:e*16/9,heightMm:e,focalLengthMm:n.focalLengthMm,focalRangeMm:{minMm:n.focalLengthMm*Gs.RANGE.min,maxMm:n.focalLengthMm*Gs.RANGE.max}},visualAid:{apertureMm:n.apertureMm,eyepieceFocalMm:Gs.DEFAULT_EYEPIECE_MM},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}}));return[...t,...i]}static names(){return Object.fromEntries(Gs.instruments().map(t=>[t.id,t.name]))}}const nu=[{id:"eye",category:"eye",name:"Naked eye",projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",category:"camera",name:"Camera, unknown device",projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"roamer-1-120",category:"camera",name:"Roamer 1, 120 film",projection:"rectilinear",frame:{widthMm:74,heightMm:60,focalLengthMm:100},fNumber:11,exposureSeconds:1/50,years:{from:1930,to:1965},detailUm:40,medium:{kind:"negative",iso:125}},{id:"instamatic-126",category:"camera",name:"Instamatic, 126 film",projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20,medium:{kind:"negative",iso:64}},{id:"slr-35mm-50",category:"camera",name:"35 mm SLR, 50 mm lens",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20,medium:{kind:"negative",iso:100}},{id:"slr-35mm-zoom",category:"camera",name:"35 mm SLR, 70-210 mm zoom",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20,medium:{kind:"negative",iso:100}},{id:"phone-landscape",category:"phone",name:"Phone, held sideways",projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"phone-portrait",category:"phone",name:"Phone, held upright",projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"dashcam",category:"video",name:"Dashcam",projection:"equidistant",frame:{widthMm:5.76,heightMm:3.24,focalLengthMm:3.2},fNumber:2,exposureSeconds:1/30,exposureRangeSeconds:{min:1/1e4,max:1/30},years:{from:2008},apertureBlades:void 0,detailUm:3,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},{id:"cctv",category:"video",name:"Security camera",projection:"rectilinear",frame:{widthMm:4.8,heightMm:3.6,focalLengthMm:3.6},fNumber:2,exposureSeconds:1/50,exposureRangeSeconds:{min:1/1e5,max:1/50},years:{from:1990},apertureBlades:void 0,detailUm:6,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},...Uc.instruments(),...Gs.instruments()];class Ti{static get default(){return nu[0]}static byId(t){return nu.find(e=>e.id===t)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(t){const e=t.frame;return e?Ti.fieldOf(t.projection,e.heightMm,e.focalLengthMm):t.visualAid?.trueFieldDeg??Ti.UNAIDED_FIELD_DEG}static fieldOf(t,e,i){return(t==="equidistant"?e/i:2*Math.atan(e/(2*i)))*180/Math.PI}static aspectOf(t){const e=t.frame;return e?e.widthMm/e.heightMm:Ti.UNAIDED_ASPECT}static frameWidthPx(t,e){return Math.round(e*Ti.aspectOf(t))}static CATEGORIES=["eye","camera","dslr","phone","video","binoculars","telescope"];static unavailability(t,e){const i=t.years;if(!(e===void 0||!i)){if(e<i.from)return{kind:"before",from:i.from};if(i.to!==void 0&&e>i.to)return{kind:"after",to:i.to}}}static availableAt(t){return t===void 0?nu:nu.filter(e=>!e.years||t>=e.years.from&&(e.years.to===void 0||t<=e.years.to))}static fieldOfViewDegAt(t,e){const i=t.frame;if(!(!i||e<=0))return Ti.fieldOf(t.projection,i.heightMm,e)}static focalLengthMmFor(t,e){const i=t.frame;if(!(!i||e<=0||e>=180))return t.projection==="equidistant"?i.heightMm/(e*Math.PI/180):i.heightMm/(2*Math.tan(e*Math.PI/360))}static bladesShowing(t,e){if(t.apertureBlades===void 0)return 0;const i=e??t.fNumber,n=t.fNumberRange?.min;if(i===void 0||n===void 0)return 1;const s=Math.max(0,Math.min(1,(i/n-1)/.3));return s*s*(3-2*s)}static starPointsOf(t,e){const i=t.apertureBlades;return i===void 0||i<3||Ti.bladesShowing(t,e)<.5?0:i%2===0?i:i*2}}class Wo extends Error{}class zf{constructor(t){this.name=t}validate(t){return!0}}class b2 extends zf{min;max;constructor(t,e,i){super(t),this.min=e,this.max=i}validate(t){if(typeof t!="number")throw new Wo(`${this.name} value must be a number, but was ${t}`);if(t<this.min||t>this.max)throw new Wo(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${t}`);return super.validate(t)}}class ji{name;min;max;duration;subUnit;validator;constructor(t,e,i,n,s=new b2(t,e,i)){this.name=t,this.min=e,this.max=i,this.subUnit=n,this.duration=n?(n.max-n.min+1)*n.duration:1,this.validator=s}validate(t){return this.validator.validate(t)}[Symbol.iterator](){let t=this.min;return{next:()=>{const e={done:t>this.max,value:t};return t++,e}}}}class w2{millisecond;second;minute;hour;day;month;year}class xw extends w2{}class S2 extends xw{millisecond=new ji("millisecond",0,999,void 0);second=new ji("second",0,59,this.millisecond);minute=new ji("minute",0,59,this.second);hour=new ji("hour",0,23,this.minute);day=new ji("day",1,31,this.hour);month=new ji("month",1,12,this.day);year=new ji("year",0,9999,this.month)}const ae=new S2;class bw extends b2{constructor(t=1,e=12){super("month",t,e)}}class Rr{static instance=new Rr;render(t){return t.value.toString()}}class Pn{unit;#t;constructor(t,e){this.unit=e,this.value=typeof t=="number"?t:t.value}get value(){return this.#t}set value(t){this.unit.validate(t),this.#t=t}get duration(){return this.value*this.unit.duration}#e(t){if(this.constructor.name!==t.constructor.name)throw new zf(`${this.unit.name} "${this.toString()}" cannot be compared with ${t.unit?.name} "${t.toString()}"`)}compare(t){return this.#e(t),this.value-t.value}isEqual(t){return this.compare(t)===0}isBefore(t){return this.compare(t)<0}isAfter(t){return this.compare(t)>0}previous(t=this.unit){const e=this.value-1;return new this.constructor(e,t)}next(t=this.unit){const e=this.value+1;return new this.constructor(e,t)}toString(t=Rr.instance){return t.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class li{static#t=new Map;static register(t,e){li.#t.set(t,e)}static get(t){const e=li.#t.get(t);if(!e)throw new Wo(`No default parser registered for ${t.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return e()}}class Od extends Pn{constructor(t=new Date().getFullYear(),e=ae.year){super(t,e)}static fromString(t,e=li.get(Od)){return new Od(e.parse(t))}}class Gr extends Rr{static default=new Gr("0",2);constructor(t,e){super(),this.char=t,this.size=e}render(t){return super.render(t).padStart(this.size,this.char)}}class Pd extends Pn{constructor(t=new Date().getMonth()+1,e=ae.month){super(t,e)}static fromString(t,e=li.get(Pd)){return new Pd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class Ld extends Pn{constructor(t=new Date().getDate(),e=ae.day){super(t,e)}static fromString(t,e=li.get(Ld)){const i=e.parse(t);return new Ld(i)}toString(t=Gr.default){return super.toString(t)}}class Nd extends Pn{constructor(t=new Date().getHours(),e=ae.hour){super(t,e)}static fromString(t,e=li.get(Nd)){return new Nd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class kd extends Pn{constructor(t=new Date().getMinutes(),e=ae.minute){super(t,e)}static fromString(t,e=li.get(kd)){return new kd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class Ud extends Pn{constructor(t=new Date().getSeconds(),e=ae.second){super(t,e)}static fromString(t,e=li.get(Ud)){return new Ud(e.parse(t),ae.second)}toString(t=Gr.default){return super.toString(t)}}class tc extends Pn{static renderer=new Gr("0",3);constructor(t,e=ae.millisecond){super(t,e)}static parseFraction(t){return parseInt(t.padEnd(3,"0").substring(0,3),10)}toString(t=tc.renderer){return super.toString(t)}}class ww{render(t){return t.toString()}}class Sw extends ww{render(t){const e=t.value,i=Math.abs(e),n=Math.floor(i/60),s=i%60;if(n===0&&s===0)return"Z";{const r=e<0?"-":"+",a=n.toString().padStart(2,"0"),c=s>0?":"+s.toString().padEnd(2,"0"):"";return r+a+c}}}class fh{value;name="timeshift";renderer;constructor(t=0){this.value=t}static fromString(t,e=li.get(fh),i=void 0){const n=e.parse(t,i);return new fh(n)}toString(t=new Sw){return t.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class In{static timeshift(t,e){return t+(In.isDaylight(e)?60:0)}static isDaylight(t){const{year:e,month:i,day:n}=t,s=t.hour??12;if(![e,i,n].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=In.rule(e);if(!r)return!1;const a=In.rank(i,n,s);return a>=In.rank(r.start.month,r.start.day,2)&&a<In.rank(r.end.month,r.end.day,2)}static rule(t){if(t<1967)return;const e={month:10,day:In.sunday(t,10,-1)};return t>=2007?{start:{month:3,day:In.sunday(t,3,2)},end:{month:11,day:In.sunday(t,11,1)}}:t>=1987?{start:{month:4,day:In.sunday(t,4,1)},end:e}:t===1975?{start:{month:2,day:23},end:e}:t===1974?{start:{month:1,day:6},end:e}:{start:{month:4,day:In.sunday(t,4,-1)},end:e}}static sunday(t,e,i){const n=new Date(Date.UTC(2e3,e-1,1));n.setUTCFullYear(t);const s=1+(7-n.getUTCDay())%7;if(i>0)return s+7*(i-1);const r=[31,In.isLeap(t)?29:28,31,30,31,30,31,31,30,31,30,31][e-1];let a=s;for(;a+7<=r;)a+=7;return a}static isLeap(t){return t%4===0&&(t%100!==0||t%400===0)}static rank(t,e,i){return(t*100+e)*100+i}}const Ew={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},Aw={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},_w={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},Tw={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},Rw={name:"PT",timeshift:o=>In.timeshift(-480,o),title:"Pacific Time (US)"},Iw={name:"MT",timeshift:o=>In.timeshift(-420,o),title:"Mountain Time (US)"},Dw={name:"CT",timeshift:o=>In.timeshift(-360,o),title:"Central Time (US)"},Cw={name:"ET",timeshift:o=>In.timeshift(-300,o),title:"Eastern Time (US)"},Ow={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},Pw={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},Lw={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},Nw={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},kw={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},Uw={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},Fw={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},zw={name:"Z",timeshift:"Z",title:"UTC"},Bw={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},Hw={name:"BST",timeshift:"+01",title:"British Summer Time"},Gw={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},Vw={name:"CET",timeshift:"+01",title:"Central European Time"},Ww={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},Xw={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},$w={name:"BJT",timeshift:"+08",title:"Beijing Time"},Yw={name:"CST",timeshift:"-06",title:"Central Standard Time"},Kw={name:"JST",timeshift:"+09",title:"Japan Standard Time"},qw={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},Zw={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},Jw={name:"LST",timeshift:"?",title:"Local Sideral Time"},D1=[Uw,qw,kw,$w,Hw,Yw,Pw,Vw,Gw,Dw,Ow,Nw,Lw,Cw,Bw,Xw,Kw,Jw,_w,Ww,Tw,Iw,Zw,Aw,Ew,Rw,Fw,zw];class Bf{static instance=new Bf;renderComponent(t,e){return t[e].toString()}renderSecond(t){return this.renderComponent(t,"second")+(t.millisecond?"."+t.millisecond.toString():"")}render(t){const e=[];t.year&&e.push(this.renderComponent(t,"year")),t.month&&e.push(this.renderComponent(t,"month")),t.day&&e.push(this.renderComponent(t,"day"));const i=[];t.hour&&i.push(this.renderComponent(t,"hour")),t.minute&&i.push(this.renderComponent(t,"minute")),t.second&&i.push(this.renderSecond(t));const n=e.join("-"),s=t.timeshift?t.timeshift.toString():"",r=i.join(":")+s;return n+(r.length>0?"T"+r:"")}}class ro extends Wo{constructor(t="method is abstract"){super(t)}}class wg{units;constructor(t){this.units=t}newYear(t){throw new ro}newMonth(t){throw new ro}newDay(t){throw new ro}newHour(t){throw new ro}newMinute(t){throw new ro}newSecond(t){throw new ro}}class jw extends w2{millisecond=new ji("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new ji("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new ji("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new ji("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new ji("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new ji("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new ji("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Sg=new jw;class Eg{static instance=new Eg;render(t){const e=mo.toSpec(t);let i="P";const n=e.years;n&&(i+=n.toString()+"Y");const s=e.months;s&&(i+=s.toString(Rr.instance)+"MM");const r=e.days;r&&(i+=r.toString(Rr.instance)+"D");const a=e.hours;a&&(i+=a.toString(Rr.instance)+"H");const c=e.minutes;c&&(i+=c.toString(Rr.instance)+"M");const h=e.seconds;return h&&(i+=h.toString(Rr.instance)+"S"),i}}class mo extends Pn{constructor(t={years:new Date().getFullYear(),months:new Date().getMonth(),days:new Date().getDate(),hours:new Date().getHours(),minutes:new Date().getMinutes(),seconds:new Date().getSeconds(),milliseconds:new Date().getMilliseconds()}){super({value:typeof t=="number"?t:+(t.years?t.years*ae.year.duration:0)+(t.months?t.months*ae.month.duration:0)+(t.days?t.days*ae.day.duration:0)+(t.hours?t.hours*ae.hour.duration:0)+(t.minutes?t.minutes*ae.minute.duration:0)+(t.seconds?t.seconds*ae.second.duration:0)},new ji("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(t,e=tS){let i=typeof t=="number"?t:t.value;const n=i>0?1:-1;i=Math.abs(i);const s={},r=i/ae.year.duration,a=Math.floor(r);a>0&&(s.years=e.newYear(n*a),i-=a*ae.year.duration);const c=i/ae.month.duration,h=Math.floor(c);h>0&&(s.months=e.newMonth(n*h),i-=h*ae.month.duration);const l=i/ae.day.duration,u=Math.floor(l);u>0&&(s.days=e.newDay(n*u),i-=u*ae.day.duration);const d=i/ae.hour.duration,f=Math.floor(d);f>0&&(s.hours=e.newHour(n*f),i-=f*ae.hour.duration);const p=i/ae.minute.duration,g=Math.floor(p);g>0&&(s.minutes=e.newMinute(n*g),i-=g*ae.minute.duration);const m=i/ae.second.duration,v=Math.floor(n*m);return v>0&&(s.seconds=e.newSecond(v)),s}static fromString(t,e=li.get(mo)){return new mo(e.parse(t))}static between(t,e){const i=e.getTime(),n=t.getTime();return new mo(i-n)}toSpec(){return mo.toSpec(this)}toString(t=Eg.instance){return t.render(this)}}class E2 extends wg{constructor(t){super(t)}newYear(t){return new Od(t,this.units.year)}newMonth(t){return new Pd(t,this.units.month)}newDay(t){return new Ld(t,this.units.day)}newHour(t){return new Nd(t,this.units.hour)}newMinute(t){return new kd(t,this.units.minute)}newSecond(t){return new Ud(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new fh(typeof t=="number"?t:t.value)}}const Qw=new E2(ae),tS=new E2(Sg);class Ks{#t;#e;#i;#n;#s;#r;#a;#o;constructor(t={year:new Date().getFullYear(),month:new Date().getMonth()+1,day:new Date().getDate(),hour:new Date().getHours(),minute:new Date().getMinutes(),second:new Date().getSeconds(),timeshift:Ks.timeshiftOf(new Date)}){this.year=t.year,this.month=t.month,this.day=t.day,this.hour=t.hour,this.minute=t.minute,this.second=t.second,this.millisecond=t.millisecond,this.timeshift=t.timeshift}get year(){return this.#t}set year(t){const e=typeof t=="number";this.#t&&e?this.#t.value=t:this.#t=e?this.factory.newYear(t):!t||t.start||t instanceof Pn?t:this.factory.newYear(t)}get month(){return this.#e}set month(t){const e=typeof t=="number";this.#e&&e?this.#e.value=t:this.#e=e?this.factory.newMonth(t):!t||t.start||t instanceof Pn?t:this.factory.newMonth(t)}get day(){return this.#i}set day(t){const e=typeof t=="number";this.#i&&e?this.#i.value=t:this.#i=e?this.factory.newDay(t):!t||t.start||t instanceof Pn?t:this.factory.newDay(t)}get hour(){return this.#n}set hour(t){const e=typeof t=="number";this.#n&&e?this.#n.value=t:this.#n=e?this.factory.newHour(t):!t||t.start||t instanceof Pn?t:this.factory.newHour(t)}get minute(){return this.#s}set minute(t){const e=typeof t=="number";this.#s&&e?this.#s.value=t:this.#s=e?this.factory.newMinute(t):!t||t.start||t instanceof Pn?t:this.factory.newMinute(t)}get second(){return this.#r}set second(t){const e=typeof t=="number";this.#r&&e?this.#r.value=t:this.#r=e?this.factory.newSecond(t):!t||t.start||t instanceof Pn?t:this.factory.newSecond(t)}get millisecond(){return this.#a}set millisecond(t){const e=typeof t=="number";this.#a&&e?this.#a.value=t:this.#a=e||t&&!(t instanceof Pn)?this.factory.newMillisecond(t):t}get timeshift(){return this.#o}set timeshift(t){const e=typeof t=="number";this.#o&&e?this.#o.value=t:this.#o=e||t&&!(t instanceof fh)?this.factory.newTimeshift(t):t}get factory(){return Qw}static fromString(t,e=li.get(Ks)){const{year:i,month:n,day:s,hour:r,minute:a,second:c,millisecond:h,timeshift:l}=e.parse(t);return new Ks({year:i,month:n,day:s,hour:r,minute:a,second:c,millisecond:h,timeshift:l})}static timeshiftOf(t){return-t.getTimezoneOffset()||0}static fromDate(t){return new Ks({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return Ks.fromString(i)}#c(t){if(this.constructor.name!==t.constructor.name)throw new zf(`Date "${this.toString()}" cannot be compared with "${t.toString()}"`)}compare(t){return this.#c(t),this.getTime()-t.getTime()}delta(t){const e=this.compare(t);return new mo(e)}getTime(){return(this.year?.duration||0)+(this.month?.duration||0)+(this.day?.duration||0)+(this.hour?.duration||0)+(this.minute?.duration||0)+(this.second?.duration||0)+(this.millisecond?.duration||0)}isEqual(t){return this.compare(t)===0}isBefore(t){return this.compare(t)<0}isAfter(t){return this.compare(t)>0}clone(){return new Ks(this.toSpec())}previous(){let t=this.clone();try{t.second=this.second.previous()}catch{try{t.minute=this.minute.previous()}catch{try{t.hour=this.hour.previous()}catch{try{t.day=this.day.previous()}catch{try{t.month=this.month.previous()}catch{t.year=this.year.previous()}}}}}return t}next(){let t=this.clone();try{t.second=this.second.next()}catch{try{t.minute=this.minute.next()}catch{try{t.hour=this.hour.next()}catch{try{t.day=this.day.next()}catch{try{t.month=this.month.next()}catch{t.year=this.year.next()}}}}}return t}toString(t=Bf.instance){return t.render(this)}toSpec(){const t={},e=this.year?.toSpec();e&&(t.year=e);const i=this.month?.toSpec();i&&(t.month=i);const n=this.day?.toSpec();n&&(t.day=n);const s=this.hour?.toSpec();s&&(t.hour=s);const r=this.minute?.toSpec();r&&(t.minute=r);const a=this.second?.toSpec();a&&(t.second=a);const c=this.millisecond?.toSpec();c&&(t.millisecond=c);const h=this.timeshift?.toSpec();return h&&(t.timeshift=h),t}toJSON(){return this.toSpec()}}class Zl extends Rr{static instance=new Zl(Gr.default);constructor(t){super(),this.valueRenderer=t}render(t){return(this.valueRenderer?this.valueRenderer.render(t):super.render(t))+this.qualifier(t)}qualifier(t){return t.uncertain?t.approximate?"%":"?":t.approximate?"~":""}}class ec extends Pn{#t;#e;constructor(t,e){super(t,e),this.#t=t.uncertain||!1,this.#e=t.approximate||!1}get uncertain(){return this.#t}set uncertain(t){return this.#t=t}get approximate(){return this.#e}set approximate(t){return this.#e=t}isCertainAndPrecise(){return!this.approximate&&!this.uncertain}isEqual(t){return this.isCertainAndPrecise()&&super.isEqual(t)}isBefore(t){return this.isCertainAndPrecise()&&super.isBefore(t)}isAfter(t){return this.isCertainAndPrecise()&&super.isAfter(t)}toString(t=Zl.instance){return super.toString(t)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class A2 extends S2{year=new ji("year",-9999,9999,this.month);yearExtended=new ji("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const md=new A2;class go extends ec{constructor(t,e=md.year){super(t,e)}static fromString(t,e=md.year,i=li.get(go)){const n=i.parse(t),s=n.value.start;if(t.startsWith("Y")&&(e=md.yearExtended),s!==void 0){const r=new go(Object.assign({...n},{value:Math.max(s,e.min)})),a=new go(Object.assign({...n},{value:Math.min(n.value.end,e.max)}));return{start:r,end:a}}else return new go(n,e)}}class _2 extends zf{monthValidator=new bw;validate(t){switch(t){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(t)}}}class vo extends ec{constructor(t,e=new ji(ae.month.name,1,24,ae.day,new _2)){super(t,e)}static fromString(t,e=li.get(vo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.month;const r=new vo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new vo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new vo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Mo extends ec{constructor(t,e=ae.day){super(t,e)}static fromString(t,e=li.get(Mo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.day;const r=new Mo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Mo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Mo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class yo extends ec{constructor(t,e=ae.hour){super(t,e)}static fromString(t,e=li.get(yo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.hour;const r=new yo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new yo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new yo(i)}}class xo extends ec{constructor(t,e=ae.minute){super(t,e)}static fromString(t,e=li.get(xo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.minute,r=new xo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new xo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new xo(i)}toString(t=Zl.instance){return super.toString(t)}}class bo extends ec{constructor(t,e=ae.second){super(t,e)}static fromString(t,e=li.get(bo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.second,r=new bo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new bo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new bo(i)}}class ph extends fh{static fromString(t,e=li.get(ph),i=void 0){return new ph(e.parse(t,i))}}class T2 extends wg{constructor(t){super(t)}newYear(t){return new go(t,this.units.year)}newMonth(t){return new vo(t,this.units.month)}newDay(t){return new Mo(t,this.units.day)}newHour(t){return new yo(t,this.units.hour)}newMinute(t){return new xo(t,this.units.minute)}newSecond(t){return new bo(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new ph(typeof t=="number"?t:t.value)}}const eS=new T2(md);new T2(Sg);class oo extends Ks{constructor(t){super(t)}get factory(){return eS}get uncertain(){return this.year?.uncertain===!0||this.month?.uncertain===!0||this.day?.uncertain===!0||this.hour?.uncertain===!0||this.minute?.uncertain===!0||this.second?.uncertain===!0}get approximate(){return this.year?.approximate===!0||this.month?.approximate===!0||this.day?.approximate===!0||this.hour?.approximate===!0||this.minute?.approximate===!0||this.second?.approximate===!0}static fromDate(t){return new oo({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static fromString(t,e=li.get(oo)){const i=e.parse(t);return new oo(i)}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return oo.fromString(i)}clone(){return new oo(this.toSpec())}}class Ah extends ec{uncertainComponent;approximateComponent;constructor(t,e){super(t,e),this.uncertainComponent=t.uncertainComponent||!1,this.approximateComponent=t.approximateComponent||!1}get uncertain(){return super.uncertain||this.uncertainComponent}set uncertain(t){return super.uncertain=t}get approximate(){return super.approximate||this.approximateComponent}set approximate(t){return super.approximate=t}get uncertainGroup(){return super.uncertain}get approximateGroup(){return super.approximate}toSpec(){return{...super.toSpec(),uncertain:this.uncertainGroup,approximate:this.approximateGroup,uncertainComponent:this.uncertainComponent,approximateComponent:this.approximateComponent}}toJSON(){return this.toSpec()}}class iS extends A2{year=new ji("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Vp=new iS;class wo extends Ah{constructor(t,e=Vp.year){super(t,e)}static fromString(t,e=Vp.year,i=li.get(wo)){const n=i.parse(t),s=n.value.start;if(s!==void 0){const r=new wo(Object.assign({...n},{value:Math.max(s,e.min)})),a=new wo(Object.assign({...n},{value:Math.min(n.value.end,e.max)})),c={start:r,end:a},h=n.value.estimate;return h&&(c.estimate=h),c}else return new wo(n)}}class nS extends _2{validate(t){switch(t){case 25:case 26:case 27:case 28:case 29:case 30:case 31:case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:return!0;default:return super.validate(t)}}}class So extends Ah{constructor(t,e=new ji(ae.month.name,1,41,ae.day,new nS)){super(t,e)}static fromString(t,e=li.get(So)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.month,r=new So(Object.assign({...i},{value:Math.max(n,s.min)})),a=new So(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new So(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Eo extends Ah{constructor(t,e=ae.day){super(t,e)}static fromString(t,e=li.get(Eo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.day,r=new Eo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Eo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Eo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Ao extends Ah{constructor(t,e=ae.hour){super(t,e)}static fromString(t,e=li.get(Ao)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.hour,r=new Ao(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Ao(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Ao(i)}}class _o extends Ah{constructor(t,e=ae.minute){super(t,e)}static fromString(t,e=li.get(_o)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.minute,r=new _o(Object.assign({...i},{value:Math.max(n,s.min)})),a=new _o(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new _o(i)}}class To extends Ah{constructor(t,e=ae.second){super(t,e)}static fromString(t,e=ae.second,i=li.get(To)){const n=i.parse(t),s=n.value.start;if(s!==void 0){const r=new To(Object.assign({...n},{value:Math.max(s,e.min)})),a=new To(Object.assign({...n},{value:Math.min(n.value.end,e.max)}));return{start:r,end:a}}else return new To(n,e)}}class R2 extends ph{}class sS extends Zl{qualifier(){return""}}class _a extends Bf{static instance=new _a;static valueRenderer=new sS(Gr.default);static names=["year","month","day","hour","minute","second"];static qualifier(t,e){return t?e?"%":"?":e?"~":""}renderComponent(t,e){const i=t[e],n=_a.names.slice(_a.names.indexOf(e)+1).map(a=>t[a]).filter(Boolean),s=_a.qualifier(i.uncertainComponent,i.approximateComponent),r=_a.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!n.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!n.some(a=>a.approximate));return s+i.toString(_a.valueRenderer)+r}}class I2 extends wg{constructor(t){super(t)}newYear(t){return new wo(t,this.units.year)}newMonth(t){return new So(t,this.units.month)}newDay(t){return new Eo(t,this.units.day)}newHour(t){return new Ao(t,this.units.hour)}newMinute(t){return new _o(t,this.units.minute)}newSecond(t){return new To(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new R2(typeof t=="number"?t:t.value)}}const rS=new I2(Vp);new I2(Sg);class co extends oo{constructor(t){super(t)}toString(t=_a.instance){return super.toString(t)}get year(){return super.year}set year(t){super.year=t}get month(){return super.month}set month(t){super.month=t}get factory(){return rS}static fromDate(t){return new co({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static fromString(t,e=li.get(co)){const i=e.parse(t);return new co(i)}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return co.fromString(i)}clone(){return new co(this.toSpec())}}class Hf{regExp;constructor(t,e){this.name=t,this.regExp=new RegExp(`^(?:${e})$`)}regexGroups(t){const e=this.regExp.exec(t);if(!e)throw new Wo(`Invalid ${this.name} "${t}"`);return e.groups}parseGroups(t){throw new ro(`${this.constructor.name} is abstract`)}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}class Ag extends Hf{constructor(t,e){super(t,e)}static read(t){return{value:t?parseInt(t,10):void 0}}parseGroups(t){return Ag.read(t[this.name])}parse(t){if(t.startsWith("-"))throw new Wo(`${this.name} cannot be negative`);return super.parse(t)}}class ct{static groupName(...t){return t.reduce((e,i)=>e?e+i.charAt(0).toUpperCase()+i.substring(1):i,"")}static group(t,...e){return`(?<${t}>${e.join("")})`}static optional(t){return t+"?"}static nonCapturingGroup(...t){return`(?:${t.join("")})`}static optionalGroup(t,...e){return ct.optional(ct.group(t,...e))}static optionalNonCapturingGroup(...t){return ct.optional(ct.nonCapturingGroup(...t))}static numberGroup(t,e,i,n="\\d"){return ct.group(t,`${i||""}[${n}]${e}`)}}const C1="timeshiftValue",O1="shiftHour",P1="shiftMinute";class _g extends Hf{static format(t=""){return D1.map(e=>e.name).join("|")+"|"+ct.nonCapturingGroup(ct.group(t+O1,ct.numberGroup(ct.groupName(t,C1),"{2}","[+-]")),ct.optionalNonCapturingGroup(":?",ct.numberGroup(ct.groupName(t,P1),"{2}",void 0)))}constructor(){super(C1,_g.format())}parse(t,e){let i=0;const n=D1.find(s=>s.name===t);if(n){if(typeof n.timeshift=="function")try{return n.timeshift(e??{})}catch(s){throw new Wo(`The time zone ${t} depends on the date: ${s.message}`)}t=n.timeshift}if(t!=="Z"){const s=this.regexGroups(t),r=s[O1];r&&(i+=parseInt(r,10)*60);const a=s[P1];a&&(i+=parseInt(a,10))}return i}}class _i extends Ag{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=_i.uncertainGroup+_i.approximateGroup;constructor(t,e){super(t,e)}static qualifierFormat(t,e){return ct.optionalGroup(t,`\\${e}`)}static formatSuffix(t){return this.qualifierFormat(ct.groupName(_i.uncertainGroup,t),"?")+this.qualifierFormat(ct.groupName(_i.approximateGroup,t),"~")+this.qualifierFormat(ct.groupName(_i.uncertainAndApproximateGroup,t),"%")}static numberFormat(t,e,i){return ct.numberGroup(t,e,i,"\\dX")+this.formatSuffix(t)}getValueAndSign(t){let e=t[this.name],i;return e.charAt(0)==="-"?(i=-1,e=e.substring(1)):i=1,{valueStr:e,sign:i}}parseGroups(t){const{valueStr:e,sign:i}=this.getValueAndSign(t);let n=0,s;for(s=0;s<e.length;s++){const h=e[s];if(h==="X")break;n=n*10+parseInt(h,10)}if(s<e.length){let h=1;for(let d=0;d<e.length-s;d++)h*=10;const l=i*n*h,u=l+h-1;n={start:l,end:u}}else n*=i;const r=t[ct.groupName(_i.uncertainAndApproximateGroup,this.name)],a=t[ct.groupName(_i.approximateGroup,this.name)]||r,c=t[ct.groupName(_i.uncertainGroup,this.name)]||r;return{value:n,approximate:a?!!a:!1,uncertain:c?!!c:!1}}}const L1="yearValue";class Fd extends _i{constructor(){super(L1,Fd.format())}static format(t=""){return"Y?"+_i.numberFormat(ct.groupName(t,L1),"+","[-]?")}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}const N1="monthValue";class zd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,N1),"{1,2}",void 0)}constructor(){super(N1,zd.format())}}const k1="dayValue";class Bd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,k1),"{1,2}",void 0)}constructor(){super(k1,Bd.format())}}const U1="hourValue";class Hd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,U1),"{1,2}",void 0)}constructor(){super(U1,Hd.format())}}const F1="minuteValue";class Gd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,F1),"{1,2}",void 0)}constructor(){super(F1,Gd.format())}}const z1="secondValue";class Vd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,z1),"{1,2}",void 0)}constructor(){super(z1,Vd.format())}}class Wd extends _g{}class tn extends Hf{static yearGroup="year";static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(t=tn.format()){super("date",t)}static format(t=""){return ct.group(ct.groupName(t,tn.yearGroup),Fd.format(t))+ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,tn.monthGroup),zd.format(t)),ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,tn.dayGroup),Bd.format(t)),ct.optionalNonCapturingGroup("[T ]",ct.group(ct.groupName(t,tn.hourGroup),Hd.format(t)),":",ct.group(ct.groupName(t,tn.minuteGroup),Gd.format(t)),ct.optionalNonCapturingGroup(":",ct.group(ct.groupName(t,tn.secondGroup),Vd.format(t)),ct.optionalNonCapturingGroup("[.,]",ct.group(ct.groupName(t,tn.millisecondGroup),"\\d+"))),ct.optionalGroup(ct.groupName(t,tn.timeshiftGroup),Wd.format(t)))))}parseGroups(t){const e=t[tn.millisecondGroup],i=e?tc.parseFraction(e):void 0,n=t[tn.secondGroup],s=n?bo.fromString(n,new Vd):void 0,r=t[tn.minuteGroup];let a;r&&(a=xo.fromString(r,new Gd),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const c=t[tn.hourGroup];let h;c&&(h=yo.fromString(c,new Hd),h.uncertain=h.uncertain||a?.uncertain||!1,h.approximate=h.approximate||a?.approximate||!1);const l=t[tn.dayGroup];let u;l&&(u=Mo.fromString(l,new Bd),u.uncertain=u.uncertain||h?.uncertain||!1,u.approximate=u.approximate||h?.approximate||!1);const d=t[tn.monthGroup];let f;d&&(f=vo.fromString(d,new zd),f.uncertain=f.uncertain||u?.uncertain||!1,f.approximate=f.approximate||u?.approximate||!1);const p=t[tn.yearGroup];let g;p&&(g=go.fromString(p,void 0,new Fd),g.uncertain=g.uncertain||f?.uncertain||!1,g.approximate=g.approximate||f?.approximate||!1);const m=t[tn.timeshiftGroup],v=m?ph.fromString(m,new Wd,{year:g?.value,month:f?.value,day:u?.value,hour:h?.value}):void 0;return{year:g,month:f,day:u,hour:h,minute:a,second:s,millisecond:i,timeshift:v}}}class Wi extends _i{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=Wi.uncertainGroup+Wi.approximateGroup;constructor(t,e){super(t,e)}static numberFormat(t,e,i){return this.qualifierFormat(ct.groupName(Wi.uncertainGroup,t),"?")+this.qualifierFormat(ct.groupName(Wi.approximateGroup,t),"~")+this.qualifierFormat(ct.groupName(Wi.uncertainAndApproximateGroup,t),"%")+_i.numberFormat(t,e,i)}parseGroups(t){const e=super.parseGroups(t),i=t[ct.groupName(Wi.uncertainAndApproximateGroup,this.name)];return(t[ct.groupName(Wi.uncertainGroup,this.name)]||i)&&(e.uncertainComponent=!0),(t[ct.groupName(Wi.approximateGroup,this.name)]||i)&&(e.approximateComponent=!0),e}}const Ch="yearValue",B1="exp",H1="signif";class Xd extends Wi{constructor(){super(Ch,Xd.format())}static format(t=""){return"Y?"+ct.nonCapturingGroup(ct.group(ct.groupName(t,B1),"[-]?\\d+E\\d+")+"|"+Wi.numberFormat(ct.groupName(t,Ch),"+","[-]?")+ct.optionalGroup(ct.groupName(t,H1),"S\\d+"))}parseGroups(t){const e=t[B1];if(e){const r=e.indexOf("E"),a=parseInt(e.substring(r+1),10),h=parseInt(e.substring(0,r),10)*Math.pow(10,a);t[Ch]=h.toString()}const i=t[H1],n=t[Ch];if(i){const r=parseInt(i.substring(1),10),{valueStr:a,sign:c}=this.getValueAndSign(t);let h="";for(let l=0;l<a.length;l++)h+=l<r?a.charAt(l):"X";t[Ch]=(c<0?"-":"")+h}const s=super.parseGroups(t);return i&&(s.value.estimate=parseInt(n,10)),s}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}const G1="monthValue";class $d extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,G1),"{1,2}",void 0)}constructor(){super(G1,$d.format())}}const V1="dayValue";class Yd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,V1),"{1,2}",void 0)}constructor(){super(V1,Yd.format())}}const W1="hourValue";class Kd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,W1),"{1,2}",void 0)}constructor(){super(W1,Kd.format())}}const X1="secondValue";class qd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,X1),"{1,2}",void 0)}constructor(){super(X1,qd.format())}}const $1="minuteValue";class Zd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,$1),"{1,2}",void 0)}constructor(){super($1,Zd.format())}}class aS extends Wd{}class en extends Hf{static yearGroup=tn.yearGroup;static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(){super("date",en.format())}static format(t=""){return ct.group(ct.groupName(t,en.yearGroup),Xd.format(t))+ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,en.monthGroup),$d.format(t)),ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,en.dayGroup),Yd.format(t)),ct.optionalNonCapturingGroup("[T ]",ct.group(ct.groupName(t,en.hourGroup),Kd.format(t)),":",ct.group(ct.groupName(t,en.minuteGroup),Zd.format(t)),ct.optionalNonCapturingGroup(":",ct.group(ct.groupName(t,en.secondGroup),qd.format(t)),ct.optionalNonCapturingGroup("[.,]",ct.group(ct.groupName(t,en.millisecondGroup),"\\d+"))),ct.optionalGroup(ct.groupName(t,en.timeshiftGroup),aS.format(t)))))}parseGroups(t){const e=t[en.millisecondGroup],i=e?tc.parseFraction(e):void 0,n=t[en.secondGroup];let s;n&&(s=To.fromString(n,void 0,new qd),s.uncertain=s?.uncertain||!1,s.approximate=s?.approximate||!1);const r=t[en.minuteGroup];let a;r&&(a=_o.fromString(r,new Zd),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const c=t[en.hourGroup];let h;c&&(h=Ao.fromString(c,new Kd),h.uncertain=h.uncertain||a?.uncertain||!1,h.approximate=h.approximate||a?.approximate||!1);const l=t[en.dayGroup];let u;l&&(u=Eo.fromString(l,new Yd),u.uncertain=u.uncertain||h?.uncertain||!1,u.approximate=u.approximate||h?.approximate||!1);const d=t[en.monthGroup];let f;d&&(f=So.fromString(d,new $d),f.uncertain=f.uncertain||u?.uncertain||!1,f.approximate=f.approximate||u?.approximate||!1);const p=t[en.yearGroup];let g;p&&(g=wo.fromString(p,void 0,new Xd),g.uncertain=g.uncertain||f?.uncertain||!1,g.approximate=g.approximate||f?.approximate||!1);const m=t[en.timeshiftGroup],v=m?R2.fromString(m,new Wd,{year:g?.value,month:f?.value,day:u?.value,hour:h?.value}):void 0;return{year:g,month:f,day:u,hour:h,minute:a,second:s,millisecond:i,timeshift:v}}}const D2=["spring","summer","autumn","winter"],Wp=21,oS=32,cS=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let hS;function lS(){return hS??=new en}function ac(o){return typeof o?.value=="number"?o.value:void 0}function h0(o){const t=o.trim();if(/^\d{1,2}:/.test(t)){const r=cS.exec(t)?.groups;return r?{year:void 0,month:void 0,day:void 0,hour:Number(r.hour),minute:Number(r.minute),second:r.second?Number(r.second):void 0,raw:t}:void 0}let e;try{e=co.fromString(t,lS())}catch{return}const i=ac(e.year),n=ac(e.month),s=n!==void 0&&n>=Wp&&n<=oS;if(!(e.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(n!==void 0&&n>12&&!s)&&!(s&&(e.day||e.hour)))return{year:i,month:s?void 0:n,...s?{season:D2[(n-Wp)%4]}:{},day:ac(e.day),hour:ac(e.hour),minute:ac(e.minute),second:ac(e.second),raw:t}}function nl(o){if(o.raw!==void 0)return o.raw;if(o.year===void 0){if(o.hour===void 0)return"";let e=`${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`;return o.second!==void 0&&(e+=`:${String(o.second).padStart(2,"0")}`),e}let t=String(o.year).padStart(4,"0");return o.season!==void 0?`${t}-${Wp+D2.indexOf(o.season)}`:(o.month===void 0||(t+=`-${String(o.month).padStart(2,"0")}`,o.day===void 0)||(t+=`-${String(o.day).padStart(2,"0")}`,o.hour===void 0)||(t+=`T${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`,o.second!==void 0&&(t+=`:${String(o.second).padStart(2,"0")}`)),t)}function Xp(o){if(o.year!==void 0)return Date.UTC(o.year,(o.month??1)-1,o.day??1,o.hour??0,o.minute??0,o.second??0)}function Y1(o){return(((o.day??0)*24+(o.hour??0))*60+(o.minute??0))*6e4+(o.second??0)*1e3}const uS=["year","month","day","hour","minute"],dS=["day","hour","minute"];function K1(o,t){return t.filter(e=>o[e]!==void 0).join(",")}function C2(o){if(o.durationSeconds!==void 0)return o.durationSeconds*1e3;const t=o.durationText===void 0?void 0:th.parse(o.durationText);if(t)return t.chosenSeconds*1e3;if(!o.time||!o.endTime)return;const e=o.time.year!==void 0&&o.endTime.year!==void 0,i=e?uS:dS,n=K1(o.time,i);if(!(n===""||n!==K1(o.endTime,i)))return e?Xp(o.endTime)-Xp(o.time):Y1(o.endTime)-Y1(o.time)}class Gf{constructor(t,e,i,n,s,r,a,c,h=[],l,u,d,f=[],p=[],g=[],m=[]){this.event=t,this.timeline=e,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,this.observer=r,this.id=a,this.weather=c,this.decor=h,this.weatherSource=l,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p,this.roads=g,this.traces=m}provenance=Kn.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;metering;lens;vehicle;get observerCount(){return 1+this.decor.filter(t=>t.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Ti.byId(this.instrumentId)}static create(t,e,i){return new Gf({eventType:"sighting",time:t,place:e},new Uf,new Cl,new Ol,new Pl,i)}}const fS=0,pS=0;function ze(o,t){const e=o.observerTrack.getInterpolatedPoseAt(t);if(e)return e;const i=o.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:fS,headingDeg:void 0,pitchDeg:pS,fovDeg:Ti.fieldOfViewDeg(o.instrument)}}function Lc(o,t){return o.weatherTrack.getInterpolatedWeatherAt(t)??o.weather??Ff}function Oh(o,t){return o.weatherTrack.getActualWeatherAt(t)??o.weather??Ff}function O2(o,t){return o.soundTrack.getInterpolatedSoundAt(t)??yw}class ms{constructor(t,e,i,n="en"){this.parts=t,this.messages=e,this.onChange=i,this.locale=n,this.setMessages(e),t.text.addEventListener("input",()=>{this.readText(),this.showDeduction()}),t.picker.addEventListener("change",()=>this.writeFromPicker()),t.mode.addEventListener("click",()=>this.setPrecise(!this.precise)),t.text.addEventListener("blur",()=>this.validate()),t.text.addEventListener("focus",()=>this.showDeduction())}precise=!0;hint="";get isPrecise(){return this.precise}setMessages(t,e=this.locale){this.messages=t,this.locale=e,t.edtfPlaceholder!==void 0&&(this.parts.text.placeholder=t.edtfPlaceholder),this.parts.mode.title=t.edtfModeTitle,this.parts.mode.setAttribute("aria-label",t.edtfModeTitle),this.setPrecise(this.precise)}setPrecise(t){this.precise=t,this.parts.picker.hidden=!t,this.parts.text.hidden=t,this.parts.mode.textContent=t?this.messages.datePrecise:this.messages.dateEdtf,this.parts.mode.setAttribute("aria-pressed",String(!t)),this.parts.help&&(this.parts.help.hidden=t),this.showDeduction()}set(t){const{text:e,picker:i}=this.parts;e.value=t?nl(t):"",i.type!=="date"&&(i.step=ms.stepFor(t)),i.value=i.type==="date"?ms.pickerDateOf(t):ms.pickerValueOf(t),e.setCustomValidity(""),e.classList.remove("invalid"),this.showDeduction()}static opensPrecise(...t){return t.every(e=>e===void 0||ms.isPickable(e)&&ms.qualifierOf(nl(e))==="")}static opensPreciseDate(...t){return t.every(e=>e===void 0||ms.isFullDate(e)&&ms.qualifierOf(nl(e))==="")}static isFullDate(t){return!!t&&t.year!==void 0&&t.month!==void 0&&t.day!==void 0}static pickerDateOf(t){if(!ms.isFullDate(t))return"";const e=(i,n=2)=>String(i).padStart(n,"0");return`${e(t.year,4)}-${e(t.month)}-${e(t.day)}`}static isPickable(t){return!!t&&t.year!==void 0&&t.month!==void 0&&t.day!==void 0&&t.hour!==void 0&&t.minute!==void 0}static pickerValueOf(t){if(!ms.isPickable(t))return"";const e=(n,s=2)=>String(n).padStart(s,"0"),i=t.second?`:${e(t.second)}`:"";return`${e(t.year,4)}-${e(t.month)}-${e(t.day)}T${e(t.hour)}:${e(t.minute)}${i}`}static stepFor(t){return t?.second?"1":"60"}static qualifierOf(t){const e=/[?%]/.test(t),i=/[~%]/.test(t);return e&&i?"%":e?"?":i?"~":""}describe(t){return ms.describeTime(t,this.messages,this.locale)}static describeTime(t,e,i){const n=nl(t),s=ms.qualifierOf(n),r=l=>String(l).padStart(2,"0"),a=[];if(t.season!==void 0){const l={spring:e.timeSeasonSpring,summer:e.timeSeasonSummer,autumn:e.timeSeasonAutumn,winter:e.timeSeasonWinter}[t.season];a.push(t.year!==void 0?`${l} ${t.year}`:l)}else if(t.year!==void 0){const l=t.day!==void 0?{...t.year>=1583?{weekday:"long"}:{},year:"numeric",month:"long",day:"numeric"}:t.month!==void 0?{year:"numeric",month:"long"}:{year:"numeric"},u=new Date(Date.UTC(t.year,(t.month??1)-1,t.day??1));a.push(new Intl.DateTimeFormat(i,{...l,timeZone:"UTC"}).format(u))}t.hour!==void 0&&a.push(`${r(t.hour)}:${r(t.minute??0)}${t.second!==void 0?`:${r(t.second)}`:""}`);const c=a.join(", "),h=s==="~"?e.timeQualifierApproximate:s==="?"?e.timeQualifierUncertain:s==="%"?e.timeQualifierBoth:"";return h?`${c} — ${h.toLowerCase()}`:c}setHint(t){this.hint=t,this.showDeduction()}showDeduction(){const{text:t}=this.parts,e=t.value.trim();if(this.precise||e===""){t.title=this.hint;return}const i=h0(e);t.title=i?`→ ${this.describe(i)}`:this.messages.edtfInvalid}readText(){const t=this.parts.text.value.trim();if(t===""){this.clean(),this.onChange(void 0);return}const e=h0(t);e&&(this.clean(),this.onChange(e))}clean(){this.parts.text.setCustomValidity(""),this.parts.text.classList.remove("invalid")}writeFromPicker(){const{picker:t,text:e}=this.parts;t.value===""&&t.validity.badInput||(e.value=t.value===""?"":t.value.replace(/\.\d+$/,""),this.readText())}validate(){const{text:t}=this.parts,e=t.value.trim();e===""||h0(e)||(t.setCustomValidity(this.messages.edtfInvalid),t.classList.add("invalid"))}}class Pr{static read(t,e){let i=t;for(const n of e.split(".")){if(i=Pr.bare(i),i===null||typeof i!="object")return;i=i[n]}return Pr.bare(i)}static write(t,e,i){const n=e.split("."),s=[];let r=t;for(let c=0;c<n.length-1;c++){let h=Pr.bare(r[n[c]]);if(h===null||typeof h!="object"||Array.isArray(h)){if(i===void 0)return;h={}}r[n[c]]=h,s.push({owner:r,part:n[c]}),r=h}const a=n[n.length-1];i===void 0?delete r[a]:r[a]=i;for(let c=s.length-1;c>=0;c--){const h=s[c].owner[s[c].part];if(Object.keys(h).length>0)break;delete s[c].owner[s[c].part]}}static stated(t,e){return Pr.read(t,e)!==void 0}static bare(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)&&"value"in t&&"basis"in t?t.value:t}}class Xo{static MODES=["off","position","dipped","main","fog"];static DISPLAY_GAIN=.006;static TOE_IN_DEG=.6;static AUTO_BELOW_SUN_DEG=-1;static BEAMS={off:void 0,position:void 0,dipped:{candela:25e3,halfAngleDeg:24,pitchDeg:2.5,penumbra:1,color:"#fff2d8"},main:{candela:12e4,halfAngleDeg:14,pitchDeg:.4,penumbra:.85,color:"#fff6e6"},fog:{candela:9e3,halfAngleDeg:38,pitchDeg:5,penumbra:1,color:"#ffe9b0"}};static isMode(t){return typeof t=="string"&&Xo.MODES.includes(t)}static at(t,e,i){if(!e||e.length===0)return t;let n=e[0];for(const s of e){if(s.t>i)break;n=s}return n.mode}static auto(t){return t<Xo.AUTO_BELOW_SUN_DEG?"dipped":"off"}static lamps(t){return t!=="off"}}function mS(o){return o==="vehicle"?["front","behind","front-left","front-right","behind-left","behind-right"]:["front","behind","left","right"]}const gS=90,Jd=2;function P2(o){return o==="building"||o==="vehicle"}function vS(o,t){return o==="building"?!0:o==="vehicle"?t!=="front"&&t!=="behind":!1}function mh(o){return o==="building"||o==="vehicle"}const L2={aircraft:{id:"poly-google-airliner"},tree:{id:"jungle-jim-tree-large-a"},observer:{id:"makehuman-farmer-40s"},entity:{id:"makehuman-farmer-40s"}},MS=["makehuman-farmer-40s","makehuman-man-overalls","makehuman-man-jacket","makehuman-old-man","makehuman-woman"];function q1(o,t){let e=0;for(const i of t)e=e*31+i.charCodeAt(0)>>>0;return{id:o[e%o.length]}}const yS=["jungle-jim-tree-large-a","jungle-jim-tree-medium-a","jungle-jim-tree-large-b","jungle-jim-tree-medium-b","jungle-jim-tree-large-c","jungle-jim-tree-medium-c","jagobo-tree-maple-a","jagobo-tree-maple-b","jagobo-tree-aspen-a","jagobo-tree-aspen-b","nicholas-3d-tree-a","nicholas-3d-tree-b","nicholas-3d-tree-c"];function jd(o){return o.model?o.model:o.kind==="tree"&&o.id!==void 0?q1(yS,o.id):(o.kind==="observer"||o.kind==="entity")&&o.id!==void 0?q1(MS,o.id):L2[o.kind]}function N2(o,t){const e=Xo.at(o.headlights,o.headlightKeyframes,t);return e!==void 0?e:Vf(o,t)?"dipped":"off"}const xS=-.5;function bS(o){return o.kind==="streetlight"&&o.origin!==void 0&&o.lit===void 0&&!o.litKeyframes?.length}function Vf(o,t,e){if(e!==void 0&&bS(o))return e<xS;const i=o.litKeyframes;if(!i||i.length===0)return o.lit??!1;let n=i[0];for(const s of i){if(s.t>t)break;n=s}return n.lit}function Z1(o,t){const e=o.observerKeyframes;if(!e||e.length===0)return{side:o.observerSide,facing:o.observerFacing};let i=e[0];for(const n of e){if(n.t>t)break;i=n}return{side:i.side,facing:i.facing}}function wS(o,t){return o.pattern.kind==="steady"?!0:k2(o,t,t+1)>.5}function k2(o,t,e){if(o.pattern.kind==="steady")return 1;const{perMinute:i,dutyCycle:n,phase:s=0}=o.pattern,r=Math.min(Math.max(n,0),1);if(r===0||i<=0)return 0;const a=6e4/i,c=t/a+s,h=e/a+s;if(h<=c)return Math.min(Math.max(c-Math.floor(c),0),r)<r?1:0;const l=u=>Math.floor(u)*r+Math.min(u-Math.floor(u),r);return(l(h)-l(c))/(h-c)}function tr(o,t){const e=o.track,i={eastM:o.eastM,northM:o.northM,altitudeM:0,headingDeg:o.headingDeg};if(!e||e.length===0)return i;if(e.length===1||t<=e[0].t)return J1(e[0],o);const n=e[e.length-1];if(t>=n.t)return J1(n,o);for(let s=0;s<e.length-1;s++){const r=e[s],a=e[s+1];if(t<r.t||t>a.t)continue;const c=a.t-r.t,h=c===0?0:(t-r.t)/c;return{eastM:r.eastM+(a.eastM-r.eastM)*h,northM:r.northM+(a.northM-r.northM)*h,altitudeM:(r.altitudeM??0)+((a.altitudeM??0)-(r.altitudeM??0))*h,headingDeg:r.headingDeg??o.headingDeg}}return i}function SS(o,t){const e=(o.track??[]).filter(i=>i.gazeAzimuthDeg!==void 0);if(e.length!==0){if(t<=e[0].t)return e[0].gazeAzimuthDeg;for(let i=0;i<e.length-1;i++){const n=e[i],s=e[i+1];if(t>s.t)continue;const r=s.t-n.t,a=r===0?0:(t-n.t)/r,c=((s.gazeAzimuthDeg-n.gazeAzimuthDeg)%360+540)%360-180;return((n.gazeAzimuthDeg+c*a)%360+360)%360}return e[e.length-1].gazeAzimuthDeg}}function J1(o,t){return{eastM:o.eastM,northM:o.northM,altitudeM:o.altitudeM??0,headingDeg:o.headingDeg??t.headingDeg}}const j1="#ff2200",Q1="#00ff44",Ja="#ffffff",su="#ffa500",oc="#ff0000",ES="#2244ff",$p=[{id:"airliner",name:"Airliner",kinds:["aircraft"],referenceSizeM:{widthM:34,heightM:12,lengthM:36},create:()=>[{id:"nav-port",offsetM:{x:-17,y:0,z:0},color:j1,pattern:{kind:"steady"}},{id:"nav-starboard",offsetM:{x:17,y:0,z:0},color:Q1,pattern:{kind:"steady"}},{id:"nav-tail",offsetM:{x:0,y:1,z:-18},color:Ja,pattern:{kind:"steady"}},{id:"beacon-top",offsetM:{x:0,y:2,z:0},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.18}},{id:"beacon-bottom",offsetM:{x:0,y:-2,z:0},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.18}},{id:"strobe-port",offsetM:{x:-17,y:0,z:-1},color:Ja,intensity:20,pattern:{kind:"flash",perMinute:60,dutyCycle:.01}},{id:"strobe-starboard",offsetM:{x:17,y:0,z:-1},color:Ja,intensity:20,pattern:{kind:"flash",perMinute:60,dutyCycle:.01,phase:.08}}]},{id:"helicopter",name:"Helicopter",kinds:["aircraft"],referenceSizeM:{widthM:10,heightM:4,lengthM:14},create:()=>[{id:"nav-port",offsetM:{x:-5,y:0,z:0},color:j1,pattern:{kind:"steady"}},{id:"nav-starboard",offsetM:{x:5,y:0,z:0},color:Q1,pattern:{kind:"steady"}},{id:"nav-tail",offsetM:{x:0,y:1,z:-7},color:Ja,pattern:{kind:"steady"}},{id:"beacon",offsetM:{x:0,y:2,z:-2},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.2}},{id:"strobe",offsetM:{x:0,y:-1,z:0},color:Ja,intensity:15,pattern:{kind:"flash",perMinute:75,dutyCycle:.015}}]},{id:"car-headlights",name:"Car, headlights on",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"head-left",offsetM:{x:-.7,y:.6,z:2},color:Ja,intensity:2,pattern:{kind:"steady"}},{id:"head-right",offsetM:{x:.7,y:.6,z:2},color:Ja,intensity:2,pattern:{kind:"steady"}},{id:"tail-left",offsetM:{x:-.7,y:.6,z:-2},color:oc,pattern:{kind:"steady"}},{id:"tail-right",offsetM:{x:.7,y:.6,z:-2},color:oc,pattern:{kind:"steady"}}]},{id:"car-hazards",name:"Car, hazard flashers",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"hazard-front-left",offsetM:{x:-.8,y:.6,z:2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-front-right",offsetM:{x:.8,y:.6,z:2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-rear-left",offsetM:{x:-.8,y:.6,z:-2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-rear-right",offsetM:{x:.8,y:.6,z:-2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}}]},{id:"emergency-beacons",name:"Emergency vehicle beacons",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"beacon-blue",offsetM:{x:-.4,y:1.6,z:0},color:ES,intensity:2.5,pattern:{kind:"flash",perMinute:120,dutyCycle:.1}},{id:"beacon-red",offsetM:{x:.4,y:1.6,z:0},color:oc,intensity:2.5,pattern:{kind:"flash",perMinute:120,dutyCycle:.1,phase:.5}}]},{id:"traffic-signal",name:"Traffic light",kinds:["trafficlight"],create:()=>fe.vehicleLights(0)},{id:"pedestrian-signal",name:"Pedestrian light",kinds:["trafficlight"],create:()=>fe.pedestrianLights(0)},{id:"streetlamp",name:"Streetlamp",kinds:["streetlight"],referenceSizeM:{widthM:1,heightM:5,lengthM:1},create:()=>[{id:"lamp",offsetM:{x:0,y:5,z:0},color:"#ffd9a0",intensity:2,pattern:{kind:"steady"}}]}];class Qd{static forKind(t){return $p.filter(e=>e.kinds.includes(t))}static byId(t){return $p.find(e=>e.id===t)}}class fe{static CYCLE_S=90;static GREEN_S=41;static AMBER_S=3;static PEDESTRIAN_DELAY_S=2;static PEDESTRIAN_GREEN_S=30;static VEHICLE_INTENSITY=3;static PEDESTRIAN_INTENSITY=1.5;static LENS_RADIUS_M=.1;static BEAM_DEG=30;static VEHICLE_HEAD_Y_M=2.9;static PEDESTRIAN_HEAD_Y_M=2.6;static LENS_SPACING_M=.3;static LENS_FRONT_M=.13;static RED="#ff1e00";static AMBER="#ffa200";static GREEN="#00ff8c";static phaseOf(t){const e=(t%180+180)%180;return e>=45&&e<135?1:0}static vehicleLights(t){const e=t*fe.CYCLE_S/2,i=fe.VEHICLE_HEAD_Y_M,n=fe.LENS_SPACING_M;return[fe.lamp("red",fe.RED,i+n,e+fe.GREEN_S+fe.AMBER_S,fe.CYCLE_S-fe.GREEN_S-fe.AMBER_S,fe.VEHICLE_INTENSITY),fe.lamp("amber",fe.AMBER,i,e+fe.GREEN_S,fe.AMBER_S,fe.VEHICLE_INTENSITY),fe.lamp("green",fe.GREEN,i-n,e,fe.GREEN_S,fe.VEHICLE_INTENSITY)]}static pedestrianLights(t){const e=t*fe.CYCLE_S/2+fe.GREEN_S+fe.AMBER_S+fe.PEDESTRIAN_DELAY_S,i=fe.PEDESTRIAN_HEAD_Y_M,n=fe.LENS_SPACING_M/2;return[fe.lamp("ped-red",fe.RED,i+n,e+fe.PEDESTRIAN_GREEN_S,fe.CYCLE_S-fe.PEDESTRIAN_GREEN_S,fe.PEDESTRIAN_INTENSITY),fe.lamp("ped-green",fe.GREEN,i-n,e,fe.PEDESTRIAN_GREEN_S,fe.PEDESTRIAN_INTENSITY)]}static isPedestrian(t){return t?.some(e=>e.id==="ped-green")??!1}static figureOf(t){return t.id==="ped-red"?"standing":t.id==="ped-green"?"walking":void 0}static lamp(t,e,i,n,s,r){const a=fe.CYCLE_S,c=Math.round(((1-n/a)%1+1)%1*1e6)/1e6;return{id:t,color:e,intensity:r,radiusM:fe.LENS_RADIUS_M,beamDeg:fe.BEAM_DEG,offsetM:{x:0,y:i,z:-.13},pattern:{kind:"flash",perMinute:60/a,dutyCycle:Math.round(s/a*1e6)/1e6,...c?{phase:c}:{}}}}}class ll{static of(t,e){const i=ll.drawnAsModel(t);return{color:e?.color??!i,lit:e?.lit??ll.litByDefault(t.kind,i),headlights:t.kind==="vehicle",lights:(e?.lights??!0)&&ll.rigsFor(t.kind,e).length>0,windows:!i&&P2(t.kind),floors:!i&&t.kind==="building",observerSide:mh(t.kind)}}static rigsFor(t,e){return Qd.forKind(t).filter(i=>e?.lightRigs===void 0||e.lightRigs.includes(i.id))}static drawnAsModel(t){return jd(t)!==void 0&&!(t.observerSide!==void 0&&mh(t.kind))}static litByDefault(t,e){return t==="streetlight"||t==="vehicle"&&!e}}class ci{static sideLabel(t){return ci.SIDE_LABELS[t]}static SIDE_LABELS={front:{en:"Front",fr:"Avant",es:"Frente",it:"Fronte"},behind:{en:"Behind",fr:"Arrière",es:"Detrás",it:"Dietro"},left:{en:"Left",fr:"Gauche",es:"Izquierda",it:"Sinistra"},right:{en:"Right",fr:"Droite",es:"Derecha",it:"Destra"},"front-left":{en:"Front-left",fr:"Avant gauche",es:"Delantero izquierdo",it:"Anteriore sinistro"},"front-right":{en:"Front-right",fr:"Avant droit",es:"Delantero derecho",it:"Anteriore destro"},"behind-left":{en:"Behind-left",fr:"Arrière gauche",es:"Trasero izquierdo",it:"Posteriore sinistro"},"behind-right":{en:"Behind-right",fr:"Arrière droit",es:"Trasero derecho",it:"Posteriore destro"}};static WINDOWS={en:"Windows",fr:"Fenêtres",es:"Ventanas",it:"Finestre"};static BUILDING={en:"Building",fr:"Bâtiment",es:"Edificio",it:"Edificio"};static BRIDGE={en:"Bridge",fr:"Pont",es:"Puente",it:"Ponte"};static RAILING={en:"Railing",fr:"Garde-corps",es:"Barandilla",it:"Parapetto"};static WIRE={en:"Overhead line",fr:"Ligne aérienne",es:"Línea aérea",it:"Linea aerea"};static together(t,e){const i=["en","fr","es","it"],n=(s,r)=>typeof s=="string"?s:s[r]??s.en;return Object.fromEntries(i.map(s=>[s,`${n(t,s)} ${n(e,s)}`]))}static of(t,e){const i=[],n=ll.drawnAsModel(t);if(!n&&t.kind==="building"&&i.push(...ci.floors(),...ci.walls(),...ci.roof()),!n&&P2(t.kind)&&i.push(...ci.windows(t.kind)),t.kind==="vehicle"&&i.push(...ci.engine()),t.kind==="observer"&&i.push(...ci.observerRecording()),t.kind==="aircraft"&&i.push(...ci.aircraftSound(e)),t.kind==="bridge"&&i.push(...ci.bridge()),t.kind==="wire"&&i.push(...ci.wire()),e?.parameters&&i.push(...e.parameters.map(s=>({...s,key:`modelParameters.${s.key}`}))),i.length!==0)return{kind:`decor-${t.kind}`,title:{en:"Properties",fr:"Propriétés",es:"Propiedades",it:"Proprietà"},parameters:i}}static floors(){const t=e=>Pr.read(e,"floors")??Jd;return[{type:"number",key:"floors",min:0,max:20,step:1,effective:()=>Jd,label:{en:"Floors",fr:"Étages",es:"Plantas",it:"Piani"},hint:{en:"Upper stories above the ground floor.",fr:"Étages au-dessus du rez-de-chaussée.",es:"Plantas sobre la planta baja.",it:"Piani sopra il pianterreno."},group:ci.BUILDING},{type:"number",key:"occupiedFloor",min:0,max:20,step:1,effective:()=>0,bounds:e=>({max:t(e)}),label:{en:"Occupied floor",fr:"Étage occupé",es:"Planta ocupada",it:"Piano occupato"},hint:{en:"The floor the observer is on, from 0 (ground floor).",fr:"L'étage où se tient l'observateur, à partir de 0 (rez-de-chaussée).",es:"La planta donde está el observador, desde 0 (planta baja).",it:"Il piano dove si trova l'osservatore, da 0 (pianterreno)."},group:ci.BUILDING}]}static walls(){const t={en:"Walls",fr:"Murs",es:"Muros",it:"Muri"};return[{type:"colour",key:"facade.color",group:t,fallback:"#d3cab8",label:{en:"Wall colour",fr:"Couleur des murs",es:"Color de los muros",it:"Colore dei muri"},hint:{en:"The colour of the walls, drawn with the facade of their kind where the width, the length and the height of the building are all stated. Empty: a pale plaster.",fr:"La couleur des murs, dessinés avec la façade de leur type là où la largeur, la longueur et la hauteur du bâtiment sont toutes énoncées. Vide : un enduit pâle.",es:"El color de los muros, dibujados con la fachada de su tipo donde el ancho, el largo y el alto del edificio están todos enunciados. Vacío: un enlucido pálido.",it:"Il colore dei muri, disegnati con la facciata del loro tipo dove larghezza, lunghezza e altezza dell'edificio sono tutte enunciate. Vuoto: un intonaco chiaro."}},{type:"choice",key:"facade.openings",group:t,label:{en:"Facade",fr:"Type de façade",es:"Tipo de fachada",it:"Tipo di facciata"},empty:{en:"A house's",fr:"D'une maison",es:"De una casa",it:"Di una casa"},hint:{en:"A house's: a window every three metres of every floor and a door, from a storey high (lower, a shed's bare wall). The tall windows of an old building, the tall narrow bays of a church, a bare wall (a warehouse, a shed, a monument), or none: the plain box.",fr:"D'une maison : une fenêtre tous les trois mètres de chaque étage et une porte, dès la hauteur d'un étage (plus bas, le mur nu d'un abri). Les hautes fenêtres d'un immeuble ancien, les hautes baies étroites d'une église, un mur nu (un entrepôt, un hangar, un monument), ou aucune : la simple boîte.",es:"De una casa: una ventana cada tres metros de cada planta y una puerta, desde la altura de una planta (más bajo, el muro liso de un cobertizo). Las ventanas altas de un edificio antiguo, los vanos altos y estrechos de una iglesia, un muro liso (un almacén, un cobertizo, un monumento), o ninguna: la caja lisa.",it:"Di una casa: una finestra ogni tre metri di ogni piano e una porta, dall'altezza di un piano (più basso, il muro liscio di un capanno). Le finestre alte di un edificio antico, le alte aperture strette di una chiesa, un muro liscio (un magazzino, un capannone, un monumento), o nessuna: la semplice scatola."},choices:[{value:"tall",label:{en:"Old building",fr:"Immeuble ancien",es:"Edificio antiguo",it:"Edificio antico"}},{value:"lancet",label:{en:"Church",fr:"Église",es:"Iglesia",it:"Chiesa"}},{value:"plain",label:{en:"Bare wall",fr:"Mur nu",es:"Muro liso",it:"Muro liscio"}},{value:"none",label:{en:"None",fr:"Aucune",es:"Ninguna",it:"Nessuna"}}]}]}static roof(){const t={en:"Roof",fr:"Toit",es:"Tejado",it:"Tetto"};return[{type:"choice",key:"roof.shape",group:t,label:{en:"Roof",fr:"Toit",es:"Tejado",it:"Tetto"},empty:{en:"Flat",fr:"Plat",es:"Plano",it:"Piano"},hint:{en:"Flat (the box), two slopes to a ridge, four slopes, or a dome.",fr:"Plat (la boîte), deux pentes jusqu'à un faîte, quatre pentes, ou une coupole.",es:"Plano (la caja), dos vertientes hasta una cumbrera, cuatro vertientes, o una cúpula.",it:"Piano (la scatola), due falde fino a un colmo, quattro falde, o una cupola."},choices:[{value:"flat",label:{en:"Flat",fr:"Plat",es:"Plano",it:"Piano"}},{value:"gable",label:{en:"Two slopes",fr:"Deux pentes",es:"Dos vertientes",it:"Due falde"}},{value:"hip",label:{en:"Four slopes",fr:"Quatre pentes",es:"Cuatro vertientes",it:"Quattro falde"}},{value:"dome",label:{en:"Dome",fr:"Coupole",es:"Cúpula",it:"Cupola"}}]},{type:"number",key:"roof.riseM",min:0,max:15,step:.1,unit:"m",group:t,effective:()=>3,label:{en:"Rise",fr:"Hauteur du toit",es:"Altura del tejado",it:"Altezza del tetto"},hint:{en:"How far the ridge stands above the eaves: the walls are the building's height less this.",fr:"De combien le faîte dépasse l'égout : les murs font la hauteur du bâtiment moins cela.",es:"Cuánto sube la cumbrera sobre el alero: los muros miden la altura del edificio menos esto.",it:"Quanto il colmo sta sopra la gronda: i muri sono l'altezza dell'edificio meno questo."},visibleWhen:i=>["gable","hip","dome"].includes(String(Pr.read(i,"roof.shape")))},{type:"choice",key:"roof.ridge",group:t,required:!1,label:{en:"Ridge along",fr:"Faîte le long de",es:"Cumbrera a lo largo de",it:"Colmo lungo"},empty:{en:"The width",fr:"La largeur",es:"El ancho",it:"La larghezza"},choices:[{value:"width",label:{en:"The width",fr:"La largeur",es:"El ancho",it:"La larghezza"}},{value:"depth",label:{en:"The depth",fr:"La profondeur",es:"El largo",it:"La profondità"}}],visibleWhen:i=>Pr.read(i,"roof.shape")==="gable"},{type:"colour",key:"roof.color",group:t,fallback:"#7a5a4a",label:{en:"Roof colour",fr:"Couleur du toit",es:"Color del tejado",it:"Colore del tetto"}}]}static windows(t){return mS(t).map(e=>({type:"number",key:`windows.${e}`,step:5,unit:"%",min:vS(t,e)?0:gS,max:100,label:ci.SIDE_LABELS[e],summary:ci.together(ci.WINDOWS,ci.SIDE_LABELS[e]),hint:{en:"Opacity of the window on this side: 0 is open, 100 shut. Empty: no window.",fr:"Opacité de la fenêtre de ce côté : 0 ouverte, 100 fermée. Vide : pas de fenêtre.",es:"Opacidad de la ventana de este lado: 0 abierta, 100 cerrada. Vacío: sin ventana.",it:"Opacità della finestra di questo lato: 0 aperta, 100 chiusa. Vuoto: nessuna finestra."},group:ci.WINDOWS}))}static engine(){const t={en:"Engine sound",fr:"Bruit du moteur",es:"Sonido del motor",it:"Suono del motore"};return[{type:"choice",key:"engine.kind",group:t,label:{en:"Engine",fr:"Moteur",es:"Motor",it:"Motore"},hint:{en:"Whether the vehicle is heard running, and what sort of engine: how many cylinders fire, how low they turn, how its gears are spaced.",fr:"Si le véhicule s'entend rouler, et de quel moteur : combien de cylindres tirent, à quel régime bas ils tournent, comment ses vitesses sont étagées.",es:"Si se oye el vehículo en marcha, y qué motor: cuántos cilindros disparan, cuán bajo giran, cómo se escalonan sus marchas.",it:"Se il veicolo si sente in marcia, e di che motore: quanti cilindri sparano, quanto in basso girano, come sono distanziate le marce."},empty:{en:"Silent (parked)",fr:"Silencieux (à l'arrêt)",es:"Silencioso (parado)",it:"Silenzioso (fermo)"},choices:[{value:"car",label:{en:"Car",fr:"Voiture",es:"Coche",it:"Auto"}},{value:"van",label:{en:"Van",fr:"Camionnette",es:"Furgoneta",it:"Furgone"}},{value:"truck",label:{en:"Truck",fr:"Camion",es:"Camión",it:"Camion"}},{value:"motorcycle",label:{en:"Motorcycle",fr:"Moto",es:"Moto",it:"Moto"}},{value:"generic",label:{en:"Unknown",fr:"Inconnu",es:"Desconocido",it:"Sconosciuto"}}]},{type:"number",key:"engine.noise",min:.1,max:3,step:.1,group:t,effective:()=>1,label:{en:"Loudness",fr:"Volume",es:"Volumen",it:"Volume"},hint:{en:"Against an ordinary one of its kind: 1 by default, 1.5 for a very noisy one.",fr:"Par rapport à un véhicule ordinaire de son genre : 1 par défaut, 1,5 pour un très bruyant.",es:"Frente a uno ordinario de su tipo: 1 por defecto, 1,5 para uno muy ruidoso.",it:"Rispetto a uno ordinario del suo tipo: 1 per impostazione predefinita, 1,5 per uno molto rumoroso."},visibleWhen:e=>Pr.read(e,"engine.kind")!==void 0||e.engine!==void 0}]}static observerRecording(){return[{type:"text",key:"sightingUrl",placeholder:"https://…/sighting.json",label:{en:"Their own recording URL",fr:"URL de son propre enregistrement",es:"URL de su propia grabación",it:"URL della sua registrazione"}}]}static aircraftSound(t){const e=(n,s,r,a,c)=>({value:n,label:{en:s,fr:r,es:a,it:c}}),i=t?.sound;return[{type:"choice",key:"aircraftSound",group:{en:"Sound",fr:"Bruit",es:"Sonido",it:"Suono"},label:{en:"Noise in flight",fr:"Bruit en vol",es:"Ruido en vuelo",it:"Rumore in volo"},hint:{en:"What it sounds like while it flies: nothing is heard of a machine that flies silent, and the stand-in of a phenomenon says so.",fr:"Ce qu'on entend quand il vole : rien d'une machine qui vole en silence, et la maquette d'un phénomène le dit.",es:"Cómo suena mientras vuela: nada se oye de una máquina que vuela en silencio, y la maqueta de un fenómeno lo dice.",it:"Come suona mentre vola: nulla si sente di una macchina che vola in silenzio, e il modello di un fenomeno lo dice."},empty:i==="silent"?{en:"Silent (as the model)",fr:"Silencieux (comme le modèle)",es:"Silencioso (como el modelo)",it:"Silenzioso (come il modello)"}:{en:"As the model",fr:"Selon le modèle",es:"Según el modelo",it:"Secondo il modello"},choices:[e("airliner-narrow","Narrow-body airliner","Avion de ligne monocouloir","Avión de pasillo único","Aereo di linea a fusoliera stretta"),e("airliner-wide","Wide-body airliner","Avion de ligne gros-porteur","Avión de fuselaje ancho","Aereo di linea a fusoliera larga"),e("regional-jet","Regional jet","Jet régional","Jet regional","Jet regionale"),e("regional-turboprop","Turboprop","Turbopropulseur","Turbohélice","Turboelica"),e("business-jet","Business jet","Jet d'affaires","Jet privado","Jet privato"),e("light-piston","Light piston aircraft","Avion léger à pistons","Avioneta de pistones","Aereo leggero a pistoni"),e("helicopter-light","Light helicopter","Hélicoptère léger","Helicóptero ligero","Elicottero leggero"),e("helicopter-medium","Medium helicopter","Hélicoptère moyen","Helicóptero medio","Elicottero medio"),e("helicopter-heavy","Heavy helicopter","Hélicoptère lourd","Helicóptero pesado","Elicottero pesante"),e("military-jet","Military jet","Avion de combat","Reactor militar","Jet militare"),e("ultralight","Ultralight","ULM","Ultraligero","Ultraleggero"),e("unmanned","Drone","Drone","Dron","Drone"),e("glider","Glider","Planeur","Planeador","Aliante"),e("silent","Silent","Silencieux","Silencioso","Silenzioso")]}]}static bridge(){const t=(e,i,n,s,r,a,c,h,l)=>({type:"number",key:e,label:i,min:n,max:s,step:r,unit:a,group:h,hint:l,effective:c===void 0?void 0:()=>c});return[t("bridge.spanM",{en:"Span",fr:"Portée",es:"Luz",it:"Luce"},.1,5e3,.1,"m",void 0,ci.BRIDGE,{en:"Metres of open span under the deck, centred. Empty: the whole length, no embankments.",fr:"Mètres de portée libre sous le tablier, centrés. Vide : toute la longueur, sans remblais.",es:"Metros de luz libre bajo el tablero, centrados. Vacío: toda la longitud, sin terraplenes.",it:"Metri di luce libera sotto l'impalcato, centrati. Vuoto: tutta la lunghezza, senza rilevati."}),t("bridge.deckThicknessM",{en:"Deck thickness",fr:"Épaisseur du tablier",es:"Espesor del tablero",it:"Spessore dell'impalcato"},.1,20,.1,"m",1.2,ci.BRIDGE),t("bridge.railing.heightM",{en:"Height",fr:"Hauteur",es:"Altura",it:"Altezza"},.1,5,.05,"m",1.05,ci.RAILING),t("bridge.railing.postSpacingM",{en:"Post spacing",fr:"Espacement des poteaux",es:"Separación de postes",it:"Distanza dei montanti"},.2,20,.1,"m",1.5,ci.RAILING),t("bridge.railing.rails",{en:"Rails",fr:"Lisses",es:"Barandas",it:"Correnti"},0,8,1,"",2,ci.RAILING)]}static wire(){return[{type:"choice",key:"wire.poles",group:ci.WIRE,label:{en:"Poles",fr:"Poteaux",es:"Postes",it:"Pali"},hint:{en:"Which ends stand on a pole: both, the one the heading points away from, the one it points towards, or none (a line anchored on buildings).",fr:"Quelles extrémités reposent sur un poteau : les deux, celle dont le cap s'éloigne, celle vers laquelle il pointe, ou aucune (une ligne ancrée sur des bâtiments).",es:"Qué extremos se apoyan en un poste: ambos, aquel del que se aleja el rumbo, aquel hacia el que apunta, o ninguno (una línea anclada en edificios).",it:"Quali estremità poggiano su un palo: entrambe, quella da cui si allontana la direzione, quella verso cui punta, o nessuna (una linea ancorata a edifici)."},choices:[{value:"both",label:{en:"Both",fr:"Les deux",es:"Ambos",it:"Entrambi"}},{value:"start",label:{en:"Start",fr:"Début",es:"Inicio",it:"Inizio"}},{value:"end",label:{en:"End",fr:"Fin",es:"Fin",it:"Fine"}},{value:"none",label:{en:"None",fr:"Aucun",es:"Ninguno",it:"Nessuno"}}],effective:()=>"both"},{type:"number",key:"wire.diameterM",min:.001,max:.2,step:.001,unit:"m",effective:()=>.008,group:ci.WIRE,label:{en:"Strand thickness",fr:"Épaisseur du brin",es:"Grosor del hilo",it:"Spessore del filo"}},{type:"number",key:"wire.poleHeightM",min:.5,max:100,step:.1,unit:"m",group:ci.WIRE,label:{en:"Pole height",fr:"Hauteur des poteaux",es:"Altura de los postes",it:"Altezza dei pali"},hint:{en:"Empty: half a metre over the highest strand.",fr:"Vide : un demi-mètre au-dessus du brin le plus haut.",es:"Vacío: medio metro sobre el hilo más alto.",it:"Vuoto: mezzo metro sopra il filo più alto."}}]}}class js{static NONE={id:"none",name:"No filter",opticalDensity:0};static SOLAR_VISUAL={id:"solar-visual",name:"Solar filter for the eye (OD 5)",opticalDensity:5,usableWith:["eye","binoculars","telescope"]};static SOLAR_PHOTO={id:"solar-photo",name:"Solar film for a camera (OD 3.8)",opticalDensity:3.8,usableWith:["camera","dslr","phone","telescope"]};static ALL=[js.NONE,js.SOLAR_VISUAL,js.SOLAR_PHOTO];static usableWith(t,e){return!t.usableWith||t.usableWith.includes(e.category)}static byId(t){return js.ALL.find(e=>e.id===t)??js.NONE}static transmittance(t){return 10**-t.opticalDensity}static magnitudes(t){return 2.5*t.opticalDensity}}class gd{constructor(t){this.names=t}name(t){return this.names[t.toLowerCase()]??t}stored(t){const e=t.trim().toLowerCase();for(const[i,n]of Object.entries(this.names))if(n.toLowerCase()===e)return i;return t.trim()}}class Ll{constructor(t,e,i,n=new gd({}),s){this.labels=t,this.naming=e,this.said=i,this.tags=n,this.timeWords=s}entriesFor(t,e,i={}){const n=[];return this.addSummary(n,t),this.addObservation(n,t),this.addObserver(n,t,e),this.addLocation(n,t,e,i.groundElevationM,i.roadGradeDeg??0),this.addDecor(n,t,e,i),i.phenomena===!0&&this.addPhenomena(n,t,e),this.addTemporal(n,t),this.addWeather(n,t,e),this.addSound(n,t,e),n}push(t,e,i,n,s,r="",a={}){s===void 0||s===""||t.push({group:e,field:i,label:n,value:String(s),unit:r,color:a.color,fromSource:a.fromSource===!0})}percent(t){return t===void 0?void 0:`${Math.round(t*100)} %`}rounded(t,e=0){return t===void 0?void 0:String(Number(t.toFixed(e)))}shows(t,e=0){return t!==void 0&&Number(t.toFixed(e))!==0}showsPercent(t){return this.shows(t===void 0?void 0:t*100)}percentShown(t){return this.showsPercent(t)?this.percent(t):void 0}roundedShown(t,e=0){return this.shows(t,e)?this.rounded(t,e):void 0}static DESCRIPTION_WORDS=3;addSummary(t,e){const i=this.said.read(e.event.description)?.trim();if(!i)return;const n=i.split(/\s+/),s=n.length>Ll.DESCRIPTION_WORDS?`${n.slice(0,Ll.DESCRIPTION_WORDS).join(" ")}…`:i;this.push(t,"summary","description",this.labels.summaryDescription,s),t[t.length-1].full=i}addObservation(t,e){const i=e.event.tags;this.push(t,"observation","tags",this.labels.tags,i&&i.length>0?i.map(n=>this.tags.name(n)).join(", "):void 0)}filterName(t){return t===js.SOLAR_VISUAL?this.labels.filterSolarVisual:t===js.SOLAR_PHOTO?this.labels.filterSolarPhoto:t.name}addObserver(t,e,i){const n=e.observer;this.push(t,"observer","observerId",this.labels.observerId,n?.id),this.push(t,"observer","observerTitle",this.labels.observerTitle,this.said.read(n?.title)),this.push(t,"observer","observerLastName",this.labels.observerLastName,n?.lastName);const s=n?.firstNames;this.push(t,"observer","observerFirstNames",this.labels.observerFirstNames,s&&s.length>0?s.join(", "):void 0);const r=e.instrument;this.push(t,"observer","instrument",this.labels.instrument,this.naming.instrument(r));const a=e.exposure;this.push(t,"observer","exposureSeconds",this.labels.exposure,a===void 0?void 0:a<1?`1/${Math.round(1/a)}`:this.rounded(a,2),"s");const c=ze(e,i);if(c){const h=Ti.focalLengthMmFor(r,c.fovDeg);h===void 0?this.push(t,"observer","focalLength",this.labels.fieldOfView,this.rounded(c.fovDeg,1),"°"):this.push(t,"observer","focalLength",this.labels.focalLength,this.rounded(h,1),"mm"),this.push(t,"observer","fNumber",this.labels.aperture,this.rounded(c.fNumber??r.fNumber,1)),this.push(t,"observer","focusDistance",this.labels.focusDistance,this.rounded(c.focusDistanceM,1),"m"),this.push(t,"observer","roll",this.labels.roll,this.roundedShown(c.rollDeg),"°");const l=js.byId(c.filter);l!==js.NONE&&this.push(t,"observer","filter",this.labels.filter,this.filterName(l))}}degreesMinutesSeconds(t,e,i){if(t===void 0||!Number.isFinite(t))return;const n=Math.round(Math.abs(t)*3600),s=Math.floor(n/3600),r=Math.floor(n%3600/60),a=n%60;return`${s}°${String(r).padStart(2,"0")}′${String(a).padStart(2,"0")}″ ${this.naming.point(t<0?i:e)}`}addLocation(t,e,i,n,s){const r=e.event.place?.[0];this.push(t,"location","placeName",this.labels.placeName,r?.name);const a=ze(e,i);if(!a)return;this.push(t,"location","lat",this.labels.latitude,this.degreesMinutesSeconds(a.lat,0,180)),this.push(t,"location","lng",this.labels.longitude,this.degreesMinutesSeconds(a.lng,90,270));const c=this.rounded(a.headingDeg);this.push(t,"location","heading",this.labels.heading,c,a.headingDeg===void 0?"°":`° (${this.naming.point(a.headingDeg)})`),this.push(t,"location","pitch",this.labels.pitch,a.pitchDeg===void 0?void 0:this.rounded(a.pitchDeg+s),"°"),n===void 0?this.push(t,"location","elevation",this.labels.heightAboveGround,this.roundedShown(a.elevationM),"m"):this.push(t,"location","elevation",this.labels.elevation,this.rounded(n+a.elevationM),"m")}addDecor(t,e,i,n){const s=e.decor.find(h=>h.id===n.decorId);if(!s){if(n.decorPicker===!0)for(const h of e.decor)this.push(t,"decor",`decor:${h.id}`,this.decorLabel(h),this.decorKindName(h.kind));return}this.push(t,"decor","decorBase.title",this.labels.decorTitle,this.said.read(s.title));const r=tr(s,i);this.push(t,"decor","decorBase.eastM",this.labels.decorEast,this.rounded(r.eastM,1),"m"),this.push(t,"decor","decorBase.northM",this.labels.decorNorth,this.rounded(r.northM,1),"m"),this.push(t,"decor","decorBase.altitudeM",this.labels.decorAltitude,this.roundedShown(r.altitudeM),"m"),this.push(t,"decor","decorBase.headingDeg",this.labels.decorHeading,this.rounded(r.headingDeg),"°"),Vf(s,i)&&this.push(t,"decor","decorState.lit",this.labels.decorLit,"✓");const a=s.lights?.map(h=>h.id).join()??"",c=a===""?void 0:$p.find(h=>h.create().map(l=>l.id).join()===a);this.push(t,"decor","decorState.lightRig",this.labels.decorLights,c?.name),this.push(t,"decor","decorState.observerSide",this.labels.decorObserverSide,this.decorSideName(s.observerSide));for(const h of ci.of(s)?.parameters??[]){const l=Pr.read(s,h.key);if(l==null)continue;const u=h.type==="choice"?this.said.read(h.choices.find(d=>d.value===l)?.label)??String(l):l;this.push(t,"decor",`decorParam.${h.key}`,this.said.read(h.summary??h.label)??h.key,typeof u=="boolean"?u?"✓":"":u,h.type==="number"?h.unit:void 0)}}timeText(t){return this.timeWords?ms.describeTime(t,this.timeWords.messages,this.timeWords.locale):nl(t)}addTemporal(t,e){const i=e.event;this.push(t,"temporal","obs-time",this.labels.observationTime,i.time&&this.timeText(i.time)),this.push(t,"temporal","obs-end-time",this.labels.observationEndTime,i.endTime&&this.timeText(i.endTime));const n=C2(i);this.push(t,"temporal","durationSeconds",this.labels.duration,this.roundedShown(n&&n/1e3,1),"s"),this.push(t,"temporal","timeZone",this.labels.utcOffset,i.timeZone),this.push(t,"temporal","utcOffsetHours",this.labels.utcOffset,this.rounded(i.utcOffsetHours,1),"UTC±h")}addWeather(t,e,i){const n=Lc(e,i),r={fromSource:e.weatherSource!==void 0},a=this.showsPercent(n.cloudCover)||this.showsPercent(n.lowerCloudCover)||this.showsPercent(n.highCloudCover);this.push(t,"weather","cloudCover",this.labels.cloudCover,this.percentShown(n.cloudCover),"",r),this.push(t,"weather","highCloudCover",this.labels.highCloudCover,this.percentShown(n.highCloudCover),"",r),this.push(t,"weather","iceCrystalAlignment",this.labels.iceCrystalAlignment,this.showsPercent(n.highCloudCover)?this.percent(n.iceCrystalAlignment):void 0),this.push(t,"weather","rareIceCrystals",this.labels.rareIceCrystals,this.showsPercent(n.highCloudCover)?this.percent(n.rareIceCrystals):void 0),this.push(t,"weather","cloudDarkness",this.labels.cloudDarkness,a?this.percent(n.cloudDarkness):void 0,"",r),this.push(t,"weather","cloudBase",this.labels.cloudBase,a?this.rounded(n.cloudBaseM):void 0,"m",r);const c=n.precipitationType!=="none"&&this.showsPercent(n.precipitationIntensity);this.push(t,"weather","precipitationType",this.labels.precipitationType,c?this.precipitationName(n.precipitationType):void 0,"",r),this.push(t,"weather","precipitationIntensity",this.labels.precipitationIntensity,c?this.percent(n.precipitationIntensity):void 0,"",r),this.push(t,"weather","windDirection",this.labels.windDirection,this.shows(n.windSpeed,2)?this.rounded(n.windDirectionDeg):void 0,"°",r),this.push(t,"weather","windSpeed",this.labels.windSpeed,this.roundedShown(n.windSpeed,2),"m/s",r),n.storm&&this.push(t,"weather","storm",this.labels.storm,"✓","",r)}addSound(t,e,i){const n=O2(e,i);n.kind!=="none"&&(this.push(t,"sound","soundKind",this.labels.soundKind,this.soundKindName(n.kind)),this.push(t,"sound","soundVolume",this.labels.soundVolume,this.percentShown(n.volume)),this.push(t,"sound","soundPitch",this.labels.soundPitch,this.roundedShown(n.pitchHz),"Hz"),this.push(t,"sound","soundSrc",this.labels.soundSrc,n.src))}addPhenomena(t,e,i){for(const n of e.timeline.sourceIds){const s=e.timeline.getInterpolatedShapeAt(i,n),r=s?.angular,a=r?`${this.rounded(r.widthDeg,2)} × ${this.rounded(r.heightDeg,2)}°`:void 0;this.push(t,"phenomenon",`shape:${n}`,this.said.read(s?.title)??n,a)}for(const n of e.interpretation?.bodies??[]){const s=n.track.find(a=>a.sizeM?.widthM!==void 0)?.sizeM?.widthM,r=n.model.id??n.model.url?.replace(/^.*\//,"");this.push(t,"phenomenon",`body:${n.id}`,this.said.read(n.title)??n.id,[r,s!==void 0?`${this.rounded(s,2)} m`:void 0].filter(Boolean).join(", "))}}decorLabel(t){return this.said.read(t.title)??this.decorKindName(t.kind)}decorKindName(t){switch(t){case"building":return this.labels.decorBuilding;case"tree":return this.labels.decorTree;case"shrub":return this.labels.decorShrub;case"bridge":return this.labels.decorBridge;case"wire":return this.labels.decorWire;case"crop":return this.labels.decorCrop;case"terrace":return this.labels.decorTerrace;case"mound":return this.labels.decorMound;case"wall":return this.labels.decorWall;case"streetlight":return this.labels.decorStreetlight;case"trafficlight":return this.labels.decorTrafficLight;case"crossing":return this.labels.decorCrossing;case"roadsign":return this.labels.decorRoadSign;case"vehicle":return this.labels.decorVehicle;case"aircraft":return this.labels.decorAircraft;default:return this.labels.decorObserver}}decorSideName(t){switch(t){case"front":return this.labels.decorSideFront;case"behind":return this.labels.decorSideBehind;case"left":return this.labels.decorSideLeft;case"right":return this.labels.decorSideRight;case"front-left":return this.labels.decorSideFrontLeft;case"front-right":return this.labels.decorSideFrontRight;case"behind-left":return this.labels.decorSideBehindLeft;case"behind-right":return this.labels.decorSideBehindRight;default:return}}precipitationName(t){switch(t){case"rain":return this.labels.precipitationRain;case"snow":return this.labels.precipitationSnow;case"hail":return this.labels.precipitationHail;default:return this.labels.precipitationNone}}soundKindName(t){switch(t){case"hum":return this.labels.soundHum;case"whistle":return this.labels.soundWhistle;case"rumble":return this.labels.soundRumble;case"crackle":return this.labels.soundCrackle;default:return this.labels.soundNone}}}class Ps{constructor(t){this.preferences=t}read(t){if(t===void 0||typeof t=="string")return t===""?void 0:t;for(const i of this.preferences){const n=t[i]??t[Ps.base(i)];if(n)return n}const e=new Set(this.preferences.map(i=>Ps.base(i)));for(const[i,n]of Object.entries(t))if(n&&e.has(Ps.base(i)))return n;return Object.values(t).find(i=>i)??void 0}write(t,e,i){const n=e?.trim()?e.trim():void 0;if(t===void 0||typeof t=="string")return n;const s={...t},r=Object.keys(s).find(a=>a===i)??Object.keys(s).find(a=>Ps.base(a)===Ps.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(t){return t.toLowerCase().split("-")[0]}}function Tg(o,t){for(const e of o){const i=e.toLowerCase().split("-")[0];if(t.includes(i))return i}return"en"}class Ga{static preferencesFor(t){const e=navigator.languages??[],i=this.declaredFor(t);return i?[i,...e]:e}static declaredFor(t){for(let e=t;e;){const i=e.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const n=e.getRootNode();e=n instanceof ShadowRoot?n.host:void 0}}}const AS="Global Meteor Network",_S="https://globalmeteornetwork.org/data/",TS="“Thunder” by Jerimee",RS="https://creativecommons.org/licenses/by/3.0/",IS="CC BY 3.0";class gn{static fill(t,e){t.innerHTML="";const i=d=>t.appendChild(d),n=e.currentTerrainAttribution;n&&i(gn.text(n));const s=e.currentRoadAttribution;s&&i(gn.text(s));const r=e.currentWaterAttribution;r&&i(gn.text(r));const a=e.currentRailwayAttribution;a&&i(gn.text(a));const c=e.ufoElement.observerMapCredit;c&&!n?.includes(c)&&i(gn.text(c));for(const d of e.decorModelCredits){const f=d.author?` — ${d.author}`:"",p=document.createElement("li");d.sourceUrl?p.append(gn.link(d.sourceUrl,d.title),document.createTextNode(`${f} (${d.license})`)):p.textContent=`${d.title}${f} (${d.license})`,i(p)}for(const d of e.ufoElement.sighting.references){if(!d.credit)continue;const f=document.createElement("li");d.creditUrl?f.appendChild(gn.link(d.creditUrl,d.credit)):f.textContent=d.credit,i(f)}if(e.ufoElement.sighting.traces.length>0){const d=new Ps(Ga.preferencesFor(e)),f=new Set(e.ufoElement.sighting.traces.map(p=>d.read(p.source)).filter(p=>!!p));for(const p of f)i(gn.text(p))}const h=e.satelliteState;if(h.status==="ready"&&h.credit){const d=document.createElement("li");d.appendChild(gn.link(h.creditUrl??"",h.credit)),i(d)}if(e.fireballState.status==="ready"&&e.fireballState.records.length>0){const d=document.createElement("li");d.append(gn.link(_S,AS),document.createTextNode(" (CC BY 4.0)")),i(d)}const l=e.aircraftState;if(l.status==="ready"&&l.shown>0){const d=document.createElement("li");if(d.appendChild(gn.link(l.creditUrl,l.credit)),i(d),l.trailCredit){const f=document.createElement("li");f.appendChild(gn.link(l.trailCredit.creditUrl,l.trailCredit.credit)),i(f)}}const u=gn.text(`${TS} (`);u.append(gn.link(RS,IS),document.createTextNode(")")),i(u)}static text(t){const e=document.createElement("li");return e.textContent=t,e}static link(t,e){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener",i.textContent=e,i}}const DS="modulepreload",CS=function(o,t){return new URL(o,t).href},tv={},Re=function(t,e,i){let n=Promise.resolve();if(e&&e.length>0){let r=function(l){return Promise.all(l.map(u=>Promise.resolve(u).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const a=document.getElementsByTagName("link"),c=document.querySelector("meta[property=csp-nonce]"),h=c?.nonce||c?.getAttribute("nonce");n=r(e.map(l=>{if(l=CS(l,i),l in tv)return;tv[l]=!0;const u=l.endsWith(".css"),d=u?'[rel="stylesheet"]':"";if(!!i)for(let g=a.length-1;g>=0;g--){const m=a[g];if(m.href===l&&(!u||m.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${l}"]${d}`))return;const p=document.createElement("link");if(p.rel=u?"stylesheet":DS,u||(p.as="script"),p.crossOrigin="",p.href=l,h&&p.setAttribute("nonce",h),document.head.appendChild(p),u)return new Promise((g,m)=>{p.addEventListener("load",g),p.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${l}`)))})}))}function s(r){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=r,window.dispatchEvent(a),!a.defaultPrevented)throw r}return n.then(r=>{for(const a of r||[])a.status==="rejected"&&s(a.reason);return t().catch(s)})},OS=[{id:"coverage",name:"Coverage",credit:"UFO@home",creditUrl:"https://ufoathome.org",create:()=>({about:"observer",assess:async o=>{const{CoverageAssessor:t}=await Re(async()=>{const{CoverageAssessor:e}=await import("./CoverageAssessor-Dd6oOWlq.js");return{CoverageAssessor:e}},[],import.meta.url);return new t().assess(o)}})},{id:"hynek",name:"Hynek",credit:"J. Allen Hynek",creditUrl:"https://rr0.org/science/crypto/ufo/observation/classification/hynek/",create:()=>({about:"temporal",assess:async o=>{const{HynekAssessor:t}=await Re(async()=>{const{HynekAssessor:e}=await import("./HynekAssessor-DPsLpEGQ.js");return{HynekAssessor:e}},[],import.meta.url);return new t().assess(o)}})}];class PS{constructor(t){this.labels=t}async read(t){const e=[],i=new Set;for(const n of OS){let s;try{s=await n.create().assess(t)}catch{continue}for(const a of s.criteria)a.basis===void 0&&!a.unsupported&&i.add(a.id);const r=s.score===void 0?s.verdict===void 0?"":this.verdictName(n.id,s.verdict):`${Math.round(s.score*100)}%`;r!==""&&e.push({group:"assessment",field:n.id,label:this.labels.assessmentNames[n.id]??n.name,value:r,unit:"",fromSource:!1,about:n.create().about})}return{entries:e,unanswered:i}}verdictName(t,e){return this.labels.assessmentVerdicts[`${t}.${e}`]??e.toUpperCase()}}const U2=Math.PI/180,tf=111320;function oe(o,t,e,i){const n=tf*Math.cos(e*U2),s=(o-e)*tf;return{x:(t-i)*n,z:-s}}function os(o,t,e,i){const n=tf*Math.cos(e*U2),s=-t,r=o;return{lat:e+s/tf,lng:i+r/n}}class Fc{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(t,e,i){const n=t.event.place?.[0],s=t.observerTrack;if(!n)return 0;const r=g=>{const m=s.getInterpolatedPoseAt(Math.max(0,g));if(!m||m.lat===void 0||m.lng===void 0)return;const v=oe(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(e-Fc.HALF_SPAN_MS),c=r(e+Fc.HALF_SPAN_MS),h=r(e);if(!a||!c||!h)return 0;const l=Math.hypot(c.eastM-a.eastM,c.northM-a.northM),u=2*Fc.HALF_SPAN_MS/1e3;if(l/u<Fc.MIN_SPEED_MS)return 0;const d=i.heightAt(c.eastM,c.northM)-i.heightAt(a.eastM,a.northM),f=Math.atan2(d,l)*180/Math.PI;if(h.heading===void 0)return f;const p=Math.atan2(c.eastM-a.eastM,c.northM-a.northM)*180/Math.PI;return f*Math.max(0,Math.cos((h.heading-p)*Math.PI/180))}}class Uo{static sessionDeclared=!1;static unlock(t){if(Uo.declarePlayback(),t.state!=="running")try{Promise.resolve(t.resume()).catch(()=>{});const e=t.createBufferSource();e.buffer=t.createBuffer(1,1,22050),e.connect(t.destination),e.start(0)}catch{}}static declarePlayback(){if(!(Uo.sessionDeclared||typeof navigator>"u")){Uo.sessionDeclared=!0;try{const t=navigator.audioSession;t&&(t.type="playback")}catch{}}}}const LS=.08,ev=.15,iv=2,NS=2e3;class kS{context;noiseBuffer;voices=new Map;level=1;master;paused=!0;requested=[];resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",t);return}}Uo.unlock(this.context),this.apply()}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}setPaused(t){t!==this.paused&&(this.paused=t,this.apply())}setVoices(t){this.requested=t,this.apply()}dispose(){for(const t of[...this.voices.keys()])this.release(t);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}apply(){const t=this.context;if(!t)return;const e=this.paused?[]:this.requested.filter(n=>n.inside||n.distanceM<NS),i=new Set(e.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of e){const s=this.voices.get(n.id)??this.build(t,n.id);this.retarget(t,s,n)}}build(t,e){const i=t.createGain();i.gain.value=0;const n=t.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(t));const s=t.createOscillator();s.type="sawtooth";const r=t.createOscillator();r.type="sine";const a=t.createGain(),c=t.createBiquadFilter();c.type="lowpass",c.frequency.value=900,s.connect(c),r.connect(c),c.connect(a).connect(n);const h=()=>{const b=t.createBufferSource();return b.buffer=this.noise(t),b.loop=!0,b.loopStart=Math.random()*iv*.5,b},l=h(),u=t.createBiquadFilter();u.type="bandpass",u.Q.value=4;const d=t.createGain();l.connect(u).connect(d).connect(n);const f=h(),p=t.createBiquadFilter();p.type="lowpass",p.frequency.value=600;const g=t.createGain();f.connect(p).connect(g).connect(n);const m=h(),v=t.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const y=t.createGain();m.connect(v).connect(y).connect(n);const x=[s,r,l,f,m];for(const b of x)b.start();const M={nodes:[i,n,a,c,u,d,p,g,v,y,...x],sources:x,firing:s,crank:r,knock:u,engineGain:a,knockGain:d,roadGain:g,windGain:y,cabin:n,output:i};return this.voices.set(e,M),M}retarget(t,e,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:c}){const h=t.currentTime,l=(y,x)=>y.setTargetAtTime(x,h,LS),u=n.rpm/60,d=u*i.cylinders/2,f=Math.min(1,n.rpm/i.shiftUpRpm),p=Math.min(1.5,n.speedMps/30);l(e.firing.frequency,d),l(e.crank.frequency,u),l(e.knock.frequency,d*3),l(e.engineGain.gain,i.engineGain*(.25+.75*n.load)*(.5+.5*f)*.3),l(e.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),l(e.roadGain.gain,i.roadGain*p**1.5*.8);const g=!r||a;l(e.windGain.gain,p**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+c/60);l(e.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(c,1));l(e.output.gain,v*s)}release(t){const e=this.voices.get(t);if(!e)return;this.voices.delete(t);const i=this.context;i&&(e.output.gain.setTargetAtTime(0,i.currentTime,ev/3),setTimeout(()=>{for(const n of e.sources)try{n.stop()}catch{}for(const n of e.nodes)n.disconnect()},ev*1e3*3))}noise(t){if(this.noiseBuffer)return this.noiseBuffer;const e=t.createBuffer(1,t.sampleRate*iv,t.sampleRate),i=e.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=e,e}}class Nl{static BY_KIND={car:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},generic:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},van:{cylinders:4,idleRpm:750,kmhPer1000Rpm:[7,12,19,27,35,42],shiftUpRpm:2600,shiftDownRpm:1200,engineGain:.8,roadGain:.7,roughness:.45},truck:{cylinders:6,idleRpm:600,kmhPer1000Rpm:[5,8,12,17,23,30,38,48],shiftUpRpm:1900,shiftDownRpm:1e3,engineGain:1,roadGain:.9,roughness:.55},motorcycle:{cylinders:2,idleRpm:1100,kmhPer1000Rpm:[12,18,24,30,35,40],shiftUpRpm:6e3,shiftDownRpm:2500,engineGain:.9,roadGain:.3,roughness:.3}};static of(t){return Nl.BY_KIND[t??"generic"]??Nl.BY_KIND.generic}}class Ro{constructor(t,e){this.samples=t,this.startMs=e}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(t,e,i,n){const s=Ro.SAMPLE_MS,r=[];for(let h=i;h<=n+s/2;h+=s){const l=e(h-s/2),u=e(h+s/2);if(!l||!u)return;r.push(Math.hypot(u.eastM-l.eastM,u.northM-l.northM)/(s/1e3))}const a=[];let c=1;for(let h=0;h<r.length;h++){const l=r[h],u=(r[Math.min(h+1,r.length-1)]-r[Math.max(h-1,0)])/(2*s/1e3);if(l<Ro.STANDING_MPS){c=1,a.push({speedMps:l,rpm:t.idleRpm,load:.1,gear:0});continue}const d=l*3.6,f=v=>d/t.kmhPer1000Rpm[v-1]*1e3;for(;c<t.kmhPer1000Rpm.length&&f(c)>t.shiftUpRpm;)c++;for(;c>1&&f(c)<t.shiftDownRpm;)c--;const p=Math.max(f(c),t.idleRpm*(1+.3*Math.min(1,l/3))),g=.15+.5*Math.min(1,(l/35)**2),m=u>.15?Math.min(1,g+u/2.5):u<-.3?.05:g;a.push({speedMps:l,rpm:p,load:m,gear:c})}return new Ro(a,i)}at(t){const e=(t-this.startMs)/Ro.SAMPLE_MS,i=Math.min(Math.max(Math.floor(e),0),this.samples.length-1),n=this.samples[i],s=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(e-i,0),1);return{speedMps:n.speedMps+(s.speedMps-n.speedMps)*r,rpm:n.rpm+(s.rpm-n.rpm)*r,load:n.load+(s.load-n.load)*r,gear:r<.5?n.gear:s.gear}}}class ef{drives=new Map;at(t,e){const i=[],n=t.event.place?.[0],s=h=>{const l=t.observerTrack.getInterpolatedPoseAt(h),u=l?.lat??n?.lat,d=l?.lng??n?.lng;if(u===void 0||d===void 0||!n)return;const f=oe(u,d,n.lat,n.lng);return{eastM:f.x,northM:-f.z}},r=Math.max(t.observerTrack.duration,(t.event.durationSeconds??0)*1e3),a=t.vehicle;if(a){const h=Nl.of(a.kind),l=this.drive(`observer:${a.kind}`,ef.trackKey(t),()=>Ro.of(h,s,0,r));l&&i.push({id:"observer",profile:h,state:l.at(e),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const c=s(e);for(const h of t.decor){if(!h.engine||!c)continue;const l=Nl.of(h.engine.kind),u=g=>{const m=tr(h,g);return{eastM:m.eastM,northM:m.northM}},d=this.drive(`decor:${h.id}`,ef.decorKey(h,r),()=>Ro.of(l,u,0,r));if(!d)continue;const f=tr(h,e),p=Math.hypot(f.eastM-c.eastM,f.northM-c.northM,f.altitudeM);i.push({id:`decor:${h.id}`,profile:l,state:d.at(e),noise:h.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:p})}return i}drive(t,e,i){const n=this.drives.get(t);if(n&&n.key===e)return n.drive;const s=i();return this.drives.set(t,{key:e,drive:s}),s}static trackKey(t){return t.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(t,e){return`${e}|${t.eastM},${t.northM}|`+(t.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const nv=864e5,sv=4e4;function US(o){const t=Math.floor(o.getTime()/nv);return{elapsedMs:o.getTime()-t*nv,shiftM:{x:rv.unit(t,2654435761)*sv,z:rv.unit(t,2246822507)*sv}}}class rv{static unit(t,e){let i=Math.imul(t|0,e)^e;return i=Math.imul(i^i>>>15,739982445),i=Math.imul(i^i>>>12,695872825),i^=i>>>15,(i>>>0)/4294967295*2-1}}function av(o,t,e,i,n,s,r){const a=i?.lat!==void 0&&i.lng!==void 0&&n?.lat!==void 0&&n.lng!==void 0?oe(n.lat,n.lng,i.lat,i.lng):{x:0,z:0};if(r){const l=t.getInterpolatedWeatherAt(0)??e,u=s===void 0?void 0:l.cloudLayers?.find(p=>p.id===s),d=(u?.windDirectionDeg??l.windDirectionDeg)*Math.PI/180,f=(u?.windSpeed??l.windSpeed)*r.elapsedMs/1e3;a.x+=r.shiftM.x-Math.sin(d)*f,a.z+=r.shiftM.z+Math.cos(d)*f}const c=Math.max(0,o),h=[0,...t.allKeyframes.map(l=>l.t).filter(l=>l>0&&l<c),c];for(let l=1;l<h.length;l++){const u=h[l-1],d=h[l]-u;if(d===0)continue;const f=32;for(let p=0;p<=f;p++){const g=t.getInterpolatedWeatherAt(u+d*p/f)??e,m=s===void 0?void 0:g.cloudLayers?.find(M=>M.id===s),v=(m?.windDirectionDeg??g.windDirectionDeg)*Math.PI/180,y=p===0||p===f?1:p%2===0?2:4,x=(m?.windSpeed??g.windSpeed)*d/1e3/f/3*y;a.x-=Math.sin(v)*x,a.z+=Math.cos(v)*x}}return a}const FS="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAARVBMVEX9sST/uyTfoCjNlSikfCqRcCx8Yy21hipTSi4TITEMHTEuMzBqWC3/wSRUX207SFj8/PyaoakmNUd5gYxBPy90fIfMz9RsB4kZAAACEUlEQVRo3u2XyXbDIAxFLeapjts6/f9PrQA3JymT25Cd3iY5xtYVIB6wLCQSiUQikUgk0nzBoVdFZ1xIpaTQbJnPACaNdYeskWwuAhaZoltnUemfnNkL4N49KEI8n0YAEXMvEWISAWQZPw2Xk1MIoF1dSNAzCMy6JsGyCR0wrkMwT3cBeDt+FH8aEHoA68LbM8HRHXQ3f0RE3/jXOOFX+s4djrKpIbzS7K+MmLrxlWCNR8mczjMw92Ar4dZLDXG4kzXinAECcOUPL3jMdN2294/GQGVG4EMHxORNJXoCfG6oT1trvDGM7iIA9N6aTOuuEbB9ra6FyCYr2gjge+fjA4CIi2uujYRoOBSw0A5/D0hT0X4PW0xtuotNpQPYtkt/fdtyM0LP6ZvOI2DtvoxtJWHvx38AxIkevLwXQ2TOA66DziYfLwC4r5wbIlwJo1ys8+VOBMy7/sxdjwIap49lVC3UePZp1mmyit4SuGUf11pjoTHVRVzXUaXFVt87kuEBsWZ055Q+2sXA76LbZYsvKR1ubvJqbKd5swl+GPI31p6L/sNYuDTe3jo+GBdr1J+P9PGawbRUw9VhleD/3ffT9uZ7DhtX1JNHL2CmNRXxYZhwSwBd3aJTyU85/GKOwhxBf5RnVk+75OSiuu+Ax4PQ3Jsg1hTeMUMwJgQp+PKCe2a+JuefFwQnkUgkEolEIpFerW8TL0hlNl2QVAAAAABJRU5ErkJggg==",zS=`
|
|
667
|
+
`;class Gp{static NAMES=["weather","place","lightPollution","decor"];static KEYS={weather:["weatherTrack","weatherSource"],place:["place"],lightPollution:["lightPollution"],decor:["decor"]};static annexName(t,e){return`${t}.${e.replace(/[A-Z]/g,i=>`-${i.toLowerCase()}`)}.json`}static fromFile(t,e){return t?.[e]!==void 0&&t[e].live!==!0}}class Qc{static NAMES=["relief","imagery","roads","water","railways","upperAir","map"];static TERRAIN=["relief","imagery","roads","water","railways"];static held(t,e){if(!t||t.live)return;const i=t[e];return i&&!i.live&&!i.refresh&&i.src!==void 0?i:void 0}static isLive(t,e){return t?.live===!0||t?.[e]?.live===!0}static annexName(t,e){const i=e==="relief"||e==="imagery"||e==="map"?"zip":"json",n=e.replace(/[A-Z]/g,s=>`-${s.toLowerCase()}`);return`${t}.${n}.${i}`}static isEmpty(t){return!t||!t.live&&Qc.NAMES.every(e=>!t[e])&&Gp.NAMES.every(e=>!t[e])}}class sc extends Error{constructor(t,e,i){super(`${t}: ${e}${i===void 0?"":` (HTTP ${i})`}`),this.kind=t,this.url=e,this.status=i,this.name="SightingFetchError"}}class Ha{static async recording(t){const e=await Ha.json(t);for(const i of Gp.NAMES){const n=e?.frozen?.[i];if(!(!n?.src||n.live))try{const s=await Ha.json(new URL(n.src,new URL(t,location.href)).href);for(const r of Gp.KEYS[i])s[r]!==void 0&&(e[r]=s[r])}catch{}}return e}static async json(t){const e=new URL(t,location.href);if(location.protocol==="https:"&&e.protocol==="http:")throw new sc("mixed-content",t);let i;try{i=await fetch(t)}catch{throw await this.diagnose(t,e)}if(!i.ok)throw new sc("status",t,i.status);try{return await i.json()}catch{throw new sc("malformed",t)}}static async diagnose(t,e){if(e.origin===location.origin)return new sc("unreachable",t);try{return await fetch(t,{mode:"no-cors"}),new sc("cors",t)}catch{return new sc("unreachable",t)}}}class Kn{constructor(t){this.entries=t}static empty(){return new Kn(new Map)}get size(){return this.entries.size}at(t){return this.entries.get(t)}paths(){return[...this.entries.keys()]}set(t,e){e.basis==="stated"&&e.rationale===void 0&&e.how===void 0?this.entries.delete(t):this.entries.set(t,e)}clear(t){for(const e of this.entries.keys())(e===t||e.startsWith(`${t}.`))&&this.entries.delete(e)}static strip(t){const e=new Kn(new Map);return{recording:Kn.stripValue(t,[],e),provenance:e}}static restore(t,e){if(e.size===0)return t;const i={...t},n=new Set([i]);for(const s of e.paths()){const r=e.at(s),a=s.split("."),c=Kn.writableHolderOf(i,a,n);if(!c)continue;const h=a[a.length-1],l=c[h];l!==void 0&&(r.of!==void 0&&JSON.stringify(r.of)!==JSON.stringify(l)||(c[h]={value:l,...r.basis==="stated"?{}:{basis:r.basis},...r.rationale===void 0?{}:{rationale:r.rationale},...r.how===void 0?{}:{how:r.how}}))}return i}static isWrapper(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&"value"in t}static stripValue(t,e,i){return Kn.isWrapper(t)?(i.set(e.join("."),{basis:t.basis??"stated",...t.rationale===void 0?{}:{rationale:t.rationale},...t.how===void 0?{}:{how:t.how},of:t.value}),Kn.stripValue(t.value,e,i)):Array.isArray(t)?t.map((n,s)=>Kn.stripValue(n,[...e,String(s)],i)):typeof t=="object"&&t!==null?Object.fromEntries(Object.entries(t).map(([n,s])=>[n,Kn.stripValue(s,[...e,n],i)])):t}static writableHolderOf(t,e,i){let n=t;for(const s of e.slice(0,-1)){const r=n[s];if(typeof r!="object"||r===null)return;if(i.has(r)){n=r;continue}const a=Array.isArray(r)?[...r]:{...r};i.add(a),n[s]=a,n=a}return n}}class nw extends Error{constructor(t,e,i){super(typeof e=="number"&&Number.isInteger(e)&&e>i?`This ${t} file is in version ${e} of its format; this UFO@home reads up to version ${i}. Read it with a newer UFO@home.`:`This ${t} file states ${JSON.stringify(e)} as its format version, which is not a version.`),this.format=t,this.found=e,this.supported=i,this.name="FormatVersionError"}said(t){return t.replace("{found}",typeof this.found=="number"?String(this.found):JSON.stringify(this.found)).replace("{supported}",String(this.supported))}}class po{static CURRENT={sighting:1,case:1,interview:1};static SCHEMA_BASE="https://ufoathome.org/schema";static schemaUrl(t,e=po.CURRENT[t]){return`${po.SCHEMA_BASE}/${e}/${t}.schema.json`}static of(t){if(typeof t!="object"||t===null)return 1;const e=t.version;return e===void 0?1:typeof e=="object"&&e!==null&&"value"in e?e.value:e}static check(t,e){const i=po.of(t),n=po.CURRENT[e];if(typeof i!="number"||!Number.isInteger(i)||i<1||i>n)throw new nw(e,i,n);return t}}class sn{static SIGHTING_EVENT="sighting";static INTERPRETATION_EVENT="interpretation";static INTERVIEW_EVENT="interview";static check(t){return po.check(t,"case")}static isCase(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&Array.isArray(t.events)&&!("timeline"in t)}static sightingUrls(t,e){return(t.events??[]).filter(i=>i.eventType===sn.SIGHTING_EVENT&&!i.interpretationOf&&typeof i.url=="string"&&i.url!=="").map(i=>new URL(i.url,e).href)}static accountIds(t,e,i,n){const s=(t.events??[]).filter(r=>r.eventType===sn.SIGHTING_EVENT&&r.id!==void 0&&typeof r.url=="string"&&i!==void 0&&new URL(r.url,e).href===i).map(r=>r.id);return n!==void 0&&s.push(n),s}static interpretationEvents(t,e){const i=[e].flat().filter(n=>!!n);return i.length===0?[]:(t.events??[]).filter(n=>n.eventType===sn.INTERPRETATION_EVENT?n.sighting!==void 0&&i.includes(n.sighting):n.eventType!==sn.SIGHTING_EVENT||n.interpretationOf===void 0?!1:[n.interpretationOf].flat().some(s=>i.includes(s))).map(n=>n)}static problems(t,e){const i=t.events??[],n=new Set,s=new Set;for(const a of i)a.id!==void 0&&(n.has(a.id)&&s.add(a.id),n.add(a.id));const r=[];for(const a of i){const c=a.eventType===sn.SIGHTING_EVENT?a.interpretationOf:a.eventType===sn.INTERVIEW_EVENT?a.interviewOf:void 0;if(c!==void 0)for(const h of[c].flat())!n.has(h)&&!e.includes(h)&&r.push({reading:a.url??a.id??"",reference:h})}return{duplicateIds:[...s],unresolved:r}}static async interpretationOf(t,e,i){if(t.bodies)return sn.withModelsFrom(Kn.strip({title:t.title,bodies:t.bodies??[],smoke:t.smoke,flares:t.flares,lanterns:t.lanterns}).recording,e);if(!t.url)return{title:t.title,bodies:[]};const n=new URL(t.url,e).href,s=await i(n),r="timeline"in s&&s.interpretation?s.interpretation:s;return sn.withModelsFrom(Kn.strip({title:t.title??r.title,bodies:r.bodies??[],smoke:r.smoke,flares:r.flares,lanterns:r.lanterns}).recording,n)}static withModelsFrom(t,e){return{...t,bodies:t.bodies.map(i=>i.model?.url?{...i,model:{...i.model,url:new URL(i.model.url,e).href}}:i)}}}class th{static ISO=/^P(?:(\d+(?:[.,]\d+)?)W)?(?:(\d+(?:[.,]\d+)?)D)?(?:T(?:(\d+(?:[.,]\d+)?)H)?(?:(\d+(?:[.,]\d+)?)M)?(?:(\d+(?:[.,]\d+)?)S)?)?$/;static seconds(t){const e=t.trim().toUpperCase(),i=th.ISO.exec(e);if(!i||e==="P"||e.endsWith("T"))return;const[,n,s,r,a,c]=i,h=u=>u===void 0?0:Number(u.replace(",",".")),l=h(n)*604800+h(s)*86400+h(r)*3600+h(a)*60+h(c);return Number.isFinite(l)?l:void 0}static parse(t){let e=t.trim();if(e==="")return;const i=e.slice(-1),n="?~%".includes(i)?i:"";n!==""&&(e=e.slice(0,-1).trim());const s=e.split("/");if(s.length>2)return;const r=s.map(u=>th.seconds(u));if(r.some(u=>u===void 0))return;const[a,c]=r,h=Math.min(a,c??a),l=Math.max(a,c??a);return{doubt:n,minSeconds:h,maxSeconds:l,chosenSeconds:(h+l)/2}}static isExact(t){const e=th.parse(t);return e!==void 0&&e.doubt===""&&e.minSeconds===e.maxSeconds}static format(t){const e=Math.max(0,Math.round(t*10)/10),i=Math.floor(e/3600),n=Math.floor(e%3600/60),s=Math.round(e%60*10)/10;return`PT${`${i>0?`${i}H`:""}${n>0?`${n}M`:""}${s>0||i===0&&n===0?`${s}S`:""}`}`}static say(t){const e=Math.round(t*10)/10;if(e<60)return`${e} s`;const i=Math.floor(e/3600),n=Math.floor(e%3600/60),s=Math.round(e%60*10)/10,r=[];return i>0&&r.push(`${i} h`),n>0&&r.push(`${n} min`),s>0&&r.push(`${s} s`),r.join(" ")}}class Qe{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(t){return 2*Math.atan(t.sizeM/(2*t.distanceM))*180/Math.PI}static inMoons(t){return t/Qe.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(t,e,i){if(!(!t||!e))return{widthDeg:t.widthDeg+(e.widthDeg-t.widthDeg)*i,heightDeg:t.heightDeg+(e.heightDeg-t.heightDeg)*i}}static sizeMAt(t,e){return 2*t*Math.tan(e*Math.PI/360)}static distanceMAt(t,e){return t/(2*Math.tan(e*Math.PI/360))}}function sw(o,t,e){if(!o||!t)return e<1?o:t;const i=((t.azimuthDeg-o.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((o.azimuthDeg+i*e)%360+360)%360,altitudeDeg:o.altitudeDeg+(t.altitudeDeg-o.altitudeDeg)*e}}function rw(o,t,e){const{bounds:i}=o;return t>=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height}function ns(o,t,e){return o+(t-o)*e}function I1(o){const t=/^#([0-9a-f]{6})$/i.exec(o);if(!t)return;const e=parseInt(t[1],16);return[e>>16&255,e>>8&255,e&255]}function aw(o){return`#${o.map(t=>Math.round(t).toString(16).padStart(2,"0")).join("")}`}function ow(o,t,e){const i=I1(o),n=I1(t);return!i||!n?e<1?o:t:aw([ns(i[0],n[0],e),ns(i[1],n[1],e),ns(i[2],n[2],e)])}function cw(o,t,e){const i={x:ns(o.bounds.x,t.bounds.x,e),y:ns(o.bounds.y,t.bounds.y,e),width:ns(o.bounds.width,t.bounds.width,e),height:ns(o.bounds.height,t.bounds.height,e)},n=ns(o.angle,t.angle,e),s=ns(o.transparency,t.transparency,e),r=ns(o.haloScale,t.haloScale,e),a=ns(o.blur??0,t.blur??0,e),c=ns(o.brightness??0,t.brightness??0,e),h=ow(o.color,t.color,e),l=Qe.lerpAngular(o.angular,t.angular,e),u=sw(o.aim,t.aim,e);return o.kind==="polygon"&&t.kind==="polygon"&&o.points.length===t.points.length?{...o,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:c,color:h,angular:l,aim:u,points:o.points.map((d,f)=>({x:ns(d.x,t.points[f].x,e),y:ns(d.y,t.points[f].y,e)}))}:{...e<1?o:t,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:c,color:h,angular:l,aim:u}}class Ea{static DEFAULT_COLOR="#e8e6df";static complete(t,e=[]){const i=new Map;return t.map((n,s)=>({keyframe:n,index:s})).sort((n,s)=>n.keyframe.t-s.keyframe.t).map(({keyframe:n,index:s})=>({t:n.t,shapes:(n.shapes??[]).map((r,a)=>{const c=`timeline.keyframes.${s}.shapes.${a}.shape`,h=Ea.completed(r,i.get(r.sourceId),c,e);return i.set(r.sourceId,h),{sourceId:r.sourceId,shape:h}})}))}static thin(t,e){const i=new Map,n=new Set;return t.map((s,r)=>({t:s.t,shapes:s.shapes.map(a=>{const c=i.get(a.sourceId);if(i.set(a.sourceId,a.shape),!c)return{sourceId:a.sourceId,shape:a.shape};const h=Ea.thinned(a.shape,c);if(e){const l=h;e(r,a.sourceId)?(delete l.bounds,delete l.points,n.add(a.sourceId)):n.delete(a.sourceId)&&(l.bounds=a.shape.bounds,a.shape.kind==="polygon"&&(l.points=a.shape.points),a.shape.aim&&(l.aim=a.shape.aim),a.shape.angular&&(l.angular=a.shape.angular))}return{sourceId:a.sourceId,shape:h}})}))}static thinned(t,e){const i=e,n={};for(const[s,r]of Object.entries(t))(typeof r=="object"&&r!==null&&!Array.isArray(r)&&"value"in r||r!==i[s]&&JSON.stringify(r)!==JSON.stringify(i[s]))&&(n[s]=r);return"bounds"in n&&(t.aim&&(n.aim=t.aim),t.angular&&(n.angular=t.angular)),n}static completed(t,e,i,n){const s=t.shape??{},r=e??Ea.firstAppearance(s,i,n),a={...r};s.bounds&&e&&(e.aim||e.angular)&&!s.aim&&!s.angular&&n.push({kind:"pixels-over-angles",path:i}),s.bounds&&(s.aim||delete a.aim,s.angular||delete a.angular);const c=s.kind??r.kind??"oval",h={...a,...s,kind:c};if(c==="polygon"&&!h.points){n.push({kind:"defaulted",path:`${i}.points`,expected:"rectangle"});const{width:l,height:u}=h.bounds;return{...h,points:[{x:0,y:0},{x:l,y:0},{x:l,y:u},{x:0,y:u}]}}return h}static firstAppearance(t,e,i){return t.kind||i.push({kind:"defaulted",path:`${e}.kind`,expected:'"oval"'}),t.color||i.push({kind:"defaulted",path:`${e}.color`,expected:`"${Ea.DEFAULT_COLOR}"`}),!t.bounds&&!t.aim&&i.push({kind:"unplaced",path:e}),!t.bounds&&!t.angular&&i.push({kind:"unsized",path:e}),{kind:t.kind??"oval",bounds:{...Ea.NEUTRAL_BOUNDS},color:Ea.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:Qe.CANVAS_WIDTH_PX/2,y:Qe.CANVAS_HEIGHT_PX/2,width:1,height:1}}class Uf{keyframes=[];order=[];groups=[];span=0;addKeyframe(t,e){const i=this.findInsertIndex(t);if(this.keyframes[i]?.t===t){const n=new Set(e.map(s=>s.sourceId));this.keyframes[i]={t,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...e]}}else this.keyframes.splice(i,0,{t,shapes:[...e]});for(const n of e)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getKeyframeAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e];return i?.t===t?i:void 0}getShapeAt(t,e){return this.getKeyframeAt(t)?.shapes.find(i=>i.sourceId===e)?.shape}getLatestShapeAt(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return n.shape}}getInterpolatedShapeAt(t,e){const i=this.findShapeAtOrBefore(t,e);if(i?.t===t)return i.shape;const n=this.findShapeAtOrAfter(t,e);return i?n?cw(i.shape,n.shape,(t-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(t,e){let i=this.findInsertIndex(t);for(this.keyframes[i]?.t!==t&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(t,e){for(let i=this.findInsertIndex(t);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===e);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(t,e,i,n){const s=this.sourceIds;for(let r=s.length-1;r>=0;r--){if(n?.has(s[r]))continue;const a=this.getInterpolatedShapeAt(t,s[r]);if(a&&rw(a,e,i))return{sourceId:s[r],shape:a}}}removeSource(t){for(let e=this.keyframes.length-1;e>=0;e--){const i=this.keyframes[e].shapes.filter(n=>n.sourceId!==t);i.length===0?this.keyframes.splice(e,1):i.length!==this.keyframes[e].shapes.length&&(this.keyframes[e]={t:this.keyframes[e].t,shapes:i})}this.order=this.order.filter(e=>e!==t),this.removeFromGroup(t)}removeShapeAt(t,e){const i=this.findInsertIndex(t),n=this.keyframes[i];if(n?.t!==t)return;const s=n.shapes.filter(r=>r.sourceId!==e);s.length===0?this.keyframes.splice(i,1):s.length!==n.shapes.length&&(this.keyframes[i]={t,shapes:s})}group(t){if(!(t.length<2)){for(const e of t)this.removeFromGroup(e);this.groups.push([...t])}}ungroup(t){const e=this.groups.findIndex(i=>i.includes(t));e!==-1&&this.groups.splice(e,1)}groupMembers(t){return this.groups.find(e=>e.includes(t))}removeFromGroup(t){const e=this.groups.findIndex(n=>n.includes(t));if(e===-1)return;const i=this.groups[e].filter(n=>n!==t);i.length<2?this.groups.splice(e,1):this.groups[e]=i}bringToFront(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.push(t))}sendToBack(t){const e=this.order.indexOf(t);e!==-1&&(this.order.splice(e,1),this.order.unshift(t))}get duration(){const t=this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t;return Math.max(t,this.span)}get hasSpan(){return this.span>0}setSpan(t){this.span=Math.max(0,t)}get sourceIds(){return[...this.order]}get allKeyframes(){return this.keyframes}toJSON(){return this.span>0?{keyframes:this.keyframes,order:this.order,groups:this.groups,span:this.span}:{keyframes:this.keyframes,order:this.order,groups:this.groups}}static fromJSON(t,e){const i=new Uf;for(const n of Ea.complete(t.keyframes??[],e))i.addKeyframe(n.t,n.shapes);if(t.span!==void 0&&t.span>0&&(i.span=t.span),t.order){const n=i.order.filter(s=>!t.order.includes(s));i.order=[...t.order,...n]}return t.groups&&(i.groups=t.groups.map(n=>n.filter(s=>i.order.includes(s))).filter(n=>n.length>=2)),i}}function hw(o,t,e){return Math.max(t,Math.min(e,o))}function lw(o,t,e){const i=((t-o)%360+540)%360-180;return((o+i*e)%360+360)%360}function rc(o,t,e){return o+(t-o)*e}function uw(o,t,e){return{lat:o.lat===void 0||t.lat===void 0?void 0:rc(o.lat,t.lat,e),lng:o.lng===void 0||t.lng===void 0?void 0:rc(o.lng,t.lng,e),elevationM:rc(o.elevationM,t.elevationM,e),headingDeg:o.headingDeg===void 0||t.headingDeg===void 0?void 0:lw(o.headingDeg,t.headingDeg,e),pitchDeg:rc(o.pitchDeg,t.pitchDeg,e),rollDeg:rc(o.rollDeg??0,t.rollDeg??0,e),fovDeg:rc(o.fovDeg,t.fovDeg,e),fNumber:o.fNumber,focusDistanceM:o.focusDistanceM,filter:o.filter}}class Dn{static at(t,e,i,n,s){const r=t[i],c=t[i+1]-r;if(c<=0)return e[i];const h=Dn.tangent(t,e,i,s),l=Dn.tangent(t,e,i+1,s),u=(n-r)/c,d=u*u,f=d*u;return(2*f-3*d+1)*e[i]+(f-2*d+u)*c*h+(-2*f+3*d)*e[i+1]+(f-d)*c*l}static SETTLE_MS=120;static ARRIVAL=.5;static gaze(t,e,i,n){const s=t[i],a=t[i+1]-s;if(a<=0)return e[i];const c=l=>l+1<e.length?e[l+1]===e[l]:!0,h=e[i+1]!==e[i];if(h&&c(i+1)){const l=Dn.tangent(t,e,i,!0),u=Dn.ARRIVAL*(e[i+1]-e[i])/a;return Dn.hermite(e[i],l,e[i+1],u,a,(n-s)/a)}return!h&&i>0&&e[i-1]!==e[i]?e[i]+Dn.settle(t,e,i,n-s,a):Dn.at(t,e,i,n,!0)}static settle(t,e,i,n,s){const r=t[i]-t[i-1];if(r<=0||n<=0)return 0;const a=Dn.ARRIVAL*(e[i]-e[i-1])/r,c=Math.min(Dn.SETTLE_MS,.4*r),h=Number.isFinite(s)?(1-Math.min(1,n/s))**2:1;return a*n*Math.exp(-n/c)*h}static hermite(t,e,i,n,s,r){const a=r*r,c=a*r;return(2*c-3*a+1)*t+(c-2*a+r)*s*e+(-2*c+3*a)*i+(c-a)*s*n}static BRAKE_S=.8;static paced(t,e,i,n){if(!i&&!n)return t;const s=e>0?Math.min(.5,Dn.BRAKE_S/e):.5;if(i&&n){const a=1/(1-s);return t<=s?a*t*t/(2*s):t>=1-s?1-a*(1-t)*(1-t)/(2*s):a*(t-s/2)}const r=a=>{const c=1/(1-s/2);if(a<=1-s)return c*a;const h=a-(1-s);return c*(1-s)+c*(h-h*h/(2*s))};return n?r(t):1-r(1-t)}static tangent(t,e,i,n){const s=t.length-1,r=f=>(e[f+1]-e[f])/(t[f+1]-t[f]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-1);const a=r(i-1),c=r(i);if(a*c<=0)return 0;const h=t[i]-t[i-1],l=t[i+1]-t[i],u=2*l+h,d=l+2*h;return(u+d)/(u/a+d/c)}}class Cl{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,pose:e}:this.keyframes.splice(i,0,{t,pose:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestPoseAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].pose:void 0}getInterpolatedPoseAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.pose;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.pose;if(!n)return this.settledAfterEnd(e-1,t);const s=uw(i.pose,n.pose,hw((t-i.t)/(n.t-i.t),0,1));return this.humanly(e-1,t,s)}settledAfterEnd(t,e){const i=this.keyframes[t];if(t<1)return i.pose;const n=this.keyframes[t-1],s=[n.t,i.t],r=(l,u)=>l===void 0||u===void 0?0:Dn.settle(s,[l,u],1,e-i.t,1/0),a=n.pose.headingDeg===void 0||i.pose.headingDeg===void 0?void 0:((i.pose.headingDeg-n.pose.headingDeg)%360+540)%360-180,c=i.pose.headingDeg===void 0||a===void 0?i.pose.headingDeg:((i.pose.headingDeg+r(0,a))%360+360)%360,h=i.pose.pitchDeg+r(n.pose.pitchDeg,i.pose.pitchDeg);return c===i.pose.headingDeg&&h===i.pose.pitchDeg?i.pose:{...i.pose,headingDeg:c,pitchDeg:h}}humanly(t,e,i){const n=Math.max(0,t-1),s=Math.min(this.keyframes.length-1,t+2),r=this.keyframes.slice(n,s+1),a=t-n,c=r.map(M=>M.t),h=(M,b)=>{const S=r.map(_=>M(_.pose));if(!S.some(_=>_===void 0))return Dn.at(c,S,a,e,b)},l=M=>{const b=r.map(S=>M(S.pose));if(!b.some(S=>S===void 0))return Dn.gaze(c,b,a,e)},u=r.map(M=>M.pose.headingDeg);let d;if(u.every(M=>M!==void 0)){const M=[u[0]];for(let b=1;b<u.length;b++)M.push(M[b-1]+((u[b]-u[b-1])%360+540)%360-180);d=(Dn.gaze(c,M,a,e)%360+360)%360}const f=this.keyframes[t],p=this.keyframes[t+1],g=(M,b)=>M.lat===b.lat&&M.lng===b.lng&&M.elevationM===b.elevationM,m=!g(f.pose,p.pose),v=m&&t>0&&g(this.keyframes[t-1].pose,f.pose),y=m&&t+2<this.keyframes.length&&g(p.pose,this.keyframes[t+2].pose);let x;if(v||y){const M=Dn.paced((e-f.t)/(p.t-f.t),(p.t-f.t)/1e3,v,y),b=(S,_)=>S===void 0||_===void 0?void 0:S+(_-S)*M;x={lat:b(f.pose.lat,p.pose.lat),lng:b(f.pose.lng,p.pose.lng),elevationM:b(f.pose.elevationM,p.pose.elevationM)}}return{...i,lat:x?x.lat:h(M=>M.lat,!1)??i.lat,lng:x?x.lng:h(M=>M.lng,!1)??i.lng,elevationM:x?x.elevationM:h(M=>M.elevationM,!1)??i.elevationM,headingDeg:d??i.headingDeg,pitchDeg:l(M=>M.pitchDeg)??i.pitchDeg,rollDeg:h(M=>M.rollDeg??0,!0)??i.rollDeg,fovDeg:h(M=>M.fovDeg,!0)??i.fovDeg}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Cl;for(const i of t.keyframes)e.addKeyframe(i.t,i.pose);return e}}class Aa{static MAX_CHANGE_PER_S=.05;points;followed;constructor(t){let e="none",i=0;this.points=t.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(e=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:e,lastFallingIntensity:i,intensity:s.precipitationType==="none"?0:s.precipitationIntensity,type:s.precipitationType})),this.followed=[];for(let n=0;n<this.points.length;n++){if(n===0){this.followed.push(this.points[0].intensity);continue}const s=this.points[n-1],r=this.points[n];this.followed.push(Aa.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.t)/1e3))}}at(t){if(this.points.length===0||t<this.points[0].t)return;let e=this.points.length-1;for(;e>0&&this.points[e].t>t;)e--;const i=this.points[e],n=this.points[e+1],s=n?Aa.follow(this.followed[e],i.intensity,n.intensity,(n.t-i.t)/1e3,(t-i.t)/1e3):Aa.follow(this.followed[e],i.intensity,i.intensity,1,(t-i.t)/1e3);return{type:Aa.typeBetween(i,n,t,s),intensity:s,character:Aa.characterBetween(i,n,t)}}static characterBetween(t,e,i){return t.type==="none"?e&&e.type!=="none"?e.intensity:t.lastFallingIntensity:!e||e.type==="none"?t.intensity:t.intensity+(e.intensity-t.intensity)*(i-t.t)/(e.t-t.t||1)}static typeBetween(t,e,i,n){return t.type==="none"?e&&e.type!=="none"&&i>t.t?e.type:n>0?t.lastFalling:"none":e&&e.type==="none"&&n<=0?"none":t.type}static follow(t,e,i,n,s){const r=Aa.MAX_CHANGE_PER_S,a=n>0?(i-e)/n:0,c=u=>e+a*Math.min(Math.max(u,0),n);let h=t,l=0;for(let u=0;u<8&&l<s;u++){const d=c(l)-h;if(Math.abs(d)<1e-9){const x=l<n?a:0;if(Math.abs(x)<=r){const b=l<n?Math.min(s,n):s;h=c(b),l=b;continue}const M=Math.min(s,n);h+=Math.sign(x)*r*(M-l),l=M;continue}const f=Math.sign(d),p=l<n?a:0,g=r-f*p,m=g>0?l+Math.abs(d)/g:1/0,v=l<n?n:1/0,y=Math.min(s,m,v);h+=f*r*(y-l),l=y,y===m&&(h=c(l))}return Math.min(1,Math.max(0,h))}}const xg=1e3,dw=.65,fw=.05,Ff={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function Cd(o){if(o.cloudLayers!==void 0)return o.cloudLayers;const t=[],e=o.lowerCloudCover??o.cloudCover;return e>0&&t.push({id:"lower",type:"cumulus",baseM:o.cloudBaseM??xg,thicknessM:650,coverage:e,sizeM:1400,density:1,darkness:o.cloudDarkness}),(o.highCloudCover??0)>0&&t.push({id:"cirrus",type:"cirrus",baseM:8e3,thicknessM:400,coverage:o.highCloudCover,sizeM:2200,density:.35,darkness:o.cloudDarkness,iceCrystalAlignment:o.iceCrystalAlignment}),t}function gi(o,t,e){return o+(t-o)*e}function bg(o,t,e){const i=((t-o)%360+540)%360-180;return((o+i*e)%360+360)%360}function pw(o,t,e){return Math.max(t,Math.min(e,o))}function mw(o=[],t=[],e){if(!(!o.length&&!t.length))return[...new Set([...o.map(i=>i.id),...t.map(i=>i.id)])].map(i=>{const n=o.find(c=>c.id===i),s=t.find(c=>c.id===i),r=n??{...s,density:0},a=s??{...n,density:0};return{...r,eastM:gi(r.eastM,a.eastM,e),northM:gi(r.northM,a.northM,e),baseM:gi(r.baseM,a.baseM,e),thicknessM:gi(r.thicknessM,a.thicknessM,e),widthM:gi(r.widthM,a.widthM,e),depthM:gi(r.depthM,a.depthM,e),rotationDeg:bg(r.rotationDeg,a.rotationDeg,e),density:gi(r.density,a.density,e),darkness:gi(r.darkness??0,a.darkness??0,e)}})}function gw(o,t,e){if(o.cloudLayers===void 0&&t.cloudLayers===void 0)return;const i=Cd(o),n=Cd(t);return e>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const a=i.find(u=>u.id===r),c=n.find(u=>u.id===r),h=a??{...c,coverage:0},l=c??{...a,coverage:0};return{...h,instances:mw(a?.instances,c?.instances,e),baseM:gi(h.baseM,l.baseM,e),thicknessM:gi(h.thicknessM,l.thicknessM,e),coverage:gi(h.coverage,l.coverage,e),sizeM:gi(h.sizeM,l.sizeM,e),density:gi(h.density,l.density,e),darkness:gi(h.darkness??o.cloudDarkness,l.darkness??t.cloudDarkness,e),iceCrystalAlignment:h.iceCrystalAlignment===void 0||l.iceCrystalAlignment===void 0?void 0:gi(h.iceCrystalAlignment,l.iceCrystalAlignment,e),windSpeed:h.windSpeed===void 0&&l.windSpeed===void 0?void 0:gi(h.windSpeed??o.windSpeed,l.windSpeed??t.windSpeed,e),windDirectionDeg:h.windDirectionDeg===void 0&&l.windDirectionDeg===void 0?void 0:bg(h.windDirectionDeg??o.windDirectionDeg,l.windDirectionDeg??t.windDirectionDeg,e)}})}function vw(o,t,e){return{cloudLayers:gw(o,t,e),cloudCover:gi(o.cloudCover,t.cloudCover,e),cloudDarkness:gi(o.cloudDarkness,t.cloudDarkness,e),highCloudCover:o.highCloudCover===void 0||t.highCloudCover===void 0?void 0:gi(o.highCloudCover,t.highCloudCover,e),iceCrystalAlignment:o.iceCrystalAlignment===void 0||t.iceCrystalAlignment===void 0?void 0:gi(o.iceCrystalAlignment,t.iceCrystalAlignment,e),rareIceCrystals:o.rareIceCrystals===void 0||t.rareIceCrystals===void 0?void 0:gi(o.rareIceCrystals,t.rareIceCrystals,e),lowerCloudCover:o.lowerCloudCover===void 0||t.lowerCloudCover===void 0?void 0:gi(o.lowerCloudCover,t.lowerCloudCover,e),cloudBaseM:o.cloudBaseM===void 0||t.cloudBaseM===void 0?void 0:gi(o.cloudBaseM,t.cloudBaseM,e),relativeHumidity:o.relativeHumidity===void 0||t.relativeHumidity===void 0?void 0:gi(o.relativeHumidity,t.relativeHumidity,e),precipitationType:e<1?o.precipitationType:t.precipitationType,precipitationIntensity:gi(o.precipitationIntensity,t.precipitationIntensity,e),windDirectionDeg:bg(o.windDirectionDeg,t.windDirectionDeg,e),windSpeed:gi(o.windSpeed,t.windSpeed,e),storm:e<1?o.storm:t.storm}}class Ol{keyframes=[];ramp;addKeyframe(t,e){this.ramp=void 0;const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,weather:e}:this.keyframes.splice(i,0,{t,weather:e})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(t){this.ramp=void 0;const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}getLatestWeatherAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].weather:void 0}getInterpolatedWeatherAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.weather;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];return i?n?vw(i.weather,n.weather,pw((t-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(t){const e=this.getInterpolatedWeatherAt(t);if(!e)return;const i=(this.ramp??=new Aa(this.keyframes)).at(t);if(!i)return e;const{type:n,intensity:s,character:r}=i,a=r>0?Math.min(1,s/r):n==="none"?0:1;return{...e,precipitationType:n,precipitationIntensity:r,precipitationAmount:a}}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Ol;for(const i of t.keyframes)e.addKeyframe(i.t,{...Ff,...i.weather});return e}}class Pl{keyframes=[];addKeyframe(t,e){const i=this.findInsertIndex(t);this.keyframes[i]?.t===t?this.keyframes[i]={t,sound:e}:this.keyframes.splice(i,0,{t,sound:e})}clear(){this.keyframes.length=0}removeKeyframeAt(t){const e=this.findInsertIndex(t);this.keyframes[e]?.t===t&&this.keyframes.splice(e,1)}getLatestSoundAt(t){let e=this.findInsertIndex(t);return this.keyframes[e]?.t!==t&&(e-=1),e>=0?this.keyframes[e].sound:void 0}getInterpolatedSoundAt(t){const e=this.findInsertIndex(t),i=this.keyframes[e]?.t===t?this.keyframes[e]:this.keyframes[e-1];if(i?.t===t)return i.sound;const n=this.keyframes[e]?.t===t?void 0:this.keyframes[e];if(!i)return n?.sound;if(!n)return i.sound;const s=(t-i.t)/(n.t-i.t);return this.lerp(i.sound,n.sound,Math.max(0,Math.min(1,s)))}get duration(){return this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t}get allKeyframes(){return this.keyframes}toJSON(){return{keyframes:this.keyframes}}static fromJSON(t){const e=new Pl;for(const i of t.keyframes)e.addKeyframe(i.t,i.sound);return e}lerp(t,e,i){return{kind:i<1?t.kind:e.kind,volume:t.volume+(e.volume-t.volume)*i,pitchHz:t.pitchHz+(e.pitchHz-t.pitchHz)*i,src:i<1?t.src:e.src}}findInsertIndex(t){let e=0,i=this.keyframes.length;for(;e<i;){const n=e+i>>>1;this.keyframes[n].t<t?e=n+1:i=n}return e}}const Mw=100,yw={kind:"none",volume:0,pitchHz:Mw};class Uc{static DEFAULT_FOCAL_MM=50;static FOCAL_RANGE_MM={minMm:14,maxMm:135};static BODIES=[{id:"eos-450d",name:"Canon EOS 450D (APS-C)",widthMm:22.2,heightMm:14.8,pixelUm:5.2,year:2008},{id:"eos-60da",name:"Canon EOS 60Da (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.3,year:2012},{id:"eos-70d",name:"Canon EOS 70D (APS-C)",widthMm:22.5,heightMm:15,pixelUm:4.1,year:2013},{id:"eos-80d",name:"Canon EOS 80D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:3.7,year:2016},{id:"eos-7d",name:"Canon EOS 7D (APS-C)",widthMm:22.3,heightMm:14.9,pixelUm:4.1,year:2009},{id:"eos-7d-ii",name:"Canon EOS 7D Mark II (APS-C)",widthMm:22.4,heightMm:15,pixelUm:4.1,year:2014},{id:"eos-5d",name:"Canon EOS 5D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:8.2,year:2005},{id:"eos-5d-ii",name:"Canon EOS 5D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:6.4,year:2008},{id:"eos-5d-iii",name:"Canon EOS 5D Mark III (full frame)",widthMm:36,heightMm:24,pixelUm:6.25,year:2012},{id:"eos-5d-iv",name:"Canon EOS 5D Mark IV (full frame)",widthMm:36,heightMm:24,pixelUm:5.36,year:2016},{id:"eos-6d",name:"Canon EOS 6D (full frame)",widthMm:35.8,heightMm:23.9,pixelUm:6.55,year:2012},{id:"eos-6d-ii",name:"Canon EOS 6D Mark II (full frame)",widthMm:36,heightMm:24,pixelUm:5.77,year:2017},{id:"nikon-d3",name:"Nikon D3 / D700 (full frame)",widthMm:36,heightMm:23.9,pixelUm:8.44,year:2007},{id:"nikon-d7000",name:"Nikon D7000 (DX)",widthMm:23.6,heightMm:15.6,pixelUm:4.78,year:2010},{id:"nikon-d7100",name:"Nikon D7100 / D7200 (DX)",widthMm:23.5,heightMm:15.6,pixelUm:3.9,year:2013},{id:"nikon-d500",name:"Nikon D500 / D7500 (DX)",widthMm:23.5,heightMm:15.7,pixelUm:4.2,year:2016}];static instruments(){return Uc.BODIES.map(t=>({id:t.id,category:"dslr",name:t.name,projection:"rectilinear",frame:{widthMm:t.widthMm,heightMm:t.heightMm,focalLengthMm:Uc.DEFAULT_FOCAL_MM,focalRangeMm:Uc.FOCAL_RANGE_MM},fNumber:8,fNumberRange:{min:1.4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/8e3,max:3600},years:{from:t.year},apertureBlades:7,detailUm:t.pixelUm,medium:{kind:"sensor",iso:100}}))}static names(){return Object.fromEntries(Uc.BODIES.map(t=>[t.id,t.name]))}}class Gs{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*Gs.DEFAULT_EYEPIECE_MM*Math.tan(Gs.DEFAULT_APPARENT_FIELD_DEG*Math.PI/360);static RANGE={min:26/40*.63,max:26/6*3};static BINOCULARS=[{id:"binoculars-zeiss-6x30",name:"Carl Zeiss 6x30",magnification:6,apertureMm:30,trueFieldDeg:5,fromYear:1960},{id:"binoculars-zeiss-dialyt-10x40",name:"Carl Zeiss Dialyt 10x40 B T*",magnification:10,apertureMm:40,trueFieldDeg:6.3,fromYear:1975},{id:"binoculars-jenoptem-10x50",name:"Jenoptem 10x50 W",magnification:10,apertureMm:50,trueFieldDeg:7.3,fromYear:1960},{id:"binoculars-swarovski-7x50-habicht",name:"Swarovski 7x50 SL Habicht",magnification:7,apertureMm:50,trueFieldDeg:6.6,fromYear:1960},{id:"binoculars-swarovski-7x50-slc",name:"Swarovski 7x50 SLC",magnification:7,apertureMm:50,trueFieldDeg:7.1,fromYear:1990},{id:"binoculars-nikon-10x42-edg",name:"Nikon 10x42 EDG",magnification:10,apertureMm:42,trueFieldDeg:6.5,fromYear:2011},{id:"binoculars-canon-15x50-is",name:"Canon 15x50 IS All Weather",magnification:15,apertureMm:50,trueFieldDeg:4.5,fromYear:2008},{id:"binoculars-celestron-15x70",name:"Celestron 15x70 SkyMaster",magnification:15,apertureMm:70,trueFieldDeg:4.4,fromYear:1990},{id:"binoculars-miyauchi-25x141",name:"Miyauchi BR-141 Galaxy 45 25x141",magnification:25,apertureMm:141,trueFieldDeg:2.6,fromYear:2e3}];static TELESCOPES=[{id:"telescope-generic-60-700",name:"Telescope 60/700",apertureMm:60,focalLengthMm:700},{id:"telescope-generic-60-1000",name:"Telescope 60/1000",apertureMm:60,focalLengthMm:1e3},{id:"telescope-celestron-onyx-80edf",name:"Celestron Onyx 80EDF",apertureMm:80,focalLengthMm:500,fromYear:2010},{id:"telescope-celestron-c5",name:"Celestron C5 f/10",apertureMm:125,focalLengthMm:1250,fromYear:1970},{id:"telescope-celestron-c8",name:"Celestron C8 f/10",apertureMm:203,focalLengthMm:2032,fromYear:1970},{id:"telescope-celestron-c11",name:"Celestron C11 f/10",apertureMm:280,focalLengthMm:2800,fromYear:1970},{id:"telescope-celestron-c14",name:"Celestron C14 f/11",apertureMm:355.6,focalLengthMm:3910,fromYear:1970},{id:"telescope-meade-etx-80",name:"Meade ETX 80 f/5",apertureMm:80,focalLengthMm:400,fromYear:1996},{id:"telescope-meade-etx-90",name:"Meade ETX 90 f/13.8",apertureMm:90,focalLengthMm:1242,fromYear:1996},{id:"telescope-meade-etx-125",name:"Meade ETX 125 f/15",apertureMm:127,focalLengthMm:1900,fromYear:1996},{id:"telescope-meade-lx200-8",name:"Meade LX200 8 in f/10",apertureMm:200,focalLengthMm:2e3,fromYear:1992},{id:"telescope-meade-lx200-10",name:"Meade LX200 10 in f/10",apertureMm:250,focalLengthMm:2500,fromYear:1992},{id:"telescope-meade-lx200-12",name:"Meade LX200 12 in f/10",apertureMm:305,focalLengthMm:3048,fromYear:1992},{id:"telescope-meade-lx200-14",name:"Meade LX200 14 in f/10",apertureMm:355,focalLengthMm:3556,fromYear:1992},{id:"telescope-meade-lx200-16",name:"Meade LX200 16 in f/10",apertureMm:406,focalLengthMm:4064,fromYear:1992}];static instruments(){const t=Gs.BINOCULARS.map(n=>({id:n.id,category:"binoculars",name:n.name,projection:"rectilinear",visualAid:{apertureMm:n.apertureMm,magnification:n.magnification,trueFieldDeg:n.trueFieldDeg},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}})),e=Gs.FIELD_STOP_MM,i=Gs.TELESCOPES.map(n=>({id:n.id,category:"telescope",name:n.name,projection:"rectilinear",frame:{widthMm:e*16/9,heightMm:e,focalLengthMm:n.focalLengthMm,focalRangeMm:{minMm:n.focalLengthMm*Gs.RANGE.min,maxMm:n.focalLengthMm*Gs.RANGE.max}},visualAid:{apertureMm:n.apertureMm,eyepieceFocalMm:Gs.DEFAULT_EYEPIECE_MM},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}}));return[...t,...i]}static names(){return Object.fromEntries(Gs.instruments().map(t=>[t.id,t.name]))}}const nu=[{id:"eye",category:"eye",name:"Naked eye",projection:"equidistant",stabilization:.97},{id:"rectilinear-lens",category:"camera",name:"Camera, unknown device",projection:"rectilinear",fNumber:8,fNumberRange:{min:2,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:8},apertureBlades:6},{id:"roamer-1-120",category:"camera",name:"Roamer 1, 120 film",projection:"rectilinear",frame:{widthMm:74,heightMm:60,focalLengthMm:100},fNumber:11,exposureSeconds:1/50,years:{from:1930,to:1965},detailUm:40,medium:{kind:"negative",iso:125}},{id:"instamatic-126",category:"camera",name:"Instamatic, 126 film",projection:"rectilinear",frame:{widthMm:28,heightMm:28,focalLengthMm:43},fNumber:11,exposureSeconds:1/90,years:{from:1963,to:1988},apertureBlades:5,detailUm:20,medium:{kind:"negative",iso:64}},{id:"slr-35mm-50",category:"camera",name:"35 mm SLR, 50 mm lens",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:50},fNumber:8,fNumberRange:{min:2,max:16},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},years:{from:1959},apertureBlades:6,detailUm:20,medium:{kind:"negative",iso:100}},{id:"slr-35mm-zoom",category:"camera",name:"35 mm SLR, 70-210 mm zoom",projection:"rectilinear",frame:{widthMm:36,heightMm:24,focalLengthMm:135,focalRangeMm:{minMm:70,maxMm:210}},fNumber:8,fNumberRange:{min:4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/1e3,max:3600},apertureBlades:8,years:{from:1975},detailUm:20,medium:{kind:"negative",iso:100}},{id:"phone-landscape",category:"phone",name:"Phone, held sideways",projection:"rectilinear",frame:{widthMm:7.6,heightMm:5.7,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"phone-portrait",category:"phone",name:"Phone, held upright",projection:"rectilinear",frame:{widthMm:5.7,heightMm:7.6,focalLengthMm:5.7},fNumber:1.8,exposureSeconds:1/120,exposureRangeSeconds:{min:1/8e3,max:10},years:{from:2007},apertureBlades:void 0,detailUm:1.4,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:3200,metering:"highlights",development:"computational"}},{id:"dashcam",mounted:!0,category:"video",name:"Dashcam",projection:"equidistant",frame:{widthMm:5.76,heightMm:3.24,focalLengthMm:3.2},fNumber:2,exposureSeconds:1/30,exposureRangeSeconds:{min:1/1e4,max:1/30},years:{from:2008},apertureBlades:void 0,detailUm:3,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},{id:"cctv",mounted:!0,category:"video",name:"Security camera",projection:"rectilinear",frame:{widthMm:4.8,heightMm:3.6,focalLengthMm:3.6},fNumber:2,exposureSeconds:1/50,exposureRangeSeconds:{min:1/1e5,max:1/50},years:{from:1990},apertureBlades:void 0,detailUm:6,medium:{kind:"sensor",iso:100,autoExposure:!0,maxIso:1600,metering:"average",exposureFollowMs:500}},...Uc.instruments(),...Gs.instruments()];class Ti{static get default(){return nu[0]}static byId(t){return nu.find(e=>e.id===t)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(t){const e=t.frame;return e?Ti.fieldOf(t.projection,e.heightMm,e.focalLengthMm):t.visualAid?.trueFieldDeg??Ti.UNAIDED_FIELD_DEG}static fieldOf(t,e,i){return(t==="equidistant"?e/i:2*Math.atan(e/(2*i)))*180/Math.PI}static aspectOf(t){const e=t.frame;return e?e.widthMm/e.heightMm:Ti.UNAIDED_ASPECT}static frameWidthPx(t,e){return Math.round(e*Ti.aspectOf(t))}static CATEGORIES=["eye","camera","dslr","phone","video","binoculars","telescope"];static unavailability(t,e){const i=t.years;if(!(e===void 0||!i)){if(e<i.from)return{kind:"before",from:i.from};if(i.to!==void 0&&e>i.to)return{kind:"after",to:i.to}}}static availableAt(t){return t===void 0?nu:nu.filter(e=>!e.years||t>=e.years.from&&(e.years.to===void 0||t<=e.years.to))}static fieldOfViewDegAt(t,e){const i=t.frame;if(!(!i||e<=0))return Ti.fieldOf(t.projection,i.heightMm,e)}static focalLengthMmFor(t,e){const i=t.frame;if(!(!i||e<=0||e>=180))return t.projection==="equidistant"?i.heightMm/(e*Math.PI/180):i.heightMm/(2*Math.tan(e*Math.PI/360))}static bladesShowing(t,e){if(t.apertureBlades===void 0)return 0;const i=e??t.fNumber,n=t.fNumberRange?.min;if(i===void 0||n===void 0)return 1;const s=Math.max(0,Math.min(1,(i/n-1)/.3));return s*s*(3-2*s)}static starPointsOf(t,e){const i=t.apertureBlades;return i===void 0||i<3||Ti.bladesShowing(t,e)<.5?0:i%2===0?i:i*2}}class Wo extends Error{}class zf{constructor(t){this.name=t}validate(t){return!0}}class b2 extends zf{min;max;constructor(t,e,i){super(t),this.min=e,this.max=i}validate(t){if(typeof t!="number")throw new Wo(`${this.name} value must be a number, but was ${t}`);if(t<this.min||t>this.max)throw new Wo(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${t}`);return super.validate(t)}}class ji{name;min;max;duration;subUnit;validator;constructor(t,e,i,n,s=new b2(t,e,i)){this.name=t,this.min=e,this.max=i,this.subUnit=n,this.duration=n?(n.max-n.min+1)*n.duration:1,this.validator=s}validate(t){return this.validator.validate(t)}[Symbol.iterator](){let t=this.min;return{next:()=>{const e={done:t>this.max,value:t};return t++,e}}}}class w2{millisecond;second;minute;hour;day;month;year}class xw extends w2{}class S2 extends xw{millisecond=new ji("millisecond",0,999,void 0);second=new ji("second",0,59,this.millisecond);minute=new ji("minute",0,59,this.second);hour=new ji("hour",0,23,this.minute);day=new ji("day",1,31,this.hour);month=new ji("month",1,12,this.day);year=new ji("year",0,9999,this.month)}const ae=new S2;class bw extends b2{constructor(t=1,e=12){super("month",t,e)}}class Rr{static instance=new Rr;render(t){return t.value.toString()}}class Pn{unit;#t;constructor(t,e){this.unit=e,this.value=typeof t=="number"?t:t.value}get value(){return this.#t}set value(t){this.unit.validate(t),this.#t=t}get duration(){return this.value*this.unit.duration}#e(t){if(this.constructor.name!==t.constructor.name)throw new zf(`${this.unit.name} "${this.toString()}" cannot be compared with ${t.unit?.name} "${t.toString()}"`)}compare(t){return this.#e(t),this.value-t.value}isEqual(t){return this.compare(t)===0}isBefore(t){return this.compare(t)<0}isAfter(t){return this.compare(t)>0}previous(t=this.unit){const e=this.value-1;return new this.constructor(e,t)}next(t=this.unit){const e=this.value+1;return new this.constructor(e,t)}toString(t=Rr.instance){return t.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class li{static#t=new Map;static register(t,e){li.#t.set(t,e)}static get(t){const e=li.#t.get(t);if(!e)throw new Wo(`No default parser registered for ${t.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return e()}}class Od extends Pn{constructor(t=new Date().getFullYear(),e=ae.year){super(t,e)}static fromString(t,e=li.get(Od)){return new Od(e.parse(t))}}class Gr extends Rr{static default=new Gr("0",2);constructor(t,e){super(),this.char=t,this.size=e}render(t){return super.render(t).padStart(this.size,this.char)}}class Pd extends Pn{constructor(t=new Date().getMonth()+1,e=ae.month){super(t,e)}static fromString(t,e=li.get(Pd)){return new Pd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class Ld extends Pn{constructor(t=new Date().getDate(),e=ae.day){super(t,e)}static fromString(t,e=li.get(Ld)){const i=e.parse(t);return new Ld(i)}toString(t=Gr.default){return super.toString(t)}}class Nd extends Pn{constructor(t=new Date().getHours(),e=ae.hour){super(t,e)}static fromString(t,e=li.get(Nd)){return new Nd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class kd extends Pn{constructor(t=new Date().getMinutes(),e=ae.minute){super(t,e)}static fromString(t,e=li.get(kd)){return new kd(e.parse(t))}toString(t=Gr.default){return super.toString(t)}}class Ud extends Pn{constructor(t=new Date().getSeconds(),e=ae.second){super(t,e)}static fromString(t,e=li.get(Ud)){return new Ud(e.parse(t),ae.second)}toString(t=Gr.default){return super.toString(t)}}class tc extends Pn{static renderer=new Gr("0",3);constructor(t,e=ae.millisecond){super(t,e)}static parseFraction(t){return parseInt(t.padEnd(3,"0").substring(0,3),10)}toString(t=tc.renderer){return super.toString(t)}}class ww{render(t){return t.toString()}}class Sw extends ww{render(t){const e=t.value,i=Math.abs(e),n=Math.floor(i/60),s=i%60;if(n===0&&s===0)return"Z";{const r=e<0?"-":"+",a=n.toString().padStart(2,"0"),c=s>0?":"+s.toString().padEnd(2,"0"):"";return r+a+c}}}class fh{value;name="timeshift";renderer;constructor(t=0){this.value=t}static fromString(t,e=li.get(fh),i=void 0){const n=e.parse(t,i);return new fh(n)}toString(t=new Sw){return t.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class In{static timeshift(t,e){return t+(In.isDaylight(e)?60:0)}static isDaylight(t){const{year:e,month:i,day:n}=t,s=t.hour??12;if(![e,i,n].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=In.rule(e);if(!r)return!1;const a=In.rank(i,n,s);return a>=In.rank(r.start.month,r.start.day,2)&&a<In.rank(r.end.month,r.end.day,2)}static rule(t){if(t<1967)return;const e={month:10,day:In.sunday(t,10,-1)};return t>=2007?{start:{month:3,day:In.sunday(t,3,2)},end:{month:11,day:In.sunday(t,11,1)}}:t>=1987?{start:{month:4,day:In.sunday(t,4,1)},end:e}:t===1975?{start:{month:2,day:23},end:e}:t===1974?{start:{month:1,day:6},end:e}:{start:{month:4,day:In.sunday(t,4,-1)},end:e}}static sunday(t,e,i){const n=new Date(Date.UTC(2e3,e-1,1));n.setUTCFullYear(t);const s=1+(7-n.getUTCDay())%7;if(i>0)return s+7*(i-1);const r=[31,In.isLeap(t)?29:28,31,30,31,30,31,31,30,31,30,31][e-1];let a=s;for(;a+7<=r;)a+=7;return a}static isLeap(t){return t%4===0&&(t%100!==0||t%400===0)}static rank(t,e,i){return(t*100+e)*100+i}}const Ew={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},Aw={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},_w={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},Tw={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},Rw={name:"PT",timeshift:o=>In.timeshift(-480,o),title:"Pacific Time (US)"},Iw={name:"MT",timeshift:o=>In.timeshift(-420,o),title:"Mountain Time (US)"},Dw={name:"CT",timeshift:o=>In.timeshift(-360,o),title:"Central Time (US)"},Cw={name:"ET",timeshift:o=>In.timeshift(-300,o),title:"Eastern Time (US)"},Ow={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},Pw={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},Lw={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},Nw={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},kw={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},Uw={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},Fw={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},zw={name:"Z",timeshift:"Z",title:"UTC"},Bw={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},Hw={name:"BST",timeshift:"+01",title:"British Summer Time"},Gw={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},Vw={name:"CET",timeshift:"+01",title:"Central European Time"},Ww={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},Xw={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},$w={name:"BJT",timeshift:"+08",title:"Beijing Time"},Yw={name:"CST",timeshift:"-06",title:"Central Standard Time"},Kw={name:"JST",timeshift:"+09",title:"Japan Standard Time"},qw={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},Zw={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},Jw={name:"LST",timeshift:"?",title:"Local Sideral Time"},D1=[Uw,qw,kw,$w,Hw,Yw,Pw,Vw,Gw,Dw,Ow,Nw,Lw,Cw,Bw,Xw,Kw,Jw,_w,Ww,Tw,Iw,Zw,Aw,Ew,Rw,Fw,zw];class Bf{static instance=new Bf;renderComponent(t,e){return t[e].toString()}renderSecond(t){return this.renderComponent(t,"second")+(t.millisecond?"."+t.millisecond.toString():"")}render(t){const e=[];t.year&&e.push(this.renderComponent(t,"year")),t.month&&e.push(this.renderComponent(t,"month")),t.day&&e.push(this.renderComponent(t,"day"));const i=[];t.hour&&i.push(this.renderComponent(t,"hour")),t.minute&&i.push(this.renderComponent(t,"minute")),t.second&&i.push(this.renderSecond(t));const n=e.join("-"),s=t.timeshift?t.timeshift.toString():"",r=i.join(":")+s;return n+(r.length>0?"T"+r:"")}}class ro extends Wo{constructor(t="method is abstract"){super(t)}}class wg{units;constructor(t){this.units=t}newYear(t){throw new ro}newMonth(t){throw new ro}newDay(t){throw new ro}newHour(t){throw new ro}newMinute(t){throw new ro}newSecond(t){throw new ro}}class jw extends w2{millisecond=new ji("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new ji("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new ji("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new ji("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new ji("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new ji("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new ji("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Sg=new jw;class Eg{static instance=new Eg;render(t){const e=mo.toSpec(t);let i="P";const n=e.years;n&&(i+=n.toString()+"Y");const s=e.months;s&&(i+=s.toString(Rr.instance)+"MM");const r=e.days;r&&(i+=r.toString(Rr.instance)+"D");const a=e.hours;a&&(i+=a.toString(Rr.instance)+"H");const c=e.minutes;c&&(i+=c.toString(Rr.instance)+"M");const h=e.seconds;return h&&(i+=h.toString(Rr.instance)+"S"),i}}class mo extends Pn{constructor(t={years:new Date().getFullYear(),months:new Date().getMonth(),days:new Date().getDate(),hours:new Date().getHours(),minutes:new Date().getMinutes(),seconds:new Date().getSeconds(),milliseconds:new Date().getMilliseconds()}){super({value:typeof t=="number"?t:+(t.years?t.years*ae.year.duration:0)+(t.months?t.months*ae.month.duration:0)+(t.days?t.days*ae.day.duration:0)+(t.hours?t.hours*ae.hour.duration:0)+(t.minutes?t.minutes*ae.minute.duration:0)+(t.seconds?t.seconds*ae.second.duration:0)},new ji("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(t,e=tS){let i=typeof t=="number"?t:t.value;const n=i>0?1:-1;i=Math.abs(i);const s={},r=i/ae.year.duration,a=Math.floor(r);a>0&&(s.years=e.newYear(n*a),i-=a*ae.year.duration);const c=i/ae.month.duration,h=Math.floor(c);h>0&&(s.months=e.newMonth(n*h),i-=h*ae.month.duration);const l=i/ae.day.duration,u=Math.floor(l);u>0&&(s.days=e.newDay(n*u),i-=u*ae.day.duration);const d=i/ae.hour.duration,f=Math.floor(d);f>0&&(s.hours=e.newHour(n*f),i-=f*ae.hour.duration);const p=i/ae.minute.duration,g=Math.floor(p);g>0&&(s.minutes=e.newMinute(n*g),i-=g*ae.minute.duration);const m=i/ae.second.duration,v=Math.floor(n*m);return v>0&&(s.seconds=e.newSecond(v)),s}static fromString(t,e=li.get(mo)){return new mo(e.parse(t))}static between(t,e){const i=e.getTime(),n=t.getTime();return new mo(i-n)}toSpec(){return mo.toSpec(this)}toString(t=Eg.instance){return t.render(this)}}class E2 extends wg{constructor(t){super(t)}newYear(t){return new Od(t,this.units.year)}newMonth(t){return new Pd(t,this.units.month)}newDay(t){return new Ld(t,this.units.day)}newHour(t){return new Nd(t,this.units.hour)}newMinute(t){return new kd(t,this.units.minute)}newSecond(t){return new Ud(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new fh(typeof t=="number"?t:t.value)}}const Qw=new E2(ae),tS=new E2(Sg);class Ks{#t;#e;#i;#n;#s;#r;#a;#o;constructor(t={year:new Date().getFullYear(),month:new Date().getMonth()+1,day:new Date().getDate(),hour:new Date().getHours(),minute:new Date().getMinutes(),second:new Date().getSeconds(),timeshift:Ks.timeshiftOf(new Date)}){this.year=t.year,this.month=t.month,this.day=t.day,this.hour=t.hour,this.minute=t.minute,this.second=t.second,this.millisecond=t.millisecond,this.timeshift=t.timeshift}get year(){return this.#t}set year(t){const e=typeof t=="number";this.#t&&e?this.#t.value=t:this.#t=e?this.factory.newYear(t):!t||t.start||t instanceof Pn?t:this.factory.newYear(t)}get month(){return this.#e}set month(t){const e=typeof t=="number";this.#e&&e?this.#e.value=t:this.#e=e?this.factory.newMonth(t):!t||t.start||t instanceof Pn?t:this.factory.newMonth(t)}get day(){return this.#i}set day(t){const e=typeof t=="number";this.#i&&e?this.#i.value=t:this.#i=e?this.factory.newDay(t):!t||t.start||t instanceof Pn?t:this.factory.newDay(t)}get hour(){return this.#n}set hour(t){const e=typeof t=="number";this.#n&&e?this.#n.value=t:this.#n=e?this.factory.newHour(t):!t||t.start||t instanceof Pn?t:this.factory.newHour(t)}get minute(){return this.#s}set minute(t){const e=typeof t=="number";this.#s&&e?this.#s.value=t:this.#s=e?this.factory.newMinute(t):!t||t.start||t instanceof Pn?t:this.factory.newMinute(t)}get second(){return this.#r}set second(t){const e=typeof t=="number";this.#r&&e?this.#r.value=t:this.#r=e?this.factory.newSecond(t):!t||t.start||t instanceof Pn?t:this.factory.newSecond(t)}get millisecond(){return this.#a}set millisecond(t){const e=typeof t=="number";this.#a&&e?this.#a.value=t:this.#a=e||t&&!(t instanceof Pn)?this.factory.newMillisecond(t):t}get timeshift(){return this.#o}set timeshift(t){const e=typeof t=="number";this.#o&&e?this.#o.value=t:this.#o=e||t&&!(t instanceof fh)?this.factory.newTimeshift(t):t}get factory(){return Qw}static fromString(t,e=li.get(Ks)){const{year:i,month:n,day:s,hour:r,minute:a,second:c,millisecond:h,timeshift:l}=e.parse(t);return new Ks({year:i,month:n,day:s,hour:r,minute:a,second:c,millisecond:h,timeshift:l})}static timeshiftOf(t){return-t.getTimezoneOffset()||0}static fromDate(t){return new Ks({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return Ks.fromString(i)}#c(t){if(this.constructor.name!==t.constructor.name)throw new zf(`Date "${this.toString()}" cannot be compared with "${t.toString()}"`)}compare(t){return this.#c(t),this.getTime()-t.getTime()}delta(t){const e=this.compare(t);return new mo(e)}getTime(){return(this.year?.duration||0)+(this.month?.duration||0)+(this.day?.duration||0)+(this.hour?.duration||0)+(this.minute?.duration||0)+(this.second?.duration||0)+(this.millisecond?.duration||0)}isEqual(t){return this.compare(t)===0}isBefore(t){return this.compare(t)<0}isAfter(t){return this.compare(t)>0}clone(){return new Ks(this.toSpec())}previous(){let t=this.clone();try{t.second=this.second.previous()}catch{try{t.minute=this.minute.previous()}catch{try{t.hour=this.hour.previous()}catch{try{t.day=this.day.previous()}catch{try{t.month=this.month.previous()}catch{t.year=this.year.previous()}}}}}return t}next(){let t=this.clone();try{t.second=this.second.next()}catch{try{t.minute=this.minute.next()}catch{try{t.hour=this.hour.next()}catch{try{t.day=this.day.next()}catch{try{t.month=this.month.next()}catch{t.year=this.year.next()}}}}}return t}toString(t=Bf.instance){return t.render(this)}toSpec(){const t={},e=this.year?.toSpec();e&&(t.year=e);const i=this.month?.toSpec();i&&(t.month=i);const n=this.day?.toSpec();n&&(t.day=n);const s=this.hour?.toSpec();s&&(t.hour=s);const r=this.minute?.toSpec();r&&(t.minute=r);const a=this.second?.toSpec();a&&(t.second=a);const c=this.millisecond?.toSpec();c&&(t.millisecond=c);const h=this.timeshift?.toSpec();return h&&(t.timeshift=h),t}toJSON(){return this.toSpec()}}class Zl extends Rr{static instance=new Zl(Gr.default);constructor(t){super(),this.valueRenderer=t}render(t){return(this.valueRenderer?this.valueRenderer.render(t):super.render(t))+this.qualifier(t)}qualifier(t){return t.uncertain?t.approximate?"%":"?":t.approximate?"~":""}}class ec extends Pn{#t;#e;constructor(t,e){super(t,e),this.#t=t.uncertain||!1,this.#e=t.approximate||!1}get uncertain(){return this.#t}set uncertain(t){return this.#t=t}get approximate(){return this.#e}set approximate(t){return this.#e=t}isCertainAndPrecise(){return!this.approximate&&!this.uncertain}isEqual(t){return this.isCertainAndPrecise()&&super.isEqual(t)}isBefore(t){return this.isCertainAndPrecise()&&super.isBefore(t)}isAfter(t){return this.isCertainAndPrecise()&&super.isAfter(t)}toString(t=Zl.instance){return super.toString(t)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class A2 extends S2{year=new ji("year",-9999,9999,this.month);yearExtended=new ji("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const md=new A2;class go extends ec{constructor(t,e=md.year){super(t,e)}static fromString(t,e=md.year,i=li.get(go)){const n=i.parse(t),s=n.value.start;if(t.startsWith("Y")&&(e=md.yearExtended),s!==void 0){const r=new go(Object.assign({...n},{value:Math.max(s,e.min)})),a=new go(Object.assign({...n},{value:Math.min(n.value.end,e.max)}));return{start:r,end:a}}else return new go(n,e)}}class _2 extends zf{monthValidator=new bw;validate(t){switch(t){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(t)}}}class vo extends ec{constructor(t,e=new ji(ae.month.name,1,24,ae.day,new _2)){super(t,e)}static fromString(t,e=li.get(vo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.month;const r=new vo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new vo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new vo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Mo extends ec{constructor(t,e=ae.day){super(t,e)}static fromString(t,e=li.get(Mo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.day;const r=new Mo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Mo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Mo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class yo extends ec{constructor(t,e=ae.hour){super(t,e)}static fromString(t,e=li.get(yo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){let s=ae.hour;const r=new yo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new yo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new yo(i)}}class xo extends ec{constructor(t,e=ae.minute){super(t,e)}static fromString(t,e=li.get(xo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.minute,r=new xo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new xo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new xo(i)}toString(t=Zl.instance){return super.toString(t)}}class bo extends ec{constructor(t,e=ae.second){super(t,e)}static fromString(t,e=li.get(bo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.second,r=new bo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new bo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new bo(i)}}class ph extends fh{static fromString(t,e=li.get(ph),i=void 0){return new ph(e.parse(t,i))}}class T2 extends wg{constructor(t){super(t)}newYear(t){return new go(t,this.units.year)}newMonth(t){return new vo(t,this.units.month)}newDay(t){return new Mo(t,this.units.day)}newHour(t){return new yo(t,this.units.hour)}newMinute(t){return new xo(t,this.units.minute)}newSecond(t){return new bo(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new ph(typeof t=="number"?t:t.value)}}const eS=new T2(md);new T2(Sg);class oo extends Ks{constructor(t){super(t)}get factory(){return eS}get uncertain(){return this.year?.uncertain===!0||this.month?.uncertain===!0||this.day?.uncertain===!0||this.hour?.uncertain===!0||this.minute?.uncertain===!0||this.second?.uncertain===!0}get approximate(){return this.year?.approximate===!0||this.month?.approximate===!0||this.day?.approximate===!0||this.hour?.approximate===!0||this.minute?.approximate===!0||this.second?.approximate===!0}static fromDate(t){return new oo({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static fromString(t,e=li.get(oo)){const i=e.parse(t);return new oo(i)}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return oo.fromString(i)}clone(){return new oo(this.toSpec())}}class Ah extends ec{uncertainComponent;approximateComponent;constructor(t,e){super(t,e),this.uncertainComponent=t.uncertainComponent||!1,this.approximateComponent=t.approximateComponent||!1}get uncertain(){return super.uncertain||this.uncertainComponent}set uncertain(t){return super.uncertain=t}get approximate(){return super.approximate||this.approximateComponent}set approximate(t){return super.approximate=t}get uncertainGroup(){return super.uncertain}get approximateGroup(){return super.approximate}toSpec(){return{...super.toSpec(),uncertain:this.uncertainGroup,approximate:this.approximateGroup,uncertainComponent:this.uncertainComponent,approximateComponent:this.approximateComponent}}toJSON(){return this.toSpec()}}class iS extends A2{year=new ji("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Vp=new iS;class wo extends Ah{constructor(t,e=Vp.year){super(t,e)}static fromString(t,e=Vp.year,i=li.get(wo)){const n=i.parse(t),s=n.value.start;if(s!==void 0){const r=new wo(Object.assign({...n},{value:Math.max(s,e.min)})),a=new wo(Object.assign({...n},{value:Math.min(n.value.end,e.max)})),c={start:r,end:a},h=n.value.estimate;return h&&(c.estimate=h),c}else return new wo(n)}}class nS extends _2{validate(t){switch(t){case 25:case 26:case 27:case 28:case 29:case 30:case 31:case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:return!0;default:return super.validate(t)}}}class So extends Ah{constructor(t,e=new ji(ae.month.name,1,41,ae.day,new nS)){super(t,e)}static fromString(t,e=li.get(So)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.month,r=new So(Object.assign({...i},{value:Math.max(n,s.min)})),a=new So(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new So(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Eo extends Ah{constructor(t,e=ae.day){super(t,e)}static fromString(t,e=li.get(Eo)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.day,r=new Eo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Eo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Eo(i)}toString(t){return super.toString(t).padStart(2,"0")}}class Ao extends Ah{constructor(t,e=ae.hour){super(t,e)}static fromString(t,e=li.get(Ao)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.hour,r=new Ao(Object.assign({...i},{value:Math.max(n,s.min)})),a=new Ao(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new Ao(i)}}class _o extends Ah{constructor(t,e=ae.minute){super(t,e)}static fromString(t,e=li.get(_o)){const i=e.parse(t),n=i.value.start;if(n!==void 0){const s=ae.minute,r=new _o(Object.assign({...i},{value:Math.max(n,s.min)})),a=new _o(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new _o(i)}}class To extends Ah{constructor(t,e=ae.second){super(t,e)}static fromString(t,e=ae.second,i=li.get(To)){const n=i.parse(t),s=n.value.start;if(s!==void 0){const r=new To(Object.assign({...n},{value:Math.max(s,e.min)})),a=new To(Object.assign({...n},{value:Math.min(n.value.end,e.max)}));return{start:r,end:a}}else return new To(n,e)}}class R2 extends ph{}class sS extends Zl{qualifier(){return""}}class _a extends Bf{static instance=new _a;static valueRenderer=new sS(Gr.default);static names=["year","month","day","hour","minute","second"];static qualifier(t,e){return t?e?"%":"?":e?"~":""}renderComponent(t,e){const i=t[e],n=_a.names.slice(_a.names.indexOf(e)+1).map(a=>t[a]).filter(Boolean),s=_a.qualifier(i.uncertainComponent,i.approximateComponent),r=_a.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!n.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!n.some(a=>a.approximate));return s+i.toString(_a.valueRenderer)+r}}class I2 extends wg{constructor(t){super(t)}newYear(t){return new wo(t,this.units.year)}newMonth(t){return new So(t,this.units.month)}newDay(t){return new Eo(t,this.units.day)}newHour(t){return new Ao(t,this.units.hour)}newMinute(t){return new _o(t,this.units.minute)}newSecond(t){return new To(t,this.units.second)}newMillisecond(t){return new tc(t,this.units.millisecond)}newTimeshift(t){return new R2(typeof t=="number"?t:t.value)}}const rS=new I2(Vp);new I2(Sg);class co extends oo{constructor(t){super(t)}toString(t=_a.instance){return super.toString(t)}get year(){return super.year}set year(t){super.year=t}get month(){return super.month}set month(t){super.month=t}get factory(){return rS}static fromDate(t){return new co({year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate(),hour:t.getHours(),minute:t.getMinutes(),second:t.getSeconds(),timeshift:Ks.timeshiftOf(t)})}static fromString(t,e=li.get(co)){const i=e.parse(t);return new co(i)}static newInstance(){const t=new Date().toISOString(),e=t.indexOf("."),i=t.substring(0,e)+t.substring(e+4);return co.fromString(i)}clone(){return new co(this.toSpec())}}class Hf{regExp;constructor(t,e){this.name=t,this.regExp=new RegExp(`^(?:${e})$`)}regexGroups(t){const e=this.regExp.exec(t);if(!e)throw new Wo(`Invalid ${this.name} "${t}"`);return e.groups}parseGroups(t){throw new ro(`${this.constructor.name} is abstract`)}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}class Ag extends Hf{constructor(t,e){super(t,e)}static read(t){return{value:t?parseInt(t,10):void 0}}parseGroups(t){return Ag.read(t[this.name])}parse(t){if(t.startsWith("-"))throw new Wo(`${this.name} cannot be negative`);return super.parse(t)}}class ct{static groupName(...t){return t.reduce((e,i)=>e?e+i.charAt(0).toUpperCase()+i.substring(1):i,"")}static group(t,...e){return`(?<${t}>${e.join("")})`}static optional(t){return t+"?"}static nonCapturingGroup(...t){return`(?:${t.join("")})`}static optionalGroup(t,...e){return ct.optional(ct.group(t,...e))}static optionalNonCapturingGroup(...t){return ct.optional(ct.nonCapturingGroup(...t))}static numberGroup(t,e,i,n="\\d"){return ct.group(t,`${i||""}[${n}]${e}`)}}const C1="timeshiftValue",O1="shiftHour",P1="shiftMinute";class _g extends Hf{static format(t=""){return D1.map(e=>e.name).join("|")+"|"+ct.nonCapturingGroup(ct.group(t+O1,ct.numberGroup(ct.groupName(t,C1),"{2}","[+-]")),ct.optionalNonCapturingGroup(":?",ct.numberGroup(ct.groupName(t,P1),"{2}",void 0)))}constructor(){super(C1,_g.format())}parse(t,e){let i=0;const n=D1.find(s=>s.name===t);if(n){if(typeof n.timeshift=="function")try{return n.timeshift(e??{})}catch(s){throw new Wo(`The time zone ${t} depends on the date: ${s.message}`)}t=n.timeshift}if(t!=="Z"){const s=this.regexGroups(t),r=s[O1];r&&(i+=parseInt(r,10)*60);const a=s[P1];a&&(i+=parseInt(a,10))}return i}}class _i extends Ag{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=_i.uncertainGroup+_i.approximateGroup;constructor(t,e){super(t,e)}static qualifierFormat(t,e){return ct.optionalGroup(t,`\\${e}`)}static formatSuffix(t){return this.qualifierFormat(ct.groupName(_i.uncertainGroup,t),"?")+this.qualifierFormat(ct.groupName(_i.approximateGroup,t),"~")+this.qualifierFormat(ct.groupName(_i.uncertainAndApproximateGroup,t),"%")}static numberFormat(t,e,i){return ct.numberGroup(t,e,i,"\\dX")+this.formatSuffix(t)}getValueAndSign(t){let e=t[this.name],i;return e.charAt(0)==="-"?(i=-1,e=e.substring(1)):i=1,{valueStr:e,sign:i}}parseGroups(t){const{valueStr:e,sign:i}=this.getValueAndSign(t);let n=0,s;for(s=0;s<e.length;s++){const h=e[s];if(h==="X")break;n=n*10+parseInt(h,10)}if(s<e.length){let h=1;for(let d=0;d<e.length-s;d++)h*=10;const l=i*n*h,u=l+h-1;n={start:l,end:u}}else n*=i;const r=t[ct.groupName(_i.uncertainAndApproximateGroup,this.name)],a=t[ct.groupName(_i.approximateGroup,this.name)]||r,c=t[ct.groupName(_i.uncertainGroup,this.name)]||r;return{value:n,approximate:a?!!a:!1,uncertain:c?!!c:!1}}}const L1="yearValue";class Fd extends _i{constructor(){super(L1,Fd.format())}static format(t=""){return"Y?"+_i.numberFormat(ct.groupName(t,L1),"+","[-]?")}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}const N1="monthValue";class zd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,N1),"{1,2}",void 0)}constructor(){super(N1,zd.format())}}const k1="dayValue";class Bd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,k1),"{1,2}",void 0)}constructor(){super(k1,Bd.format())}}const U1="hourValue";class Hd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,U1),"{1,2}",void 0)}constructor(){super(U1,Hd.format())}}const F1="minuteValue";class Gd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,F1),"{1,2}",void 0)}constructor(){super(F1,Gd.format())}}const z1="secondValue";class Vd extends _i{static format(t=""){return _i.numberFormat(ct.groupName(t,z1),"{1,2}",void 0)}constructor(){super(z1,Vd.format())}}class Wd extends _g{}class tn extends Hf{static yearGroup="year";static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(t=tn.format()){super("date",t)}static format(t=""){return ct.group(ct.groupName(t,tn.yearGroup),Fd.format(t))+ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,tn.monthGroup),zd.format(t)),ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,tn.dayGroup),Bd.format(t)),ct.optionalNonCapturingGroup("[T ]",ct.group(ct.groupName(t,tn.hourGroup),Hd.format(t)),":",ct.group(ct.groupName(t,tn.minuteGroup),Gd.format(t)),ct.optionalNonCapturingGroup(":",ct.group(ct.groupName(t,tn.secondGroup),Vd.format(t)),ct.optionalNonCapturingGroup("[.,]",ct.group(ct.groupName(t,tn.millisecondGroup),"\\d+"))),ct.optionalGroup(ct.groupName(t,tn.timeshiftGroup),Wd.format(t)))))}parseGroups(t){const e=t[tn.millisecondGroup],i=e?tc.parseFraction(e):void 0,n=t[tn.secondGroup],s=n?bo.fromString(n,new Vd):void 0,r=t[tn.minuteGroup];let a;r&&(a=xo.fromString(r,new Gd),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const c=t[tn.hourGroup];let h;c&&(h=yo.fromString(c,new Hd),h.uncertain=h.uncertain||a?.uncertain||!1,h.approximate=h.approximate||a?.approximate||!1);const l=t[tn.dayGroup];let u;l&&(u=Mo.fromString(l,new Bd),u.uncertain=u.uncertain||h?.uncertain||!1,u.approximate=u.approximate||h?.approximate||!1);const d=t[tn.monthGroup];let f;d&&(f=vo.fromString(d,new zd),f.uncertain=f.uncertain||u?.uncertain||!1,f.approximate=f.approximate||u?.approximate||!1);const p=t[tn.yearGroup];let g;p&&(g=go.fromString(p,void 0,new Fd),g.uncertain=g.uncertain||f?.uncertain||!1,g.approximate=g.approximate||f?.approximate||!1);const m=t[tn.timeshiftGroup],v=m?ph.fromString(m,new Wd,{year:g?.value,month:f?.value,day:u?.value,hour:h?.value}):void 0;return{year:g,month:f,day:u,hour:h,minute:a,second:s,millisecond:i,timeshift:v}}}class Wi extends _i{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=Wi.uncertainGroup+Wi.approximateGroup;constructor(t,e){super(t,e)}static numberFormat(t,e,i){return this.qualifierFormat(ct.groupName(Wi.uncertainGroup,t),"?")+this.qualifierFormat(ct.groupName(Wi.approximateGroup,t),"~")+this.qualifierFormat(ct.groupName(Wi.uncertainAndApproximateGroup,t),"%")+_i.numberFormat(t,e,i)}parseGroups(t){const e=super.parseGroups(t),i=t[ct.groupName(Wi.uncertainAndApproximateGroup,this.name)];return(t[ct.groupName(Wi.uncertainGroup,this.name)]||i)&&(e.uncertainComponent=!0),(t[ct.groupName(Wi.approximateGroup,this.name)]||i)&&(e.approximateComponent=!0),e}}const Ch="yearValue",B1="exp",H1="signif";class Xd extends Wi{constructor(){super(Ch,Xd.format())}static format(t=""){return"Y?"+ct.nonCapturingGroup(ct.group(ct.groupName(t,B1),"[-]?\\d+E\\d+")+"|"+Wi.numberFormat(ct.groupName(t,Ch),"+","[-]?")+ct.optionalGroup(ct.groupName(t,H1),"S\\d+"))}parseGroups(t){const e=t[B1];if(e){const r=e.indexOf("E"),a=parseInt(e.substring(r+1),10),h=parseInt(e.substring(0,r),10)*Math.pow(10,a);t[Ch]=h.toString()}const i=t[H1],n=t[Ch];if(i){const r=parseInt(i.substring(1),10),{valueStr:a,sign:c}=this.getValueAndSign(t);let h="";for(let l=0;l<a.length;l++)h+=l<r?a.charAt(l):"X";t[Ch]=(c<0?"-":"")+h}const s=super.parseGroups(t);return i&&(s.value.estimate=parseInt(n,10)),s}parse(t){const e=this.regexGroups(t);return this.parseGroups(e)}}const G1="monthValue";class $d extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,G1),"{1,2}",void 0)}constructor(){super(G1,$d.format())}}const V1="dayValue";class Yd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,V1),"{1,2}",void 0)}constructor(){super(V1,Yd.format())}}const W1="hourValue";class Kd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,W1),"{1,2}",void 0)}constructor(){super(W1,Kd.format())}}const X1="secondValue";class qd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,X1),"{1,2}",void 0)}constructor(){super(X1,qd.format())}}const $1="minuteValue";class Zd extends Wi{static format(t=""){return Wi.numberFormat(ct.groupName(t,$1),"{1,2}",void 0)}constructor(){super($1,Zd.format())}}class aS extends Wd{}class en extends Hf{static yearGroup=tn.yearGroup;static monthGroup="month";static dayGroup="day";static hourGroup="hour";static minuteGroup="minute";static secondGroup="second";static millisecondGroup="millisecond";static timeshiftGroup="timeshift";constructor(){super("date",en.format())}static format(t=""){return ct.group(ct.groupName(t,en.yearGroup),Xd.format(t))+ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,en.monthGroup),$d.format(t)),ct.optionalNonCapturingGroup("-",ct.group(ct.groupName(t,en.dayGroup),Yd.format(t)),ct.optionalNonCapturingGroup("[T ]",ct.group(ct.groupName(t,en.hourGroup),Kd.format(t)),":",ct.group(ct.groupName(t,en.minuteGroup),Zd.format(t)),ct.optionalNonCapturingGroup(":",ct.group(ct.groupName(t,en.secondGroup),qd.format(t)),ct.optionalNonCapturingGroup("[.,]",ct.group(ct.groupName(t,en.millisecondGroup),"\\d+"))),ct.optionalGroup(ct.groupName(t,en.timeshiftGroup),aS.format(t)))))}parseGroups(t){const e=t[en.millisecondGroup],i=e?tc.parseFraction(e):void 0,n=t[en.secondGroup];let s;n&&(s=To.fromString(n,void 0,new qd),s.uncertain=s?.uncertain||!1,s.approximate=s?.approximate||!1);const r=t[en.minuteGroup];let a;r&&(a=_o.fromString(r,new Zd),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const c=t[en.hourGroup];let h;c&&(h=Ao.fromString(c,new Kd),h.uncertain=h.uncertain||a?.uncertain||!1,h.approximate=h.approximate||a?.approximate||!1);const l=t[en.dayGroup];let u;l&&(u=Eo.fromString(l,new Yd),u.uncertain=u.uncertain||h?.uncertain||!1,u.approximate=u.approximate||h?.approximate||!1);const d=t[en.monthGroup];let f;d&&(f=So.fromString(d,new $d),f.uncertain=f.uncertain||u?.uncertain||!1,f.approximate=f.approximate||u?.approximate||!1);const p=t[en.yearGroup];let g;p&&(g=wo.fromString(p,void 0,new Xd),g.uncertain=g.uncertain||f?.uncertain||!1,g.approximate=g.approximate||f?.approximate||!1);const m=t[en.timeshiftGroup],v=m?R2.fromString(m,new Wd,{year:g?.value,month:f?.value,day:u?.value,hour:h?.value}):void 0;return{year:g,month:f,day:u,hour:h,minute:a,second:s,millisecond:i,timeshift:v}}}const D2=["spring","summer","autumn","winter"],Wp=21,oS=32,cS=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let hS;function lS(){return hS??=new en}function ac(o){return typeof o?.value=="number"?o.value:void 0}function h0(o){const t=o.trim();if(/^\d{1,2}:/.test(t)){const r=cS.exec(t)?.groups;return r?{year:void 0,month:void 0,day:void 0,hour:Number(r.hour),minute:Number(r.minute),second:r.second?Number(r.second):void 0,raw:t}:void 0}let e;try{e=co.fromString(t,lS())}catch{return}const i=ac(e.year),n=ac(e.month),s=n!==void 0&&n>=Wp&&n<=oS;if(!(e.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(n!==void 0&&n>12&&!s)&&!(s&&(e.day||e.hour)))return{year:i,month:s?void 0:n,...s?{season:D2[(n-Wp)%4]}:{},day:ac(e.day),hour:ac(e.hour),minute:ac(e.minute),second:ac(e.second),raw:t}}function nl(o){if(o.raw!==void 0)return o.raw;if(o.year===void 0){if(o.hour===void 0)return"";let e=`${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`;return o.second!==void 0&&(e+=`:${String(o.second).padStart(2,"0")}`),e}let t=String(o.year).padStart(4,"0");return o.season!==void 0?`${t}-${Wp+D2.indexOf(o.season)}`:(o.month===void 0||(t+=`-${String(o.month).padStart(2,"0")}`,o.day===void 0)||(t+=`-${String(o.day).padStart(2,"0")}`,o.hour===void 0)||(t+=`T${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`,o.second!==void 0&&(t+=`:${String(o.second).padStart(2,"0")}`)),t)}function Xp(o){if(o.year!==void 0)return Date.UTC(o.year,(o.month??1)-1,o.day??1,o.hour??0,o.minute??0,o.second??0)}function Y1(o){return(((o.day??0)*24+(o.hour??0))*60+(o.minute??0))*6e4+(o.second??0)*1e3}const uS=["year","month","day","hour","minute"],dS=["day","hour","minute"];function K1(o,t){return t.filter(e=>o[e]!==void 0).join(",")}function C2(o){if(o.durationSeconds!==void 0)return o.durationSeconds*1e3;const t=o.durationText===void 0?void 0:th.parse(o.durationText);if(t)return t.chosenSeconds*1e3;if(!o.time||!o.endTime)return;const e=o.time.year!==void 0&&o.endTime.year!==void 0,i=e?uS:dS,n=K1(o.time,i);if(!(n===""||n!==K1(o.endTime,i)))return e?Xp(o.endTime)-Xp(o.time):Y1(o.endTime)-Y1(o.time)}class Gf{constructor(t,e,i,n,s,r,a,c,h=[],l,u,d,f=[],p=[],g=[],m=[]){this.event=t,this.timeline=e,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,this.observer=r,this.id=a,this.weather=c,this.decor=h,this.weatherSource=l,this.instrumentId=u,this.exposureSeconds=d,this.milestones=f,this.references=p,this.roads=g,this.traces=m}provenance=Kn.empty();loadIssues=[];account;sources;interpretation;variants=[];skyEvents;frozen;sway;lightPollution;observerMap;iso;metering;lens;vehicle;get observerCount(){return 1+this.decor.filter(t=>t.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Ti.byId(this.instrumentId)}static create(t,e,i){return new Gf({eventType:"sighting",time:t,place:e},new Uf,new Cl,new Ol,new Pl,i)}}const fS=0,pS=0;function ze(o,t){const e=o.observerTrack.getInterpolatedPoseAt(t);if(e)return e;const i=o.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:fS,headingDeg:void 0,pitchDeg:pS,fovDeg:Ti.fieldOfViewDeg(o.instrument)}}function Lc(o,t){return o.weatherTrack.getInterpolatedWeatherAt(t)??o.weather??Ff}function Oh(o,t){return o.weatherTrack.getActualWeatherAt(t)??o.weather??Ff}function O2(o,t){return o.soundTrack.getInterpolatedSoundAt(t)??yw}class ms{constructor(t,e,i,n="en"){this.parts=t,this.messages=e,this.onChange=i,this.locale=n,this.setMessages(e),t.text.addEventListener("input",()=>{this.readText(),this.showDeduction()}),t.picker.addEventListener("change",()=>this.writeFromPicker()),t.mode.addEventListener("click",()=>this.setPrecise(!this.precise)),t.text.addEventListener("blur",()=>this.validate()),t.text.addEventListener("focus",()=>this.showDeduction())}precise=!0;hint="";get isPrecise(){return this.precise}setMessages(t,e=this.locale){this.messages=t,this.locale=e,t.edtfPlaceholder!==void 0&&(this.parts.text.placeholder=t.edtfPlaceholder),this.parts.mode.title=t.edtfModeTitle,this.parts.mode.setAttribute("aria-label",t.edtfModeTitle),this.setPrecise(this.precise)}setPrecise(t){this.precise=t,this.parts.picker.hidden=!t,this.parts.text.hidden=t,this.parts.mode.textContent=t?this.messages.datePrecise:this.messages.dateEdtf,this.parts.mode.setAttribute("aria-pressed",String(!t)),this.parts.help&&(this.parts.help.hidden=t),this.showDeduction()}set(t){const{text:e,picker:i}=this.parts;e.value=t?nl(t):"",i.type!=="date"&&(i.step=ms.stepFor(t)),i.value=i.type==="date"?ms.pickerDateOf(t):ms.pickerValueOf(t),e.setCustomValidity(""),e.classList.remove("invalid"),this.showDeduction()}static opensPrecise(...t){return t.every(e=>e===void 0||ms.isPickable(e)&&ms.qualifierOf(nl(e))==="")}static opensPreciseDate(...t){return t.every(e=>e===void 0||ms.isFullDate(e)&&ms.qualifierOf(nl(e))==="")}static isFullDate(t){return!!t&&t.year!==void 0&&t.month!==void 0&&t.day!==void 0}static pickerDateOf(t){if(!ms.isFullDate(t))return"";const e=(i,n=2)=>String(i).padStart(n,"0");return`${e(t.year,4)}-${e(t.month)}-${e(t.day)}`}static isPickable(t){return!!t&&t.year!==void 0&&t.month!==void 0&&t.day!==void 0&&t.hour!==void 0&&t.minute!==void 0}static pickerValueOf(t){if(!ms.isPickable(t))return"";const e=(n,s=2)=>String(n).padStart(s,"0"),i=t.second?`:${e(t.second)}`:"";return`${e(t.year,4)}-${e(t.month)}-${e(t.day)}T${e(t.hour)}:${e(t.minute)}${i}`}static stepFor(t){return t?.second?"1":"60"}static qualifierOf(t){const e=/[?%]/.test(t),i=/[~%]/.test(t);return e&&i?"%":e?"?":i?"~":""}describe(t){return ms.describeTime(t,this.messages,this.locale)}static describeTime(t,e,i){const n=nl(t),s=ms.qualifierOf(n),r=l=>String(l).padStart(2,"0"),a=[];if(t.season!==void 0){const l={spring:e.timeSeasonSpring,summer:e.timeSeasonSummer,autumn:e.timeSeasonAutumn,winter:e.timeSeasonWinter}[t.season];a.push(t.year!==void 0?`${l} ${t.year}`:l)}else if(t.year!==void 0){const l=t.day!==void 0?{...t.year>=1583?{weekday:"long"}:{},year:"numeric",month:"long",day:"numeric"}:t.month!==void 0?{year:"numeric",month:"long"}:{year:"numeric"},u=new Date(Date.UTC(t.year,(t.month??1)-1,t.day??1));a.push(new Intl.DateTimeFormat(i,{...l,timeZone:"UTC"}).format(u))}t.hour!==void 0&&a.push(`${r(t.hour)}:${r(t.minute??0)}${t.second!==void 0?`:${r(t.second)}`:""}`);const c=a.join(", "),h=s==="~"?e.timeQualifierApproximate:s==="?"?e.timeQualifierUncertain:s==="%"?e.timeQualifierBoth:"";return h?`${c} — ${h.toLowerCase()}`:c}setHint(t){this.hint=t,this.showDeduction()}showDeduction(){const{text:t}=this.parts,e=t.value.trim();if(this.precise||e===""){t.title=this.hint;return}const i=h0(e);t.title=i?`→ ${this.describe(i)}`:this.messages.edtfInvalid}readText(){const t=this.parts.text.value.trim();if(t===""){this.clean(),this.onChange(void 0);return}const e=h0(t);e&&(this.clean(),this.onChange(e))}clean(){this.parts.text.setCustomValidity(""),this.parts.text.classList.remove("invalid")}writeFromPicker(){const{picker:t,text:e}=this.parts;t.value===""&&t.validity.badInput||(e.value=t.value===""?"":t.value.replace(/\.\d+$/,""),this.readText())}validate(){const{text:t}=this.parts,e=t.value.trim();e===""||h0(e)||(t.setCustomValidity(this.messages.edtfInvalid),t.classList.add("invalid"))}}class Pr{static read(t,e){let i=t;for(const n of e.split(".")){if(i=Pr.bare(i),i===null||typeof i!="object")return;i=i[n]}return Pr.bare(i)}static write(t,e,i){const n=e.split("."),s=[];let r=t;for(let c=0;c<n.length-1;c++){let h=Pr.bare(r[n[c]]);if(h===null||typeof h!="object"||Array.isArray(h)){if(i===void 0)return;h={}}r[n[c]]=h,s.push({owner:r,part:n[c]}),r=h}const a=n[n.length-1];i===void 0?delete r[a]:r[a]=i;for(let c=s.length-1;c>=0;c--){const h=s[c].owner[s[c].part];if(Object.keys(h).length>0)break;delete s[c].owner[s[c].part]}}static stated(t,e){return Pr.read(t,e)!==void 0}static bare(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)&&"value"in t&&"basis"in t?t.value:t}}class Xo{static MODES=["off","position","dipped","main","fog"];static DISPLAY_GAIN=.006;static TOE_IN_DEG=.6;static AUTO_BELOW_SUN_DEG=-1;static BEAMS={off:void 0,position:void 0,dipped:{candela:25e3,halfAngleDeg:24,pitchDeg:2.5,penumbra:1,color:"#fff2d8"},main:{candela:12e4,halfAngleDeg:14,pitchDeg:.4,penumbra:.85,color:"#fff6e6"},fog:{candela:9e3,halfAngleDeg:38,pitchDeg:5,penumbra:1,color:"#ffe9b0"}};static isMode(t){return typeof t=="string"&&Xo.MODES.includes(t)}static at(t,e,i){if(!e||e.length===0)return t;let n=e[0];for(const s of e){if(s.t>i)break;n=s}return n.mode}static auto(t){return t<Xo.AUTO_BELOW_SUN_DEG?"dipped":"off"}static lamps(t){return t!=="off"}}function mS(o){return o==="vehicle"?["front","behind","front-left","front-right","behind-left","behind-right"]:["front","behind","left","right"]}const gS=90,Jd=2;function P2(o){return o==="building"||o==="vehicle"}function vS(o,t){return o==="building"?!0:o==="vehicle"?t!=="front"&&t!=="behind":!1}function mh(o){return o==="building"||o==="vehicle"}const L2={aircraft:{id:"poly-google-airliner"},tree:{id:"jungle-jim-tree-large-a"},observer:{id:"makehuman-farmer-40s"},entity:{id:"makehuman-farmer-40s"}},MS=["makehuman-farmer-40s","makehuman-man-overalls","makehuman-man-jacket","makehuman-old-man","makehuman-woman"];function q1(o,t){let e=0;for(const i of t)e=e*31+i.charCodeAt(0)>>>0;return{id:o[e%o.length]}}const yS=["jungle-jim-tree-large-a","jungle-jim-tree-medium-a","jungle-jim-tree-large-b","jungle-jim-tree-medium-b","jungle-jim-tree-large-c","jungle-jim-tree-medium-c","jagobo-tree-maple-a","jagobo-tree-maple-b","jagobo-tree-aspen-a","jagobo-tree-aspen-b","nicholas-3d-tree-a","nicholas-3d-tree-b","nicholas-3d-tree-c"];function jd(o){return o.model?o.model:o.kind==="tree"&&o.id!==void 0?q1(yS,o.id):(o.kind==="observer"||o.kind==="entity")&&o.id!==void 0?q1(MS,o.id):L2[o.kind]}function N2(o,t){const e=Xo.at(o.headlights,o.headlightKeyframes,t);return e!==void 0?e:Vf(o,t)?"dipped":"off"}const xS=-.5;function bS(o){return o.kind==="streetlight"&&o.origin!==void 0&&o.lit===void 0&&!o.litKeyframes?.length}function Vf(o,t,e){if(e!==void 0&&bS(o))return e<xS;const i=o.litKeyframes;if(!i||i.length===0)return o.lit??!1;let n=i[0];for(const s of i){if(s.t>t)break;n=s}return n.lit}function Z1(o,t){const e=o.observerKeyframes;if(!e||e.length===0)return{side:o.observerSide,facing:o.observerFacing};let i=e[0];for(const n of e){if(n.t>t)break;i=n}return{side:i.side,facing:i.facing}}function wS(o,t){return o.pattern.kind==="steady"?!0:k2(o,t,t+1)>.5}function k2(o,t,e){if(o.pattern.kind==="steady")return 1;const{perMinute:i,dutyCycle:n,phase:s=0}=o.pattern,r=Math.min(Math.max(n,0),1);if(r===0||i<=0)return 0;const a=6e4/i,c=t/a+s,h=e/a+s;if(h<=c)return Math.min(Math.max(c-Math.floor(c),0),r)<r?1:0;const l=u=>Math.floor(u)*r+Math.min(u-Math.floor(u),r);return(l(h)-l(c))/(h-c)}function tr(o,t){const e=o.track,i={eastM:o.eastM,northM:o.northM,altitudeM:0,headingDeg:o.headingDeg};if(!e||e.length===0)return i;if(e.length===1||t<=e[0].t)return J1(e[0],o);const n=e[e.length-1];if(t>=n.t)return J1(n,o);for(let s=0;s<e.length-1;s++){const r=e[s],a=e[s+1];if(t<r.t||t>a.t)continue;const c=a.t-r.t,h=c===0?0:(t-r.t)/c;return{eastM:r.eastM+(a.eastM-r.eastM)*h,northM:r.northM+(a.northM-r.northM)*h,altitudeM:(r.altitudeM??0)+((a.altitudeM??0)-(r.altitudeM??0))*h,headingDeg:r.headingDeg??o.headingDeg}}return i}function SS(o,t){const e=(o.track??[]).filter(i=>i.gazeAzimuthDeg!==void 0);if(e.length!==0){if(t<=e[0].t)return e[0].gazeAzimuthDeg;for(let i=0;i<e.length-1;i++){const n=e[i],s=e[i+1];if(t>s.t)continue;const r=s.t-n.t,a=r===0?0:(t-n.t)/r,c=((s.gazeAzimuthDeg-n.gazeAzimuthDeg)%360+540)%360-180;return((n.gazeAzimuthDeg+c*a)%360+360)%360}return e[e.length-1].gazeAzimuthDeg}}function J1(o,t){return{eastM:o.eastM,northM:o.northM,altitudeM:o.altitudeM??0,headingDeg:o.headingDeg??t.headingDeg}}const j1="#ff2200",Q1="#00ff44",Ja="#ffffff",su="#ffa500",oc="#ff0000",ES="#2244ff",$p=[{id:"airliner",name:"Airliner",kinds:["aircraft"],referenceSizeM:{widthM:34,heightM:12,lengthM:36},create:()=>[{id:"nav-port",offsetM:{x:-17,y:0,z:0},color:j1,pattern:{kind:"steady"}},{id:"nav-starboard",offsetM:{x:17,y:0,z:0},color:Q1,pattern:{kind:"steady"}},{id:"nav-tail",offsetM:{x:0,y:1,z:-18},color:Ja,pattern:{kind:"steady"}},{id:"beacon-top",offsetM:{x:0,y:2,z:0},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.18}},{id:"beacon-bottom",offsetM:{x:0,y:-2,z:0},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.18}},{id:"strobe-port",offsetM:{x:-17,y:0,z:-1},color:Ja,intensity:20,pattern:{kind:"flash",perMinute:60,dutyCycle:.01}},{id:"strobe-starboard",offsetM:{x:17,y:0,z:-1},color:Ja,intensity:20,pattern:{kind:"flash",perMinute:60,dutyCycle:.01,phase:.08}}]},{id:"helicopter",name:"Helicopter",kinds:["aircraft"],referenceSizeM:{widthM:10,heightM:4,lengthM:14},create:()=>[{id:"nav-port",offsetM:{x:-5,y:0,z:0},color:j1,pattern:{kind:"steady"}},{id:"nav-starboard",offsetM:{x:5,y:0,z:0},color:Q1,pattern:{kind:"steady"}},{id:"nav-tail",offsetM:{x:0,y:1,z:-7},color:Ja,pattern:{kind:"steady"}},{id:"beacon",offsetM:{x:0,y:2,z:-2},color:oc,intensity:1.5,pattern:{kind:"flash",perMinute:45,dutyCycle:.2}},{id:"strobe",offsetM:{x:0,y:-1,z:0},color:Ja,intensity:15,pattern:{kind:"flash",perMinute:75,dutyCycle:.015}}]},{id:"car-headlights",name:"Car, headlights on",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"head-left",offsetM:{x:-.7,y:.6,z:2},color:Ja,intensity:2,pattern:{kind:"steady"}},{id:"head-right",offsetM:{x:.7,y:.6,z:2},color:Ja,intensity:2,pattern:{kind:"steady"}},{id:"tail-left",offsetM:{x:-.7,y:.6,z:-2},color:oc,pattern:{kind:"steady"}},{id:"tail-right",offsetM:{x:.7,y:.6,z:-2},color:oc,pattern:{kind:"steady"}}]},{id:"car-hazards",name:"Car, hazard flashers",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"hazard-front-left",offsetM:{x:-.8,y:.6,z:2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-front-right",offsetM:{x:.8,y:.6,z:2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-rear-left",offsetM:{x:-.8,y:.6,z:-2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}},{id:"hazard-rear-right",offsetM:{x:.8,y:.6,z:-2},color:su,pattern:{kind:"flash",perMinute:90,dutyCycle:.5}}]},{id:"emergency-beacons",name:"Emergency vehicle beacons",kinds:["vehicle"],referenceSizeM:{widthM:1.8,heightM:1.5,lengthM:4.5},create:()=>[{id:"beacon-blue",offsetM:{x:-.4,y:1.6,z:0},color:ES,intensity:2.5,pattern:{kind:"flash",perMinute:120,dutyCycle:.1}},{id:"beacon-red",offsetM:{x:.4,y:1.6,z:0},color:oc,intensity:2.5,pattern:{kind:"flash",perMinute:120,dutyCycle:.1,phase:.5}}]},{id:"traffic-signal",name:"Traffic light",kinds:["trafficlight"],create:()=>fe.vehicleLights(0)},{id:"pedestrian-signal",name:"Pedestrian light",kinds:["trafficlight"],create:()=>fe.pedestrianLights(0)},{id:"streetlamp",name:"Streetlamp",kinds:["streetlight"],referenceSizeM:{widthM:1,heightM:5,lengthM:1},create:()=>[{id:"lamp",offsetM:{x:0,y:5,z:0},color:"#ffd9a0",intensity:2,pattern:{kind:"steady"}}]}];class Qd{static forKind(t){return $p.filter(e=>e.kinds.includes(t))}static byId(t){return $p.find(e=>e.id===t)}}class fe{static CYCLE_S=90;static GREEN_S=41;static AMBER_S=3;static PEDESTRIAN_DELAY_S=2;static PEDESTRIAN_GREEN_S=30;static VEHICLE_INTENSITY=3;static PEDESTRIAN_INTENSITY=1.5;static LENS_RADIUS_M=.1;static BEAM_DEG=30;static VEHICLE_HEAD_Y_M=2.9;static PEDESTRIAN_HEAD_Y_M=2.6;static LENS_SPACING_M=.3;static LENS_FRONT_M=.13;static RED="#ff1e00";static AMBER="#ffa200";static GREEN="#00ff8c";static phaseOf(t){const e=(t%180+180)%180;return e>=45&&e<135?1:0}static vehicleLights(t){const e=t*fe.CYCLE_S/2,i=fe.VEHICLE_HEAD_Y_M,n=fe.LENS_SPACING_M;return[fe.lamp("red",fe.RED,i+n,e+fe.GREEN_S+fe.AMBER_S,fe.CYCLE_S-fe.GREEN_S-fe.AMBER_S,fe.VEHICLE_INTENSITY),fe.lamp("amber",fe.AMBER,i,e+fe.GREEN_S,fe.AMBER_S,fe.VEHICLE_INTENSITY),fe.lamp("green",fe.GREEN,i-n,e,fe.GREEN_S,fe.VEHICLE_INTENSITY)]}static pedestrianLights(t){const e=t*fe.CYCLE_S/2+fe.GREEN_S+fe.AMBER_S+fe.PEDESTRIAN_DELAY_S,i=fe.PEDESTRIAN_HEAD_Y_M,n=fe.LENS_SPACING_M/2;return[fe.lamp("ped-red",fe.RED,i+n,e+fe.PEDESTRIAN_GREEN_S,fe.CYCLE_S-fe.PEDESTRIAN_GREEN_S,fe.PEDESTRIAN_INTENSITY),fe.lamp("ped-green",fe.GREEN,i-n,e,fe.PEDESTRIAN_GREEN_S,fe.PEDESTRIAN_INTENSITY)]}static isPedestrian(t){return t?.some(e=>e.id==="ped-green")??!1}static figureOf(t){return t.id==="ped-red"?"standing":t.id==="ped-green"?"walking":void 0}static lamp(t,e,i,n,s,r){const a=fe.CYCLE_S,c=Math.round(((1-n/a)%1+1)%1*1e6)/1e6;return{id:t,color:e,intensity:r,radiusM:fe.LENS_RADIUS_M,beamDeg:fe.BEAM_DEG,offsetM:{x:0,y:i,z:-.13},pattern:{kind:"flash",perMinute:60/a,dutyCycle:Math.round(s/a*1e6)/1e6,...c?{phase:c}:{}}}}}class ll{static of(t,e){const i=ll.drawnAsModel(t);return{color:e?.color??!i,lit:e?.lit??ll.litByDefault(t.kind,i),headlights:t.kind==="vehicle",lights:(e?.lights??!0)&&ll.rigsFor(t.kind,e).length>0,windows:!i&&P2(t.kind),floors:!i&&t.kind==="building",observerSide:mh(t.kind)}}static rigsFor(t,e){return Qd.forKind(t).filter(i=>e?.lightRigs===void 0||e.lightRigs.includes(i.id))}static drawnAsModel(t){return jd(t)!==void 0&&!(t.observerSide!==void 0&&mh(t.kind))}static litByDefault(t,e){return t==="streetlight"||t==="vehicle"&&!e}}class ci{static sideLabel(t){return ci.SIDE_LABELS[t]}static SIDE_LABELS={front:{en:"Front",fr:"Avant",es:"Frente",it:"Fronte"},behind:{en:"Behind",fr:"Arrière",es:"Detrás",it:"Dietro"},left:{en:"Left",fr:"Gauche",es:"Izquierda",it:"Sinistra"},right:{en:"Right",fr:"Droite",es:"Derecha",it:"Destra"},"front-left":{en:"Front-left",fr:"Avant gauche",es:"Delantero izquierdo",it:"Anteriore sinistro"},"front-right":{en:"Front-right",fr:"Avant droit",es:"Delantero derecho",it:"Anteriore destro"},"behind-left":{en:"Behind-left",fr:"Arrière gauche",es:"Trasero izquierdo",it:"Posteriore sinistro"},"behind-right":{en:"Behind-right",fr:"Arrière droit",es:"Trasero derecho",it:"Posteriore destro"}};static WINDOWS={en:"Windows",fr:"Fenêtres",es:"Ventanas",it:"Finestre"};static BUILDING={en:"Building",fr:"Bâtiment",es:"Edificio",it:"Edificio"};static BRIDGE={en:"Bridge",fr:"Pont",es:"Puente",it:"Ponte"};static RAILING={en:"Railing",fr:"Garde-corps",es:"Barandilla",it:"Parapetto"};static WIRE={en:"Overhead line",fr:"Ligne aérienne",es:"Línea aérea",it:"Linea aerea"};static together(t,e){const i=["en","fr","es","it"],n=(s,r)=>typeof s=="string"?s:s[r]??s.en;return Object.fromEntries(i.map(s=>[s,`${n(t,s)} ${n(e,s)}`]))}static of(t,e){const i=[],n=ll.drawnAsModel(t);if(!n&&t.kind==="building"&&i.push(...ci.floors(),...ci.walls(),...ci.roof()),!n&&P2(t.kind)&&i.push(...ci.windows(t.kind)),t.kind==="vehicle"&&i.push(...ci.engine()),t.kind==="observer"&&i.push(...ci.observerRecording()),t.kind==="aircraft"&&i.push(...ci.aircraftSound(e)),t.kind==="bridge"&&i.push(...ci.bridge()),t.kind==="wire"&&i.push(...ci.wire()),e?.parameters&&i.push(...e.parameters.map(s=>({...s,key:`modelParameters.${s.key}`}))),i.length!==0)return{kind:`decor-${t.kind}`,title:{en:"Properties",fr:"Propriétés",es:"Propiedades",it:"Proprietà"},parameters:i}}static floors(){const t=e=>Pr.read(e,"floors")??Jd;return[{type:"number",key:"floors",min:0,max:20,step:1,effective:()=>Jd,label:{en:"Floors",fr:"Étages",es:"Plantas",it:"Piani"},hint:{en:"Upper stories above the ground floor.",fr:"Étages au-dessus du rez-de-chaussée.",es:"Plantas sobre la planta baja.",it:"Piani sopra il pianterreno."},group:ci.BUILDING},{type:"number",key:"occupiedFloor",min:0,max:20,step:1,effective:()=>0,bounds:e=>({max:t(e)}),label:{en:"Occupied floor",fr:"Étage occupé",es:"Planta ocupada",it:"Piano occupato"},hint:{en:"The floor the observer is on, from 0 (ground floor).",fr:"L'étage où se tient l'observateur, à partir de 0 (rez-de-chaussée).",es:"La planta donde está el observador, desde 0 (planta baja).",it:"Il piano dove si trova l'osservatore, da 0 (pianterreno)."},group:ci.BUILDING}]}static walls(){const t={en:"Walls",fr:"Murs",es:"Muros",it:"Muri"};return[{type:"colour",key:"facade.color",group:t,fallback:"#d3cab8",label:{en:"Wall colour",fr:"Couleur des murs",es:"Color de los muros",it:"Colore dei muri"},hint:{en:"The colour of the walls, drawn with the facade of their kind where the width, the length and the height of the building are all stated. Empty: a pale plaster.",fr:"La couleur des murs, dessinés avec la façade de leur type là où la largeur, la longueur et la hauteur du bâtiment sont toutes énoncées. Vide : un enduit pâle.",es:"El color de los muros, dibujados con la fachada de su tipo donde el ancho, el largo y el alto del edificio están todos enunciados. Vacío: un enlucido pálido.",it:"Il colore dei muri, disegnati con la facciata del loro tipo dove larghezza, lunghezza e altezza dell'edificio sono tutte enunciate. Vuoto: un intonaco chiaro."}},{type:"choice",key:"facade.openings",group:t,label:{en:"Facade",fr:"Type de façade",es:"Tipo de fachada",it:"Tipo di facciata"},empty:{en:"A house's",fr:"D'une maison",es:"De una casa",it:"Di una casa"},hint:{en:"A house's: a window every three metres of every floor and a door, from a storey high (lower, a shed's bare wall). The tall windows of an old building, the tall narrow bays of a church, a bare wall (a warehouse, a shed, a monument), or none: the plain box.",fr:"D'une maison : une fenêtre tous les trois mètres de chaque étage et une porte, dès la hauteur d'un étage (plus bas, le mur nu d'un abri). Les hautes fenêtres d'un immeuble ancien, les hautes baies étroites d'une église, un mur nu (un entrepôt, un hangar, un monument), ou aucune : la simple boîte.",es:"De una casa: una ventana cada tres metros de cada planta y una puerta, desde la altura de una planta (más bajo, el muro liso de un cobertizo). Las ventanas altas de un edificio antiguo, los vanos altos y estrechos de una iglesia, un muro liso (un almacén, un cobertizo, un monumento), o ninguna: la caja lisa.",it:"Di una casa: una finestra ogni tre metri di ogni piano e una porta, dall'altezza di un piano (più basso, il muro liscio di un capanno). Le finestre alte di un edificio antico, le alte aperture strette di una chiesa, un muro liscio (un magazzino, un capannone, un monumento), o nessuna: la semplice scatola."},choices:[{value:"tall",label:{en:"Old building",fr:"Immeuble ancien",es:"Edificio antiguo",it:"Edificio antico"}},{value:"lancet",label:{en:"Church",fr:"Église",es:"Iglesia",it:"Chiesa"}},{value:"plain",label:{en:"Bare wall",fr:"Mur nu",es:"Muro liso",it:"Muro liscio"}},{value:"none",label:{en:"None",fr:"Aucune",es:"Ninguna",it:"Nessuna"}}]}]}static roof(){const t={en:"Roof",fr:"Toit",es:"Tejado",it:"Tetto"};return[{type:"choice",key:"roof.shape",group:t,label:{en:"Roof",fr:"Toit",es:"Tejado",it:"Tetto"},empty:{en:"Flat",fr:"Plat",es:"Plano",it:"Piano"},hint:{en:"Flat (the box), two slopes to a ridge, four slopes, or a dome.",fr:"Plat (la boîte), deux pentes jusqu'à un faîte, quatre pentes, ou une coupole.",es:"Plano (la caja), dos vertientes hasta una cumbrera, cuatro vertientes, o una cúpula.",it:"Piano (la scatola), due falde fino a un colmo, quattro falde, o una cupola."},choices:[{value:"flat",label:{en:"Flat",fr:"Plat",es:"Plano",it:"Piano"}},{value:"gable",label:{en:"Two slopes",fr:"Deux pentes",es:"Dos vertientes",it:"Due falde"}},{value:"hip",label:{en:"Four slopes",fr:"Quatre pentes",es:"Cuatro vertientes",it:"Quattro falde"}},{value:"dome",label:{en:"Dome",fr:"Coupole",es:"Cúpula",it:"Cupola"}}]},{type:"number",key:"roof.riseM",min:0,max:15,step:.1,unit:"m",group:t,effective:()=>3,label:{en:"Rise",fr:"Hauteur du toit",es:"Altura del tejado",it:"Altezza del tetto"},hint:{en:"How far the ridge stands above the eaves: the walls are the building's height less this.",fr:"De combien le faîte dépasse l'égout : les murs font la hauteur du bâtiment moins cela.",es:"Cuánto sube la cumbrera sobre el alero: los muros miden la altura del edificio menos esto.",it:"Quanto il colmo sta sopra la gronda: i muri sono l'altezza dell'edificio meno questo."},visibleWhen:i=>["gable","hip","dome"].includes(String(Pr.read(i,"roof.shape")))},{type:"choice",key:"roof.ridge",group:t,required:!1,label:{en:"Ridge along",fr:"Faîte le long de",es:"Cumbrera a lo largo de",it:"Colmo lungo"},empty:{en:"The width",fr:"La largeur",es:"El ancho",it:"La larghezza"},choices:[{value:"width",label:{en:"The width",fr:"La largeur",es:"El ancho",it:"La larghezza"}},{value:"depth",label:{en:"The depth",fr:"La profondeur",es:"El largo",it:"La profondità"}}],visibleWhen:i=>Pr.read(i,"roof.shape")==="gable"},{type:"colour",key:"roof.color",group:t,fallback:"#7a5a4a",label:{en:"Roof colour",fr:"Couleur du toit",es:"Color del tejado",it:"Colore del tetto"}}]}static windows(t){return mS(t).map(e=>({type:"number",key:`windows.${e}`,step:5,unit:"%",min:vS(t,e)?0:gS,max:100,label:ci.SIDE_LABELS[e],summary:ci.together(ci.WINDOWS,ci.SIDE_LABELS[e]),hint:{en:"Opacity of the window on this side: 0 is open, 100 shut. Empty: no window.",fr:"Opacité de la fenêtre de ce côté : 0 ouverte, 100 fermée. Vide : pas de fenêtre.",es:"Opacidad de la ventana de este lado: 0 abierta, 100 cerrada. Vacío: sin ventana.",it:"Opacità della finestra di questo lato: 0 aperta, 100 chiusa. Vuoto: nessuna finestra."},group:ci.WINDOWS}))}static engine(){const t={en:"Engine sound",fr:"Bruit du moteur",es:"Sonido del motor",it:"Suono del motore"};return[{type:"choice",key:"engine.kind",group:t,label:{en:"Engine",fr:"Moteur",es:"Motor",it:"Motore"},hint:{en:"Whether the vehicle is heard running, and what sort of engine: how many cylinders fire, how low they turn, how its gears are spaced.",fr:"Si le véhicule s'entend rouler, et de quel moteur : combien de cylindres tirent, à quel régime bas ils tournent, comment ses vitesses sont étagées.",es:"Si se oye el vehículo en marcha, y qué motor: cuántos cilindros disparan, cuán bajo giran, cómo se escalonan sus marchas.",it:"Se il veicolo si sente in marcia, e di che motore: quanti cilindri sparano, quanto in basso girano, come sono distanziate le marce."},empty:{en:"Silent (parked)",fr:"Silencieux (à l'arrêt)",es:"Silencioso (parado)",it:"Silenzioso (fermo)"},choices:[{value:"car",label:{en:"Car",fr:"Voiture",es:"Coche",it:"Auto"}},{value:"van",label:{en:"Van",fr:"Camionnette",es:"Furgoneta",it:"Furgone"}},{value:"truck",label:{en:"Truck",fr:"Camion",es:"Camión",it:"Camion"}},{value:"motorcycle",label:{en:"Motorcycle",fr:"Moto",es:"Moto",it:"Moto"}},{value:"generic",label:{en:"Unknown",fr:"Inconnu",es:"Desconocido",it:"Sconosciuto"}}]},{type:"number",key:"engine.noise",min:.1,max:3,step:.1,group:t,effective:()=>1,label:{en:"Loudness",fr:"Volume",es:"Volumen",it:"Volume"},hint:{en:"Against an ordinary one of its kind: 1 by default, 1.5 for a very noisy one.",fr:"Par rapport à un véhicule ordinaire de son genre : 1 par défaut, 1,5 pour un très bruyant.",es:"Frente a uno ordinario de su tipo: 1 por defecto, 1,5 para uno muy ruidoso.",it:"Rispetto a uno ordinario del suo tipo: 1 per impostazione predefinita, 1,5 per uno molto rumoroso."},visibleWhen:e=>Pr.read(e,"engine.kind")!==void 0||e.engine!==void 0}]}static observerRecording(){return[{type:"text",key:"sightingUrl",placeholder:"https://…/sighting.json",label:{en:"Their own recording URL",fr:"URL de son propre enregistrement",es:"URL de su propia grabación",it:"URL della sua registrazione"}}]}static aircraftSound(t){const e=(n,s,r,a,c)=>({value:n,label:{en:s,fr:r,es:a,it:c}}),i=t?.sound;return[{type:"choice",key:"aircraftSound",group:{en:"Sound",fr:"Bruit",es:"Sonido",it:"Suono"},label:{en:"Noise in flight",fr:"Bruit en vol",es:"Ruido en vuelo",it:"Rumore in volo"},hint:{en:"What it sounds like while it flies: nothing is heard of a machine that flies silent, and the stand-in of a phenomenon says so.",fr:"Ce qu'on entend quand il vole : rien d'une machine qui vole en silence, et la maquette d'un phénomène le dit.",es:"Cómo suena mientras vuela: nada se oye de una máquina que vuela en silencio, y la maqueta de un fenómeno lo dice.",it:"Come suona mentre vola: nulla si sente di una macchina che vola in silenzio, e il modello di un fenomeno lo dice."},empty:i==="silent"?{en:"Silent (as the model)",fr:"Silencieux (comme le modèle)",es:"Silencioso (como el modelo)",it:"Silenzioso (come il modello)"}:{en:"As the model",fr:"Selon le modèle",es:"Según el modelo",it:"Secondo il modello"},choices:[e("airliner-narrow","Narrow-body airliner","Avion de ligne monocouloir","Avión de pasillo único","Aereo di linea a fusoliera stretta"),e("airliner-wide","Wide-body airliner","Avion de ligne gros-porteur","Avión de fuselaje ancho","Aereo di linea a fusoliera larga"),e("regional-jet","Regional jet","Jet régional","Jet regional","Jet regionale"),e("regional-turboprop","Turboprop","Turbopropulseur","Turbohélice","Turboelica"),e("business-jet","Business jet","Jet d'affaires","Jet privado","Jet privato"),e("light-piston","Light piston aircraft","Avion léger à pistons","Avioneta de pistones","Aereo leggero a pistoni"),e("helicopter-light","Light helicopter","Hélicoptère léger","Helicóptero ligero","Elicottero leggero"),e("helicopter-medium","Medium helicopter","Hélicoptère moyen","Helicóptero medio","Elicottero medio"),e("helicopter-heavy","Heavy helicopter","Hélicoptère lourd","Helicóptero pesado","Elicottero pesante"),e("military-jet","Military jet","Avion de combat","Reactor militar","Jet militare"),e("ultralight","Ultralight","ULM","Ultraligero","Ultraleggero"),e("unmanned","Drone","Drone","Dron","Drone"),e("glider","Glider","Planeur","Planeador","Aliante"),e("silent","Silent","Silencieux","Silencioso","Silenzioso")]}]}static bridge(){const t=(e,i,n,s,r,a,c,h,l)=>({type:"number",key:e,label:i,min:n,max:s,step:r,unit:a,group:h,hint:l,effective:c===void 0?void 0:()=>c});return[t("bridge.spanM",{en:"Span",fr:"Portée",es:"Luz",it:"Luce"},.1,5e3,.1,"m",void 0,ci.BRIDGE,{en:"Metres of open span under the deck, centred. Empty: the whole length, no embankments.",fr:"Mètres de portée libre sous le tablier, centrés. Vide : toute la longueur, sans remblais.",es:"Metros de luz libre bajo el tablero, centrados. Vacío: toda la longitud, sin terraplenes.",it:"Metri di luce libera sotto l'impalcato, centrati. Vuoto: tutta la lunghezza, senza rilevati."}),t("bridge.deckThicknessM",{en:"Deck thickness",fr:"Épaisseur du tablier",es:"Espesor del tablero",it:"Spessore dell'impalcato"},.1,20,.1,"m",1.2,ci.BRIDGE),t("bridge.railing.heightM",{en:"Height",fr:"Hauteur",es:"Altura",it:"Altezza"},.1,5,.05,"m",1.05,ci.RAILING),t("bridge.railing.postSpacingM",{en:"Post spacing",fr:"Espacement des poteaux",es:"Separación de postes",it:"Distanza dei montanti"},.2,20,.1,"m",1.5,ci.RAILING),t("bridge.railing.rails",{en:"Rails",fr:"Lisses",es:"Barandas",it:"Correnti"},0,8,1,"",2,ci.RAILING)]}static wire(){return[{type:"choice",key:"wire.poles",group:ci.WIRE,label:{en:"Poles",fr:"Poteaux",es:"Postes",it:"Pali"},hint:{en:"Which ends stand on a pole: both, the one the heading points away from, the one it points towards, or none (a line anchored on buildings).",fr:"Quelles extrémités reposent sur un poteau : les deux, celle dont le cap s'éloigne, celle vers laquelle il pointe, ou aucune (une ligne ancrée sur des bâtiments).",es:"Qué extremos se apoyan en un poste: ambos, aquel del que se aleja el rumbo, aquel hacia el que apunta, o ninguno (una línea anclada en edificios).",it:"Quali estremità poggiano su un palo: entrambe, quella da cui si allontana la direzione, quella verso cui punta, o nessuna (una linea ancorata a edifici)."},choices:[{value:"both",label:{en:"Both",fr:"Les deux",es:"Ambos",it:"Entrambi"}},{value:"start",label:{en:"Start",fr:"Début",es:"Inicio",it:"Inizio"}},{value:"end",label:{en:"End",fr:"Fin",es:"Fin",it:"Fine"}},{value:"none",label:{en:"None",fr:"Aucun",es:"Ninguno",it:"Nessuno"}}],effective:()=>"both"},{type:"number",key:"wire.diameterM",min:.001,max:.2,step:.001,unit:"m",effective:()=>.008,group:ci.WIRE,label:{en:"Strand thickness",fr:"Épaisseur du brin",es:"Grosor del hilo",it:"Spessore del filo"}},{type:"number",key:"wire.poleHeightM",min:.5,max:100,step:.1,unit:"m",group:ci.WIRE,label:{en:"Pole height",fr:"Hauteur des poteaux",es:"Altura de los postes",it:"Altezza dei pali"},hint:{en:"Empty: half a metre over the highest strand.",fr:"Vide : un demi-mètre au-dessus du brin le plus haut.",es:"Vacío: medio metro sobre el hilo más alto.",it:"Vuoto: mezzo metro sopra il filo più alto."}}]}}class js{static NONE={id:"none",name:"No filter",opticalDensity:0};static SOLAR_VISUAL={id:"solar-visual",name:"Solar filter for the eye (OD 5)",opticalDensity:5,usableWith:["eye","binoculars","telescope"]};static SOLAR_PHOTO={id:"solar-photo",name:"Solar film for a camera (OD 3.8)",opticalDensity:3.8,usableWith:["camera","dslr","phone","telescope"]};static ALL=[js.NONE,js.SOLAR_VISUAL,js.SOLAR_PHOTO];static usableWith(t,e){return!t.usableWith||t.usableWith.includes(e.category)}static byId(t){return js.ALL.find(e=>e.id===t)??js.NONE}static transmittance(t){return 10**-t.opticalDensity}static magnitudes(t){return 2.5*t.opticalDensity}}class gd{constructor(t){this.names=t}name(t){return this.names[t.toLowerCase()]??t}stored(t){const e=t.trim().toLowerCase();for(const[i,n]of Object.entries(this.names))if(n.toLowerCase()===e)return i;return t.trim()}}class Ll{constructor(t,e,i,n=new gd({}),s){this.labels=t,this.naming=e,this.said=i,this.tags=n,this.timeWords=s}entriesFor(t,e,i={}){const n=[];return this.addSummary(n,t),this.addObservation(n,t),this.addObserver(n,t,e),this.addLocation(n,t,e,i.groundElevationM,i.roadGradeDeg??0),this.addDecor(n,t,e,i),i.phenomena===!0&&this.addPhenomena(n,t,e),this.addTemporal(n,t),this.addWeather(n,t,e),this.addSound(n,t,e),n}push(t,e,i,n,s,r="",a={}){s===void 0||s===""||t.push({group:e,field:i,label:n,value:String(s),unit:r,color:a.color,fromSource:a.fromSource===!0})}percent(t){return t===void 0?void 0:`${Math.round(t*100)} %`}rounded(t,e=0){return t===void 0?void 0:String(Number(t.toFixed(e)))}shows(t,e=0){return t!==void 0&&Number(t.toFixed(e))!==0}showsPercent(t){return this.shows(t===void 0?void 0:t*100)}percentShown(t){return this.showsPercent(t)?this.percent(t):void 0}roundedShown(t,e=0){return this.shows(t,e)?this.rounded(t,e):void 0}static DESCRIPTION_WORDS=3;addSummary(t,e){const i=this.said.read(e.event.description)?.trim();if(!i)return;const n=i.split(/\s+/),s=n.length>Ll.DESCRIPTION_WORDS?`${n.slice(0,Ll.DESCRIPTION_WORDS).join(" ")}…`:i;this.push(t,"summary","description",this.labels.summaryDescription,s),t[t.length-1].full=i}addObservation(t,e){const i=e.event.tags;this.push(t,"observation","tags",this.labels.tags,i&&i.length>0?i.map(n=>this.tags.name(n)).join(", "):void 0)}filterName(t){return t===js.SOLAR_VISUAL?this.labels.filterSolarVisual:t===js.SOLAR_PHOTO?this.labels.filterSolarPhoto:t.name}addObserver(t,e,i){const n=e.observer;this.push(t,"observer","observerId",this.labels.observerId,n?.id),this.push(t,"observer","observerTitle",this.labels.observerTitle,this.said.read(n?.title)),this.push(t,"observer","observerLastName",this.labels.observerLastName,n?.lastName);const s=n?.firstNames;this.push(t,"observer","observerFirstNames",this.labels.observerFirstNames,s&&s.length>0?s.join(", "):void 0);const r=e.instrument;this.push(t,"observer","instrument",this.labels.instrument,this.naming.instrument(r));const a=e.exposure;this.push(t,"observer","exposureSeconds",this.labels.exposure,a===void 0?void 0:a<1?`1/${Math.round(1/a)}`:this.rounded(a,2),"s");const c=ze(e,i);if(c){const h=Ti.focalLengthMmFor(r,c.fovDeg);h===void 0?this.push(t,"observer","focalLength",this.labels.fieldOfView,this.rounded(c.fovDeg,1),"°"):this.push(t,"observer","focalLength",this.labels.focalLength,this.rounded(h,1),"mm"),this.push(t,"observer","fNumber",this.labels.aperture,this.rounded(c.fNumber??r.fNumber,1)),this.push(t,"observer","focusDistance",this.labels.focusDistance,this.rounded(c.focusDistanceM,1),"m"),this.push(t,"observer","roll",this.labels.roll,this.roundedShown(c.rollDeg),"°");const l=js.byId(c.filter);l!==js.NONE&&this.push(t,"observer","filter",this.labels.filter,this.filterName(l))}}degreesMinutesSeconds(t,e,i){if(t===void 0||!Number.isFinite(t))return;const n=Math.round(Math.abs(t)*3600),s=Math.floor(n/3600),r=Math.floor(n%3600/60),a=n%60;return`${s}°${String(r).padStart(2,"0")}′${String(a).padStart(2,"0")}″ ${this.naming.point(t<0?i:e)}`}addLocation(t,e,i,n,s){const r=e.event.place?.[0];this.push(t,"location","placeName",this.labels.placeName,r?.name);const a=ze(e,i);if(!a)return;this.push(t,"location","lat",this.labels.latitude,this.degreesMinutesSeconds(a.lat,0,180)),this.push(t,"location","lng",this.labels.longitude,this.degreesMinutesSeconds(a.lng,90,270));const c=this.rounded(a.headingDeg);this.push(t,"location","heading",this.labels.heading,c,a.headingDeg===void 0?"°":`° (${this.naming.point(a.headingDeg)})`),this.push(t,"location","pitch",this.labels.pitch,a.pitchDeg===void 0?void 0:this.rounded(a.pitchDeg+s),"°"),n===void 0?this.push(t,"location","elevation",this.labels.heightAboveGround,this.roundedShown(a.elevationM),"m"):this.push(t,"location","elevation",this.labels.elevation,this.rounded(n+a.elevationM),"m")}addDecor(t,e,i,n){const s=e.decor.find(h=>h.id===n.decorId);if(!s){if(n.decorPicker===!0)for(const h of e.decor)this.push(t,"decor",`decor:${h.id}`,this.decorLabel(h),this.decorKindName(h.kind));return}this.push(t,"decor","decorBase.title",this.labels.decorTitle,this.said.read(s.title));const r=tr(s,i);this.push(t,"decor","decorBase.eastM",this.labels.decorEast,this.rounded(r.eastM,1),"m"),this.push(t,"decor","decorBase.northM",this.labels.decorNorth,this.rounded(r.northM,1),"m"),this.push(t,"decor","decorBase.altitudeM",this.labels.decorAltitude,this.roundedShown(r.altitudeM),"m"),this.push(t,"decor","decorBase.headingDeg",this.labels.decorHeading,this.rounded(r.headingDeg),"°"),Vf(s,i)&&this.push(t,"decor","decorState.lit",this.labels.decorLit,"✓");const a=s.lights?.map(h=>h.id).join()??"",c=a===""?void 0:$p.find(h=>h.create().map(l=>l.id).join()===a);this.push(t,"decor","decorState.lightRig",this.labels.decorLights,c?.name),this.push(t,"decor","decorState.observerSide",this.labels.decorObserverSide,this.decorSideName(s.observerSide));for(const h of ci.of(s)?.parameters??[]){const l=Pr.read(s,h.key);if(l==null)continue;const u=h.type==="choice"?this.said.read(h.choices.find(d=>d.value===l)?.label)??String(l):l;this.push(t,"decor",`decorParam.${h.key}`,this.said.read(h.summary??h.label)??h.key,typeof u=="boolean"?u?"✓":"":u,h.type==="number"?h.unit:void 0)}}timeText(t){return this.timeWords?ms.describeTime(t,this.timeWords.messages,this.timeWords.locale):nl(t)}addTemporal(t,e){const i=e.event;this.push(t,"temporal","obs-time",this.labels.observationTime,i.time&&this.timeText(i.time)),this.push(t,"temporal","obs-end-time",this.labels.observationEndTime,i.endTime&&this.timeText(i.endTime));const n=C2(i);this.push(t,"temporal","durationSeconds",this.labels.duration,this.roundedShown(n&&n/1e3,1),"s"),this.push(t,"temporal","timeZone",this.labels.utcOffset,i.timeZone),this.push(t,"temporal","utcOffsetHours",this.labels.utcOffset,this.rounded(i.utcOffsetHours,1),"UTC±h")}addWeather(t,e,i){const n=Lc(e,i),r={fromSource:e.weatherSource!==void 0},a=this.showsPercent(n.cloudCover)||this.showsPercent(n.lowerCloudCover)||this.showsPercent(n.highCloudCover);this.push(t,"weather","cloudCover",this.labels.cloudCover,this.percentShown(n.cloudCover),"",r),this.push(t,"weather","highCloudCover",this.labels.highCloudCover,this.percentShown(n.highCloudCover),"",r),this.push(t,"weather","iceCrystalAlignment",this.labels.iceCrystalAlignment,this.showsPercent(n.highCloudCover)?this.percent(n.iceCrystalAlignment):void 0),this.push(t,"weather","rareIceCrystals",this.labels.rareIceCrystals,this.showsPercent(n.highCloudCover)?this.percent(n.rareIceCrystals):void 0),this.push(t,"weather","cloudDarkness",this.labels.cloudDarkness,a?this.percent(n.cloudDarkness):void 0,"",r),this.push(t,"weather","cloudBase",this.labels.cloudBase,a?this.rounded(n.cloudBaseM):void 0,"m",r);const c=n.precipitationType!=="none"&&this.showsPercent(n.precipitationIntensity);this.push(t,"weather","precipitationType",this.labels.precipitationType,c?this.precipitationName(n.precipitationType):void 0,"",r),this.push(t,"weather","precipitationIntensity",this.labels.precipitationIntensity,c?this.percent(n.precipitationIntensity):void 0,"",r),this.push(t,"weather","windDirection",this.labels.windDirection,this.shows(n.windSpeed,2)?this.rounded(n.windDirectionDeg):void 0,"°",r),this.push(t,"weather","windSpeed",this.labels.windSpeed,this.roundedShown(n.windSpeed,2),"m/s",r),n.storm&&this.push(t,"weather","storm",this.labels.storm,"✓","",r)}addSound(t,e,i){const n=O2(e,i);n.kind!=="none"&&(this.push(t,"sound","soundKind",this.labels.soundKind,this.soundKindName(n.kind)),this.push(t,"sound","soundVolume",this.labels.soundVolume,this.percentShown(n.volume)),this.push(t,"sound","soundPitch",this.labels.soundPitch,this.roundedShown(n.pitchHz),"Hz"),this.push(t,"sound","soundSrc",this.labels.soundSrc,n.src))}addPhenomena(t,e,i){for(const n of e.timeline.sourceIds){const s=e.timeline.getInterpolatedShapeAt(i,n),r=s?.angular,a=r?`${this.rounded(r.widthDeg,2)} × ${this.rounded(r.heightDeg,2)}°`:void 0;this.push(t,"phenomenon",`shape:${n}`,this.said.read(s?.title)??n,a)}for(const n of e.interpretation?.bodies??[]){const s=n.track.find(a=>a.sizeM?.widthM!==void 0)?.sizeM?.widthM,r=n.model.id??n.model.url?.replace(/^.*\//,"");this.push(t,"phenomenon",`body:${n.id}`,this.said.read(n.title)??n.id,[r,s!==void 0?`${this.rounded(s,2)} m`:void 0].filter(Boolean).join(", "))}}decorLabel(t){return this.said.read(t.title)??this.decorKindName(t.kind)}decorKindName(t){switch(t){case"building":return this.labels.decorBuilding;case"tree":return this.labels.decorTree;case"shrub":return this.labels.decorShrub;case"bridge":return this.labels.decorBridge;case"wire":return this.labels.decorWire;case"crop":return this.labels.decorCrop;case"terrace":return this.labels.decorTerrace;case"mound":return this.labels.decorMound;case"wall":return this.labels.decorWall;case"streetlight":return this.labels.decorStreetlight;case"trafficlight":return this.labels.decorTrafficLight;case"crossing":return this.labels.decorCrossing;case"roadsign":return this.labels.decorRoadSign;case"vehicle":return this.labels.decorVehicle;case"aircraft":return this.labels.decorAircraft;default:return this.labels.decorObserver}}decorSideName(t){switch(t){case"front":return this.labels.decorSideFront;case"behind":return this.labels.decorSideBehind;case"left":return this.labels.decorSideLeft;case"right":return this.labels.decorSideRight;case"front-left":return this.labels.decorSideFrontLeft;case"front-right":return this.labels.decorSideFrontRight;case"behind-left":return this.labels.decorSideBehindLeft;case"behind-right":return this.labels.decorSideBehindRight;default:return}}precipitationName(t){switch(t){case"rain":return this.labels.precipitationRain;case"snow":return this.labels.precipitationSnow;case"hail":return this.labels.precipitationHail;default:return this.labels.precipitationNone}}soundKindName(t){switch(t){case"hum":return this.labels.soundHum;case"whistle":return this.labels.soundWhistle;case"rumble":return this.labels.soundRumble;case"crackle":return this.labels.soundCrackle;default:return this.labels.soundNone}}}class Ps{constructor(t){this.preferences=t}read(t){if(t===void 0||typeof t=="string")return t===""?void 0:t;for(const i of this.preferences){const n=t[i]??t[Ps.base(i)];if(n)return n}const e=new Set(this.preferences.map(i=>Ps.base(i)));for(const[i,n]of Object.entries(t))if(n&&e.has(Ps.base(i)))return n;return Object.values(t).find(i=>i)??void 0}write(t,e,i){const n=e?.trim()?e.trim():void 0;if(t===void 0||typeof t=="string")return n;const s={...t},r=Object.keys(s).find(a=>a===i)??Object.keys(s).find(a=>Ps.base(a)===Ps.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(t){return t.toLowerCase().split("-")[0]}}function Tg(o,t){for(const e of o){const i=e.toLowerCase().split("-")[0];if(t.includes(i))return i}return"en"}class Ga{static preferencesFor(t){const e=navigator.languages??[],i=this.declaredFor(t);return i?[i,...e]:e}static declaredFor(t){for(let e=t;e;){const i=e.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const n=e.getRootNode();e=n instanceof ShadowRoot?n.host:void 0}}}const AS="Global Meteor Network",_S="https://globalmeteornetwork.org/data/",TS="“Thunder” by Jerimee",RS="https://creativecommons.org/licenses/by/3.0/",IS="CC BY 3.0";class gn{static fill(t,e){t.innerHTML="";const i=d=>t.appendChild(d),n=e.currentTerrainAttribution;n&&i(gn.text(n));const s=e.currentRoadAttribution;s&&i(gn.text(s));const r=e.currentWaterAttribution;r&&i(gn.text(r));const a=e.currentRailwayAttribution;a&&i(gn.text(a));const c=e.ufoElement.observerMapCredit;c&&!n?.includes(c)&&i(gn.text(c));for(const d of e.decorModelCredits){const f=d.author?` — ${d.author}`:"",p=document.createElement("li");d.sourceUrl?p.append(gn.link(d.sourceUrl,d.title),document.createTextNode(`${f} (${d.license})`)):p.textContent=`${d.title}${f} (${d.license})`,i(p)}for(const d of e.ufoElement.sighting.references){if(!d.credit)continue;const f=document.createElement("li");d.creditUrl?f.appendChild(gn.link(d.creditUrl,d.credit)):f.textContent=d.credit,i(f)}if(e.ufoElement.sighting.traces.length>0){const d=new Ps(Ga.preferencesFor(e)),f=new Set(e.ufoElement.sighting.traces.map(p=>d.read(p.source)).filter(p=>!!p));for(const p of f)i(gn.text(p))}const h=e.satelliteState;if(h.status==="ready"&&h.credit){const d=document.createElement("li");d.appendChild(gn.link(h.creditUrl??"",h.credit)),i(d)}if(e.fireballState.status==="ready"&&e.fireballState.records.length>0){const d=document.createElement("li");d.append(gn.link(_S,AS),document.createTextNode(" (CC BY 4.0)")),i(d)}const l=e.aircraftState;if(l.status==="ready"&&l.shown>0){const d=document.createElement("li");if(d.appendChild(gn.link(l.creditUrl,l.credit)),i(d),l.trailCredit){const f=document.createElement("li");f.appendChild(gn.link(l.trailCredit.creditUrl,l.trailCredit.credit)),i(f)}}const u=gn.text(`${TS} (`);u.append(gn.link(RS,IS),document.createTextNode(")")),i(u)}static text(t){const e=document.createElement("li");return e.textContent=t,e}static link(t,e){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener",i.textContent=e,i}}const DS="modulepreload",CS=function(o,t){return new URL(o,t).href},tv={},Re=function(t,e,i){let n=Promise.resolve();if(e&&e.length>0){let r=function(l){return Promise.all(l.map(u=>Promise.resolve(u).then(d=>({status:"fulfilled",value:d}),d=>({status:"rejected",reason:d}))))};const a=document.getElementsByTagName("link"),c=document.querySelector("meta[property=csp-nonce]"),h=c?.nonce||c?.getAttribute("nonce");n=r(e.map(l=>{if(l=CS(l,i),l in tv)return;tv[l]=!0;const u=l.endsWith(".css"),d=u?'[rel="stylesheet"]':"";if(!!i)for(let g=a.length-1;g>=0;g--){const m=a[g];if(m.href===l&&(!u||m.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${l}"]${d}`))return;const p=document.createElement("link");if(p.rel=u?"stylesheet":DS,u||(p.as="script"),p.crossOrigin="",p.href=l,h&&p.setAttribute("nonce",h),document.head.appendChild(p),u)return new Promise((g,m)=>{p.addEventListener("load",g),p.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${l}`)))})}))}function s(r){const a=new Event("vite:preloadError",{cancelable:!0});if(a.payload=r,window.dispatchEvent(a),!a.defaultPrevented)throw r}return n.then(r=>{for(const a of r||[])a.status==="rejected"&&s(a.reason);return t().catch(s)})},OS=[{id:"coverage",name:"Coverage",credit:"UFO@home",creditUrl:"https://ufoathome.org",create:()=>({about:"observer",assess:async o=>{const{CoverageAssessor:t}=await Re(async()=>{const{CoverageAssessor:e}=await import("./CoverageAssessor-Dd6oOWlq.js");return{CoverageAssessor:e}},[],import.meta.url);return new t().assess(o)}})},{id:"hynek",name:"Hynek",credit:"J. Allen Hynek",creditUrl:"https://rr0.org/science/crypto/ufo/observation/classification/hynek/",create:()=>({about:"temporal",assess:async o=>{const{HynekAssessor:t}=await Re(async()=>{const{HynekAssessor:e}=await import("./HynekAssessor-DPsLpEGQ.js");return{HynekAssessor:e}},[],import.meta.url);return new t().assess(o)}})}];class PS{constructor(t){this.labels=t}async read(t){const e=[],i=new Set;for(const n of OS){let s;try{s=await n.create().assess(t)}catch{continue}for(const a of s.criteria)a.basis===void 0&&!a.unsupported&&i.add(a.id);const r=s.score===void 0?s.verdict===void 0?"":this.verdictName(n.id,s.verdict):`${Math.round(s.score*100)}%`;r!==""&&e.push({group:"assessment",field:n.id,label:this.labels.assessmentNames[n.id]??n.name,value:r,unit:"",fromSource:!1,about:n.create().about})}return{entries:e,unanswered:i}}verdictName(t,e){return this.labels.assessmentVerdicts[`${t}.${e}`]??e.toUpperCase()}}const U2=Math.PI/180,tf=111320;function oe(o,t,e,i){const n=tf*Math.cos(e*U2),s=(o-e)*tf;return{x:(t-i)*n,z:-s}}function os(o,t,e,i){const n=tf*Math.cos(e*U2),s=-t,r=o;return{lat:e+s/tf,lng:i+r/n}}class Fc{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(t,e,i){const n=t.event.place?.[0],s=t.observerTrack;if(!n)return 0;const r=g=>{const m=s.getInterpolatedPoseAt(Math.max(0,g));if(!m||m.lat===void 0||m.lng===void 0)return;const v=oe(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(e-Fc.HALF_SPAN_MS),c=r(e+Fc.HALF_SPAN_MS),h=r(e);if(!a||!c||!h)return 0;const l=Math.hypot(c.eastM-a.eastM,c.northM-a.northM),u=2*Fc.HALF_SPAN_MS/1e3;if(l/u<Fc.MIN_SPEED_MS)return 0;const d=i.heightAt(c.eastM,c.northM)-i.heightAt(a.eastM,a.northM),f=Math.atan2(d,l)*180/Math.PI;if(h.heading===void 0)return f;const p=Math.atan2(c.eastM-a.eastM,c.northM-a.northM)*180/Math.PI;return f*Math.max(0,Math.cos((h.heading-p)*Math.PI/180))}}class Uo{static sessionDeclared=!1;static unlock(t){if(Uo.declarePlayback(),t.state!=="running")try{Promise.resolve(t.resume()).catch(()=>{});const e=t.createBufferSource();e.buffer=t.createBuffer(1,1,22050),e.connect(t.destination),e.start(0)}catch{}}static declarePlayback(){if(!(Uo.sessionDeclared||typeof navigator>"u")){Uo.sessionDeclared=!0;try{const t=navigator.audioSession;t&&(t.type="playback")}catch{}}}}const LS=.08,ev=.15,iv=2,NS=2e3;class kS{context;noiseBuffer;voices=new Map;level=1;master;paused=!0;requested=[];resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",t);return}}Uo.unlock(this.context),this.apply()}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}setPaused(t){t!==this.paused&&(this.paused=t,this.apply())}setVoices(t){this.requested=t,this.apply()}dispose(){for(const t of[...this.voices.keys()])this.release(t);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}apply(){const t=this.context;if(!t)return;const e=this.paused?[]:this.requested.filter(n=>n.inside||n.distanceM<NS),i=new Set(e.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of e){const s=this.voices.get(n.id)??this.build(t,n.id);this.retarget(t,s,n)}}build(t,e){const i=t.createGain();i.gain.value=0;const n=t.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(t));const s=t.createOscillator();s.type="sawtooth";const r=t.createOscillator();r.type="sine";const a=t.createGain(),c=t.createBiquadFilter();c.type="lowpass",c.frequency.value=900,s.connect(c),r.connect(c),c.connect(a).connect(n);const h=()=>{const b=t.createBufferSource();return b.buffer=this.noise(t),b.loop=!0,b.loopStart=Math.random()*iv*.5,b},l=h(),u=t.createBiquadFilter();u.type="bandpass",u.Q.value=4;const d=t.createGain();l.connect(u).connect(d).connect(n);const f=h(),p=t.createBiquadFilter();p.type="lowpass",p.frequency.value=600;const g=t.createGain();f.connect(p).connect(g).connect(n);const m=h(),v=t.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const y=t.createGain();m.connect(v).connect(y).connect(n);const x=[s,r,l,f,m];for(const b of x)b.start();const M={nodes:[i,n,a,c,u,d,p,g,v,y,...x],sources:x,firing:s,crank:r,knock:u,engineGain:a,knockGain:d,roadGain:g,windGain:y,cabin:n,output:i};return this.voices.set(e,M),M}retarget(t,e,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:c}){const h=t.currentTime,l=(y,x)=>y.setTargetAtTime(x,h,LS),u=n.rpm/60,d=u*i.cylinders/2,f=Math.min(1,n.rpm/i.shiftUpRpm),p=Math.min(1.5,n.speedMps/30);l(e.firing.frequency,d),l(e.crank.frequency,u),l(e.knock.frequency,d*3),l(e.engineGain.gain,i.engineGain*(.25+.75*n.load)*(.5+.5*f)*.3),l(e.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),l(e.roadGain.gain,i.roadGain*p**1.5*.8);const g=!r||a;l(e.windGain.gain,p**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+c/60);l(e.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(c,1));l(e.output.gain,v*s)}release(t){const e=this.voices.get(t);if(!e)return;this.voices.delete(t);const i=this.context;i&&(e.output.gain.setTargetAtTime(0,i.currentTime,ev/3),setTimeout(()=>{for(const n of e.sources)try{n.stop()}catch{}for(const n of e.nodes)n.disconnect()},ev*1e3*3))}noise(t){if(this.noiseBuffer)return this.noiseBuffer;const e=t.createBuffer(1,t.sampleRate*iv,t.sampleRate),i=e.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=e,e}}class Nl{static BY_KIND={car:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},generic:{cylinders:4,idleRpm:800,kmhPer1000Rpm:[8,14,21,29,37,45],shiftUpRpm:3e3,shiftDownRpm:1300,engineGain:.6,roadGain:.5,roughness:.15},van:{cylinders:4,idleRpm:750,kmhPer1000Rpm:[7,12,19,27,35,42],shiftUpRpm:2600,shiftDownRpm:1200,engineGain:.8,roadGain:.7,roughness:.45},truck:{cylinders:6,idleRpm:600,kmhPer1000Rpm:[5,8,12,17,23,30,38,48],shiftUpRpm:1900,shiftDownRpm:1e3,engineGain:1,roadGain:.9,roughness:.55},motorcycle:{cylinders:2,idleRpm:1100,kmhPer1000Rpm:[12,18,24,30,35,40],shiftUpRpm:6e3,shiftDownRpm:2500,engineGain:.9,roadGain:.3,roughness:.3}};static of(t){return Nl.BY_KIND[t??"generic"]??Nl.BY_KIND.generic}}class Ro{constructor(t,e){this.samples=t,this.startMs=e}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(t,e,i,n){const s=Ro.SAMPLE_MS,r=[];for(let h=i;h<=n+s/2;h+=s){const l=e(h-s/2),u=e(h+s/2);if(!l||!u)return;r.push(Math.hypot(u.eastM-l.eastM,u.northM-l.northM)/(s/1e3))}const a=[];let c=1;for(let h=0;h<r.length;h++){const l=r[h],u=(r[Math.min(h+1,r.length-1)]-r[Math.max(h-1,0)])/(2*s/1e3);if(l<Ro.STANDING_MPS){c=1,a.push({speedMps:l,rpm:t.idleRpm,load:.1,gear:0});continue}const d=l*3.6,f=v=>d/t.kmhPer1000Rpm[v-1]*1e3;for(;c<t.kmhPer1000Rpm.length&&f(c)>t.shiftUpRpm;)c++;for(;c>1&&f(c)<t.shiftDownRpm;)c--;const p=Math.max(f(c),t.idleRpm*(1+.3*Math.min(1,l/3))),g=.15+.5*Math.min(1,(l/35)**2),m=u>.15?Math.min(1,g+u/2.5):u<-.3?.05:g;a.push({speedMps:l,rpm:p,load:m,gear:c})}return new Ro(a,i)}at(t){const e=(t-this.startMs)/Ro.SAMPLE_MS,i=Math.min(Math.max(Math.floor(e),0),this.samples.length-1),n=this.samples[i],s=this.samples[Math.min(i+1,this.samples.length-1)],r=Math.min(Math.max(e-i,0),1);return{speedMps:n.speedMps+(s.speedMps-n.speedMps)*r,rpm:n.rpm+(s.rpm-n.rpm)*r,load:n.load+(s.load-n.load)*r,gear:r<.5?n.gear:s.gear}}}class ef{drives=new Map;at(t,e){const i=[],n=t.event.place?.[0],s=h=>{const l=t.observerTrack.getInterpolatedPoseAt(h),u=l?.lat??n?.lat,d=l?.lng??n?.lng;if(u===void 0||d===void 0||!n)return;const f=oe(u,d,n.lat,n.lng);return{eastM:f.x,northM:-f.z}},r=Math.max(t.observerTrack.duration,(t.event.durationSeconds??0)*1e3),a=t.vehicle;if(a){const h=Nl.of(a.kind),l=this.drive(`observer:${a.kind}`,ef.trackKey(t),()=>Ro.of(h,s,0,r));l&&i.push({id:"observer",profile:h,state:l.at(e),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const c=s(e);for(const h of t.decor){if(!h.engine||!c)continue;const l=Nl.of(h.engine.kind),u=g=>{const m=tr(h,g);return{eastM:m.eastM,northM:m.northM}},d=this.drive(`decor:${h.id}`,ef.decorKey(h,r),()=>Ro.of(l,u,0,r));if(!d)continue;const f=tr(h,e),p=Math.hypot(f.eastM-c.eastM,f.northM-c.northM,f.altitudeM);i.push({id:`decor:${h.id}`,profile:l,state:d.at(e),noise:h.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:p})}return i}drive(t,e,i){const n=this.drives.get(t);if(n&&n.key===e)return n.drive;const s=i();return this.drives.set(t,{key:e,drive:s}),s}static trackKey(t){return t.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(t,e){return`${e}|${t.eastM},${t.northM}|`+(t.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const nv=864e5,sv=4e4;function US(o){const t=Math.floor(o.getTime()/nv);return{elapsedMs:o.getTime()-t*nv,shiftM:{x:rv.unit(t,2654435761)*sv,z:rv.unit(t,2246822507)*sv}}}class rv{static unit(t,e){let i=Math.imul(t|0,e)^e;return i=Math.imul(i^i>>>15,739982445),i=Math.imul(i^i>>>12,695872825),i^=i>>>15,(i>>>0)/4294967295*2-1}}function av(o,t,e,i,n,s,r){const a=i?.lat!==void 0&&i.lng!==void 0&&n?.lat!==void 0&&n.lng!==void 0?oe(n.lat,n.lng,i.lat,i.lng):{x:0,z:0};if(r){const l=t.getInterpolatedWeatherAt(0)??e,u=s===void 0?void 0:l.cloudLayers?.find(p=>p.id===s),d=(u?.windDirectionDeg??l.windDirectionDeg)*Math.PI/180,f=(u?.windSpeed??l.windSpeed)*r.elapsedMs/1e3;a.x+=r.shiftM.x-Math.sin(d)*f,a.z+=r.shiftM.z+Math.cos(d)*f}const c=Math.max(0,o),h=[0,...t.allKeyframes.map(l=>l.t).filter(l=>l>0&&l<c),c];for(let l=1;l<h.length;l++){const u=h[l-1],d=h[l]-u;if(d===0)continue;const f=32;for(let p=0;p<=f;p++){const g=t.getInterpolatedWeatherAt(u+d*p/f)??e,m=s===void 0?void 0:g.cloudLayers?.find(M=>M.id===s),v=(m?.windDirectionDeg??g.windDirectionDeg)*Math.PI/180,y=p===0||p===f?1:p%2===0?2:4,x=(m?.windSpeed??g.windSpeed)*d/1e3/f/3*y;a.x-=Math.sin(v)*x,a.z+=Math.cos(v)*x}}return a}const FS="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAARVBMVEX9sST/uyTfoCjNlSikfCqRcCx8Yy21hipTSi4TITEMHTEuMzBqWC3/wSRUX207SFj8/PyaoakmNUd5gYxBPy90fIfMz9RsB4kZAAACEUlEQVRo3u2XyXbDIAxFLeapjts6/f9PrQA3JymT25Cd3iY5xtYVIB6wLCQSiUQikUgk0nzBoVdFZ1xIpaTQbJnPACaNdYeskWwuAhaZoltnUemfnNkL4N49KEI8n0YAEXMvEWISAWQZPw2Xk1MIoF1dSNAzCMy6JsGyCR0wrkMwT3cBeDt+FH8aEHoA68LbM8HRHXQ3f0RE3/jXOOFX+s4djrKpIbzS7K+MmLrxlWCNR8mczjMw92Ar4dZLDXG4kzXinAECcOUPL3jMdN2294/GQGVG4EMHxORNJXoCfG6oT1trvDGM7iIA9N6aTOuuEbB9ra6FyCYr2gjge+fjA4CIi2uujYRoOBSw0A5/D0hT0X4PW0xtuotNpQPYtkt/fdtyM0LP6ZvOI2DtvoxtJWHvx38AxIkevLwXQ2TOA66DziYfLwC4r5wbIlwJo1ys8+VOBMy7/sxdjwIap49lVC3UePZp1mmyit4SuGUf11pjoTHVRVzXUaXFVt87kuEBsWZ055Q+2sXA76LbZYsvKR1ubvJqbKd5swl+GPI31p6L/sNYuDTe3jo+GBdr1J+P9PGawbRUw9VhleD/3ffT9uZ7DhtX1JNHL2CmNRXxYZhwSwBd3aJTyU85/GKOwhxBf5RnVk+75OSiuu+Ax4PQ3Jsg1hTeMUMwJgQp+PKCe2a+JuefFwQnkUgkEolEIpFerW8TL0hlNl2QVAAAAABJRU5ErkJggg==",zS=`
|
|
668
668
|
<div class="stage" id="stage">
|
|
669
669
|
<div class="frame" id="frame">
|
|
670
670
|
<canvas id="scene-canvas"></canvas>
|
|
@@ -2398,12 +2398,12 @@ canvas[data-cursor="rotate"] {
|
|
|
2398
2398
|
pointer-events: none;
|
|
2399
2399
|
white-space: nowrap;
|
|
2400
2400
|
}
|
|
2401
|
-
`;class eh{constructor(t){this.points=t}static STATIONARY_M=5;static of(t){const e=[];for(const i of t.observerTrack.allKeyframes){const{lat:n,lng:s,headingDeg:r}=i.pose;n===void 0||s===void 0||e.push({t:i.t,lat:n,lng:s,headingDeg:r})}if(e.length===0){const i=t.event.place?.[0];if(!i)return;e.push({t:0,lat:i.lat,lng:i.lng})}return new eh(e)}static TRAVEL_M=50;get travels(){return this.spanM>eh.TRAVEL_M}get moved(){return this.spanM>eh.STATIONARY_M}get spanM(){const t=this.box,e=(t.south+t.north)/2,i=(t.west+t.east)/2;return Math.max(Math.abs(oe(e,t.east,e,t.west).x),Math.abs(oe(t.north,i,t.south,i).z))}get center(){const t=this.box;return{lat:(t.south+t.north)/2,lng:(t.west+t.east)/2}}boundsAround(t,e){const{lat:i,lng:n}=this.center,s=Math.max(this.spanM*(1+e),t)/2;return{north:os(0,-s,i,n).lat,south:os(0,s,i,n).lat,east:os(s,0,i,n).lng,west:os(-s,0,i,n).lng}}get box(){const t=this.points.map(i=>i.lat),e=this.points.map(i=>i.lng);return{south:Math.min(...t),north:Math.max(...t),west:Math.min(...e),east:Math.max(...e)}}}class Ts{constructor(t,e){this.rotationPassed=t,this.scale=e}static SWAY_M=.012;static BREATH_M=.003;static DRIFT_YAW_DEG=.5;static DRIFT_PITCH_DEG=.4;static DRIFT_ROLL_DEG=.3;static GAZE_DRIFT_SHARE=.35;static HAND_HELD_S=.5;static HZ=[.11,.23,.17,.29,.37,.07];static of(t){const e=t.event.tags?.includes("paralysis")||(t.exposure??0)>Ts.HAND_HELD_S,i=t.sway??(e?0:1);if(i>0)return new Ts(Math.max(1-(t.instrument.stabilization??0),Ts.GAZE_DRIFT_SHARE),i)}offsetAt(t){const e=t/1e3,i=this.scale,n=(u,d)=>Math.sin(2*Math.PI*u*e+d),[s,r,a,c,h,l]=Ts.HZ;return{eastM:i*Ts.SWAY_M*(.7*n(s,.3)+.3*n(c,1.9)),northM:i*Ts.SWAY_M*(.6*n(a,2.2)+.4*n(h,.8)),upM:i*Ts.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*Ts.DRIFT_YAW_DEG*(.6*n(l,1.1)+.4*n(c,2.7)),pitchDeg:i*this.rotationPassed*Ts.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(a,.4)),rollDeg:i*this.rotationPassed*Ts.DRIFT_ROLL_DEG*n(s,2.9)}}}class qe{constructor(t,e){this.stretches=t,this.rotationPassed=e}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STOP_LURCH_M=.035;static STOP_PITCH_DEG=3;static START_LURCH_M=.015;static START_PITCH_DEG=1.2;static JOLT_HZ=1.4;static JOLT_DECAY_S=.35;static JOLT_LASTS_MS=1500;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(t){const e=eh.of(t);if(!e||e.points.length<2)return;const i=[];let n=0;for(let s=1;s<e.points.length;s++){const r=e.points[s-1],a=e.points[s],c=(a.t-r.t)/1e3;if(c<=0)continue;const h=oe(a.lat,a.lng,r.lat,r.lng),l=h.x,u=-h.z,d=Math.hypot(l,u),f=d/c,p=qe.stepHzFor(f);i.push({startMs:r.t,endMs:a.t,speedMPerS:f,eastUnit:d>0?l/d:0,northUnit:d>0?u/d:0,stepHz:p,stepsBefore:n,rampsIn:!0,rampsOut:!0}),n+=p*c}for(let s=0;s<i.length;s++){const r=i[s-1],a=i[s+1];i[s].rampsIn=r===void 0||r.stepHz===0,i[s].rampsOut=a===void 0||a.stepHz===0}if(i.some(s=>s.stepHz>0))return new qe(i,1-(t.instrument.stabilization??0))}static bodyAt(t,e,i=!1){const n=qe.of(t)?.offsetAt(e)??qe.STILL;return i?n:qe.add(n,Ts.of(t)?.offsetAt(e))}static stepHzFor(t){return t<qe.SLOWEST_WALK_M_PER_S||t>qe.FASTEST_WALK_M_PER_S?0:qe.REFERENCE_STEP_HZ*Math.pow(t/qe.REFERENCE_SPEED_M_PER_S,qe.CADENCE_EXPONENT)}offsetAt(t){return qe.add(this.cycleAt(t),this.joltAt(t))}joltAt(t){for(const e of this.stretches){if(e.stepHz===0)continue;const i=e.speedMPerS/qe.REFERENCE_SPEED_M_PER_S,n=(a,c,h,l)=>{if(a<0||a>qe.JOLT_LASTS_MS)return;const u=a/1e3,d=Math.exp(-u/qe.JOLT_DECAY_S)*Math.sin(2*Math.PI*qe.JOLT_HZ*u),f=l*c*i*d;return{eastM:f*e.eastUnit,northM:f*e.northUnit,upM:-Math.abs(f)*.3,rollDeg:0,pitchDeg:-l*h*i*d*this.rotationPassed,yawDeg:0}},s=e.rampsOut?n(t-e.endMs,qe.STOP_LURCH_M,qe.STOP_PITCH_DEG,1):void 0;if(s)return s;const r=e.rampsIn?n(t-e.startMs,qe.START_LURCH_M,qe.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(t,e){return e?{eastM:t.eastM+e.eastM,northM:t.northM+e.northM,upM:t.upM+e.upM,rollDeg:t.rollDeg+e.rollDeg,pitchDeg:t.pitchDeg+e.pitchDeg,yawDeg:t.yawDeg+e.yawDeg}:t}cycleAt(t){const e=this.stretches.find(c=>t>=c.startMs&&t<=c.endMs);if(!e||e.stepHz===0)return qe.STILL;const i=e.stepsBefore+e.stepHz*(t-e.startMs)/1e3,n=2*Math.PI*i,s=this.amplitudeAt(e,t),r=qe.SWAY_M*s*Math.cos(n/2),a=s*this.rotationPassed*e.speedMPerS/qe.REFERENCE_SPEED_M_PER_S;return{eastM:r*e.northUnit,northM:-r*e.eastUnit,upM:qe.RISE_M_PER_M_PER_S*e.speedMPerS*s*Math.cos(n),rollDeg:qe.HEAD_ROLL_DEG*a*Math.cos(n/2),pitchDeg:-1.25*a*Math.cos(n),yawDeg:qe.HEAD_YAW_DEG*a*Math.cos(n/2)}}amplitudeAt(t,e){const i=1e3/t.stepHz,n=Math.min(i,(t.endMs-t.startMs)/2);if(n<=0)return 1;const s=e-t.startMs,r=t.endMs-e,a=Math.min(t.rampsIn?s/n:1,t.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class VS{constructor(t,e){this.timeline=t,this.onFrame=e}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const t=()=>{if(this.state!=="playing")return;const e=performance.now();if(this.currentT+=(e-this.lastWallTime)*this.playbackRate,this.lastWallTime=e,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t)};this.rafId=requestAnimationFrame(t)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(t){this.currentT=Math.max(0,Math.min(t,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(t){const e=new Map;for(const i of this.timeline.sourceIds){const n=this.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}this.onFrame(t,e)}}const F2=["nw","n","ne","e","se","s","sw","w"],WS=24,ru=8,XS=3,$S=8;function au(o,t,e){const i=o.x-t.x,n=o.y-t.y,s=Math.cos(e),r=Math.sin(e);return{x:t.x+i*s-n*r,y:t.y+i*r+n*s}}function Ph(o){return{x:o.x+o.width/2,y:o.y+o.height/2}}const YS={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 ys{static handlePointsFor(t){const{x:e,y:i,width:n,height:s}=t.bounds,r={nw:{x:e,y:i},n:{x:e+n/2,y:i},ne:{x:e+n,y:i},e:{x:e+n,y:i+s/2},se:{x:e+n,y:i+s},s:{x:e+n/2,y:i+s},sw:{x:e,y:i+s},w:{x:e,y:i+s/2},rotate:{x:e+n/2,y:i-WS}},a=Ph(t.bounds),c={};for(const h of Object.keys(r))c[h]=au(r[h],a,t.angle);return c}static hitTestHandle(t,e,i=8,n=[...F2,"rotate"]){const s=ys.handlePointsFor(t);for(const r of n)if(Math.hypot(e.x-s[r].x,e.y-s[r].y)<=i)return r}static HANDLE_DIRECTION_DEG={e:0,se:45,s:90,sw:135,w:180,nw:225,n:270,ne:315};static resizeAxisFor(t,e){const n=((ys.HANDLE_DIRECTION_DEG[t]+e*180/Math.PI)%180+180)%180/45,s=["ew","nwse","ns","nesw"];return s[Math.round(n)%s.length]}static resizeBounds(t,e,i,n){const s=Ph(t),r=au(n,s,-e),{x:a,y:c,width:h,height:l}=t,u=YS[i];let d=a,f=c,p=a+h,g=c+l;return u.left&&(d=Math.min(r.x,p-ru)),u.right&&(p=Math.max(r.x,d+ru)),u.top&&(f=Math.min(r.y,g-ru)),u.bottom&&(g=Math.max(r.y,f+ru)),{x:d,y:f,width:p-d,height:g-f}}static resizeShape(t,e,i){if(e==="rotate")throw new Error("resizeShape does not accept the rotate handle");const{width:n,height:s}=t.bounds,r=ys.resizeBounds(t.bounds,t.angle,e,i);if(t.kind==="oval")return{...t,bounds:r};const a=n===0?1:r.width/n,c=s===0?1:r.height/s;return{...t,bounds:r,points:t.points.map(h=>({x:h.x*a,y:h.y*c}))}}static rotateShape(t,e){const i=Ph(t.bounds),n=Math.atan2(e.y-i.y,e.x-i.x)+Math.PI/2;return{...t,angle:n}}static groupBoundsFor(t){const e=Math.min(...t.map(r=>r.x)),i=Math.min(...t.map(r=>r.y)),n=Math.max(...t.map(r=>r.x+r.width)),s=Math.max(...t.map(r=>r.y+r.height));return{x:e,y:i,width:n-e,height:s-i}}static vertexPointsFor(t){const e=Ph(t.bounds);return t.points.map(i=>au({x:t.bounds.x+i.x,y:t.bounds.y+i.y},e,t.angle))}static hitTestVertex(t,e,i=$S){const n=ys.vertexPointsFor(t);let s,r=i;return n.forEach((a,c)=>{const h=Math.hypot(e.x-a.x,e.y-a.y);h<=r&&(r=h,s=c)}),s}static toLocalPoint(t,e){const i=Ph(t.bounds),n=au(e,i,-t.angle);return{x:n.x-t.bounds.x,y:n.y-t.bounds.y}}static moveVertex(t,e,i){const n=t.points.map((u,d)=>d===e?ys.toLocalPoint(t,i):u),s=Math.min(...n.map(u=>u.x)),r=Math.min(...n.map(u=>u.y)),a=Math.max(...n.map(u=>u.x)),c=Math.max(...n.map(u=>u.y)),h={x:t.bounds.x+s,y:t.bounds.y+r,width:a-s,height:c-r},l=n.map(u=>({x:u.x-s,y:u.y-r}));return{...t,bounds:h,points:l}}static insertVertexNear(t,e){const i=ys.toLocalPoint(t,e),{points:n}=t;let s=n.length-1,r=1/0;for(let c=0;c<n.length;c++){const h=n[c],l=n[(c+1)%n.length],u=ys.distanceToSegment(i,h,l);u<r&&(r=u,s=c)}const a=[...n.slice(0,s+1),i,...n.slice(s+1)];return{...t,points:a}}static distanceToSegment(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=n*n+s*s,a=r===0?0:Math.max(0,Math.min(1,((t.x-e.x)*n+(t.y-e.y)*s)/r)),c=e.x+a*n,h=e.y+a*s;return Math.hypot(t.x-c,t.y-h)}static deleteVertex(t,e){return t.points.length<=XS?t:{...t,points:t.points.filter((i,n)=>n!==e)}}}const Yp=6,ou=Yp/2,ov=20,cv=24,hv=9,lv=6,uv=7,dv=6,or=4;class gh{constructor(t){this.ctx=t}starPoints=0;roll=0;clear(t,e){this.ctx.clearRect(0,0,t,e)}static paintExtent(t){const{x:e,y:i,width:n,height:s}=t.bounds,r=e+n/2,a=i+s/2,c=t.angle%(2*Math.PI)!==0,h=Math.hypot(n,s)/2,l=c?h:n/2,u=c?h:s/2,d=Math.max(n,s)/2,f=t.brightness??0,p=f>0?Math.max(d*(1+hv*f),dv*f)-d:0,g=f>0?d*(1+uv*f)-d:0,m=3*cv*(t.blur??0)+1.5*ov*t.haloScale,v=Math.max(p,g,0)+m+2;return{x:r-l-v,y:a-u-v,width:2*(l+v),height:2*(u+v)}}paintInto(t,e,i,n=!1){this.ctx.save(),this.ctx.scale(i,i),this.ctx.translate(-e.x,-e.y);const s=t.selected?{...t,selected:!1}:t;n?this.paintGhost(s,1.5):this.paintShape(s),this.ctx.restore()}paintShape(t){this.ctx.save(),this.ctx.globalAlpha=1-t.transparency;const e=t.blur??0;e>0&&(this.ctx.filter=`blur(${(cv*e).toFixed(2)}px)`);const i=t.brightness??0;i>0&&this.paintDazzle(t,i),t.haloScale>0&&this.paintHalo(t),this.paintBase(t),this.ctx.restore(),t.selected&&this.paintSelectionHandles(t)}setStarPoints(t){this.starPoints=Math.max(0,Math.floor(t))}setRoll(t){this.roll=t}paintDazzle(t,e){const{x:i,y:n,width:s,height:r}=t.bounds,a=i+s/2,c=n+r/2,h=Math.max(s,r)/2,l=Math.max(h*(1+hv*e),dv*e);if(l<=0)return;this.ctx.save(),this.ctx.globalCompositeOperation="lighter";const u=this.ctx.createRadialGradient(a,c,0,a,c,l);for(let d=0;d<=lv;d++){const f=d/lv,p=1/(1+24*f*f);this.ctx.globalAlpha=1,u.addColorStop(f,this.withAlpha(t.color,p*e*.55))}if(this.ctx.fillStyle=u,this.ctx.beginPath(),this.ctx.arc(a,c,l,0,2*Math.PI),this.ctx.fill(),this.starPoints>0){const d=h*(1+uv*e);this.ctx.lineWidth=Math.max(1,h*.12),this.ctx.lineCap="round";for(let f=0;f<this.starPoints;f++){const p=f/this.starPoints*Math.PI*2+this.roll,g=a+Math.cos(p)*d,m=c+Math.sin(p)*d,v=this.ctx.createLinearGradient(a,c,g,m);v.addColorStop(0,this.withAlpha(t.color,e*.55)),v.addColorStop(.35,this.withAlpha(t.color,e*.22)),v.addColorStop(1,this.withAlpha(t.color,0)),this.ctx.strokeStyle=v,this.ctx.beginPath(),this.ctx.moveTo(a,c),this.ctx.lineTo(g,m),this.ctx.stroke()}}this.ctx.restore()}dazzledFill(t,e){if(e<=0)return t.color;const i=/^#([0-9a-f]{6})$/i.exec(t.color.trim());if(!i)return t.color;const n=Number.parseInt(i[1],16),s=r=>Math.round(r+(255-r)*e);return`rgb(${s(n>>16&255)}, ${s(n>>8&255)}, ${s(n&255)})`}withAlpha(t,e){const i=Math.max(0,Math.min(1,e)),n=/^#([0-9a-f]{6})$/i.exec(t.trim());if(!n)return t;const s=Number.parseInt(n[1],16);return`rgba(${s>>16&255}, ${s>>8&255}, ${s&255}, ${i.toFixed(3)})`}paintBase(t){this.ctx.fillStyle=this.dazzledFill(t,t.brightness??0),this.tracePath(t),this.ctx.fill()}paintGhost(t,e){this.ctx.save(),this.tracePath(t),this.ctx.setLineDash([e*3,e*2]),this.ctx.lineWidth=e,this.ctx.strokeStyle=t.color,this.ctx.stroke(),this.ctx.restore()}tracePath(t){if(this.ctx.beginPath(),t.kind==="oval"){const{x:e,y:i,width:n,height:s}=t.bounds,r=n/2,a=s/2;this.ctx.ellipse(e+r,i+a,r,a,t.angle,0,2*Math.PI)}else{const{x:e,y:i,width:n,height:s}=t.bounds;this.ctx.save(),this.ctx.translate(e+n/2,i+s/2),this.ctx.rotate(t.angle),this.ctx.translate(-n/2,-s/2),t.points.forEach((r,a)=>{a===0?this.ctx.moveTo(r.x,r.y):this.ctx.lineTo(r.x,r.y)}),this.ctx.closePath(),this.ctx.restore()}}paintHalo(t){this.ctx.save(),this.ctx.shadowColor=t.color,this.ctx.shadowBlur=ov*t.haloScale,this.paintBase(t),this.ctx.restore()}paintSelectionHandles(t){this.paintHandleFrame(ys.handlePointsFor(t),{includeRotate:!0}),t.kind==="polygon"&&this.paintVertexHandles(t)}paintVertexHandles(t){this.ctx.fillStyle="#39f";for(const e of ys.vertexPointsFor(t))this.ctx.beginPath(),this.ctx.ellipse(e.x,e.y,or,or,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(t){this.paintOutline(ys.handlePointsFor(t))}paintSelectionOnly(t){this.paintSelectionHandles(t)}paintPictureFrame(t,e,i){const n=this.ctx;if(n.save(),t&&t.length===4){n.strokeStyle="#39f",n.lineWidth=1.5,n.setLineDash([6,4]),n.beginPath(),n.moveTo(t[0].x,t[0].y);for(const s of t.slice(1))n.lineTo(s.x,s.y);n.closePath(),n.stroke(),n.setLineDash([])}for(const s of e){const r=gh.landmarkColour(s.residualDeg),a=s.selected?3:2;s.selected&&(n.strokeStyle="#fff",n.lineWidth=a+3,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,or+2,or+2,0,0,2*Math.PI),n.stroke()),s.scene&&(n.strokeStyle=r,n.lineWidth=1,n.beginPath(),n.moveTo(s.picture.x,s.picture.y),n.lineTo(s.scene.x,s.scene.y),n.stroke(),n.fillStyle=r,n.beginPath(),n.ellipse(s.scene.x,s.scene.y,or,or,0,0,2*Math.PI),n.fill()),n.strokeStyle=r,n.lineWidth=a,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,or+2,or+2,0,0,2*Math.PI),n.stroke(),this.paintLabel(s.label,s.picture.x+or+5,s.picture.y-or-2,r)}i&&this.paintLabel(i,8,8,"#fff",13),n.restore()}paintGhosts(t,e,i){const n=this.ctx;n.save();const s=(c,h,l,u=[])=>{n.setLineDash(u),n.lineWidth=l+2,n.strokeStyle="rgba(0, 0, 0, 0.6)",c(),n.lineWidth=l,n.strokeStyle=h,c(),n.setLineDash([])},r=(c,h)=>()=>{n.beginPath(),n.arc(c.x,c.y,h,0,2*Math.PI),n.stroke()},a=(c,h,l)=>()=>{const[u,d]=l?[h,h]:[h,0];n.beginPath(),n.moveTo(c.x-u,c.y-d),n.lineTo(c.x+u,c.y+d),n.moveTo(c.x+d,c.y-u),n.lineTo(c.x-d,c.y+u),n.stroke()};for(const c of t)s(()=>{n.beginPath(),n.moveTo(c.ghost.x,c.ghost.y),n.lineTo(c.light.x,c.light.y),n.stroke()},"rgba(255, 255, 255, 0.85)",1,[4,4]),s(r(c.light,7),"#ffffff",1.5),s(r(c.ghost,Math.max(9,c.ghostRadius)),"#ffd23f",2);e&&s(a(e,8,!1),"#ffd23f",2),i&&s(a(i,5,!0),"rgba(255, 255, 255, 0.7)",1),n.restore()}static landmarkColour(t){return t===void 0?"#ffb000":t<=1?"#3c3":t<=3?"#ffb000":"#f33"}paintLabel(t,e,i,n,s=11){const r=this.ctx;r.save(),r.font=`${s}px system-ui, sans-serif`,r.textBaseline="top";const a=r.measureText(t).width;r.fillStyle="rgba(0, 0, 0, 0.6)",r.fillRect(e-3,i-2,a+6,s+4),r.fillStyle=n,r.fillText(t,e,i),r.restore()}paintGroupHandles(t){this.paintHandleFrame(ys.handlePointsFor({bounds:t,angle:0}),{includeRotate:!0})}paintOutline(t){this.ctx.strokeStyle="lightgray",this.ctx.beginPath(),this.ctx.moveTo(t.nw.x,t.nw.y),this.ctx.lineTo(t.ne.x,t.ne.y),this.ctx.lineTo(t.se.x,t.se.y),this.ctx.lineTo(t.sw.x,t.sw.y),this.ctx.closePath(),this.ctx.stroke()}paintHandleFrame(t,{includeRotate:e}){this.paintOutline(t),this.ctx.fillStyle="lightgray";for(const i of F2){const n=t[i];this.ctx.fillRect(n.x-ou,n.y-ou,Yp,Yp)}e&&(this.ctx.beginPath(),this.ctx.moveTo(t.n.x,t.n.y),this.ctx.lineTo(t.rotate.x,t.rotate.y),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.ellipse(t.rotate.x,t.rotate.y,ou+1,ou+1,0,0,2*Math.PI),this.ctx.fill())}}const fv=.05,pv=.08,mv=2,gv=3,KS=14,qS=.02;class ZS{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",t);return}}Uo.unlock(this.context)}setSound(t){if(this.requested=t,!this.context)return;const e=this.keyFor(t);if(!e){this.silence();return}if(this.voice?.key!==e){this.stopVoice();const i=++this.voiceToken;e.startsWith("src:")?this.buildRecordedVoice(t.src,e,i):this.voice=this.buildSynthesizedVoice(t,e)}this.applyTo(this.voice,t)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(t){if(!(t.volume<=0))return t.src?`src:${t.src}`:t.kind==="none"?void 0:t.kind}applyTo(t,e){const i=this.context;if(!t||!i)return;const n=i.currentTime;t.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,e.volume))*t.gainScale,n,fv);for(const{param:s,ratio:r}of t.pitch)s.setTargetAtTime(Math.min(e.pitchHz*r,i.sampleRate/2-1),n,fv)}buildSynthesizedVoice(t,e){const i=this.context;if(i)switch(t.kind){case"hum":return this.buildHum(i,e);case"whistle":return this.buildWhistle(i,e);case"rumble":return this.buildRumble(i,e);case"crackle":return this.buildCrackle(i,e);default:return}}buildHum(t,e){const i=t.createOscillator();i.type="sawtooth";const n=t.createOscillator();n.type="sawtooth";const s=t.createBiquadFilter();s.type="lowpass",s.Q.value=1;const r=t.createGain();return r.gain.value=0,i.connect(s),n.connect(s),s.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.16,pitch:[{param:i.frequency,ratio:1},{param:n.frequency,ratio:1.006},{param:s.frequency,ratio:6}]}}buildWhistle(t,e){const i=t.createOscillator();i.type="sine";const n=t.createOscillator();n.type="sine",n.frequency.value=5;const s=t.createGain(),r=t.createGain();return r.gain.value=0,n.connect(s).connect(i.frequency),i.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:s.gain,ratio:.012}]}}buildRumble(t,e){const i=t.createBufferSource();i.buffer=this.brownNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="lowpass",n.Q.value=.8;const s=t.createGain();return s.gain.value=0,i.connect(n).connect(s).connect(this.output(t)),i.start(),{key:e,nodes:[n,s],sources:[i],volumeParam:s.gain,gainScale:1.4,pitch:[{param:n.frequency,ratio:1}]}}buildCrackle(t,e){const i=t.createBufferSource();i.buffer=this.whiteNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="bandpass",n.Q.value=1.2;const s=t.createGain();s.gain.value=0;const r=t.createBufferSource();r.buffer=this.crackleEnvelope(t),r.loop=!0;const a=t.createGain();return a.gain.value=0,r.connect(a).connect(s.gain),i.connect(n).connect(s).connect(this.output(t)),i.start(),r.start(),{key:e,nodes:[n,s,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:n.frequency,ratio:4}]}}async buildRecordedVoice(t,e,i){const n=this.context;if(!n)return;let s;try{s=await this.getBuffer(t)}catch(c){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",c);return}if(i!==this.voiceToken||!this.context)return;const r=n.createBufferSource();r.buffer=s,r.loop=!0;const a=n.createGain();a.gain.value=0,r.connect(a).connect(this.output(n)),r.start(),this.voice={key:e,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(t){const e=this.context;if(!e)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(t);return i||(i=fetch(t).then(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${t}`);return n.arrayBuffer()}).then(n=>e.decodeAudioData(n)),this.buffers.set(t,i)),i}whiteNoise(t){if(!this.noiseBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*mv),t.sampleRate),i=e.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;this.noiseBuffer=e}return this.noiseBuffer}brownNoise(t){const e=t.createBuffer(1,Math.floor(t.sampleRate*mv),t.sampleRate),i=e.getChannelData(0);let n=0,s=0;for(let r=0;r<i.length;r++)n=(n+.02*(Math.random()*2-1))/1.02,i[r]=n,s=Math.max(s,Math.abs(n));if(s>0)for(let r=0;r<i.length;r++)i[r]/=s;return e}crackleEnvelope(t){if(!this.crackleBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*gv),t.sampleRate),i=e.getChannelData(0),n=Math.max(1,Math.floor(qS*t.sampleRate)),s=Math.round(gv*KS);for(let r=0;r<s;r++){const a=Math.floor(Math.random()*i.length),c=.4+Math.random()*.6;for(let h=0;h<n&&a+h<i.length;h++)i[a+h]=Math.max(i[a+h],c*(1-h/n))}this.crackleBuffer=e}return this.crackleBuffer}stopVoice(){const t=this.voice,e=this.context;if(this.voice=void 0,!t||!e)return;const i=e.currentTime;t.volumeParam.cancelScheduledValues(i),t.volumeParam.setTargetAtTime(0,i,pv/3);const n=i+pv;for(const s of t.sources){s.onended=()=>{s.disconnect();for(const r of t.nodes)r.disconnect()};try{s.stop(n)}catch{s.disconnect();for(const r of t.nodes)r.disconnect()}}}}class gr{static KINDS=["beams","launches","reentries"];static isEmpty(t){return!t||gr.KINDS.every(e=>!t[e]?.length)}static written(t){if(gr.isEmpty(t))return;const e={};for(const i of gr.KINDS)t[i]?.length&&(e[i]=t[i]);return e}static read(t,e){const i=e,n={};for(const r of gr.KINDS){const a=[...t?.[r]??[],...i?.[r]??[]];a.length>0&&(n[r]=a)}let s=e;if(i&&gr.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:c,...h}=i;s=gr.isReading(h)?h:void 0}return{skyEvents:gr.written(n),interpretation:s}}static isReading(t){return(t.bodies?.length??0)>0||t.title!==void 0||(t.smoke?.length??0)>0}}function ul(o){return[...o].sort((t,e)=>t.t-e.t)}function l0(o,t){let e;for(const i of ul(o)){if(i.t>t)break;e=i}return e}const u0=Math.PI/180,cu=180/Math.PI;class Ir{constructor(t,e,i){this.kind=t,this.canvasHeightPx=e,this.fovDeg=i;const n=i*u0/2;this.focalPx=t==="equidistant"?e/2/n:e/2/Math.tan(n)}focalPx;static of(t,e,i){return new Ir(t.projection,e,i)}degToPx(t){const e=t*u0;return this.kind==="equidistant"?this.focalPx*e:2*this.focalPx*Math.tan(e/2)}pxToDeg(t){return this.kind==="equidistant"?t/this.focalPx*cu:2*Math.atan(t/(2*this.focalPx))*cu}angleDegToRadiusPx(t){const e=t*u0;return this.kind==="equidistant"?this.focalPx*e:this.focalPx*Math.tan(e)}halfWidthAngleDeg(t){return this.radiusPxToAngleDeg(this.canvasHeightPx*t/2)}radiusPxToAngleDeg(t){return this.kind==="equidistant"?t/this.focalPx*cu:Math.atan(t/this.focalPx)*cu}ofBounds(t){return{widthDeg:this.pxToDeg(t.width),heightDeg:this.pxToDeg(t.height)}}toBoundsSize(t){return{width:this.degToPx(t.widthDeg),height:this.degToPx(t.heightDeg)}}widthPx(t){return this.degToPx(Qe.angularWidthDeg(t))}}class Ln{static fovOf(t,e){return ze(t,e)?.fovDeg??Ti.fieldOfViewDeg(t.instrument)}static toAngular(t){this.eachKeyframe(t,(e,i)=>{const n=i.ofBounds(e.bounds);return e.angular?.widthDeg===n.widthDeg&&e.angular.heightDeg===n.heightDeg?e:{...e,angular:n}})}static toBounds(t){this.eachKeyframe(t,(e,i)=>this.sizedFromAngle(e,i))}static sizedFromAngle(t,e){if(!t.angular)return t;const{width:i,height:n}=e.toBoundsSize(t.angular),s={x:t.bounds.x+(t.bounds.width-i)/2,y:t.bounds.y+(t.bounds.height-n)/2,width:i,height:n};if(t.kind!=="polygon")return{...t,bounds:s};const r=t.bounds.width===0?1:i/t.bounds.width,a=t.bounds.height===0?1:n/t.bounds.height;return{...t,bounds:s,points:t.points.map(c=>({x:c.x*r,y:c.y*a}))}}static toAim(t){this.eachKeyframe(t,(e,i,n)=>{const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);if(s&&Math.abs(s.x-e.bounds.x)<Ln.UNMOVED_PX&&Math.abs(s.y-e.bounds.y)<Ln.UNMOVED_PX)return e;const r=this.aimFrom(t,i,n,e.bounds);return r?{...e,aim:r}:e})}static UNMOVED_PX=.01;static aimOf(t,e,i){const n=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,this.fovOf(t,e));return this.aimFrom(t,n,ze(t,e),i)}static aimFrom(t,e,i,n){if(i?.headingDeg===void 0)return;const s=this.frameCentre(t),r=e.radiusPxToAngleDeg(n.x+n.width/2-s.x),a=e.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(t){this.eachKeyframe(t,(e,i,n)=>this.placedByAim(t,e,i,n))}static placedByAim(t,e,i,n){const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);return s?{...e,bounds:{...e.bounds,...s}}:e}static derivable(t){const e=new Set,i=new Map,n=new Map;return t.timeline.allKeyframes.forEach((s,r)=>{const a=ze(t,s.t),c=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,this.fovOf(t,s.t));for(const{sourceId:h,shape:l}of s.shapes){const u=n.get(h),d=i.get(h);if(n.set(h,l),!u||!d){i.set(h,l);continue}const f=Object.fromEntries(Object.entries(l).filter(([m,v])=>m!=="bounds"&&m!=="points"&&JSON.stringify(v)!==JSON.stringify(u[m]))),p={...d,...f},g=this.placedByAim(t,this.sizedFromAngle(p,c),c,a);Ln.near(g,l)?(e.add(`${r}:${h}`),i.set(h,p)):i.set(h,l)}}),(s,r)=>e.has(`${s}:${r}`)}static SAME_PX=1e-6;static near(t,e){const i=(r,a)=>Math.abs(r-a)<=Ln.SAME_PX*Math.max(1,Math.abs(a)),n=t.bounds,s=e.bounds;return!i(n.x,s.x)||!i(n.y,s.y)||!i(n.width,s.width)||!i(n.height,s.height)?!1:e.kind!=="polygon"||t.kind!=="polygon"?!0:t.points.length===e.points.length&&t.points.every((r,a)=>i(r.x,e.points[a].x)&&i(r.y,e.points[a].y))}static positionOf(t,e,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(t),a=this.shortestArc(e.azimuthDeg-s.headingDeg),c=e.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,a)-i.width/2,y:r.y-this.offAxisPx(n,c)-i.height/2}}static frameCentre(t){return{x:Ti.frameWidthPx(t.instrument,Qe.CANVAS_HEIGHT_PX)/2,y:Qe.CANVAS_HEIGHT_PX/2}}static shortestArc(t){return(t%360+540)%360-180}static offAxisPx(t,e){return Math.abs(e)>=Ln.OFF_CANVAS_DEG?Math.sign(e)*Ln.OFF_CANVAS_PX:t.angleDegToRadiusPx(e)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(t,e,i){const n=Ti.frameWidthPx(e,Qe.CANVAS_HEIGHT_PX)/2,s=Ti.frameWidthPx(t.instrument,Qe.CANVAS_HEIGHT_PX)/2,r=Qe.CANVAS_HEIGHT_PX/2;for(const a of[...t.timeline.allKeyframes]){const c=this.fovOf(t,a.t),h=i?.get(a.t)??c,l=Ir.of(e,Qe.CANVAS_HEIGHT_PX,h),u=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,c);t.timeline.addKeyframe(a.t,a.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-n,g=f.y+f.height/2-r,m=Math.hypot(p,g),v=m===0?1:u.angleDegToRadiusPx(l.radiusPxToAngleDeg(m))/m,y={...f,x:s+p*v-f.width/2,y:r+g*v-f.height/2};return{...d,shape:{...d.shape,bounds:y}}}))}this.toBounds(t)}static eachKeyframe(t,e){const{timeline:i}=t;for(const n of[...i.allKeyframes]){const s=ze(t,n.t),r=this.fovOf(t,n.t),a=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,r);let c=!1;const h=n.shapes.map(l=>{const u=e(l.shape,a,s);return u===l.shape?l:(c=!0,{...l,shape:u})});c&&i.addKeyframe(n.t,h)}}}class Vn{static isRelative(t){return t!==void 0&&typeof t.eastM=="number"&&typeof t.northM=="number"}static isAbsolute(t){return t!==void 0&&typeof t.lat=="number"&&typeof t.lng=="number"}static referenceOf(t,e){return e.references.find(i=>(i.id??void 0)===(t.relativeTo??void 0))}static resolve(t,e){if(Vn.isRelative(t)){const i=Vn.referenceOf(t,e);return i?{eastM:i.eastM+t.eastM,northM:i.northM+t.northM}:void 0}return Vn.isAbsolute(t)&&e.origin?Vn.toLocal(t,e.origin):void 0}static restated(t,e,i){if(Vn.isRelative(t)){const s=Vn.referenceOf(t,i);return s?Vn.relative(e.eastM-s.eastM,e.northM-s.northM,t.relativeTo):void 0}if(!i.origin)return t;const n=Vn.toGeo(e,i.origin);return{lat:Vn.degrees(n.lat),lng:Vn.degrees(n.lng)}}static relative(t,e,i){const n={eastM:Vn.metres(t),northM:Vn.metres(e)};return i!==void 0&&(n.relativeTo=i),n}static toLocal(t,e){const i=oe(t.lat,t.lng,e.lat,e.lng);return{eastM:i.x,northM:-i.z}}static toGeo(t,e){return os(t.eastM,-t.northM,e.lat,e.lng)}static metres(t){return Math.round(t*100)/100}static degrees(t){return Math.round(t*1e7)/1e7}}class Xn{static restatedDecor(t){const e=Xn.originOf(t);return t.decor.map(i=>{let n=i;if(i.saidPosition){const s=Xn.restated(i.saidPosition,i,Xn.frameAt(t,0,e,i.id));JSON.stringify(s)!==JSON.stringify(i.saidPosition)&&(n={...i,saidPosition:s},s||delete n.saidPosition)}if(i.track?.some(s=>s.saidPosition)){const s=i.track.map(r=>{if(!r.saidPosition)return r;const a=Xn.restated(r.saidPosition,r,Xn.frameAt(t,r.t,e,i.id));if(JSON.stringify(a)===JSON.stringify(r.saidPosition))return r;const c={...r,saidPosition:a};return a||delete c.saidPosition,c});n={...n,track:s}}return n})}static restatedObserverTrack(t){const e=t.observerTrack.toJSON(),i=Xn.originOf(t);return!i||!e.keyframes.some(n=>n.pose.saidPosition)?e:{...e,keyframes:e.keyframes.map(n=>{const{pose:s}=n;if(!s.saidPosition||s.lat===void 0||s.lng===void 0)return n;const r=Vn.toLocal({lat:s.lat,lng:s.lng},i),a=Xn.restated(s.saidPosition,r,Xn.frameAt(t,n.t,i));if(JSON.stringify(a)===JSON.stringify(s.saidPosition))return n;const c={...s,saidPosition:a};return a||delete c.saidPosition,{...n,pose:c}})}}static restatedInterpretation(t){const e=t.interpretation;if(!e?.bodies.some(n=>n.track.some(s=>s.saidPosition)))return e;const i=Xn.originOf(t);return{...e,bodies:e.bodies.map(n=>n.track.some(s=>s.saidPosition)?{...n,track:n.track.map(s=>{if(!s.saidPosition)return s;const r=s.eastM!==void 0&&s.northM!==void 0?Xn.restated(s.saidPosition,{eastM:s.eastM,northM:s.northM},Xn.frameAt(t,s.t,i)):void 0;if(JSON.stringify(r)===JSON.stringify(s.saidPosition))return s;const a={...s,saidPosition:r};return r||delete a.saidPosition,a})}:n)}}static originOf(t){const e=t.observerTrack.getInterpolatedPoseAt(0),i=t.event.place?.[0],n=e?.lat??i?.lat,s=e?.lng??i?.lng;return typeof n=="number"&&typeof s=="number"?{lat:n,lng:s}:void 0}static frameAt(t,e,i,n){const s=[{label:"",eastM:0,northM:0},...t.decor.filter(r=>r.id!==n).map(r=>{const{eastM:a,northM:c}=tr(r,e);return{id:r.id,label:r.id,eastM:a,northM:c}})];return{origin:i,references:s}}static restated(t,e,i){return Vn.restated(t,{eastM:e.eastM,northM:e.northM},i)}}function JS(o){return Kn.restore(jS(o),o.provenance)}function jS(o){return Ln.toAngular(o),Ln.toAim(o),{version:1,id:o.id,time:o.event.time,endTime:o.event.endTime,durationSeconds:o.event.durationSeconds,durationText:o.event.durationText,utcOffsetHours:o.event.utcOffsetHours,timeZone:o.event.timeZone,place:o.event.place,observer:o.observer,account:o.account,sources:o.sources?.length?o.sources:void 0,sway:o.sway,vehicle:o.vehicle,description:o.event.description,image:o.event.image,summary:o.event.summary,summaryTime:o.event.summaryTime,tags:o.event.tags,timeline:o.timeline.toJSON(),observerTrack:Xn.restatedObserverTrack(o),weatherTrack:o.weatherTrack.toJSON(),soundTrack:o.soundTrack.toJSON(),weather:o.weather,decor:Xn.restatedDecor(o),milestones:o.milestones.length>0?o.milestones:void 0,references:o.references.length>0?o.references:void 0,roads:o.roads.length>0?o.roads:void 0,traces:o.traces.length>0?o.traces:void 0,weatherSource:o.weatherSource,instrument:o.instrumentId,exposureSeconds:o.exposureSeconds,iso:o.iso,metering:o.metering,lens:o.lens,lightPollution:o.lightPollution,observerMap:o.observerMap,interpretation:Xn.restatedInterpretation(o),variants:o.variants.length>0?o.variants:void 0,skyEvents:gr.written(o.skyEvents),frozen:o.frozen}}function QS(o){po.check(o,"sighting");const{recording:t,provenance:e}=Kn.strip(o),i=tE(t);return i.provenance=e,i}function tE(o){const t=[],e=new Gf({eventType:"sighting",time:o.time,endTime:o.endTime,durationSeconds:o.durationSeconds,durationText:o.durationText,utcOffsetHours:o.utcOffsetHours,timeZone:o.timeZone,place:o.place,description:o.description,image:o.image,summary:o.summary,summaryTime:o.summaryTime,tags:o.tags},Uf.fromJSON(o.timeline,t),o.observerTrack?Cl.fromJSON(o.observerTrack):new Cl,o.weatherTrack?Ol.fromJSON(o.weatherTrack):new Ol,o.soundTrack?Pl.fromJSON(o.soundTrack):new Pl,o.observer&&{id:o.observer.id,title:o.observer.title,lastName:o.observer.lastName,firstNames:o.observer.firstNames},o.id,o.weather,(o.decor??[]).map(n=>{if(!n.facade?.plain)return n;const{plain:s,...r}=n.facade;return{...n,facade:{...r,openings:"plain"}}}),o.weatherSource,o.instrument,o.exposureSeconds??o.observerTrack?.keyframes.map(n=>n.pose.exposureSeconds).find(n=>n!==void 0),ul(o.milestones??[]),o.references??[],o.roads??[],o.traces??[]);e.account=o.account,e.sources=o.sources,e.sway=o.sway,e.iso=o.iso,e.metering=o.metering,e.lens=o.lens,e.lightPollution=o.lightPollution,e.observerMap=o.observerMap,e.vehicle=o.vehicle;const i=gr.read(o.skyEvents,o.interpretation);return e.interpretation=i.interpretation,e.variants=Array.isArray(o.variants)?o.variants:[],e.skyEvents=i.skyEvents,e.frozen=o.frozen,e.loadIssues=t,Ln.toBounds(e),Ln.toPosition(e),e}class vh{static EN={"unknown-key":"{path}: unknown key, ignored","wrong-type":"{path}: expected {expected}, found {found}","not-in-list":"{path}: {found} is not one of {expected}",defaulted:"{path}: missing, {expected} used",unplaced:"{path}: no aim (and no bounds), drawn at the middle of the view",unsized:"{path}: no angular size (and no bounds), drawn one pixel wide","pixels-over-angles":"{path}: bounds restated without aim or angular, so the shape follows the pixels"};static text(t,e=vh.EN){return e[t.kind].replace("{path}",t.path).replace("{expected}",t.expected??"").replace("{found}",t.found??"")}static warn(t,e){if(t.length===0)return;const i=t.map(n=>` ${vh.text(n)}`);console.warn(`UFO@home: ${t.length} problem(s) in ${e??"this recording"}:
|
|
2401
|
+
`;class eh{constructor(t){this.points=t}static STATIONARY_M=5;static of(t){const e=[];for(const i of t.observerTrack.allKeyframes){const{lat:n,lng:s,headingDeg:r}=i.pose;n===void 0||s===void 0||e.push({t:i.t,lat:n,lng:s,headingDeg:r})}if(e.length===0){const i=t.event.place?.[0];if(!i)return;e.push({t:0,lat:i.lat,lng:i.lng})}return new eh(e)}static TRAVEL_M=50;get travels(){return this.spanM>eh.TRAVEL_M}get moved(){return this.spanM>eh.STATIONARY_M}get spanM(){const t=this.box,e=(t.south+t.north)/2,i=(t.west+t.east)/2;return Math.max(Math.abs(oe(e,t.east,e,t.west).x),Math.abs(oe(t.north,i,t.south,i).z))}get center(){const t=this.box;return{lat:(t.south+t.north)/2,lng:(t.west+t.east)/2}}boundsAround(t,e){const{lat:i,lng:n}=this.center,s=Math.max(this.spanM*(1+e),t)/2;return{north:os(0,-s,i,n).lat,south:os(0,s,i,n).lat,east:os(s,0,i,n).lng,west:os(-s,0,i,n).lng}}get box(){const t=this.points.map(i=>i.lat),e=this.points.map(i=>i.lng);return{south:Math.min(...t),north:Math.max(...t),west:Math.min(...e),east:Math.max(...e)}}}class Ts{constructor(t,e){this.rotationPassed=t,this.scale=e}static SWAY_M=.012;static BREATH_M=.003;static DRIFT_YAW_DEG=.5;static DRIFT_PITCH_DEG=.4;static DRIFT_ROLL_DEG=.3;static GAZE_DRIFT_SHARE=.35;static HAND_HELD_S=.5;static HZ=[.11,.23,.17,.29,.37,.07];static of(t){if(t.instrument.mounted)return;const e=t.event.tags?.includes("paralysis")||(t.exposure??0)>Ts.HAND_HELD_S,i=t.sway??(e?0:1);if(i>0)return new Ts(Math.max(1-(t.instrument.stabilization??0),Ts.GAZE_DRIFT_SHARE),i)}offsetAt(t){const e=t/1e3,i=this.scale,n=(u,d)=>Math.sin(2*Math.PI*u*e+d),[s,r,a,c,h,l]=Ts.HZ;return{eastM:i*Ts.SWAY_M*(.7*n(s,.3)+.3*n(c,1.9)),northM:i*Ts.SWAY_M*(.6*n(a,2.2)+.4*n(h,.8)),upM:i*Ts.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*Ts.DRIFT_YAW_DEG*(.6*n(l,1.1)+.4*n(c,2.7)),pitchDeg:i*this.rotationPassed*Ts.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(a,.4)),rollDeg:i*this.rotationPassed*Ts.DRIFT_ROLL_DEG*n(s,2.9)}}}class qe{constructor(t,e){this.stretches=t,this.rotationPassed=e}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static STOP_LURCH_M=.035;static STOP_PITCH_DEG=3;static START_LURCH_M=.015;static START_PITCH_DEG=1.2;static JOLT_HZ=1.4;static JOLT_DECAY_S=.35;static JOLT_LASTS_MS=1500;static STILL=Object.freeze({eastM:0,northM:0,upM:0,rollDeg:0,pitchDeg:0,yawDeg:0});static of(t){const e=eh.of(t);if(!e||e.points.length<2)return;const i=[];let n=0;for(let s=1;s<e.points.length;s++){const r=e.points[s-1],a=e.points[s],c=(a.t-r.t)/1e3;if(c<=0)continue;const h=oe(a.lat,a.lng,r.lat,r.lng),l=h.x,u=-h.z,d=Math.hypot(l,u),f=d/c,p=qe.stepHzFor(f);i.push({startMs:r.t,endMs:a.t,speedMPerS:f,eastUnit:d>0?l/d:0,northUnit:d>0?u/d:0,stepHz:p,stepsBefore:n,rampsIn:!0,rampsOut:!0}),n+=p*c}for(let s=0;s<i.length;s++){const r=i[s-1],a=i[s+1];i[s].rampsIn=r===void 0||r.stepHz===0,i[s].rampsOut=a===void 0||a.stepHz===0}if(i.some(s=>s.stepHz>0))return new qe(i,1-(t.instrument.stabilization??0))}static bodyAt(t,e,i=!1){const n=qe.of(t)?.offsetAt(e)??qe.STILL;return i?n:qe.add(n,Ts.of(t)?.offsetAt(e))}static stepHzFor(t){return t<qe.SLOWEST_WALK_M_PER_S||t>qe.FASTEST_WALK_M_PER_S?0:qe.REFERENCE_STEP_HZ*Math.pow(t/qe.REFERENCE_SPEED_M_PER_S,qe.CADENCE_EXPONENT)}offsetAt(t){return qe.add(this.cycleAt(t),this.joltAt(t))}joltAt(t){for(const e of this.stretches){if(e.stepHz===0)continue;const i=e.speedMPerS/qe.REFERENCE_SPEED_M_PER_S,n=(a,c,h,l)=>{if(a<0||a>qe.JOLT_LASTS_MS)return;const u=a/1e3,d=Math.exp(-u/qe.JOLT_DECAY_S)*Math.sin(2*Math.PI*qe.JOLT_HZ*u),f=l*c*i*d;return{eastM:f*e.eastUnit,northM:f*e.northUnit,upM:-Math.abs(f)*.3,rollDeg:0,pitchDeg:-l*h*i*d*this.rotationPassed,yawDeg:0}},s=e.rampsOut?n(t-e.endMs,qe.STOP_LURCH_M,qe.STOP_PITCH_DEG,1):void 0;if(s)return s;const r=e.rampsIn?n(t-e.startMs,qe.START_LURCH_M,qe.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(t,e){return e?{eastM:t.eastM+e.eastM,northM:t.northM+e.northM,upM:t.upM+e.upM,rollDeg:t.rollDeg+e.rollDeg,pitchDeg:t.pitchDeg+e.pitchDeg,yawDeg:t.yawDeg+e.yawDeg}:t}cycleAt(t){const e=this.stretches.find(c=>t>=c.startMs&&t<=c.endMs);if(!e||e.stepHz===0)return qe.STILL;const i=e.stepsBefore+e.stepHz*(t-e.startMs)/1e3,n=2*Math.PI*i,s=this.amplitudeAt(e,t),r=qe.SWAY_M*s*Math.cos(n/2),a=s*this.rotationPassed*e.speedMPerS/qe.REFERENCE_SPEED_M_PER_S;return{eastM:r*e.northUnit,northM:-r*e.eastUnit,upM:qe.RISE_M_PER_M_PER_S*e.speedMPerS*s*Math.cos(n),rollDeg:qe.HEAD_ROLL_DEG*a*Math.cos(n/2),pitchDeg:-1.25*a*Math.cos(n),yawDeg:qe.HEAD_YAW_DEG*a*Math.cos(n/2)}}amplitudeAt(t,e){const i=1e3/t.stepHz,n=Math.min(i,(t.endMs-t.startMs)/2);if(n<=0)return 1;const s=e-t.startMs,r=t.endMs-e,a=Math.min(t.rampsIn?s/n:1,t.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class VS{constructor(t,e){this.timeline=t,this.onFrame=e}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const t=()=>{if(this.state!=="playing")return;const e=performance.now();if(this.currentT+=(e-this.lastWallTime)*this.playbackRate,this.lastWallTime=e,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(t)};this.rafId=requestAnimationFrame(t)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(t){this.currentT=Math.max(0,Math.min(t,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(t){const e=new Map;for(const i of this.timeline.sourceIds){const n=this.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}this.onFrame(t,e)}}const F2=["nw","n","ne","e","se","s","sw","w"],WS=24,ru=8,XS=3,$S=8;function au(o,t,e){const i=o.x-t.x,n=o.y-t.y,s=Math.cos(e),r=Math.sin(e);return{x:t.x+i*s-n*r,y:t.y+i*r+n*s}}function Ph(o){return{x:o.x+o.width/2,y:o.y+o.height/2}}const YS={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 ys{static handlePointsFor(t){const{x:e,y:i,width:n,height:s}=t.bounds,r={nw:{x:e,y:i},n:{x:e+n/2,y:i},ne:{x:e+n,y:i},e:{x:e+n,y:i+s/2},se:{x:e+n,y:i+s},s:{x:e+n/2,y:i+s},sw:{x:e,y:i+s},w:{x:e,y:i+s/2},rotate:{x:e+n/2,y:i-WS}},a=Ph(t.bounds),c={};for(const h of Object.keys(r))c[h]=au(r[h],a,t.angle);return c}static hitTestHandle(t,e,i=8,n=[...F2,"rotate"]){const s=ys.handlePointsFor(t);for(const r of n)if(Math.hypot(e.x-s[r].x,e.y-s[r].y)<=i)return r}static HANDLE_DIRECTION_DEG={e:0,se:45,s:90,sw:135,w:180,nw:225,n:270,ne:315};static resizeAxisFor(t,e){const n=((ys.HANDLE_DIRECTION_DEG[t]+e*180/Math.PI)%180+180)%180/45,s=["ew","nwse","ns","nesw"];return s[Math.round(n)%s.length]}static resizeBounds(t,e,i,n){const s=Ph(t),r=au(n,s,-e),{x:a,y:c,width:h,height:l}=t,u=YS[i];let d=a,f=c,p=a+h,g=c+l;return u.left&&(d=Math.min(r.x,p-ru)),u.right&&(p=Math.max(r.x,d+ru)),u.top&&(f=Math.min(r.y,g-ru)),u.bottom&&(g=Math.max(r.y,f+ru)),{x:d,y:f,width:p-d,height:g-f}}static resizeShape(t,e,i){if(e==="rotate")throw new Error("resizeShape does not accept the rotate handle");const{width:n,height:s}=t.bounds,r=ys.resizeBounds(t.bounds,t.angle,e,i);if(t.kind==="oval")return{...t,bounds:r};const a=n===0?1:r.width/n,c=s===0?1:r.height/s;return{...t,bounds:r,points:t.points.map(h=>({x:h.x*a,y:h.y*c}))}}static rotateShape(t,e){const i=Ph(t.bounds),n=Math.atan2(e.y-i.y,e.x-i.x)+Math.PI/2;return{...t,angle:n}}static groupBoundsFor(t){const e=Math.min(...t.map(r=>r.x)),i=Math.min(...t.map(r=>r.y)),n=Math.max(...t.map(r=>r.x+r.width)),s=Math.max(...t.map(r=>r.y+r.height));return{x:e,y:i,width:n-e,height:s-i}}static vertexPointsFor(t){const e=Ph(t.bounds);return t.points.map(i=>au({x:t.bounds.x+i.x,y:t.bounds.y+i.y},e,t.angle))}static hitTestVertex(t,e,i=$S){const n=ys.vertexPointsFor(t);let s,r=i;return n.forEach((a,c)=>{const h=Math.hypot(e.x-a.x,e.y-a.y);h<=r&&(r=h,s=c)}),s}static toLocalPoint(t,e){const i=Ph(t.bounds),n=au(e,i,-t.angle);return{x:n.x-t.bounds.x,y:n.y-t.bounds.y}}static moveVertex(t,e,i){const n=t.points.map((u,d)=>d===e?ys.toLocalPoint(t,i):u),s=Math.min(...n.map(u=>u.x)),r=Math.min(...n.map(u=>u.y)),a=Math.max(...n.map(u=>u.x)),c=Math.max(...n.map(u=>u.y)),h={x:t.bounds.x+s,y:t.bounds.y+r,width:a-s,height:c-r},l=n.map(u=>({x:u.x-s,y:u.y-r}));return{...t,bounds:h,points:l}}static insertVertexNear(t,e){const i=ys.toLocalPoint(t,e),{points:n}=t;let s=n.length-1,r=1/0;for(let c=0;c<n.length;c++){const h=n[c],l=n[(c+1)%n.length],u=ys.distanceToSegment(i,h,l);u<r&&(r=u,s=c)}const a=[...n.slice(0,s+1),i,...n.slice(s+1)];return{...t,points:a}}static distanceToSegment(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=n*n+s*s,a=r===0?0:Math.max(0,Math.min(1,((t.x-e.x)*n+(t.y-e.y)*s)/r)),c=e.x+a*n,h=e.y+a*s;return Math.hypot(t.x-c,t.y-h)}static deleteVertex(t,e){return t.points.length<=XS?t:{...t,points:t.points.filter((i,n)=>n!==e)}}}const Yp=6,ou=Yp/2,ov=20,cv=24,hv=9,lv=6,uv=7,dv=6,or=4;class gh{constructor(t){this.ctx=t}starPoints=0;roll=0;clear(t,e){this.ctx.clearRect(0,0,t,e)}static paintExtent(t){const{x:e,y:i,width:n,height:s}=t.bounds,r=e+n/2,a=i+s/2,c=t.angle%(2*Math.PI)!==0,h=Math.hypot(n,s)/2,l=c?h:n/2,u=c?h:s/2,d=Math.max(n,s)/2,f=t.brightness??0,p=f>0?Math.max(d*(1+hv*f),dv*f)-d:0,g=f>0?d*(1+uv*f)-d:0,m=3*cv*(t.blur??0)+1.5*ov*t.haloScale,v=Math.max(p,g,0)+m+2;return{x:r-l-v,y:a-u-v,width:2*(l+v),height:2*(u+v)}}paintInto(t,e,i,n=!1){this.ctx.save(),this.ctx.scale(i,i),this.ctx.translate(-e.x,-e.y);const s=t.selected?{...t,selected:!1}:t;n?this.paintGhost(s,1.5):this.paintShape(s),this.ctx.restore()}paintShape(t){this.ctx.save(),this.ctx.globalAlpha=1-t.transparency;const e=t.blur??0;e>0&&(this.ctx.filter=`blur(${(cv*e).toFixed(2)}px)`);const i=t.brightness??0;i>0&&this.paintDazzle(t,i),t.haloScale>0&&this.paintHalo(t),this.paintBase(t),this.ctx.restore(),t.selected&&this.paintSelectionHandles(t)}setStarPoints(t){this.starPoints=Math.max(0,Math.floor(t))}setRoll(t){this.roll=t}paintDazzle(t,e){const{x:i,y:n,width:s,height:r}=t.bounds,a=i+s/2,c=n+r/2,h=Math.max(s,r)/2,l=Math.max(h*(1+hv*e),dv*e);if(l<=0)return;this.ctx.save(),this.ctx.globalCompositeOperation="lighter";const u=this.ctx.createRadialGradient(a,c,0,a,c,l);for(let d=0;d<=lv;d++){const f=d/lv,p=1/(1+24*f*f);this.ctx.globalAlpha=1,u.addColorStop(f,this.withAlpha(t.color,p*e*.55))}if(this.ctx.fillStyle=u,this.ctx.beginPath(),this.ctx.arc(a,c,l,0,2*Math.PI),this.ctx.fill(),this.starPoints>0){const d=h*(1+uv*e);this.ctx.lineWidth=Math.max(1,h*.12),this.ctx.lineCap="round";for(let f=0;f<this.starPoints;f++){const p=f/this.starPoints*Math.PI*2+this.roll,g=a+Math.cos(p)*d,m=c+Math.sin(p)*d,v=this.ctx.createLinearGradient(a,c,g,m);v.addColorStop(0,this.withAlpha(t.color,e*.55)),v.addColorStop(.35,this.withAlpha(t.color,e*.22)),v.addColorStop(1,this.withAlpha(t.color,0)),this.ctx.strokeStyle=v,this.ctx.beginPath(),this.ctx.moveTo(a,c),this.ctx.lineTo(g,m),this.ctx.stroke()}}this.ctx.restore()}dazzledFill(t,e){if(e<=0)return t.color;const i=/^#([0-9a-f]{6})$/i.exec(t.color.trim());if(!i)return t.color;const n=Number.parseInt(i[1],16),s=r=>Math.round(r+(255-r)*e);return`rgb(${s(n>>16&255)}, ${s(n>>8&255)}, ${s(n&255)})`}withAlpha(t,e){const i=Math.max(0,Math.min(1,e)),n=/^#([0-9a-f]{6})$/i.exec(t.trim());if(!n)return t;const s=Number.parseInt(n[1],16);return`rgba(${s>>16&255}, ${s>>8&255}, ${s&255}, ${i.toFixed(3)})`}paintBase(t){this.ctx.fillStyle=this.dazzledFill(t,t.brightness??0),this.tracePath(t),this.ctx.fill()}paintGhost(t,e){this.ctx.save(),this.tracePath(t),this.ctx.setLineDash([e*3,e*2]),this.ctx.lineWidth=e,this.ctx.strokeStyle=t.color,this.ctx.stroke(),this.ctx.restore()}tracePath(t){if(this.ctx.beginPath(),t.kind==="oval"){const{x:e,y:i,width:n,height:s}=t.bounds,r=n/2,a=s/2;this.ctx.ellipse(e+r,i+a,r,a,t.angle,0,2*Math.PI)}else{const{x:e,y:i,width:n,height:s}=t.bounds;this.ctx.save(),this.ctx.translate(e+n/2,i+s/2),this.ctx.rotate(t.angle),this.ctx.translate(-n/2,-s/2),t.points.forEach((r,a)=>{a===0?this.ctx.moveTo(r.x,r.y):this.ctx.lineTo(r.x,r.y)}),this.ctx.closePath(),this.ctx.restore()}}paintHalo(t){this.ctx.save(),this.ctx.shadowColor=t.color,this.ctx.shadowBlur=ov*t.haloScale,this.paintBase(t),this.ctx.restore()}paintSelectionHandles(t){this.paintHandleFrame(ys.handlePointsFor(t),{includeRotate:!0}),t.kind==="polygon"&&this.paintVertexHandles(t)}paintVertexHandles(t){this.ctx.fillStyle="#39f";for(const e of ys.vertexPointsFor(t))this.ctx.beginPath(),this.ctx.ellipse(e.x,e.y,or,or,0,0,2*Math.PI),this.ctx.fill()}paintMemberOutline(t){this.paintOutline(ys.handlePointsFor(t))}paintSelectionOnly(t){this.paintSelectionHandles(t)}paintPictureFrame(t,e,i){const n=this.ctx;if(n.save(),t&&t.length===4){n.strokeStyle="#39f",n.lineWidth=1.5,n.setLineDash([6,4]),n.beginPath(),n.moveTo(t[0].x,t[0].y);for(const s of t.slice(1))n.lineTo(s.x,s.y);n.closePath(),n.stroke(),n.setLineDash([])}for(const s of e){const r=gh.landmarkColour(s.residualDeg),a=s.selected?3:2;s.selected&&(n.strokeStyle="#fff",n.lineWidth=a+3,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,or+2,or+2,0,0,2*Math.PI),n.stroke()),s.scene&&(n.strokeStyle=r,n.lineWidth=1,n.beginPath(),n.moveTo(s.picture.x,s.picture.y),n.lineTo(s.scene.x,s.scene.y),n.stroke(),n.fillStyle=r,n.beginPath(),n.ellipse(s.scene.x,s.scene.y,or,or,0,0,2*Math.PI),n.fill()),n.strokeStyle=r,n.lineWidth=a,n.beginPath(),n.ellipse(s.picture.x,s.picture.y,or+2,or+2,0,0,2*Math.PI),n.stroke(),this.paintLabel(s.label,s.picture.x+or+5,s.picture.y-or-2,r)}i&&this.paintLabel(i,8,8,"#fff",13),n.restore()}paintGhosts(t,e,i){const n=this.ctx;n.save();const s=(c,h,l,u=[])=>{n.setLineDash(u),n.lineWidth=l+2,n.strokeStyle="rgba(0, 0, 0, 0.6)",c(),n.lineWidth=l,n.strokeStyle=h,c(),n.setLineDash([])},r=(c,h)=>()=>{n.beginPath(),n.arc(c.x,c.y,h,0,2*Math.PI),n.stroke()},a=(c,h,l)=>()=>{const[u,d]=l?[h,h]:[h,0];n.beginPath(),n.moveTo(c.x-u,c.y-d),n.lineTo(c.x+u,c.y+d),n.moveTo(c.x+d,c.y-u),n.lineTo(c.x-d,c.y+u),n.stroke()};for(const c of t)s(()=>{n.beginPath(),n.moveTo(c.ghost.x,c.ghost.y),n.lineTo(c.light.x,c.light.y),n.stroke()},"rgba(255, 255, 255, 0.85)",1,[4,4]),s(r(c.light,7),"#ffffff",1.5),s(r(c.ghost,Math.max(9,c.ghostRadius)),"#ffd23f",2);e&&s(a(e,8,!1),"#ffd23f",2),i&&s(a(i,5,!0),"rgba(255, 255, 255, 0.7)",1),n.restore()}static landmarkColour(t){return t===void 0?"#ffb000":t<=1?"#3c3":t<=3?"#ffb000":"#f33"}paintLabel(t,e,i,n,s=11){const r=this.ctx;r.save(),r.font=`${s}px system-ui, sans-serif`,r.textBaseline="top";const a=r.measureText(t).width;r.fillStyle="rgba(0, 0, 0, 0.6)",r.fillRect(e-3,i-2,a+6,s+4),r.fillStyle=n,r.fillText(t,e,i),r.restore()}paintGroupHandles(t){this.paintHandleFrame(ys.handlePointsFor({bounds:t,angle:0}),{includeRotate:!0})}paintOutline(t){this.ctx.strokeStyle="lightgray",this.ctx.beginPath(),this.ctx.moveTo(t.nw.x,t.nw.y),this.ctx.lineTo(t.ne.x,t.ne.y),this.ctx.lineTo(t.se.x,t.se.y),this.ctx.lineTo(t.sw.x,t.sw.y),this.ctx.closePath(),this.ctx.stroke()}paintHandleFrame(t,{includeRotate:e}){this.paintOutline(t),this.ctx.fillStyle="lightgray";for(const i of F2){const n=t[i];this.ctx.fillRect(n.x-ou,n.y-ou,Yp,Yp)}e&&(this.ctx.beginPath(),this.ctx.moveTo(t.n.x,t.n.y),this.ctx.lineTo(t.rotate.x,t.rotate.y),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.ellipse(t.rotate.x,t.rotate.y,ou+1,ou+1,0,0,2*Math.PI),this.ctx.fill())}}const fv=.05,pv=.08,mv=2,gv=3,KS=14,qS=.02;class ZS{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(t){return this.master||(this.master=t.createGain(),this.master.gain.value=this.level,this.master.connect(t.destination)),this.master}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",t);return}}Uo.unlock(this.context)}setSound(t){if(this.requested=t,!this.context)return;const e=this.keyFor(t);if(!e){this.silence();return}if(this.voice?.key!==e){this.stopVoice();const i=++this.voiceToken;e.startsWith("src:")?this.buildRecordedVoice(t.src,e,i):this.voice=this.buildSynthesizedVoice(t,e)}this.applyTo(this.voice,t)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(t){if(!(t.volume<=0))return t.src?`src:${t.src}`:t.kind==="none"?void 0:t.kind}applyTo(t,e){const i=this.context;if(!t||!i)return;const n=i.currentTime;t.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,e.volume))*t.gainScale,n,fv);for(const{param:s,ratio:r}of t.pitch)s.setTargetAtTime(Math.min(e.pitchHz*r,i.sampleRate/2-1),n,fv)}buildSynthesizedVoice(t,e){const i=this.context;if(i)switch(t.kind){case"hum":return this.buildHum(i,e);case"whistle":return this.buildWhistle(i,e);case"rumble":return this.buildRumble(i,e);case"crackle":return this.buildCrackle(i,e);default:return}}buildHum(t,e){const i=t.createOscillator();i.type="sawtooth";const n=t.createOscillator();n.type="sawtooth";const s=t.createBiquadFilter();s.type="lowpass",s.Q.value=1;const r=t.createGain();return r.gain.value=0,i.connect(s),n.connect(s),s.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.16,pitch:[{param:i.frequency,ratio:1},{param:n.frequency,ratio:1.006},{param:s.frequency,ratio:6}]}}buildWhistle(t,e){const i=t.createOscillator();i.type="sine";const n=t.createOscillator();n.type="sine",n.frequency.value=5;const s=t.createGain(),r=t.createGain();return r.gain.value=0,n.connect(s).connect(i.frequency),i.connect(r).connect(this.output(t)),i.start(),n.start(),{key:e,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:s.gain,ratio:.012}]}}buildRumble(t,e){const i=t.createBufferSource();i.buffer=this.brownNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="lowpass",n.Q.value=.8;const s=t.createGain();return s.gain.value=0,i.connect(n).connect(s).connect(this.output(t)),i.start(),{key:e,nodes:[n,s],sources:[i],volumeParam:s.gain,gainScale:1.4,pitch:[{param:n.frequency,ratio:1}]}}buildCrackle(t,e){const i=t.createBufferSource();i.buffer=this.whiteNoise(t),i.loop=!0;const n=t.createBiquadFilter();n.type="bandpass",n.Q.value=1.2;const s=t.createGain();s.gain.value=0;const r=t.createBufferSource();r.buffer=this.crackleEnvelope(t),r.loop=!0;const a=t.createGain();return a.gain.value=0,r.connect(a).connect(s.gain),i.connect(n).connect(s).connect(this.output(t)),i.start(),r.start(),{key:e,nodes:[n,s,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:n.frequency,ratio:4}]}}async buildRecordedVoice(t,e,i){const n=this.context;if(!n)return;let s;try{s=await this.getBuffer(t)}catch(c){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",c);return}if(i!==this.voiceToken||!this.context)return;const r=n.createBufferSource();r.buffer=s,r.loop=!0;const a=n.createGain();a.gain.value=0,r.connect(a).connect(this.output(n)),r.start(),this.voice={key:e,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(t){const e=this.context;if(!e)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(t);return i||(i=fetch(t).then(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${t}`);return n.arrayBuffer()}).then(n=>e.decodeAudioData(n)),this.buffers.set(t,i)),i}whiteNoise(t){if(!this.noiseBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*mv),t.sampleRate),i=e.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;this.noiseBuffer=e}return this.noiseBuffer}brownNoise(t){const e=t.createBuffer(1,Math.floor(t.sampleRate*mv),t.sampleRate),i=e.getChannelData(0);let n=0,s=0;for(let r=0;r<i.length;r++)n=(n+.02*(Math.random()*2-1))/1.02,i[r]=n,s=Math.max(s,Math.abs(n));if(s>0)for(let r=0;r<i.length;r++)i[r]/=s;return e}crackleEnvelope(t){if(!this.crackleBuffer){const e=t.createBuffer(1,Math.floor(t.sampleRate*gv),t.sampleRate),i=e.getChannelData(0),n=Math.max(1,Math.floor(qS*t.sampleRate)),s=Math.round(gv*KS);for(let r=0;r<s;r++){const a=Math.floor(Math.random()*i.length),c=.4+Math.random()*.6;for(let h=0;h<n&&a+h<i.length;h++)i[a+h]=Math.max(i[a+h],c*(1-h/n))}this.crackleBuffer=e}return this.crackleBuffer}stopVoice(){const t=this.voice,e=this.context;if(this.voice=void 0,!t||!e)return;const i=e.currentTime;t.volumeParam.cancelScheduledValues(i),t.volumeParam.setTargetAtTime(0,i,pv/3);const n=i+pv;for(const s of t.sources){s.onended=()=>{s.disconnect();for(const r of t.nodes)r.disconnect()};try{s.stop(n)}catch{s.disconnect();for(const r of t.nodes)r.disconnect()}}}}class gr{static KINDS=["beams","launches","reentries"];static isEmpty(t){return!t||gr.KINDS.every(e=>!t[e]?.length)}static written(t){if(gr.isEmpty(t))return;const e={};for(const i of gr.KINDS)t[i]?.length&&(e[i]=t[i]);return e}static read(t,e){const i=e,n={};for(const r of gr.KINDS){const a=[...t?.[r]??[],...i?.[r]??[]];a.length>0&&(n[r]=a)}let s=e;if(i&&gr.KINDS.some(r=>r in i)){const{beams:r,launches:a,reentries:c,...h}=i;s=gr.isReading(h)?h:void 0}return{skyEvents:gr.written(n),interpretation:s}}static isReading(t){return(t.bodies?.length??0)>0||t.title!==void 0||(t.smoke?.length??0)>0}}function ul(o){return[...o].sort((t,e)=>t.t-e.t)}function l0(o,t){let e;for(const i of ul(o)){if(i.t>t)break;e=i}return e}const u0=Math.PI/180,cu=180/Math.PI;class Ir{constructor(t,e,i){this.kind=t,this.canvasHeightPx=e,this.fovDeg=i;const n=i*u0/2;this.focalPx=t==="equidistant"?e/2/n:e/2/Math.tan(n)}focalPx;static of(t,e,i){return new Ir(t.projection,e,i)}degToPx(t){const e=t*u0;return this.kind==="equidistant"?this.focalPx*e:2*this.focalPx*Math.tan(e/2)}pxToDeg(t){return this.kind==="equidistant"?t/this.focalPx*cu:2*Math.atan(t/(2*this.focalPx))*cu}angleDegToRadiusPx(t){const e=t*u0;return this.kind==="equidistant"?this.focalPx*e:this.focalPx*Math.tan(e)}halfWidthAngleDeg(t){return this.radiusPxToAngleDeg(this.canvasHeightPx*t/2)}radiusPxToAngleDeg(t){return this.kind==="equidistant"?t/this.focalPx*cu:Math.atan(t/this.focalPx)*cu}ofBounds(t){return{widthDeg:this.pxToDeg(t.width),heightDeg:this.pxToDeg(t.height)}}toBoundsSize(t){return{width:this.degToPx(t.widthDeg),height:this.degToPx(t.heightDeg)}}widthPx(t){return this.degToPx(Qe.angularWidthDeg(t))}}class Ln{static fovOf(t,e){return ze(t,e)?.fovDeg??Ti.fieldOfViewDeg(t.instrument)}static toAngular(t){this.eachKeyframe(t,(e,i)=>{const n=i.ofBounds(e.bounds);return e.angular?.widthDeg===n.widthDeg&&e.angular.heightDeg===n.heightDeg?e:{...e,angular:n}})}static toBounds(t){this.eachKeyframe(t,(e,i)=>this.sizedFromAngle(e,i))}static sizedFromAngle(t,e){if(!t.angular)return t;const{width:i,height:n}=e.toBoundsSize(t.angular),s={x:t.bounds.x+(t.bounds.width-i)/2,y:t.bounds.y+(t.bounds.height-n)/2,width:i,height:n};if(t.kind!=="polygon")return{...t,bounds:s};const r=t.bounds.width===0?1:i/t.bounds.width,a=t.bounds.height===0?1:n/t.bounds.height;return{...t,bounds:s,points:t.points.map(c=>({x:c.x*r,y:c.y*a}))}}static toAim(t){this.eachKeyframe(t,(e,i,n)=>{const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);if(s&&Math.abs(s.x-e.bounds.x)<Ln.UNMOVED_PX&&Math.abs(s.y-e.bounds.y)<Ln.UNMOVED_PX)return e;const r=this.aimFrom(t,i,n,e.bounds);return r?{...e,aim:r}:e})}static UNMOVED_PX=.01;static aimOf(t,e,i){const n=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,this.fovOf(t,e));return this.aimFrom(t,n,ze(t,e),i)}static aimFrom(t,e,i,n){if(i?.headingDeg===void 0)return;const s=this.frameCentre(t),r=e.radiusPxToAngleDeg(n.x+n.width/2-s.x),a=e.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(t){this.eachKeyframe(t,(e,i,n)=>this.placedByAim(t,e,i,n))}static placedByAim(t,e,i,n){const s=e.aim&&this.positionOf(t,e.aim,e.bounds,i,n);return s?{...e,bounds:{...e.bounds,...s}}:e}static derivable(t){const e=new Set,i=new Map,n=new Map;return t.timeline.allKeyframes.forEach((s,r)=>{const a=ze(t,s.t),c=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,this.fovOf(t,s.t));for(const{sourceId:h,shape:l}of s.shapes){const u=n.get(h),d=i.get(h);if(n.set(h,l),!u||!d){i.set(h,l);continue}const f=Object.fromEntries(Object.entries(l).filter(([m,v])=>m!=="bounds"&&m!=="points"&&JSON.stringify(v)!==JSON.stringify(u[m]))),p={...d,...f},g=this.placedByAim(t,this.sizedFromAngle(p,c),c,a);Ln.near(g,l)?(e.add(`${r}:${h}`),i.set(h,p)):i.set(h,l)}}),(s,r)=>e.has(`${s}:${r}`)}static SAME_PX=1e-6;static near(t,e){const i=(r,a)=>Math.abs(r-a)<=Ln.SAME_PX*Math.max(1,Math.abs(a)),n=t.bounds,s=e.bounds;return!i(n.x,s.x)||!i(n.y,s.y)||!i(n.width,s.width)||!i(n.height,s.height)?!1:e.kind!=="polygon"||t.kind!=="polygon"?!0:t.points.length===e.points.length&&t.points.every((r,a)=>i(r.x,e.points[a].x)&&i(r.y,e.points[a].y))}static positionOf(t,e,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(t),a=this.shortestArc(e.azimuthDeg-s.headingDeg),c=e.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,a)-i.width/2,y:r.y-this.offAxisPx(n,c)-i.height/2}}static frameCentre(t){return{x:Ti.frameWidthPx(t.instrument,Qe.CANVAS_HEIGHT_PX)/2,y:Qe.CANVAS_HEIGHT_PX/2}}static shortestArc(t){return(t%360+540)%360-180}static offAxisPx(t,e){return Math.abs(e)>=Ln.OFF_CANVAS_DEG?Math.sign(e)*Ln.OFF_CANVAS_PX:t.angleDegToRadiusPx(e)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(t,e,i){const n=Ti.frameWidthPx(e,Qe.CANVAS_HEIGHT_PX)/2,s=Ti.frameWidthPx(t.instrument,Qe.CANVAS_HEIGHT_PX)/2,r=Qe.CANVAS_HEIGHT_PX/2;for(const a of[...t.timeline.allKeyframes]){const c=this.fovOf(t,a.t),h=i?.get(a.t)??c,l=Ir.of(e,Qe.CANVAS_HEIGHT_PX,h),u=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,c);t.timeline.addKeyframe(a.t,a.shapes.map(d=>{const{bounds:f}=d.shape,p=f.x+f.width/2-n,g=f.y+f.height/2-r,m=Math.hypot(p,g),v=m===0?1:u.angleDegToRadiusPx(l.radiusPxToAngleDeg(m))/m,y={...f,x:s+p*v-f.width/2,y:r+g*v-f.height/2};return{...d,shape:{...d.shape,bounds:y}}}))}this.toBounds(t)}static eachKeyframe(t,e){const{timeline:i}=t;for(const n of[...i.allKeyframes]){const s=ze(t,n.t),r=this.fovOf(t,n.t),a=Ir.of(t.instrument,Qe.CANVAS_HEIGHT_PX,r);let c=!1;const h=n.shapes.map(l=>{const u=e(l.shape,a,s);return u===l.shape?l:(c=!0,{...l,shape:u})});c&&i.addKeyframe(n.t,h)}}}class Vn{static isRelative(t){return t!==void 0&&typeof t.eastM=="number"&&typeof t.northM=="number"}static isAbsolute(t){return t!==void 0&&typeof t.lat=="number"&&typeof t.lng=="number"}static referenceOf(t,e){return e.references.find(i=>(i.id??void 0)===(t.relativeTo??void 0))}static resolve(t,e){if(Vn.isRelative(t)){const i=Vn.referenceOf(t,e);return i?{eastM:i.eastM+t.eastM,northM:i.northM+t.northM}:void 0}return Vn.isAbsolute(t)&&e.origin?Vn.toLocal(t,e.origin):void 0}static restated(t,e,i){if(Vn.isRelative(t)){const s=Vn.referenceOf(t,i);return s?Vn.relative(e.eastM-s.eastM,e.northM-s.northM,t.relativeTo):void 0}if(!i.origin)return t;const n=Vn.toGeo(e,i.origin);return{lat:Vn.degrees(n.lat),lng:Vn.degrees(n.lng)}}static relative(t,e,i){const n={eastM:Vn.metres(t),northM:Vn.metres(e)};return i!==void 0&&(n.relativeTo=i),n}static toLocal(t,e){const i=oe(t.lat,t.lng,e.lat,e.lng);return{eastM:i.x,northM:-i.z}}static toGeo(t,e){return os(t.eastM,-t.northM,e.lat,e.lng)}static metres(t){return Math.round(t*100)/100}static degrees(t){return Math.round(t*1e7)/1e7}}class Xn{static restatedDecor(t){const e=Xn.originOf(t);return t.decor.map(i=>{let n=i;if(i.saidPosition){const s=Xn.restated(i.saidPosition,i,Xn.frameAt(t,0,e,i.id));JSON.stringify(s)!==JSON.stringify(i.saidPosition)&&(n={...i,saidPosition:s},s||delete n.saidPosition)}if(i.track?.some(s=>s.saidPosition)){const s=i.track.map(r=>{if(!r.saidPosition)return r;const a=Xn.restated(r.saidPosition,r,Xn.frameAt(t,r.t,e,i.id));if(JSON.stringify(a)===JSON.stringify(r.saidPosition))return r;const c={...r,saidPosition:a};return a||delete c.saidPosition,c});n={...n,track:s}}return n})}static restatedObserverTrack(t){const e=t.observerTrack.toJSON(),i=Xn.originOf(t);return!i||!e.keyframes.some(n=>n.pose.saidPosition)?e:{...e,keyframes:e.keyframes.map(n=>{const{pose:s}=n;if(!s.saidPosition||s.lat===void 0||s.lng===void 0)return n;const r=Vn.toLocal({lat:s.lat,lng:s.lng},i),a=Xn.restated(s.saidPosition,r,Xn.frameAt(t,n.t,i));if(JSON.stringify(a)===JSON.stringify(s.saidPosition))return n;const c={...s,saidPosition:a};return a||delete c.saidPosition,{...n,pose:c}})}}static restatedInterpretation(t){const e=t.interpretation;if(!e?.bodies.some(n=>n.track.some(s=>s.saidPosition)))return e;const i=Xn.originOf(t);return{...e,bodies:e.bodies.map(n=>n.track.some(s=>s.saidPosition)?{...n,track:n.track.map(s=>{if(!s.saidPosition)return s;const r=s.eastM!==void 0&&s.northM!==void 0?Xn.restated(s.saidPosition,{eastM:s.eastM,northM:s.northM},Xn.frameAt(t,s.t,i)):void 0;if(JSON.stringify(r)===JSON.stringify(s.saidPosition))return s;const a={...s,saidPosition:r};return r||delete a.saidPosition,a})}:n)}}static originOf(t){const e=t.observerTrack.getInterpolatedPoseAt(0),i=t.event.place?.[0],n=e?.lat??i?.lat,s=e?.lng??i?.lng;return typeof n=="number"&&typeof s=="number"?{lat:n,lng:s}:void 0}static frameAt(t,e,i,n){const s=[{label:"",eastM:0,northM:0},...t.decor.filter(r=>r.id!==n).map(r=>{const{eastM:a,northM:c}=tr(r,e);return{id:r.id,label:r.id,eastM:a,northM:c}})];return{origin:i,references:s}}static restated(t,e,i){return Vn.restated(t,{eastM:e.eastM,northM:e.northM},i)}}function JS(o){return Kn.restore(jS(o),o.provenance)}function jS(o){return Ln.toAngular(o),Ln.toAim(o),{version:1,id:o.id,time:o.event.time,endTime:o.event.endTime,durationSeconds:o.event.durationSeconds,durationText:o.event.durationText,utcOffsetHours:o.event.utcOffsetHours,timeZone:o.event.timeZone,place:o.event.place,observer:o.observer,account:o.account,sources:o.sources?.length?o.sources:void 0,sway:o.sway,vehicle:o.vehicle,description:o.event.description,image:o.event.image,summary:o.event.summary,summaryTime:o.event.summaryTime,tags:o.event.tags,timeline:o.timeline.toJSON(),observerTrack:Xn.restatedObserverTrack(o),weatherTrack:o.weatherTrack.toJSON(),soundTrack:o.soundTrack.toJSON(),weather:o.weather,decor:Xn.restatedDecor(o),milestones:o.milestones.length>0?o.milestones:void 0,references:o.references.length>0?o.references:void 0,roads:o.roads.length>0?o.roads:void 0,traces:o.traces.length>0?o.traces:void 0,weatherSource:o.weatherSource,instrument:o.instrumentId,exposureSeconds:o.exposureSeconds,iso:o.iso,metering:o.metering,lens:o.lens,lightPollution:o.lightPollution,observerMap:o.observerMap,interpretation:Xn.restatedInterpretation(o),variants:o.variants.length>0?o.variants:void 0,skyEvents:gr.written(o.skyEvents),frozen:o.frozen}}function QS(o){po.check(o,"sighting");const{recording:t,provenance:e}=Kn.strip(o),i=tE(t);return i.provenance=e,i}function tE(o){const t=[],e=new Gf({eventType:"sighting",time:o.time,endTime:o.endTime,durationSeconds:o.durationSeconds,durationText:o.durationText,utcOffsetHours:o.utcOffsetHours,timeZone:o.timeZone,place:o.place,description:o.description,image:o.image,summary:o.summary,summaryTime:o.summaryTime,tags:o.tags},Uf.fromJSON(o.timeline,t),o.observerTrack?Cl.fromJSON(o.observerTrack):new Cl,o.weatherTrack?Ol.fromJSON(o.weatherTrack):new Ol,o.soundTrack?Pl.fromJSON(o.soundTrack):new Pl,o.observer&&{id:o.observer.id,title:o.observer.title,lastName:o.observer.lastName,firstNames:o.observer.firstNames},o.id,o.weather,(o.decor??[]).map(n=>{if(!n.facade?.plain)return n;const{plain:s,...r}=n.facade;return{...n,facade:{...r,openings:"plain"}}}),o.weatherSource,o.instrument,o.exposureSeconds??o.observerTrack?.keyframes.map(n=>n.pose.exposureSeconds).find(n=>n!==void 0),ul(o.milestones??[]),o.references??[],o.roads??[],o.traces??[]);e.account=o.account,e.sources=o.sources,e.sway=o.sway,e.iso=o.iso,e.metering=o.metering,e.lens=o.lens,e.lightPollution=o.lightPollution,e.observerMap=o.observerMap,e.vehicle=o.vehicle;const i=gr.read(o.skyEvents,o.interpretation);return e.interpretation=i.interpretation,e.variants=Array.isArray(o.variants)?o.variants:[],e.skyEvents=i.skyEvents,e.frozen=o.frozen,e.loadIssues=t,Ln.toBounds(e),Ln.toPosition(e),e}class vh{static EN={"unknown-key":"{path}: unknown key, ignored","wrong-type":"{path}: expected {expected}, found {found}","not-in-list":"{path}: {found} is not one of {expected}",defaulted:"{path}: missing, {expected} used",unplaced:"{path}: no aim (and no bounds), drawn at the middle of the view",unsized:"{path}: no angular size (and no bounds), drawn one pixel wide","pixels-over-angles":"{path}: bounds restated without aim or angular, so the shape follows the pixels"};static text(t,e=vh.EN){return e[t.kind].replace("{path}",t.path).replace("{expected}",t.expected??"").replace("{found}",t.found??"")}static warn(t,e){if(t.length===0)return;const i=t.map(n=>` ${vh.text(n)}`);console.warn(`UFO@home: ${t.length} problem(s) in ${e??"this recording"}:
|
|
2402
2402
|
${i.join(`
|
|
2403
2403
|
`)}`)}}class Vs{constructor(t){this.format=t}issues(t){const e=[];return this.object(t,this.format,"",e),e}object(t,e,i,n){if(!Vs.isObject(t)){n.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:Vs.typeOf(t)});return}for(const[s,r]of Object.entries(t)){const a=i?`${i}.${s}`:s,c=e[s];c?this.field(r,c,a,n):n.push({kind:"unknown-key",path:a})}}field(t,e,i,n){if(Vs.isStated(t)){this.field(t.value,e,i,n);return}if(!(e.loose||t===void 0||t===null))switch(e.type){case"enum":(typeof t!="string"||!e.values?.includes(t))&&n.push({kind:"not-in-list",path:i,expected:(e.values??[]).map(s=>`"${s}"`).join(", "),found:JSON.stringify(t)});return;case"object":e.fields?this.object(t,e.fields,i,n):Vs.isObject(t)||n.push({kind:"wrong-type",path:i,expected:"object",found:Vs.typeOf(t)});return;case"array":Array.isArray(t)?e.fields&&t.forEach((s,r)=>{const a=Vs.isStated(s)?s.value:s;this.object(a,e.fields,`${i}.${r}`,n)}):n.push({kind:"wrong-type",path:i,expected:"array",found:Vs.typeOf(t)});return;default:typeof t!==e.type&&n.push({kind:"wrong-type",path:i,expected:e.type,found:Vs.typeOf(t)})}}static isObject(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}static isStated(t){return Vs.isObject(t)&&"value"in t&&Object.keys(t).every(e=>e==="value"||e==="basis"||e==="rationale")}static typeOf(t){return Array.isArray(t)?"array":t===null?"null":typeof t}}class qs{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(t,e){const i=Number.isFinite(e)?Math.max(0,e):0,n=Math.max(0,t-i*1e3),s=Math.max(0,t-n);return{fromMs:n,toMs:t,ms:s,seconds:s/1e3}}static instants(t,e,i,n,s){if(!(n>0))return 1;const r=s>0?qs.travelDegOver(t,e,i,i+n*1e3)/s/qs.PIXELS_PER_INSTANT:0,a=qs.flashesOver(t,n)*qs.INSTANTS_PER_FLASH,c=Math.ceil(Math.max(r,a));return c<2?1:Math.min(qs.MAX_INSTANTS,c)}static travelDegOver(t,e,i,n){let s=0;for(const r of t){if(!r.track||r.track.length<2)continue;const a=qs.directionAt(r,e,i),c=qs.directionAt(r,e,n),h=Math.min(1,Math.max(-1,a.x*c.x+a.y*c.y+a.z*c.z));s=Math.max(s,Math.acos(h)*180/Math.PI)}return s}static flashesOver(t,e){let i=0;for(const n of t)for(const s of n.lights??[])s.pattern.kind==="flash"&&(i=Math.max(i,s.pattern.perMinute));return i/60*e}static directionAt(t,e,i){const n=tr(t,i),s=n.eastM,r=n.altitudeM-e,a=n.northM,c=Math.hypot(s,r,a);return c===0?{x:0,y:1,z:0}:{x:s/c,y:r/c,z:a/c}}}const Rg=["en","fr","es","it"],eE={en:()=>Re(()=>Promise.resolve().then(()=>cE),void 0,import.meta.url).then(o=>o.ufoMessages_en),fr:()=>Re(()=>import("./UfoMessages_fr-Cs2GCHEt.js"),[],import.meta.url).then(o=>o.ufoMessages_fr),es:()=>Re(()=>import("./UfoMessages_es-BRCWkzr3.js"),[],import.meta.url).then(o=>o.ufoMessages_es),it:()=>Re(()=>import("./UfoMessages_it-B2hvjhgb.js"),[],import.meta.url).then(o=>o.ufoMessages_it)};function iE(o){return eE[o]()}const nE={en:()=>Re(()=>Promise.resolve().then(()=>YO),void 0,import.meta.url).then(o=>o.sightingMessages_en),fr:()=>Re(()=>import("./SightingMessages_fr-G2VuAfwH.js"),[],import.meta.url).then(o=>o.sightingMessages_fr),es:()=>Re(()=>import("./SightingMessages_es-CM9UNBab.js"),[],import.meta.url).then(o=>o.sightingMessages_es),it:()=>Re(()=>import("./SightingMessages_it-B66vxPfo.js"),[],import.meta.url).then(o=>o.sightingMessages_it)};function sE(o){return nE[o]()}const rE={en:()=>Re(()=>Promise.resolve().then(()=>KO),void 0,import.meta.url).then(o=>o.shareMessages_en),fr:()=>Re(()=>import("./ShareMessages_fr-DyOB2E5o.js"),[],import.meta.url).then(o=>o.shareMessages_fr),es:()=>Re(()=>import("./ShareMessages_es-BM5hHumO.js"),[],import.meta.url).then(o=>o.shareMessages_es),it:()=>Re(()=>import("./ShareMessages_it-C9F8UHk_.js"),[],import.meta.url).then(o=>o.shareMessages_it)};function aE(o){return rE[o]()}function oE(o){switch(o){case"fr":return Re(()=>import("./TagNames_fr-Dnqq6HQ5.js"),[],import.meta.url).then(t=>t.tagNames_fr);case"es":return Re(()=>import("./TagNames_es-BfnMpc3D.js"),[],import.meta.url).then(t=>t.tagNames_es);case"it":return Re(()=>import("./TagNames_it-n6E4EGYO.js"),[],import.meta.url).then(t=>t.tagNames_it);default:return Promise.resolve({})}}function z2(o){switch(o){case"fr":return Re(()=>import("./SceneNames_fr-CRYRL6bz.js"),[],import.meta.url).then(t=>t.sceneNames_fr);case"es":return Re(()=>import("./SceneNames_es-yKx3UAlW.js"),[],import.meta.url).then(t=>t.sceneNames_es);case"it":return Re(()=>import("./SceneNames_it-YZZnoK8j.js"),[],import.meta.url).then(t=>t.sceneNames_it);default:return Promise.resolve(void 0)}}const B2={play:"Play",clickToPlay:"Click to play",pause:"Pause",noDuration:"No observation duration",currentPosition:"Current position",duration:"Duration",switchToElapsed:"click to show elapsed time",switchToClockTime:"click to show the time of day",fullscreen:"Fullscreen",exitFullscreen:"Exit fullscreen",mute:"Mute",unmute:"Unmute",noSound:"No sound recorded",moments:"Moments",moreControls:"More controls",fewerControls:"Fewer controls",showObserverMap:"Show where the observer was",hideObserverMap:"Hide where the observer was",mapImageryUnavailable:"Aerial imagery unavailable",zoomMapIn:"Zoom in",zoomMapOut:"Zoom out",fitMap:"Back to the whole path",placeObserverHere:"Put the observer here",showReferences:"Show the pictures of the place",hideReferences:"Hide the pictures of the place",showTraces:"Show the investigator's lines",hideTraces:"Hide the investigator's lines",referenceOpacity:"Picture opacity",referencesMenu:"Pictures of the place",showMilestones:"Show the account's moments",hideMilestones:"Hide the account's moments",observerHere:"The observer, here",decorHere:"Scenery",recordingIssues:"{count} problem(s) in this recording: it may not play as its author meant",issueTemplates:vh.EN},cE=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:B2},Symbol.toStringTag,{value:"Module"})),H2=Math.PI/180,hE=180/Math.PI,lE=256,G2=19,uE=1.25;function V2(o,t){return 156543.03392*Math.cos(o*H2)/2**t}function W2(o,t){return V2(o,t)*lE}function dE(o,t){let e=0;for(;e<G2&&W2(o,e+1)>=t;)e++;return e}function X2(o,t){return W2(o,t)}function fE(o,t){const e=t*uE;let i=0;for(;i<G2&&V2(o,i)>e;)i++;return i}function vd(o){const t=o*H2;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}function $2(o,t,e){const i=2**e;return{x:(o+180)/360*i,y:vd(t)*i}}function Y2(o,t,e){const i=vd(o.north),n=vd(o.south);return{x:(t-o.west)/(o.east-o.west),y:(vd(e)-i)/(n-i)}}function pE(o,t,e){const{x:i,y:n}=$2(o,t,e);return{x:Math.floor(i),y:Math.floor(n),z:e}}function mE(o){const t=2**o.z,e=o.x/t*360-180,i=(o.x+1)/t*360-180,n=vv(o.y,t);return{south:vv(o.y+1,t),north:n,west:e,east:i}}function vv(o,t){const e=o/t;return Math.atan(Math.sinh(Math.PI*(1-2*e)))*hE}function K2(o,t,e,i){const n=pE(o,t,e),s=Math.floor(i/2),r=[];for(let h=-s;h<=s;h++)for(let l=-s;l<=s;l++)r.push({x:n.x+l,y:n.y+h,z:e});const a=r.map(mE),c={south:Math.min(...a.map(h=>h.south)),north:Math.max(...a.map(h=>h.north)),west:Math.min(...a.map(h=>h.west)),east:Math.max(...a.map(h=>h.east))};return{tiles:r,bounds:c}}const gE="#2ec4ff";class ho{constructor(t){this.ctx=t}static SCALE_STEPS_M=[5e3,2e3,1e3,500,200,100,50,20,10,5];static MARKER_RADIUS_PX=8.5;static ON_MARKER_M=3;targets=[];hitTest(t,e){let i,n=1/0;for(const s of this.targets){const r=Math.hypot(s.x-t,s.y-e);r>s.radius||r>n||(i=s,n=r)}return i}get width(){return this.ctx.canvas.width}get height(){return this.ctx.canvas.height}paint(t){const{ctx:e}=this;e.save(),this.targets=[],e.clearRect(0,0,this.width,this.height),this.paintGround(t),this.paintNight(t.nightFraction),this.paintPath(t),this.paintTraces(t),t.position?(this.paintCone(t,t.position),this.paintDecor(t),this.paintMarkers(t),this.paintObserver(t,t.position)):(this.paintDecor(t),this.paintMarkers(t)),this.paintNorth(),this.paintFooter(t.bounds,t.attribution),e.restore()}toCanvas(t,e,i){const n=Y2(t,i,e);return{x:n.x*this.width,y:n.y*this.height}}paintGround(t){const{ctx:e}=this;e.fillStyle="#1d2321",e.fillRect(0,0,this.width,this.height);const i=t.imagery;if(!i)return;const n=this.toCanvas(t.bounds,i.bounds.north,i.bounds.west),s=this.toCanvas(t.bounds,i.bounds.south,i.bounds.east);e.drawImage(i.source,n.x,n.y,s.x-n.x,s.y-n.y)}paintNight(t=0){if(t<=0)return;const{ctx:e}=this;e.save(),e.fillStyle=`rgba(6, 12, 30, ${Math.min(t,1)*.78})`,e.fillRect(0,0,this.width,this.height),e.restore()}paintDecor(t){const{ctx:e}=this;for(const i of t.decor){const n=this.toCanvas(t.bounds,i.lat,i.lng);if(i.label&&this.targets.push({kind:"decor",label:i.label,lat:i.lat,lng:i.lng,x:n.x,y:n.y,radius:7}),e.beginPath(),e.rect(n.x-3.5,n.y-3.5,7,7),e.fillStyle="rgba(120, 220, 255, 0.85)",e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.7)",e.stroke(),i.headingDeg===void 0)continue;const s=(i.headingDeg-90)*Math.PI/180;e.beginPath(),e.moveTo(n.x,n.y),e.lineTo(n.x+Math.cos(s)*10,n.y+Math.sin(s)*10),e.lineWidth=3,e.strokeStyle="rgba(0, 0, 0, 0.6)",e.stroke(),e.lineWidth=1.5,e.strokeStyle="rgba(120, 220, 255, 0.9)",e.stroke()}}paintPath(t){if(!t.path.moved)return;const{ctx:e}=this,i=t.path.points.map(n=>this.toCanvas(t.bounds,n.lat,n.lng));e.beginPath(),e.moveTo(i[0].x,i[0].y);for(const n of i.slice(1))e.lineTo(n.x,n.y);e.lineJoin="round",e.lineCap="round",e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=5,e.stroke(),e.strokeStyle="rgba(255, 255, 255, 0.9)",e.lineWidth=2,e.stroke()}paintTraces(t){const{ctx:e}=this;for(const i of t.traces??[]){const n=i.points.map(r=>this.toCanvas(t.bounds,r.lat,r.lng));if(n.length===0)continue;const s=i.color??gE;if(i.kind==="point")e.beginPath(),e.moveTo(n[0].x,n[0].y-6),e.lineTo(n[0].x+6,n[0].y),e.lineTo(n[0].x,n[0].y+6),e.lineTo(n[0].x-6,n[0].y),e.closePath(),e.fillStyle=s,e.fill(),e.lineWidth=1.5,e.strokeStyle="rgba(0, 0, 0, 0.8)",e.stroke();else{e.beginPath(),e.moveTo(n[0].x,n[0].y);for(const r of n.slice(1))e.lineTo(r.x,r.y);i.kind==="polygon"&&e.closePath(),e.lineJoin="round",e.setLineDash([]),e.strokeStyle="rgba(0, 0, 0, 0.65)",e.lineWidth=4.5,e.stroke(),e.setLineDash([9,5]),e.strokeStyle=s,e.lineWidth=2.5,e.stroke(),e.setLineDash([])}if(i.label){e.font="11px sans-serif",e.textAlign="left",e.textBaseline="middle";let r=n[0];if(i.kind==="line"&&t.position){const a=this.toCanvas(t.bounds,t.position.lat,t.position.lng);r=n.reduce((c,h)=>Math.hypot(h.x-a.x,h.y-a.y)>Math.hypot(c.x-a.x,c.y-a.y)?h:c)}this.paintOutlinedText(i.label,r.x+9,r.y-9)}}}paintCone(t,e){const{headingDeg:i,coneHalfAngleDeg:n}=t;if(i===void 0||n===void 0)return;const{ctx:s}=this,r=this.toCanvas(t.bounds,e.lat,e.lng),a=Math.hypot(this.width,this.height),c=(i-90)*Math.PI/180,h=n*Math.PI/180;s.save(),s.beginPath(),s.moveTo(r.x,r.y),s.arc(r.x,r.y,a,c-h,c+h),s.closePath();const l=s.createRadialGradient(r.x,r.y,0,r.x,r.y,a);l.addColorStop(0,"rgba(255, 224, 130, 0.55)"),l.addColorStop(.35,"rgba(255, 224, 130, 0.22)"),l.addColorStop(1,"rgba(255, 224, 130, 0)"),s.fillStyle=l,s.fill(),s.restore()}paintMarkers(t){const{ctx:e}=this;e.textAlign="center",e.textBaseline="middle",e.font="bold 10px sans-serif";for(const i of[...t.markers].sort((n,s)=>Number(n.current)-Number(s.current))){const n=this.toCanvas(t.bounds,i.lat,i.lng);this.targets.push({kind:"milestone",label:i.note?`${i.label} — ${i.note}`:i.label,lat:i.lat,lng:i.lng,t:i.t,x:n.x,y:n.y,radius:ho.MARKER_RADIUS_PX}),e.beginPath(),e.arc(n.x,n.y,ho.MARKER_RADIUS_PX,0,Math.PI*2),e.fillStyle=i.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",e.fill(),e.lineWidth=2,e.strokeStyle="rgba(255, 255, 255, 0.9)",e.stroke(),e.fillStyle=i.current?"#1d2321":"#fff",e.fillText(i.label,n.x,n.y)}}paintObserver(t,e){const{ctx:i}=this,n=this.toCanvas(t.bounds,e.lat,e.lng);t.observerLabel&&this.targets.push({kind:"observer",label:t.observerLabel,lat:e.lat,lng:e.lng,x:n.x,y:n.y,radius:8});const s=t.markers.some(r=>{if(!r.current)return!1;const a=oe(r.lat,r.lng,e.lat,e.lng);return Math.hypot(a.x,a.z)<=ho.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?ho.MARKER_RADIUS_PX+2.5:5.5,0,Math.PI*2),s||(i.fillStyle="#ff5a3c",i.fill()),i.lineWidth=4,i.strokeStyle="rgba(0, 0, 0, 0.5)",i.stroke(),i.lineWidth=s?3:2.5,i.strokeStyle=s?"#ff5a3c":"#fff",i.stroke()}paintNorth(){const{ctx:t}=this,e=this.width-14,i=16;t.beginPath(),t.moveTo(e,i-9),t.lineTo(e-4.5,i+5),t.lineTo(e,i+2),t.lineTo(e+4.5,i+5),t.closePath(),t.fillStyle="rgba(255, 255, 255, 0.92)",t.strokeStyle="rgba(0, 0, 0, 0.6)",t.lineWidth=1,t.fill(),t.stroke(),t.font="bold 9px sans-serif",t.textAlign="center",t.textBaseline="top",t.strokeText("N",e,i+6),t.fillText("N",e,i+6)}paintFooter(t,e){const{ctx:i}=this;i.font="9px sans-serif",i.textBaseline="bottom";const n=e?this.wrap(e,this.width-20):[];let s=this.height-4;i.textAlign="right";for(const f of n.slice().reverse())this.paintOutlinedText(f,this.width-6,s),s-=11;const r=(t.south+t.north)/2,c=Math.abs(oe(r,t.east,r,t.west).x)/this.width,h=ho.SCALE_STEPS_M.find(f=>f/c<=this.width/3);if(h===void 0)return;const l=h/c,u=8,d=s-3;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.6)",i.beginPath(),i.moveTo(u,d),i.lineTo(u+l,d),i.stroke(),i.lineWidth=1.5,i.strokeStyle="rgba(255, 255, 255, 0.95)",i.stroke(),i.textAlign="left",this.paintOutlinedText(h>=1e3?`${h/1e3} km`:`${h} m`,u,d-3)}paintOutlinedText(t,e,i){const{ctx:n}=this;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.75)",n.strokeText(t,e,i),n.fillStyle="#fff",n.fillText(t,e,i)}wrap(t,e){const i=[];let n="";for(const s of t.split(" ")){const r=n?`${n} ${s}`:s;n&&this.ctx.measureText(r).width>e?(i.push(n),n=s):n=r}return n&&i.push(n),i}}class si{static MIN_ZOOM=.25;static MAX_ZOOM=64;static MIN_SPAN_M=400;static MARGIN=.6;static IMAGERY_PX=768;static fitted(t,e){return si.including(t.boundsAround(si.MIN_SPAN_M,si.MARGIN),e)}zoom=1;centerX=.5;centerY=.5;get changed(){return this.zoom!==1||this.centerX!==.5||this.centerY!==.5}get zoomFactor(){return this.zoom}reset(){this.zoom=1,this.centerX=.5,this.centerY=.5}zoomAt(t,e,i){const n=Math.min(si.MAX_ZOOM,Math.max(si.MIN_ZOOM,this.zoom*i)),s=this.centerX+(t-.5)/this.zoom,r=this.centerY+(e-.5)/this.zoom;this.centerX=s-(t-.5)/n,this.centerY=r-(e-.5)/n,this.zoom=n}panBy(t,e){this.centerX-=t/this.zoom,this.centerY-=e/this.zoom}refit(t,e){if(!this.changed)return;const i=this.boundsWithin(t),n=si.mercatorY01(e.north),s=si.mercatorY01(e.south),r=si.mercatorY01(i.north),a=si.mercatorY01(i.south);this.zoom=(e.east-e.west)/(i.east-i.west),this.centerX=((i.west+i.east)/2-e.west)/(e.east-e.west),this.centerY=((r+a)/2-n)/(s-n)}keepInView(t,e,i){if(!this.changed)return!1;const n=this.boundsWithin(t),s=si.mercatorY01(n.north),r=si.mercatorY01(n.south),a=(e.lng-n.west)/(n.east-n.west),c=(si.mercatorY01(e.lat)-s)/(r-s);return a>=i&&a<=1-i&&c>=i&&c<=1-i?!1:(this.panBy(.5-a,.5-c),!0)}boundsWithin(t){if(!this.changed)return t;const e=.5/this.zoom,i=si.mercatorY01(t.north),n=si.mercatorY01(t.south),s=t.east-t.west;return{west:t.west+(this.centerX-e)*s,east:t.west+(this.centerX+e)*s,north:si.latitudeAt(i+(this.centerY-e)*(n-i)),south:si.latitudeAt(i+(this.centerY+e)*(n-i))}}static including(t,e,i=3){const n=(t.north+t.south)/2,s=(t.east+t.west)/2,r=oe(n,t.east,n,s).x;let a=r;for(const c of e){const{x:h,z:l}=oe(c.lat,c.lng,n,s),u=Math.max(Math.abs(h),Math.abs(l));u<=r*i&&(a=Math.max(a,u*1.15))}return a<=r?t:{north:os(0,-a,n,s).lat,south:os(0,a,n,s).lat,east:os(a,0,n,s).lng,west:os(-a,0,n,s).lng}}static expand(t,e){const i=t.east-t.west,n=t.north-t.south;return{west:t.west-i*e,east:t.east+i*e,south:t.south-n*e,north:t.north+n*e}}static pointAt(t,e,i){const n=si.mercatorY01(t.north),s=si.mercatorY01(t.south);return{lat:si.latitudeAt(n+i*(s-n)),lng:t.west+e*(t.east-t.west)}}static mercatorY01(t){const e=t*Math.PI/180;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}static latitudeAt(t){return Math.atan(Math.sinh(Math.PI*(1-2*t)))*180/Math.PI}}const As=256,Mv=3,vE=32768;class ME{fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(t,e){const i=(t.south+t.north)/2,n=(t.west+t.east)/2,s=Math.abs(oe(i,t.east,i,t.west).x),r=Math.abs(oe(t.north,n,t.south,n).z),a=dE(i,Math.max(s,r)),{tiles:c}=K2(n,i,a,Mv),h=Mv*As,l=new Float32Array(h*h),u=c[0];await Promise.all(c.map(f=>this.decodeTileInto(f,u,l,h)));const d=new Float32Array(e.width*e.height);for(let f=0;f<e.height;f++){const p=t.north+(t.south-t.north)*(f/(e.height-1));for(let g=0;g<e.width;g++){const m=t.west+(t.east-t.west)*(g/(e.width-1));d[f*e.width+g]=this.sampleAt(p,m,a,u,l,h)}}return{heights:d,width:e.width,height:e.height,bounds:t}}async decodeTileInto(t,e,i,n){const s=this.tileUrlTemplate.replace("{z}",String(t.z)).replace("{x}",String(t.x)).replace("{y}",String(t.y)),r=await this.fetchImpl(s);if(!r.ok)throw new Error(`Elevation tile fetch failed (${r.status}): ${s}`);const a=await createImageBitmap(await r.blob()),c=document.createElement("canvas");c.width=As,c.height=As;const h=c.getContext("2d");if(!h)throw new Error("2D canvas context unavailable");h.drawImage(a,0,0);const{data:l}=h.getImageData(0,0,As,As),u=(t.x-e.x)*As,d=(t.y-e.y)*As;for(let f=0;f<As;f++)for(let p=0;p<As;p++){const g=(f*As+p)*4,m=l[g]*256+l[g+1]+l[g+2]/256-vE,v=u+p,y=d+f;i[y*n+v]=m}}sampleAt(t,e,i,n,s,r){const{x:a,y:c}=$2(e,t,i),h=(a-n.x)*As,l=(c-n.y)*As,u=Math.max(0,Math.min(r-1,Math.floor(h))),d=Math.max(0,Math.min(r-1,Math.floor(l))),f=Math.min(r-1,u+1),p=Math.min(r-1,d+1),g=h-u,m=l-d,v=s[d*r+u],y=s[d*r+f],x=s[p*r+u],M=s[p*r+f],b=v+(y-v)*g,S=x+(M-x)*g;return b+(S-b)*m}}class Wf{constructor(t,e,i,n){this.width=t,this.height=e,this.samples=i,this.values=n}at(t,e,i=0){return this.values[(e*this.width+t)*this.samples+i]}static parse(t){const e=new DataView(t);if(t.byteLength<8||e.getUint16(0)!==18761||e.getUint16(2,!0)!==42)throw new Error("Not a little-endian TIFF");const i=e.getUint32(4,!0),n=e.getUint16(i,!0),s=new Map;for(let v=0;v<n;v++){const y=i+2+v*12;s.set(e.getUint16(y,!0),{type:e.getUint16(y+2,!0),count:e.getUint32(y+4,!0),value:e.getUint32(y+8,!0)})}const r=(v,y)=>{const x=s.get(v);if(x===void 0){if(y===void 0)throw new Error(`TIFF without tag ${v}`);return y}return x.type===3?x.value&65535:x.value},a=v=>{const y=s.get(v);if(y===void 0)throw new Error(`TIFF without tag ${v}`);const x=y.type===3?2:4,M=[];if(y.count*x<=4){const b=new DataView(new ArrayBuffer(4));b.setUint32(0,y.value,!0);for(let S=0;S<y.count;S++)M.push(x===2?b.getUint16(S*2,!0):b.getUint32(0,!0))}else for(let b=0;b<y.count;b++)M.push(x===2?e.getUint16(y.value+b*2,!0):e.getUint32(y.value+b*4,!0));return M};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(s.has(322))throw new Error("Tiled TIFF");const c=r(256),h=r(257),l=r(277,1),u=a(258)[0],d=r(339,1)===3;if(!(d&&u===32||!d&&u===8))throw new Error(`Unsupported TIFF samples: ${u} bits`);const f=a(273),p=a(279),g=new Uint8Array(c*h*l*(u/8));let m=0;for(let v=0;v<f.length&&m<g.length;v++){const y=Math.min(p[v],g.length-m);g.set(new Uint8Array(t,f[v],y),m),m+=y}if(m<g.length)throw new Error("Truncated TIFF");return new Wf(c,h,l,d?new Float32Array(g.buffer):g)}}class fa extends Error{constructor(t,e){super(e),this.reason=t,this.name="SurroundingsUnavailableError"}}class yE{constructor(t,e,i,n,s){this.heights=t,this.plants=e,this.buildings=i,this.size=n,this.metresPerPixel=s}structureAt(t,e){const i=Math.floor(t/this.metresPerPixel+this.size/2),n=Math.floor(this.size/2-e/this.metresPerPixel);if(i<0||n<0||i>=this.size||n>=this.size)return;const s=n*this.size+i;if(!(this.plants[s]||this.buildings[s]))return this.heights[s]}tallestStructureNear(t,e,i){let n;const s=Math.ceil(i/this.metresPerPixel);for(let r=-s;r<=s;r++)for(let a=-s;a<=s;a++){if(Math.hypot(a,r)*this.metresPerPixel>i)continue;const c=this.structureAt(t+a*this.metresPerPixel,e+r*this.metresPerPixel);c!==void 0&&(n===void 0||c>n)&&(n=c)}return n}}class Ce{static covers(t,e){return t>=41.2&&t<=51.3&&e>=-5.4&&e<=9.8}static WMS="https://data.geopf.fr/wms-r/wms";static WFS="https://data.geopf.fr/wfs/ows";static HEIGHT_LAYER="IGNF_LIDAR-HD_MNH_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93";static CLASS_LAYER="IGNF_LIDAR-HD_CLASS";static PHOTO_LAYER="ORTHOIMAGERY.ORTHOPHOTOS";static MAX_PHOTO_PIXELS=1e3;static METRES_PER_PIXEL=.5;static MAX_RADIUS_M=3e3;static MAX_LIDAR_RADIUS_M=150;static NO_DATA=-9999;static METRES_PER_DEGREE=111320;fetchImpl;wms;wfs;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??Ce.WMS,this.wfs=t.wfsEndpoint??Ce.WFS}static radius(t){return Math.min(t,Ce.MAX_RADIUS_M)}static lidarRadius(t){return Math.min(t,Ce.MAX_LIDAR_RADIUS_M)}async lidar(t,e){const i=Ce.lidarRadius(e),n=Math.ceil(2*i/Ce.METRES_PER_PIXEL),[s,r]=await Promise.all([this.raster(t,i,n,Ce.HEIGHT_LAYER),this.raster(t,i,n,Ce.CLASS_LAYER)]);if(s.samples!==1||r.samples<3)throw new fa("unreachable","The survey answered in a layout this does not read");const a=s.values;if(a.every(u=>u===Ce.NO_DATA))throw new fa("no-coverage","No LiDAR HD survey here yet");const c=new Uint8Array(n*n),h=new Uint8Array(n*n);for(let u=0;u<n*n;u++){const d=r.values[u*r.samples],f=r.values[u*r.samples+1],p=r.values[u*r.samples+2];c[u]=f>d&&f>p?1:0,h[u]=d>120&&f<90&&p<90?1:0}const l=2*i/n;return{size:n,metresPerPixel:l,heights:a,vegetation:c,building:h,structures:new yE(a,c,h,n,l)}}async laserDate(t){return Ce.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",t))}async photoDate(t){return Ce.latest(await this.dated("ORTHOIMAGERY.ORTHOPHOTOS.GRAPHE-MOSAIQUAGE:graphe_bdortho","geom","date_vol",t))}static latest(t){return t.map(i=>/^\d{4}-\d{2}-\d{2}/.exec(String(i??""))?.[0]).filter(i=>i!==void 0).sort().at(-1)}async dated(t,e,i,n){const r=[n.lng-1e-4,n.lat-1e-4,n.lng+1e-4,n.lat+1e-4].map(a=>a.toFixed(6)).join(",");try{return(await this.features(t,`BBOX(${e},${r},'EPSG:4326')`,i,20)).map(a=>a.properties[i])}catch{return[]}}async photo(t,e){const i=Ce.radius(e),n=Math.min(Ce.MAX_PHOTO_PIXELS,Math.ceil(2*i/Ce.METRES_PER_PIXEL)),s=await this.raster(t,i,n,Ce.PHOTO_LAYER);if(s.samples<3)throw new fa("unreachable","The photograph came in a layout this does not read");return{size:n,metresPerPixel:2*i/n,samples:s.samples,values:s.values}}async vectors(t,e,i){const n=Ce.radius(e),s=n/Ce.METRES_PER_DEGREE,r=n/(Ce.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),c=`BBOX(geometrie,${[t.lng-r,t.lat-s,t.lng+r,t.lat+s].map(v=>v.toFixed(6)).join(",")},'EPSG:4326')`,[h,l,u,d,f,p]=await Promise.all([this.features("construction_lineaire",`${c} AND nature='Pont'`,"nature,geometrie"),this.features("troncon_de_route",`${c} AND position_par_rapport_au_sol>'0'`,"nature,largeur_de_chaussee,position_par_rapport_au_sol,nom_voie_ban_gauche,nom_voie_ban_droite,cpx_toponyme_route_nommee,geometrie"),this.features("troncon_de_voie_ferree",`${c} AND position_par_rapport_au_sol>'0'`,"position_par_rapport_au_sol,geometrie").catch(()=>[]),this.features("ligne_electrique",c,"voltage,geometrie"),i?this.features("batiment",c,Ce.BUILDING_PROPERTIES,5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",c,"toponyme,categorie,geometrie",100).catch(()=>[]):Promise.resolve([])]),g=i?await this.wholeWorship(p,f,[t.lng-r,t.lat-s,t.lng+r,t.lat+s]):[],m=[...f,...g];return{bridges:h,elevatedRoads:l,elevatedRailways:u,lines:d,buildings:m,zones:p,mapDate:Ce.latest(m.map(v=>v.properties.date_modification))}}static BUILDING_PROPERTIES="cleabs,nature,usage_1,hauteur,nombre_d_etages,materiaux_des_murs,materiaux_de_la_toiture,date_d_apparition,date_modification,geometrie";static MAX_WHOLE_M=300;async wholeWorship(t,e,i){const[n,s,r,a]=i,c=Ce.MAX_WHOLE_M/Ce.METRES_PER_DEGREE;let h;for(const u of t){if(u.properties.categorie!=="Religieux")continue;const[d,f,p,g]=Ce.extent(u);if(d>=n&&f>=s&&p<=r&&g<=a)continue;const m=[Math.max(d,n-c),Math.max(f,s-c),Math.min(p,r+c),Math.min(g,a+c)];h=h?[Math.min(h[0],m[0]),Math.min(h[1],m[1]),Math.max(h[2],m[2]),Math.max(h[3],m[3])]:m}if(!h)return[];const l=new Set(e.map(u=>u.properties.cleabs));try{return(await this.features("batiment",`BBOX(geometrie,${h.map(d=>d.toFixed(6)).join(",")},'EPSG:4326')`,Ce.BUILDING_PROPERTIES,1e3)).filter(d=>!l.has(d.properties.cleabs))}catch{return[]}}static extent(t){let e=1/0,i=1/0,n=-1/0,s=-1/0;const r=a=>{Array.isArray(a)&&typeof a[0]=="number"?(e=Math.min(e,a[0]),n=Math.max(n,a[0]),i=Math.min(i,a[1]),s=Math.max(s,a[1])):Array.isArray(a)&&a.forEach(r)};return r(t.geometry.coordinates),[e,i,n,s]}async elevatedRoadLines(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(s=>s.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${e} AND position_par_rapport_au_sol>'0'`,"geometrie",300),n=[];for(const s of i){const{type:r,coordinates:a}=s.geometry,c=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const h of c)n.push(h.map(l=>({lat:l[1],lng:l[0]})))}return n}async waterSurfaces(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("surface_hydrographique",`${e} AND position_par_rapport_au_sol='0' AND persistance='Permanent'`,"cleabs,nature,geometrie",500)}async roads(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_route",`${e} AND nature<>'Sentier' AND nature<>'Escalier' AND position_par_rapport_au_sol>='0'`,"cleabs,nature,largeur_de_chaussee,nombre_de_voies,sens_de_circulation,vitesse_moyenne_vl,urbain,nom_voie_ban_gauche,nom_voie_ban_droite,cpx_toponyme_route_nommee,geometrie",3e3)}async railways(t){const e=`BBOX(geometrie,${[t.west,t.south,t.east,t.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_voie_ferree",`${e} AND etat_de_l_objet='En service'`,"cleabs,nature,electrifie,largeur,nombre_de_voies,position_par_rapport_au_sol,cpx_toponyme,geometrie",3e3)}async raster(t,e,i,n){const s=e/Ce.METRES_PER_DEGREE,r=e/(Ce.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:n,STYLES:"",CRS:"EPSG:4326",BBOX:[t.lat-s,t.lng-r,t.lat+s,t.lng+r].map(h=>h.toFixed(6)).join(","),WIDTH:String(i),HEIGHT:String(i),FORMAT:"image/geotiff"});let c;try{c=await this.fetchImpl(`${this.wms}?${a}`)}catch(h){throw new fa("unreachable",h instanceof Error?h.message:String(h))}if(!c.ok)throw new fa("unreachable",`The survey answered ${c.status}`);try{return Wf.parse(await c.arrayBuffer())}catch(h){throw new fa("unreachable",h instanceof Error?h.message:String(h))}}async features(t,e,i,n=200){const s=new URLSearchParams({SERVICE:"WFS",VERSION:"2.0.0",REQUEST:"GetFeature",TYPENAMES:t.includes(":")?t:`BDTOPO_V3:${t}`,SRSNAME:"EPSG:4326",OUTPUTFORMAT:"application/json",COUNT:String(n),CQL_FILTER:e,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${s}`)}catch(c){throw new fa("unreachable",c instanceof Error?c.message:String(c))}if(!r.ok)throw new fa("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class Ta{static NEAR_M=15;static ALIGNED_DEG=30;static LONG_ENOUGH_M=15;static SAMPLE_M=5;static follows(t,e){if(t.length<2||e.length<2)return!1;const i=e[0],n=e.map(a=>oe(a.lat,a.lng,i.lat,i.lng)),s=t.map(a=>oe(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<s.length-1;a++){const c=s[a],h=s[a+1],l=Math.hypot(h.x-c.x,h.z-c.z);if(l<1e-6)continue;const u=Math.max(1,Math.ceil(l/Ta.SAMPLE_M)),d=Math.atan2(h.x-c.x,-(h.z-c.z));for(let f=0;f<=u;f++){const p=f/u,g=Ta.nearest(n,c.x+(h.x-c.x)*p,c.z+(h.z-c.z)*p);g.distanceM>Ta.NEAR_M||Ta.angleBetween(d,g.heading)<=Ta.ALIGNED_DEG&&(r+=l/u)}}return r>=Ta.LONG_ENOUGH_M}static nearest(t,e,i){let n={distanceM:1/0,heading:0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,h=a.z-r.z,l=c*c+h*h,u=l<1e-9?0:Math.max(0,Math.min(1,((e-r.x)*c+(i-r.z)*h)/l)),d=Math.hypot(e-(r.x+c*u),i-(r.z+h*u));d<n.distanceM&&(n={distanceM:d,heading:Math.atan2(c,-h)})}return n}static angleBetween(t,e){const i=Math.abs((t-e)*180/Math.PI%180);return Math.min(i,180-i)}}class Te{static WMS="https://data.geopf.fr/wms-r/wms";static LAYERS=["IGNF_LIDAR-HD_MNT_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93","ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES"];static METRES_PER_PIXEL=4;static METRES_PER_DEGREE=111320;static CLASS_LAYER="IGNF_LIDAR-HD_CLASS";static SURFACE_LAYER="IGNF_LIDAR-HD_MNS_ELEVATION.ELEVATIONGRIDCOVERAGE.LAMB93";static DECK=[240,240,0];static NO_CLASS=[0,0,0];static DECK_END_PIXELS=3;static DECK_HALF_WIDTH_M=8;static DECK_APPROACH_M=10;static DECK_STRAIGHT_MAX_M=200;static MIN_PIXELS=8;static MAX_PIXELS=700;static NO_DATA_BELOW=-100;static COARSE_METRES_PER_PIXEL=20;static MESH_FROM_VERTICES=33;static FINE_SPACING_M=7;static MAX_SEGMENTS=256;static MAX_HOLE_SHARE=.05;static DEFAULT_TIMEOUT_MS=12e3;static MAX_WINDOW_M=50;fetchImpl;wms;timeoutMs;maxWindowM;geoplatform;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.wms=t.wmsEndpoint??Te.WMS,this.timeoutMs=t.timeoutMs??Te.DEFAULT_TIMEOUT_MS,this.maxWindowM=t.maxWindowM??Te.MAX_WINDOW_M,this.geoplatform=new Ce({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:t.wfsEndpoint})}async getElevationGrid(t,e,i){const n={lat:(t.south+t.north)/2,lng:(t.west+t.east)/2};if(!Ce.covers(n.lat,n.lng))throw new Error("The IGN's relief covers France only");const s=Math.abs(oe(n.lat,t.east,n.lat,t.west).x),r=Math.abs(oe(t.north,n.lng,t.south,n.lng).z);e=this.finer(e,s,r);const a={x:s/Math.max(1,e.width-1),y:r/Math.max(1,e.height-1)},c={x:Math.min(a.x,this.maxWindowM),y:Math.min(a.y,this.maxWindowM)},h={south:t.south-c.y/Te.METRES_PER_DEGREE,north:t.north+c.y/Te.METRES_PER_DEGREE,west:t.west-c.x/(Te.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180)),east:t.east+c.x/(Te.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180))},l=g=>Math.min(Te.MAX_PIXELS,Math.max(Te.MIN_PIXELS,Math.ceil(g/Te.METRES_PER_PIXEL))),u={width:l(s+2*c.x),height:l(r+2*c.y)},d={x:(s+2*c.x)/u.width,y:(r+2*c.y)/u.height};let f=new Error("No layer of the IGN's relief answered");const p=Math.max(d.x,d.y)>Te.COARSE_METRES_PER_PIXEL;for(const g of p?[...Te.LAYERS].reverse():Te.LAYERS)try{const m=await this.heights(h,u,g);g===Te.LAYERS[0]&&await this.layBridgeDecks(m,h,u,i?.route);const v=this.sample(m,e,t,h,d,a);if(v)return{heights:v,width:e.width,height:e.height,bounds:t};f=new Error(`${g} does not cover this place`)}catch(m){f=m}throw f}finer(t,e,i){if(t.width<Te.MESH_FROM_VERTICES||t.height<Te.MESH_FROM_VERTICES)return t;const n=(s,r)=>{const a=Math.ceil(s/Te.FINE_SPACING_M),c=Math.max(r-1,Math.min(Te.MAX_SEGMENTS,a));return c%2===0?c:c+1};return{width:n(e,t.width)+1,height:n(i,t.height)+1}}async raster(t,e,i){const n=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:i,STYLES:"",CRS:"EPSG:4326",BBOX:[t.south,t.west,t.north,t.east].map(r=>r.toFixed(6)).join(","),WIDTH:String(e.width),HEIGHT:String(e.height),FORMAT:"image/geotiff"}),s=await this.fetchImpl(`${this.wms}?${n}`,{signal:AbortSignal.timeout(this.timeoutMs)});if(!s.ok)throw new Error(`The IGN's relief answered ${s.status}`);return Wf.parse(await s.arrayBuffer())}async heights(t,e,i){const n=await this.raster(t,e,i);if(n.samples!==1||!(n.values instanceof Float32Array))throw new Error("The IGN's relief came in a layout this does not read");return n}async layBridgeDecks(t,e,i,n){if(!(!n||n.length<2)&&!(!(t.values instanceof Float32Array)||!t.values.some(s=>s>Te.NO_DATA_BELOW)))try{const s=(await this.geoplatform.elevatedRoadLines({west:e.west,south:e.south,east:e.east,north:e.north})).filter(a=>Ta.follows(n,a));if(s.length===0)return;const r=Float32Array.from(t.values);await this.layClassifiedDecks(t,e,i,s),this.layRouteDecks(t,r,e,s)}catch{}}async layClassifiedDecks(t,e,i,n){try{const s=await this.raster(e,i,Te.CLASS_LAYER);if(s.samples<3||s.width!==t.width||s.height!==t.height)return;const r=(m,[v,y,x])=>s.values[m*s.samples]===v&&s.values[m*s.samples+1]===y&&s.values[m*s.samples+2]===x,a=t.width,c=t.height,h=new Uint8Array(a*c);let l=!1;for(let m=0;m<h.length;m++)r(m,Te.DECK)&&(h[m]=1,l=!0);if(!l)return;const u=Te.DECK_END_PIXELS,d=[];for(let m=0;m<h.length;m++){if(h[m]!==1)continue;const v=m%a,y=(m-v)/a;for(let x=-u;x<=u;x++)for(let M=-u;M<=u;M++){const b=v+M,S=y+x;if(b<0||S<0||b>=a||S>=c)continue;const _=S*a+b;h[_]===0&&r(_,Te.NO_CLASS)&&d.push(_)}}for(const m of d)h[m]=1;const f=this.paint(n,e,a,c),p=this.touching(h,f,a,c);if(p.every(m=>m===0))return;const g=await this.heights(e,i,Te.SURFACE_LAYER);if(g.width!==a||g.height!==c)return;for(let m=0;m<p.length;m++){if(p[m]===0)continue;const v=g.values[m];Number.isFinite(v)&&v>Te.NO_DATA_BELOW&&v>t.values[m]&&(t.values[m]=v)}}catch{}}layRouteDecks(t,e,i,n){const{width:s,height:r}=t,a=(i.north+i.south)/2,c=(i.east-i.west)*Te.METRES_PER_DEGREE*Math.cos(a*Math.PI/180),h=(i.north-i.south)*Te.METRES_PER_DEGREE,l=c/s,u=h/r,d=v=>({x:(v.lng-i.west)/(i.east-i.west)*c,y:(i.north-v.lat)/(i.north-i.south)*h}),f=(v,y)=>{const x=Math.floor(v/l),M=Math.floor(y/u);if(x<0||M<0||x>=s||M>=r)return;const b=e[M*s+x];return Number.isFinite(b)&&b>Te.NO_DATA_BELOW?b:void 0},p=Te.DECK_HALF_WIDTH_M,g=Te.DECK_APPROACH_M,m=(v,y)=>{const x=Math.hypot(v.x-y.x,v.y-y.y)||1,M={x:(v.x-y.x)/x,y:(v.y-y.y)/x},b=[0,g/2,g].map(S=>f(v.x+M.x*S,v.y+M.y*S)).filter(S=>S!==void 0);return b.length>0?Math.max(...b):void 0};for(const v of Te.chains(n.map(y=>y.map(d)))){const y=[0];for(let D=1;D<v.length;D++)y.push(y[D-1]+Math.hypot(v[D].x-v[D-1].x,v[D].y-v[D-1].y));const x=y[y.length-1];if(x<1||x>Te.DECK_STRAIGHT_MAX_M)continue;const M=m(v[0],v[1]),b=m(v[v.length-1],v[v.length-2]);if(M===void 0||b===void 0)continue;const S=p+g,_=Math.max(0,Math.floor((Math.min(...v.map(D=>D.x))-S)/l)),w=Math.min(s-1,Math.ceil((Math.max(...v.map(D=>D.x))+S)/l)),A=Math.max(0,Math.floor((Math.min(...v.map(D=>D.y))-S)/u)),I=Math.min(r-1,Math.ceil((Math.max(...v.map(D=>D.y))+S)/u));for(let D=A;D<=I;D++)for(let C=_;C<=w;C++){const L=Te.nearestAlong(v,y,{x:(C+.5)*l,y:(D+.5)*u});if(L.distance>p||L.s<-g||L.s>x+g)continue;const N=M+(b-M)*Math.min(1,Math.max(0,L.s/x)),P=D*s+C;e[P]>=N||(t.values[P]=N)}}}static chains(t){const e=t.filter(s=>s.length>=2).map(s=>[...s]),i=[],n=(s,r)=>Math.hypot(s.x-r.x,s.y-r.y)<=1;for(;e.length>0;){let s=e.shift(),r=!0;for(;r;){r=!1;for(let a=0;a<e.length;a++){const c=e[a],h=s[0],l=s[s.length-1];if(n(l,c[0]))s=[...s,...c.slice(1)];else if(n(l,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else if(n(h,c[c.length-1]))s=[...c.slice(0,-1),...s];else if(n(h,c[0]))s=[...[...c].reverse().slice(0,-1),...s];else continue;e.splice(a,1),r=!0;break}}i.push(s)}return i}static nearestAlong(t,e,i){let n={s:0,distance:1/0};for(let s=0;s<t.length-1;s++){const r=t[s],a=t[s+1],c=a.x-r.x,h=a.y-r.y,l=c*c+h*h;if(l<1e-9)continue;let u=((i.x-r.x)*c+(i.y-r.y)*h)/l;s>0&&(u=Math.max(0,u)),s<t.length-2&&(u=Math.min(1,u));const d=Math.hypot(i.x-(r.x+c*u),i.y-(r.y+h*u));d<n.distance&&(n={s:e[s]+u*Math.sqrt(l),distance:d})}return n}paint(t,e,i,n){const s=new Uint8Array(i*n),r=c=>(c-e.west)/(e.east-e.west)*i,a=c=>(e.north-c)/(e.north-e.south)*n;for(const c of t)for(let h=0;h<c.length-1;h++){const l=r(c[h].lng),u=a(c[h].lat),d=r(c[h+1].lng),f=a(c[h+1].lat),p=Math.max(1,Math.ceil(Math.hypot(d-l,f-u)*2));for(let g=0;g<=p;g++){const m=Math.floor(l+(d-l)*g/p),v=Math.floor(u+(f-u)*g/p);for(let y=-1;y<=1;y++)for(let x=-1;x<=1;x++){const M=m+x,b=v+y;M>=0&&b>=0&&M<i&&b<n&&(s[b*i+M]=1)}}}return s}touching(t,e,i,n){const s=new Uint8Array(t.length),r=new Uint8Array(t.length);for(let a=0;a<t.length;a++){if(t[a]===0||r[a]===1)continue;const c=[],h=[a];r[a]=1;let l=!1;for(;h.length>0;){const u=h.pop();c.push(u),e[u]===1&&(l=!0);const d=u%i,f=(u-d)/i;for(let p=-1;p<=1;p++)for(let g=-1;g<=1;g++){const m=d+g,v=f+p;if(m<0||v<0||m>=i||v>=n)continue;const y=v*i+m;t[y]===1&&r[y]===0&&(r[y]=1,h.push(y))}}if(l)for(const u of c)s[u]=1}return s}sample(t,e,i,n,s,r){const{width:a,height:c}=e,h=new Float32Array(a*c),l=new Uint8Array(a*c),u=Math.min(r.x,this.maxWindowM)/s.x,d=Math.min(r.y,this.maxWindowM)/s.y;let f=0;for(let p=0;p<c;p++){const g=i.north+(i.south-i.north)*(c===1?.5:p/(c-1)),m=(n.north-g)/(n.north-n.south)*t.height-.5;for(let v=0;v<a;v++){const x=(i.west+(i.east-i.west)*(a===1?.5:v/(a-1))-n.west)/(n.east-n.west)*t.width-.5,M=u>1||d>1?this.tent(t,x,m,Math.max(1,u),Math.max(1,d)):this.bilinear(t,x,m),b=p*a+v;M===void 0?f++:(h[b]=M,l[b]=1)}}if(!(f===a*c||f/(a*c)>Te.MAX_HOLE_SHARE))return this.fill(h,l,a,c),h}tent(t,e,i,n,s){let r=0,a=0,c=0;const h=Math.max(0,Math.ceil(i-s)),l=Math.min(t.height-1,Math.floor(i+s)),u=Math.max(0,Math.ceil(e-n)),d=Math.min(t.width-1,Math.floor(e+n));for(let f=h;f<=l;f++){const p=1-Math.abs(f-i)/s;if(!(p<=0))for(let g=u;g<=d;g++){const m=p*(1-Math.abs(g-e)/n);if(m<=0)continue;c+=m;const v=t.at(g,f);!Number.isFinite(v)||v<Te.NO_DATA_BELOW||(r+=m*v,a+=m)}}return c>0&&a>=c*.5?r/a:void 0}bilinear(t,e,i){const n=Math.max(0,Math.min(t.width-1,Math.floor(e))),s=Math.max(0,Math.min(t.height-1,Math.floor(i))),r=Math.min(t.width-1,n+1),a=Math.min(t.height-1,s+1),c=Math.max(0,Math.min(1,e-n)),h=Math.max(0,Math.min(1,i-s)),l=t.at(n,s),u=t.at(r,s),d=t.at(n,a),f=t.at(r,a);for(const m of[l,u,d,f])if(!Number.isFinite(m)||m<Te.NO_DATA_BELOW)return;const p=l+(u-l)*c,g=d+(f-d)*c;return p+(g-p)*h}fill(t,e,i,n){let s=e.reduce((r,a)=>r+(a?0:1),0);for(;s>0;){const r=[];for(let a=0;a<n;a++)for(let c=0;c<i;c++){const h=a*i+c;if(e[h])continue;let l=0,u=0;for(let d=-1;d<=1;d++)for(let f=-1;f<=1;f++){const p=a+d,g=c+f;p<0||g<0||p>=n||g>=i||!e[p*i+g]||(l+=t[p*i+g],u++)}u>0&&r.push([h,l/u])}if(r.length===0)return;for(const[a,c]of r)t[a]=c,e[a]=1;s-=r.length}}}class xE{providers;constructor(...t){this.providers=t}async getElevationGrid(t,e,i){let n=new Error("No source of relief to ask");for(const s of this.providers)try{return await s.getElevationGrid(t,e,i)}catch(r){n=r}throw n}}const Md=256,bE=5;async function q2(o,t,e,i){const n=(o.south+o.north)/2,s=(o.west+o.east)/2,r=Math.abs(oe(n,o.east,n,o.west).x),a=Math.abs(oe(o.north,s,o.south,s).z),c=Math.max(r,a),{zoom:h,gridSize:l}=wE(n,c,Math.max(t.width,t.height)),{tiles:u,bounds:d}=K2(s,n,h,l),f=l*Md,p=document.createElement("canvas");p.width=f,p.height=f;const g=p.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");const m=u[0];await Promise.all(u.map(async M=>{const b=e(M),S=await i(b);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${b}`);const _=await createImageBitmap(await S.blob());g.drawImage(_,(M.x-m.x)*Md,(M.y-m.y)*Md)}));const v=Math.min(Math.max(t.width,t.height),f);if(v===f)return{source:p,width:f,height:f,bounds:d};const y=document.createElement("canvas");y.width=v,y.height=v;const x=y.getContext("2d");if(!x)throw new Error("2D canvas context unavailable");return x.drawImage(p,0,0,f,f,0,0,v,v),{source:y,width:v,height:v,bounds:d}}function wE(o,t,e){let i=fE(o,t/Math.max(1,e)),n=yv(o,i,t);for(;n>bE&&i>0;)i--,n=yv(o,i,t);return{zoom:i,gridSize:n,mPerPixel:X2(o,i)/Md}}function yv(o,t,e){const i=Math.ceil(e/2/X2(o,t));return Math.max(3,2*i+1)}class Z2{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=t.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(t,e){return q2(t,e,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class ss{static ENDPOINTS=["https://overpass-api.de/api/interpreter","https://overpass.kumi.systems/api/interpreter","https://overpass.private.coffee/api/interpreter"];static FRANCE_ENDPOINT="https://overpass.openstreetmap.fr/api/interpreter";static FRANCE={south:41.3,west:-5.2,north:51.1,east:9.6};static endpointsFor(t,e=ss.ENDPOINTS){const i=/\((-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)\)/.exec(t);if(!i)return[...e];const[n,s,r,a]=i.slice(1).map(Number),c=(n+r)/2,h=(s+a)/2,l=ss.FRANCE;return c>=l.south&&c<=l.north&&h>=l.west&&h<=l.east?[ss.FRANCE_ENDPOINT,...e.filter(d=>d!==ss.FRANCE_ENDPOINT)]:[...e]}fetchImpl;endpoints;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.endpoints=t.endpoints}static queue=Promise.resolve();static HANG_MS=4e4;static RETRY_MS=4e3;query(t){return this.queued(()=>this.ask(t))}queued(t){const e=ss.queue.then(t,t);return ss.queue=e.catch(()=>{}),e}async ask(t){let e;for(const i of this.endpoints??ss.endpointsFor(t))for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(t)}`,{signal:AbortSignal.timeout(ss.HANG_MS)});if(s.ok)return await s.json();if(e=new Error(`${new URL(i).host} refused (${s.status})`),s.status!==429&&s.status!==504)break}catch(s){e=new Error(`${new URL(i).host} unreachable (${String(s)})`);break}await new Promise(s=>setTimeout(s,ss.RETRY_MS))}throw e??new Error("No Overpass instance answered")}}class Ra{attribution="Roads © OpenStreetMap contributors, as surveyed today";contemporary=!0;static DRIVABLE=["motorway","trunk","primary","secondary","tertiary","unclassified","residential","service","track","motorway_link","trunk_link","primary_link","secondary_link","tertiary_link"];static WIDTH_M={motorway:11,trunk:9,primary:8,secondary:7,tertiary:6.5,unclassified:5.5,residential:5.5,service:4,track:3.5};static DEFAULT_WIDTH_M=5;client;constructor(t={}){this.client=new ss(t)}async getRoads(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];way["highway"~"^(${Ra.DRIVABLE.join("|")})$"](${e});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(t){const e=[];for(const i of t.elements??[]){const n=i.geometry,s=i.tags;!s||!n||n.length<2||e.push({id:`osm-${i.id??e.length}`,name:s.name,surface:Ra.surfaceOf(s),widthM:Ra.widthOf(s),...Ra.paintOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return e}static paintOf(t){const e=t.highway??"",i=t.junction==="roundabout"||t.junction==="circular",n=t.oneway,s=n==="yes"||n==="1"||n==="true"||n===void 0&&(e==="motorway"||i),r=n==="-1"||n==="reverse",a=Number.parseInt(t.lanes??"",10),c=Number.parseInt(t.maxspeed??"",10),h=i?"roundabout":e==="motorway"?"motorway":e.endsWith("_link")?"slip":(e==="trunk"||e==="primary")&&(s||r)?"dual":e?"road":void 0;return{...h?{kind:h}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...n!==void 0||e==="motorway"||i?{direction:r?"backward":s?"forward":"both"}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{}}}static widthOf(t){const e=Number.parseFloat(t.width??t.est_width??"");if(Number.isFinite(e)&&e>0)return e;const i=Number.parseInt(t.lanes??"",10);return Number.isFinite(i)&&i>0?i*3.5:Ra.WIDTH_M[t.highway]??Ra.DEFAULT_WIDTH_M}static surfaceOf(t){const e=t.surface;return e==="dirt"||e==="earth"||e==="mud"?"dirt":e==="gravel"||e==="fine_gravel"||e==="compacted"||e==="ground"||e==="sand"||e==="unpaved"?"gravel":e?"paved":t.highway==="track"?"gravel":"paved"}}const d0="https://ufoathome.org/roads/index.json";class zc{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??zc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Roads © OpenStreetMap contributors"}get contemporary(){return this.contemporaryRead??this.fallback?.contemporary??!0}async getRoads(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRoads(t);return this.attributionRead=this.fallback.attribution,this.contemporaryRead=this.fallback.contemporary,i}async held(t){let e;try{e=await this.load()}catch{return}const i=e.find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.ways)?(this.attributionRead=s.attribution,this.contemporaryRead=s.contemporary,s.ways):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const t=this.indexUrls.join(`
|
|
2404
|
-
`);let e=zc.shared.get(t);return e||(e=this.fetchFirstAvailable(),zc.shared.set(t,e),e.then(i=>{i.length===0&&zc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.
|
|
2405
|
-
`);let e=Bc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Bc.shared.set(t,e),e.then(i=>{i.length===0&&Bc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.0")}`,e=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(e&&e!==f0?[e,f0]:[f0]).map(i=>i+t)}}class es{constructor(t){this.water=t}static CACHE_NAME="rr0-water";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static asked=new Map;get attribution(){return this.water.attribution}async getWater(t){const e=es.key(t);let i=es.asked.get(e);return i===void 0&&(i=this.recalled(e,t),es.asked.set(e,i),i.catch(()=>es.asked.delete(e))),structuredClone(await i)}static forget(){es.asked.clear()}static key(t){return`v${es.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}async recalled(t,e){const i=await es.openCache(),n=es.request(t);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:c}=await r.json();if(Date.now()-a<es.MAX_AGE_MS&&Array.isArray(c))return c;await i.delete(n)}}catch{}const s=await this.water.getWater(e);return i&&es.store(i,n,s),s}static async store(t,e,i){try{const n={savedAt:Date.now(),surfaces:i};await t.put(e,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await t.keys();for(const r of s.slice(0,Math.max(0,s.length-es.MAX_STORED)))await t.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(es.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__water__/${encodeURIComponent(t)}`)}}class Pa{attribution="Railways © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Voie ferrée principale":{kind:"rail"},LGV:{kind:"rail",highSpeed:!0},"Voie de service":{kind:"rail",service:!0},Métro:{kind:"subway"},Tramway:{kind:"tram"},"Transport urbain":{kind:"light_rail"},"Funiculaire ou crémaillère":{kind:"funicular"}};static GAUGE_MM={Normale:1435,Etroite:1e3,Étroite:1e3,Large:1668};static NO_ALTITUDE=-1e3;platform;constructor(t={}){this.platform=new Ce(t)}static covers(t){return Ce.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRailways(t){return(await this.platform.railways(t)).flatMap((i,n)=>Pa.linesOf(i,n))}static linesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=Pa.BY_NATURE[String(t.properties.nature??"")];if(!r)return[];const a=String(t.properties.cleabs??`ign-rail-${e}`),c=Number(t.properties.nombre_de_voies),h=Number(t.properties.position_par_rapport_au_sol),l=t.properties.cpx_toponyme,u=Pa.GAUGE_MM[String(t.properties.largeur??"")]??1435,d=Pa.electrificationOf(r.kind,u,t.properties.electrifie);return s.flatMap((f,p)=>{const g=f.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>Pa.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.length>1?`${a}-${p}`:a,...typeof l=="string"&&l.length>0?{name:l}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:u,tracks:Number.isInteger(c)&&c>0?c:1,...d?{electrification:d}:{},level:Number.isFinite(h)?h:0,points:g}]})}static electrificationOf(t,e,i){if(i===!1)return"none";if(i===!0){if(t==="subway")return"third_rail";if(!(t==="funicular"||e<1435))return"overhead"}}}class Mn{static NEAR_M=15;static ALIGNED_DEG=30;static SAMPLE_M=10;static ROUTES="train|subway|light_rail|tram|monorail";static KINDS="rail|light_rail|subway|tram|narrow_gauge|funicular|preserved";client;constructor(t={}){this.client=new ss(t)}async named(t,e){if(t.length===0)return[...t];const i=`${e.south},${e.west},${e.north},${e.east}`,n=`[out:json][timeout:120];way["railway"~"^(${Mn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${Mn.ROUTES})$"];out body;`;return Mn.apply(t,await this.client.query(n),e)}static apply(t,e,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=Mn.ways(e,n);return s.length===0?[...t]:t.map(r=>{const a=r.points.map(v=>oe(v.lat,v.lng,n.lat,n.lng)),c=new Map,h=new Map,l=new Map;let u=0;const d=s.filter(v=>v.service===!!r.service);for(const v of Mn.samples(a)){u++;const y=Mn.waysAt(d,v);if(y.length===0)continue;const[x]=y;x.name&&c.set(x.name,(c.get(x.name)??0)+1),x.voltageV&&h.set(x.voltageV,(h.get(x.voltageV)??0)+1);for(const M of new Set(y.flatMap(b=>b.services)))l.set(M,(l.get(M)??0)+1)}const f=v=>[...v.entries()].sort((y,x)=>x[1]-y[1])[0]?.[0],p=r.name??f(c),g=r.voltageV??(r.electrification==="none"?void 0:f(h)),m=[...l.entries()].filter(([,v])=>v*4>=u).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...p?{name:p}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}static serviceOf(t){const e=t.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return e||[t.network,t.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(t){const e=new Map;for(const i of t.elements??[]){if(i.type!=="relation"||!i.tags)continue;const n=Mn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=e.get(s.ref)??new Set;r.add(n),e.set(s.ref,r)}}return e}static voltageOf(t){const e=Number.parseInt((t.voltage??"").split(";")[0],10);return Number.isFinite(e)&&e>0?e:void 0}static ways(t,e){const i=Mn.servicesByWay(t),n=[];for(const s of t.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=Mn.voltageOf(r);n.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(s.id??-1)??[]],path:s.geometry.map(c=>oe(c.lat,c.lon,e.lat,e.lng))})}return n}static samples(t){const e=[];for(let i=0;i<t.length-1;i++){const n=Math.hypot(t[i+1].x-t[i].x,t[i+1].z-t[i].z);if(n<1e-6)continue;const s=(t[i+1].x-t[i].x)/n,r=(t[i+1].z-t[i].z)/n;for(let a=Mn.SAMPLE_M/2;a<n;a+=Mn.SAMPLE_M)e.push({x:t[i].x+s*a,z:t[i].z+r*a,dx:s,dz:r})}return e}static waysAt(t,e){const i=Math.cos(Mn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of t){let r;for(let a=0;a<s.path.length-1;a++){const c=s.path[a],h=s.path[a+1],l=h.x-c.x,u=h.z-c.z,d=Math.hypot(l,u);if(d<1e-6||Math.abs((l*e.dx+u*e.dz)/d)<i)continue;const f=Math.max(0,Math.min(1,((e.x-c.x)*l+(e.z-c.z)*u)/(d*d))),p=Math.hypot(e.x-(c.x+l*f),e.z-(c.z+u*f));p<=Mn.NEAR_M&&(r===void 0||p<r)&&(r=p)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Hc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(t={}){this.client=new ss(t)}async getRailways(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Hc.KINDS.join("|")})$"](${e})->.w;.w out tags geom;rel(bw.w)["route"~"^(${Mn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(t){const e=[],i=Mn.servicesByWay(t);for(const n of t.elements??[]){const s=n.geometry,r=n.tags;if(n.type==="relation"||!r||!s||s.length<2)continue;const a=[...i.get(n.id??-1)??[]].sort(),c=Mn.voltageOf(r),h=Hc.kindOf(r),l=Number.parseInt((r.gauge??"").split(";")[0],10),u=Number.parseInt(r.tracks??"",10),d=Hc.electrificationOf(r.electrified),f=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;e.push({id:`osm-rail-${n.id??e.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...c?{voltageV:c}:{},kind:h,...r.service||r.usage==="industrial"?{service:!0}:{},...f?{highSpeed:!0}:{},gaugeMm:Number.isFinite(l)&&l>300?l:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(u)&&u>0?u:1,...d?{electrification:d}:{},level:Hc.levelOf(r),points:s.map(p=>({lat:p.lat,lng:p.lon}))})}return e}static kindOf(t){switch(t.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(t){if(t!==void 0){if(t==="no")return"none";if(t==="contact_line"||t==="yes")return"overhead";if(t==="rail"||t==="4th_rail"||t==="ground-level_power_supply")return"third_rail"}}static levelOf(t){const e=Number.parseInt(t.layer??"",10);return t.tunnel&&t.tunnel!=="no"?Number.isFinite(e)&&e<0?e:-1:t.covered==="yes"&&t.location==="underground"?-1:t.bridge&&t.bridge!=="no"?Number.isFinite(e)&&e>0?e:1:0}}class AE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(t){if(!Pa.covers(t))return this.worldwide.getRailways(t);let e;try{if(e=await this.regional.getRailways(t),e.length>0)return e}catch{}try{return await this.worldwide.getRailways(t)}catch(i){if(e)return e;throw i}}}class Zi{constructor(t,e=Date.now){this.railways=t,this.now=e}static CACHE_NAME="rr0-railways";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static RETRY_AFTER_MS=300*1e3;static asked=new Map;static failedAt=-1/0;get attribution(){return this.railways.attribution}get contemporary(){return this.railways.contemporary}async getRailways(t){const e=Zi.key(t);let i=Zi.asked.get(e)??Zi.containing(t);if(i===void 0){const n=this.recalled(e,t);i={bounds:t,answer:n},Zi.asked.set(e,i),n.catch(()=>Zi.asked.delete(e))}return structuredClone(await i.answer)}static forget(){Zi.asked.clear(),Zi.failedAt=-1/0}static key(t){return`v${Zi.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}static containing(t){for(const e of Zi.asked.values()){const i=e.bounds;if(i.north>=t.north&&i.south<=t.south&&i.east>=t.east&&i.west<=t.west)return e}}async recalled(t,e){const i=await Zi.openCache(),n=Zi.request(t);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:c,lines:h}=await a.json();if(Array.isArray(h)){if(this.now()-c<Zi.MAX_AGE_MS)return h;s=h}}}catch{}if(this.now()-Zi.failedAt<Zi.RETRY_AFTER_MS){if(s)return s;throw new Error("The railway survey failed a moment ago: not asked again yet")}let r;try{r=await this.railways.getRailways(e)}catch(a){if(Zi.failedAt=this.now(),s)return s;throw a}return i&&Zi.store(i,n,{savedAt:this.now(),lines:r}),r}static async store(t,e,i){try{await t.delete(e),await t.put(e,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const n=await t.keys();for(const s of n.slice(0,Math.max(0,n.length-Zi.MAX_STORED)))await t.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Zi.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__railways__/${encodeURIComponent(t)}`)}}const p0="https://ufoathome.org/railways/index.json";class Gc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Gc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRailways(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.lines)?(this.attributionRead=s.attribution,s.lines):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const t=this.indexUrls.join(`
|
|
2406
|
-
`);let e=Gc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Gc.shared.set(t,e),e.then(i=>{i.length===0&&Gc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.0")}`,e=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(e&&e!==p0?[e,p0]:[p0]).map(i=>i+t)}}function J2(){return{elevation:_E(),imagery:j2(),roads:TE(),water:RE(),railways:IE()}}function _E(){return new xE(new Te,new ME)}function j2(){return new Z2}function TE(){return new zc({fallback:new SE(new Oa,new Ra)})}function RE(){return new Bc({fallback:new es(new EE(new kl,new lo))})}function IE(){return new Gc({fallback:new Zi(new AE(new Pa,new Hc))})}const DE=new Set,Lr="show-observer-map",Nr="hide-milestones",Io="minified";class Ue extends HTMLElement{static get observedAttributes(){return["src",Lr,Nr,Io]}shadow;stageElement;canvas;canvasRenderer;chromeCanvas;chromeRenderer;chromeResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>{this.chromeDirty&&this.refresh()});chromeDirty=!1;tooltip;toolbar;issuesBox;issuesButton;issuesPanel;playPauseButton;fullscreenButton;cornerButtons;observerMapButton;referencesButton;tracesButton;tracesShownState=!0;referenceOpacityInput;referencesShownState=!0;accountHidden=!1;referenceViews=new Map;referencesMenu;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;mapZoomInButton;mapZoomOutButton;mapFitButton;observerMapView=new si;observerMapDrag;suppressObserverMapClick=!1;observerMapImageryTimer;observerPlacing=!1;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;timePill;muteButton;volumeInput;controlsRow;momentsBox;momentsButton;momentsCurrent;momentsMenu;moreButton;controlsRight;seekSegments;seekDot;playerTitleBox;seekPreview;seekPreviewCanvas;seekPreviewTitle;seekPreviewTime;observerPath;observerMapBounds;observerMapImagery;observerMapImageryBounds;observerMapImageryViewWidth=0;observerMapImageryLoading=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Gf.create();issues=[];issueCheck=0;sightingAudio=new ZS;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;static LIVE_BODY_MAX_RATE=2;get steadyBody(){return this.steadyObserver||this.player.playbackState!=="playing"||this.player.playbackRate>Ue.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=B2;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const t=this.controlsRow,e=t.classList.contains("more-open"),i=()=>t.scrollWidth>t.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,t.classList.remove("narrow","more-open","nomoments","compact","tiny"),t.clientWidth>0&&i()){t.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;t.classList.add(s)}e&&t.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(t){this.controlsRow.classList.toggle("more-open",!t),this.updateMoreButton()}updateMoreButton(){const t=this.controlsRow.classList.contains("more-open");Ue.setIcon(this.moreButton,t?Zt.UNFOLDED:Zt.FOLDED);const e=t?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=e,this.moreButton.setAttribute("aria-label",e),this.moreButton.setAttribute("aria-expanded",String(t))}addControl(t){this.controlsRight.insertBefore(t,this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null),this.fitControls()}observerMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeObserverMap());resizeObserverMap(){this.observerMapPanel.hidden||(this.sizeObserverMapCanvas(),this.paintObserverMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=t=>{t.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=t=>{const e=this.canvasPointFromEvent(t),i=e&&this.shapeAt(e.x,e.y),n=this.said.read(i?.shape.title);if(!n){this.tooltip.hidden=!0;return}this.tooltip.textContent=n,this.tooltip.hidden=!1;const s=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-s.left+12}px`,this.tooltip.style.top=`${t.clientY-s.top+12}px`};handleObserverMapPointerMove=t=>{if(this.dragObserverMap(t))return;const e=this.observerMapTargetFrom(t);if(!e){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(t,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(t,e.label)};showObserverMapTooltip(t,e){this.tooltip.textContent=e,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-i.left+12}px`,this.tooltip.style.top=`${t.clientY-i.top+12}px`}handleObserverMapClick=t=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const e=this.observerMapTargetFrom(t);if(!e){this.observerPlacing&&this.placeObserverFrom(t);return}if(e.kind==="milestone"&&e.t!==void 0){this.player.seek(e.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:e.lat,lng:e.lng,kind:e.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(t){const e=this.observerMapCanvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return this.observerMapRenderer.hitTest((t.clientX-e.left)/e.width*this.observerMapCanvas.width,(t.clientY-e.top)/e.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=t=>{t.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,moved:!1})};handleObserverMapPointerUp=t=>{const e=this.observerMapDrag;!e||e.pointerId!==t.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),e.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(t.pointerId)&&this.observerMapCanvas.releasePointerCapture(t.pointerId)))};dragObserverMap(t){const e=this.observerMapDrag;if(!e||e.pointerId!==t.pointerId)return!1;if(!e.moved){if(Math.hypot(t.clientX-e.startX,t.clientY-e.startY)<Ue.OBSERVER_MAP_DRAG_PX)return!1;e.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(t.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((t.clientX-e.lastX)/i.width,(t.clientY-e.lastY)/i.height),this.observerMapViewChanged()),e.lastX=t.clientX,e.lastY=t.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=t=>{t.preventDefault();const e=this.observerMapCanvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=t.deltaMode===0?t.deltaY:t.deltaY*40;this.zoomObserverMap((t.clientX-e.left)/e.width,(t.clientY-e.top)/e.height,Math.exp(-i*.002))};zoomObserverMap(t,e,i){this.observerMapView.zoomAt(t,e,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=si.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=si.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Ue.OBSERVER_MAP_IMAGERY_DELAY_MS))}static OBSERVER_MAP_FOLLOW_MARGIN=.1;static OBSERVER_MAP_IMAGERY_DELAY_MS=300;get observerMapViewBounds(){return this.observerMapBounds&&this.observerMapView.boundsWithin(this.observerMapBounds)}placeObserverFrom(t){const e=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!e||i.width===0||i.height===0)return;const n=si.pointAt(e,(t.clientX-i.left)/i.width,(t.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:n,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${GS}</style>${HS}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new gh(this.canvas.getContext("2d")),this.chromeCanvas=this.shadow.getElementById("chrome"),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.issuesBox=this.shadow.getElementById("issues"),this.issuesButton=this.shadow.getElementById("issues-button"),this.issuesPanel=this.shadow.getElementById("issues-panel"),this.issuesButton.addEventListener("click",a=>{a.stopPropagation(),this.issuesPanel.hidden=!this.issuesPanel.hidden,this.issuesButton.setAttribute("aria-expanded",String(!this.issuesPanel.hidden))}),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.tracesButton=this.shadow.getElementById("traces"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.referencesMenu=this.shadow.getElementById("references-menu"),this.milestonesButton=this.shadow.getElementById("milestones"),this.observerMapPanel=this.shadow.getElementById("observer-map-panel"),this.observerMapCanvas=this.shadow.getElementById("observer-map-canvas"),this.observerMapRenderer=new ho(this.observerMapCanvas.getContext("2d")),this.mapZoomInButton=this.shadow.getElementById("map-zoom-in"),this.mapZoomOutButton=this.shadow.getElementById("map-zoom-out"),this.mapFitButton=this.shadow.getElementById("map-fit"),this.seekInput=this.shadow.getElementById("seek"),this.playbackFlash=this.shadow.getElementById("playback-flash"),this.milestoneMarks=this.shadow.getElementById("milestone-marks"),this.milestoneCaption=this.shadow.getElementById("milestone-caption"),this.timeStartLabel=this.shadow.getElementById("time-start"),this.timeEndLabel=this.shadow.getElementById("time-end"),this.timePill=this.shadow.getElementById("time"),this.muteButton=this.shadow.getElementById("mute"),this.controlsRight=this.shadow.getElementById("controls-right"),this.seekSegments=this.shadow.getElementById("seek-segments"),this.seekDot=this.shadow.getElementById("seek-dot"),this.playerTitleBox=this.shadow.getElementById("player-title"),this.seekPreview=this.shadow.getElementById("seek-preview"),this.seekPreviewCanvas=this.shadow.getElementById("seek-preview-canvas"),this.seekPreviewTitle=this.shadow.getElementById("seek-preview-title"),this.seekPreviewTime=this.shadow.getElementById("seek-preview-time"),this.timePill.addEventListener("click",()=>this.toggleTimeDisplay()),this.timePill.addEventListener("keydown",a=>{a.key!=="Enter"&&a.key!==" "||(a.preventDefault(),this.toggleTimeDisplay())}),this.volumeInput=this.shadow.getElementById("volume"),this.controlsRow=this.shadow.querySelector(".controls"),this.momentsBox=this.shadow.getElementById("moments"),this.momentsButton=this.shadow.getElementById("moments-button"),this.momentsCurrent=this.shadow.getElementById("moments-current"),this.momentsMenu=this.shadow.getElementById("moments-menu"),this.momentsButton.addEventListener("click",()=>this.toggleMomentsMenu()),this.moreButton=this.shadow.getElementById("controls-more"),this.moreButton.addEventListener("click",()=>this.setControlsFolded(this.controlsRow.classList.contains("more-open"))),this.muteButton.addEventListener("click",()=>this.toggleMuted()),this.miniPlayed=this.shadow.getElementById("mini-played"),this.miniRemaining=this.shadow.getElementById("mini-remaining"),this.miniMuteButton=this.shadow.getElementById("mini-mute"),this.miniDot=this.shadow.getElementById("mini-dot"),this.miniScrubTime=this.shadow.getElementById("mini-scrub-time");const e=this.shadow.getElementById("mini-bar"),i=e.querySelector(".mini-track"),n=a=>{const c=i.getBoundingClientRect(),h=this.player.seekableDuration;if(c.width<=0||h<=0)return;const l=Math.min(Math.max((a.clientX-c.left)/c.width,0),1)*h;this.player.seek(l),this.miniScrubTime.textContent=this.formatElapsedAt(l),this.miniScrubTime.style.left=this.miniDot.style.left};let s=!1;e.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),e.setPointerCapture(a.pointerId),e.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),e.addEventListener("pointermove",a=>{e.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{e.classList.contains("scrubbing")&&(e.classList.remove("scrubbing"),e.hasPointerCapture(a.pointerId)&&e.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&this.play())};e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r),e.addEventListener("click",a=>a.stopPropagation()),this.miniMuteButton.addEventListener("click",a=>{a.stopPropagation(),this.toggleMuted()}),this.stageElement.addEventListener("pointerenter",this.handleMinifiedEnter),this.stageElement.addEventListener("pointerleave",this.handleMinifiedLeave),this.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>{this.player.seek(this.snapSeekToMark(Number(this.seekInput.value))),this.announceReveal()}),this.seekInput.addEventListener("pointerdown",a=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(a),this.beginTouchScrub(a)}),this.seekInput.addEventListener("pointerup",a=>{this.seekSnapArmed=!1,this.endTouchScrub(a)}),this.seekInput.addEventListener("pointercancel",a=>this.endTouchScrub(a)),this.seekInput.addEventListener("pointermove",a=>{this.nameMarkUnder(a),this.hoverSeek(a),this.touchScrub(a)}),this.seekInput.addEventListener("pointerleave",()=>{this.seekInput.removeAttribute("title"),this.leaveSeek()}),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.stageElement.addEventListener("pointerdown",()=>{this.handlePointerDown(),this.touchedStage()},!0);for(const a of["touchend","click"])this.stageElement.addEventListener(a,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",a=>{if(!(!this.enableClickToPlay||this.minified)){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}a.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",a=>{!this.enableClickToPlay||this.minified||(a.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),document.addEventListener("pointerdown",this.handleMomentsDismiss,!0),document.addEventListener("keydown",this.handleMomentsDismiss,!0),document.addEventListener("visibilitychange",this.handleVisibility),window.addEventListener("pagehide",this.handleHidden),document.addEventListener("pointerup",this.handlePointerRelease,!0),document.addEventListener("pointercancel",this.handlePointerRelease,!0),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.chromeResizeObserver?.observe(this.chromeCanvas),this.controlsFitObserver?.observe(this.controlsRow),this.controlsFitObserver?.observe(this.controlsRow.querySelector(".controls-left")),typeof MutationObserver<"u"&&(this.controlsMutations=new MutationObserver(()=>this.fitControls()),this.controlsMutations.observe(this.controlsRight,{attributes:!0,attributeFilter:["hidden"],childList:!0,subtree:!0})),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.refresh()}connectedCallback(){this.saidTexts=void 0,this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),document.removeEventListener("pointerdown",this.handleMomentsDismiss,!0),document.removeEventListener("keydown",this.handleMomentsDismiss,!0),document.removeEventListener("visibilitychange",this.handleVisibility),window.removeEventListener("pagehide",this.handleHidden),document.removeEventListener("pointerup",this.handlePointerRelease,!0),document.removeEventListener("pointercancel",this.handlePointerRelease,!0),window.clearTimeout(this.controlsIdleTimer),this.observerMapResizeObserver?.disconnect(),this.chromeResizeObserver?.disconnect(),this.controlsFitObserver?.disconnect(),this.controlsMutations?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===Lr&&this.applyObserverMapDefault(),t===Nr&&this.setMilestonesShown(!this.hasAttribute(Nr)),t===Io){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&e===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(Io)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(tx)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const t=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",t),t&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(t){this.sightingData=await Ha.recording(t)}get sightingData(){return JS(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=QS(t),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(t,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.started=!1,this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault(),this.minified&&this.minifiedHovered&&this.play()}set playerTitle(t){this.titleOverride=t,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const t=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=t,this.playerTitleBox.hidden=t===""}get recordingIssues(){return this.issues}async reportIssues(t,e){const i=++this.issueCheck;let n=[];try{const{default:s}=await Re(async()=>{const{default:r}=await import("./sightingSchema-Bc1JhWrZ.js");return{default:r}},[],import.meta.url);n=new Vs(s).issues(t)}catch{}i===this.issueCheck&&(this.issues=[...n,...e.loadIssues],vh.warn(this.issues,e.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(CE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const t=this.issues.length;this.issuesBox.hidden=t===0,this.shadow.getElementById("issues-count").textContent=String(t);const e=this.messages.recordingIssues.replace("{count}",String(t));this.issuesButton.title=e,this.issuesButton.setAttribute("aria-label",e),this.shadow.getElementById("issues-title").textContent=e,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=vh.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(t){this.soundPreview=t,this.sightingAudio.resume(),this.sightingAudio.setSound(t)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(t){this.player.seek(t)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(t){t!==this.loopEnabled&&this.toggleLoop()}play(){if(!(this.player.seekableDuration<=0||this.playbackState==="playing")){if(this.clockHeld){this.playAfterHold=!0,this.announcePlayRequest();return}this.togglePlayPause()}}get playRequested(){return this.playbackState==="playing"||this.playAfterHold}announcePlayRequest(){this.announceReveal(),this.dispatchEvent(new CustomEvent("playrequest"))}announceReveal(){this.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("revealrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(t){if(t!==this.clockHeld){if(this.clockHeld=t,t){if(this.playbackState!=="playing")return;this.playAfterHold=!0,this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton();return}this.playAfterHold&&(this.playAfterHold=!1,!(this.player.seekableDuration<=0||this.playbackState==="playing")&&(this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton()))}}pause(){this.playAfterHold=!1,this.playbackState==="playing"&&this.togglePlayPause()}get positionLabel(){return this.timeStartLabel.textContent??""}get durationLabel(){return this.timeEndLabel.textContent??""}get showingClockTime(){return this.canShowClockTime}get canSwitchTimeDisplay(){return this.realStartMs!==void 0}toggleTimeDisplay(){this.canSwitchTimeDisplay&&(this.showClockTime=!this.showClockTime,this.updateTimeLabels(),this.updateTimeLabelTitles(),this.dispatchEvent(new CustomEvent("timedisplaychange",{bubbles:!0,composed:!0})))}get canShowClockTime(){return this.realStartMs!==void 0&&this.showClockTime}set showToolbar(t){this.toolbar.classList.toggle("hidden",!t),t?this.controlsRight.appendChild(this.fullscreenButton):this.cornerButtons.appendChild(this.fullscreenButton)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(t){this.currentSighting.event.durationSeconds=t,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(t){const e=new Set(t);e.size===this.highlightedSourceIds.size&&[...e].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=e,this.refresh())}hasVisibleShapeAt(t,e){return this.shapeAt(t,e)!==void 0}refresh(){this.applyFrameFormat(),this.updateMuteButton(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.updateTracesButton(),this.player.seek(this.player.time)}repaintOverlay(){this.quietFrame=!0;try{this.player.seek(this.player.time)}finally{this.quietFrame=!1}}quietFrame=!1;hostControls(t){const e=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of e)this.controlsRight.insertBefore(n,i)}}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}get severalReferences(){return this.currentSighting.references.length>1}toggleReferences(){if(this.severalReferences){this.toggleReferencesMenu();return}this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const t=this.currentSighting.references;!this.referenceOpacityTouched&&t.length>0&&(this.referenceOpacityInput.value=String(t[0].opacity));for(const e of[...this.referenceViews.keys()])t.some(i=>i.id===e)||this.referenceViews.delete(e);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(t){let e=this.referenceViews.get(t.id);return e||(e={shown:!0,opacity:t.opacity},this.referenceViews.set(t.id,e)),e}toggleReferencesMenu(){this.referencesMenu.hidden?this.openReferencesMenu():this.closeReferencesMenu()}openReferencesMenu(){this.renderReferencesMenu(),this.referencesMenu.hidden=!1,this.placeReferencesMenu(),this.referencesButton.setAttribute("aria-expanded","true"),document.addEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.addEventListener("keydown",this.handleReferencesMenuKey,!0)}closeReferencesMenu(){this.referencesMenu.hidden||(this.referencesMenu.hidden=!0,this.referencesButton.setAttribute("aria-expanded","false"),document.removeEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.removeEventListener("keydown",this.handleReferencesMenuKey,!0))}handleReferencesMenuOutside=t=>{const e=t.composedPath();e.includes(this.referencesMenu)||e.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=t=>{t.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const t=this.referencesButton.getBoundingClientRect(),e=this.referencesMenu,i=4;e.style.bottom=`${Math.max(i,window.innerHeight-t.top+i)}px`,e.style.top="auto";const n=e.getBoundingClientRect().width;e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const t=this.currentSighting.references.map(e=>{const i=this.viewOfReference(e),n=this.said.read(e.title)??e.id,s=document.createElement("div");s.className="reference-row";const r=document.createElement("label"),a=document.createElement("input");a.type="checkbox",a.checked=i.shown;const c=document.createElement("span");c.textContent=n,c.title=n,r.append(a,c);const h=document.createElement("input");return h.type="range",h.min="0",h.max="1",h.step="0.05",h.value=String(i.opacity),h.title=this.messages.referenceOpacity,h.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),h.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,h.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),h.addEventListener("input",()=>{i.opacity=Number(h.value),this.dispatchReferenceView()}),s.append(r,h),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...t)}updateReferencesButton(){const t=this.currentSighting.references.length>0,e=this.severalReferences,i=e?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState||e,this.referencesButton.setAttribute("aria-pressed",String(i)),e?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Ue.setIcon(this.referencesButton,i?Zt.PICTURES_ON:Zt.PICTURES_OFF);const n=e?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=n,this.referencesButton.setAttribute("aria-label",n),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}get tracesShown(){return this.tracesShownState}toggleTraces(){this.tracesShownState=!this.tracesShownState,this.updateTracesButton(),this.updateObserverMap(),this.dispatchEvent(new CustomEvent("traceview",{detail:{shown:this.tracesShown}}))}updateTracesButton(){this.tracesButton.hidden=this.currentSighting.traces.length===0,this.tracesButton.setAttribute("aria-pressed",String(this.tracesShownState)),Ue.setIcon(this.tracesButton,this.tracesShownState?Zt.TRACES_ON:Zt.TRACES_OFF);const t=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=t,this.tracesButton.setAttribute("aria-label",t)}dispatchReferenceView(){const t=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(e=>[e.id,{...this.viewOfReference(e)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:t}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?ul(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...e.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/t,0),1)*100}%`;const s=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${s} — ${r}`:s;return n.title=a,n.setAttribute("aria-label",a),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n})),this.refreshSeekSegments(t,e.map(i=>i.t)),this.refreshMomentsPicker(e)}refreshMomentsPicker(t){const e=this.milestonesShown&&t.length>0;this.momentsBox.hidden=!e,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...t.map(i=>{const n=document.createElement("li"),s=document.createElement("button");s.type="button",s.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return s.textContent=a?`${r} — ${a}`:r,s.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),n.appendChild(s),n})),this.momentsButton.title=this.messages.moments,this.showCurrentMoment(void 0)}showCurrentMoment(t){const i=(t?this.said.read(t.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=t!==void 0&&Number(n.dataset.t)===t.t;n.getAttribute("aria-current")==="true"!==s&&n.setAttribute("aria-current",String(s))}}toggleMomentsMenu(){this.momentsMenu.hidden?(this.momentsMenu.hidden=!1,this.momentsButton.setAttribute("aria-expanded","true")):this.closeMomentsMenu()}closeMomentsMenu(){this.momentsMenu.hidden=!0,this.momentsButton.setAttribute("aria-expanded","false")}handleMomentsDismiss=t=>{if(!this.momentsMenu.hidden){if(t instanceof KeyboardEvent){t.key==="Escape"&&this.closeMomentsMenu();return}t.composedPath().some(e=>e===this.momentsMenu||e===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(t,e){const n=[0,...this.milestonesShown&&t>0?[...new Set(e.filter(r=>r>0&&r<t))].sort((r,a)=>r-a):[],Math.max(t,0)];this.seekSegmentList=[];const s=[];for(let r=0;r<n.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(n[r+1]-n[r],1));const c=document.createElement("i");c.className="seek-hover";const h=document.createElement("i");h.className="seek-played",a.append(c,h),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:h,hover:c})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(t,e){const i=t.end-t.start,n=i>0?(e-t.start)/i:e>=t.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintMiniProgress(t){const e=this.player.seekableDuration,i=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(t)}miniDot;miniScrubTime;paintSeekProgress(t){for(const i of this.seekSegmentList)i.played.style.width=Ue.fillOf(i,t);const e=this.player.seekableDuration;this.seekDot.style.left=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`}hoverSeek(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((f,p)=>{f.hover.style.width=Ue.fillOf(f,s),f.element.classList.toggle("hovered",s>=f.start&&(s<f.end||p===r))});const a=this.milestonesShown?this.sighting.milestones:[],c=a.length>0?l0(a,s):void 0,h=c?this.said.read(c.label)??"":"",l=c?this.said.read(c.note):void 0,u=l?`${h} — ${l}`:h;this.seekPreviewTitle.textContent=u,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const d=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*e.width-d/2,0),Math.max(e.width-d,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const t of this.seekSegmentList)t.hover.style.width="0",t.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(t){const e=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=e===void 0,e?.(t,this.seekPreviewCanvas)}paintChrome(t){const e=this.chromeCanvas.getContext("2d"),i=this.overlayPainter!==void 0||this.selectionShown;if(!i&&!this.chromeDirty)return;const n=this.chromeCanvas.clientWidth,s=this.chromeCanvas.clientHeight;if(!e||typeof e.setTransform!="function"||n===0||s===0){t(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),c=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==c&&(this.chromeCanvas.height=c),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,a,c),this.chromeDirty=!1,i&&(e.setTransform(a/this.canvas.width,0,0,c/this.canvas.height,0,0),this.chromeRenderer??=new gh(e),this.chromeDirty=!0,t(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(t){if(t.pointerType!=="mouse"){this.scrubbingPointer=t.pointerId;try{this.seekInput.setPointerCapture(t.pointerId)}catch{}this.seekToPointer(t)}}touchScrub(t){t.pointerId===this.scrubbingPointer&&this.seekToPointer(t)}endTouchScrub(t){t.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(t))}seekToPointer(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(t){const e=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(e<=0||i<=0)return;const n=Ue.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-t)>n||(!s||Math.abs(a-t)<Math.abs(s.t-t))&&(s={t:a,name:r.title})}return s}snapSeekToMark(t){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(t)?.t??t):t}nameMarkUnder(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=(t.clientX-e.left)/e.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(t){const e=this.milestonesShown&&this.sighting.milestones.length>0?l0(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,this.showCurrentMoment(e),!e)return;const i=document.createElement("b");i.textContent=this.said.read(e.label)??"";const n=this.said.read(e.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(t){const e=this.exposureTimes(t),i=1/e.length;return e.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(t=this.currentTime){const e=qs.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Ue.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Ue.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Ue.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Ue.EXPOSURE_STEP_PX),s=Math.min(Ue.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(e.fromMs+e.ms*a/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,a]of i){const c=n.get(r);if(!c)continue;const h=c.bounds.x+c.bounds.width/2-(a.bounds.x+a.bounds.width/2),l=c.bounds.y+c.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(h,l))}return s}shapeAt(t,e,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,t,e,i);if(s)return s}}shapesAt(t){const e=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}return e}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const t=Ti.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===t)return;this.canvas.width=t,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${t} / ${this.canvas.height}`)}canvasPointFromEvent(t){const e=this.canvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return{x:(t.clientX-e.left)/e.width*this.canvas.width,y:(t.clientY-e.top)/e.height*this.canvas.height}}onFrame(t,e){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:DE;this.canvasRenderer.setStarPoints(Ti.starPointsOf(this.sighting.instrument,ze(this.sighting,t)?.fNumber));const n=(ze(this.sighting,t)?.rollDeg??0)+this.gaitAt(t).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(t),r=this.frameShift;if(this.paintsShapes)for(const c of s)for(const[,h]of c.shapes){const l=c.share,u=l===1?h:{...h,transparency:1-(1-h.transparency)*l};this.canvasRenderer.paintShape(this.shifted(u,r))}for(const[c,h]of s[0].shapes)!this.selectionShown||!i.has(c)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...h,selected:!0}):this.canvasRenderer.paintMemberOutline(h):this.canvasRenderer.paintSelectionOnly(this.shifted(h,r)));const a=this.selectionShown&&i.size>1?ys.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds)):void 0;this.chromeDraw=c=>{a&&c.paintGroupHandles(a),this.overlayPainter?.(c)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(c=>[...c.shapes.values()].filter(h=>h.transparency<1).map(h=>this.shifted(h,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.paintSeekProgress(t),this.minified&&this.paintMiniProgress(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(O2(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:t}}))}shifted(t,e){return e.x===0&&e.y===0?t:{...t,bounds:{...t.bounds,x:t.bounds.x+e.x,y:t.bounds.y+e.y}}}createPlayer(){const t=new VS(this.currentSighting.timeline,(e,i)=>this.onFrame(e,i));return t.loop=this.loopEnabled,t.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},t}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=t=>{t.key.toLowerCase()!=="f"||t.altKey||t.ctrlKey||t.metaKey||!this.enableClickToPlay||t.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(t.preventDefault(),this.toggleFullscreen())};handleSeekKey=t=>{if(t.altKey||t.ctrlKey||t.metaKey)return;const e=t.key==="ArrowLeft"?-1:t.key==="ArrowRight"?1:0;if(e){t.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+e*Ue.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.preventDefault(),this.togglePlayPause())};togglePlayPause(){if(!(this.player.seekableDuration<=0)){if(this.player.playbackState==="playing")this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh();else if(this.clockHeld){this.playAfterHold=!this.playAfterHold,this.playAfterHold&&this.announcePlayRequest();return}else this.announcePlayRequest(),this.sightingAudio.resume(),this.player.play();this.updatePlayPauseButton(),this.flashPlayback()}}flashPlayback(){const t=this.playbackFlash;t.innerHTML=this.player.playbackState==="playing"?Zt.PLAY:Zt.PAUSE,t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}static icons=new WeakMap;static setIcon(t,e){Ue.icons.get(t)!==e&&(Ue.icons.set(t,e),t.innerHTML=e)}set captionHeld(t){this.stageElement.classList.toggle("caption-held",t)}set controlsHeld(t){this.stageElement.classList.toggle("controls-held",t)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(t){this.quietControlsValue=t,this.stageElement.classList.toggle("quiet",t)}tapRevealedOnly=!1;get hoverless(){return typeof matchMedia=="function"&&matchMedia("(hover: none)").matches}touchedStage(){if(!this.hoverless)return;this.player.playbackState==="playing"&&!this.stageElement.classList.contains("touched")&&(this.tapRevealedOnly=!0),this.revealControls()}pointerHeld=!1;handlePointerDown=()=>{this.pointerHeld=!0};resumeAfterScrub=!1;suspendForScrub(){this.player.playbackState==="playing"&&(this.resumeAfterScrub=!0,this.stopPlaying())}stopPlaying(){this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton()}resumeFromScrub(){this.resumeAfterScrub&&(this.resumeAfterScrub=!1,this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton())}handleHidden=()=>{this.player.playbackState==="playing"&&this.stopPlaying(),this.resumeAfterScrub=!1};handleVisibility=()=>{document.visibilityState==="hidden"&&this.handleHidden()};handlePointerRelease=()=>{this.resumeAfterScrub&&window.setTimeout(()=>this.resumeFromScrub(),0),this.pointerHeld&&(this.pointerHeld=!1,this.hoverless&&this.stageElement.classList.contains("touched")&&this.revealControls())};revealControls(){this.stageElement.classList.add("touched"),window.clearTimeout(this.controlsIdleTimer),this.player.playbackState==="playing"&&(this.pointerHeld||!this.momentsMenu.hidden||(this.controlsIdleTimer=window.setTimeout(()=>{this.stageElement.classList.remove("touched"),this.tapRevealedOnly=!1},Ue.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!t),t!==this.wasPlaying&&t&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=t,this.updateStartState(),Ue.setIcon(this.playPauseButton,t?Zt.PAUSE:Zt.PLAY);const e=this.player.seekableDuration>0;this.playPauseButton.disabled=!e;const i=e?t?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=i,this.playPauseButton.setAttribute("aria-label",i)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const t=this.playbackBeforeClick;t&&(this.currentTime=t.time,t.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(t=>{console.error("<rr0-ufo>: requestFullscreen() failed —",t)})}enterSimulatedFullscreen(){const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=t.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const e=t.style;e.setProperty("position","fixed"),e.setProperty("inset","0"),e.setProperty("margin","0"),e.setProperty("max-width","none"),e.setProperty("max-height","none"),e.setProperty("aspect-ratio","auto"),e.setProperty("z-index","2147483647"),e.setProperty("background","#000"),e.setProperty("width","100vw"),e.setProperty("width","100dvw"),e.setProperty("height","100vh"),e.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?t.setAttribute("style",this.styleBeforeSimulatedFullscreen):t.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const t=this.observerMapPanel.hidden;this.observerMapAsked=t,this.setObserverMapOpen(t),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:t}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const t=this.getAttribute(Lr),e=t===null?this.sighting.observerMap??this.observerPath?.travels===!0:t!=="false";this.setObserverMapOpen(e&&this.observerPath!==void 0)}setObserverMapOpen(t){this.observerMapPanel.hidden=!t,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(t)),this.updateObserverMapButton(),t&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const t=!this.observerMapPanel.hidden;Ue.setIcon(this.observerMapButton,t?Zt.MAP_ON:Zt.MAP_OFF);const e=t?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e);const i=[[this.mapZoomInButton,this.messages.zoomMapIn],[this.mapZoomOutButton,this.messages.zoomMapOut],[this.mapFitButton,this.messages.fitMap]];for(const[n,s]of i)n.title=s,n.setAttribute("aria-label",s)}updateObserverMap(){const t=this.observerPath!==void 0;if(this.observerPath=eh.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!t&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const e=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=si.fitted(this.observerPath,e);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,i))&&(this.observerMapBounds&&this.observerMapView.refit(this.observerMapBounds,i),this.observerMapBounds=i,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||this.loadObserverMapImagery())}sameGround(t,e){const i=Math.abs(t.east-t.west)/20;return Math.abs(t.north-e.north)<i&&Math.abs(t.south-e.south)<i&&Math.abs(t.west-e.west)<i&&Math.abs(t.east-e.east)<i}async loadObserverMapImagery(){const t=this.observerMapViewBounds;if(!t||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(t)))return;const e=this.observerMapView.changed,i=e?si.expand(t,Ue.OBSERVER_MAP_IMAGERY_AHEAD):t,n=si.IMAGERY_PX*(e?1+2*Ue.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=t.east-t.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:j2();try{const a=r?await r.getImageryTexture(i,{width:n,height:n}):await s.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??s).attribution,this.observerMapImageryFailed=!1}catch{if(this.observerMapImageryBounds!==i)return;this.observerMapImageryFailed=this.observerMapImagery===void 0}finally{this.observerMapImageryBounds===i&&(this.observerMapImageryLoading=!1)}this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}static OBSERVER_MAP_IMAGERY_AHEAD=.5;static OBSERVER_MAP_IMAGERY_LOOKAHEAD=.25;observerMapImageryNeededFor(t){const e=this.observerMapImageryBounds;if(!e)return!0;const i=this.observerMapImagery?.bounds??e,n=this.observerMapView.changed?si.expand(t,Ue.OBSERVER_MAP_IMAGERY_LOOKAHEAD):t,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=t.east-t.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(t){t!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=t,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||(this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime)))}get observerMapFrozen(){return this.observerMapFrozenImagery}observerMapFrozenImagery;observerMapFrozenSource;get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(t){this.mapSceneBounds=t.map(e=>({x:e.x*this.canvas.width,y:e.y*this.canvas.height,width:e.width*this.canvas.width,height:e.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const t=this.observerMapBoxPx;if(!t)return;const e=[...this.mapShapeBounds,...this.mapSceneBounds],i=(h,l,u)=>{for(const d of e)if(!(d.x+d.width<h-u||d.x>l+u)&&!(d.y>t.bottom+u||d.y+d.height<t.top-u))return!0;return!1},n=[this.canvas.width-t.width,this.canvas.width],s=[0,t.width],r=Ue.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&c&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(c||!i(n[0],n[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(n[0],n[1],0)&&!i(s[0],s[1],0)&&this.observerMapPanel.classList.add("on-the-left")}observerMapBoxPx;static OBSERVER_MAP_CLEARANCE_PX=24;sizeObserverMapCanvas(){const t=this.observerMapPanel.clientWidth;if(t===0)return;const e=Math.round(t*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==e&&(this.observerMapCanvas.width=e,this.observerMapCanvas.height=e)}measureObserverMapBox(){const t=this.observerMapPanel.getBoundingClientRect(),e=this.canvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=this.canvas.width/e.width,n=this.canvas.height/e.height;this.observerMapBoxPx={width:t.width*i,top:(t.top-e.top)*n,bottom:(t.bottom-e.top)*n}}paintObserverMap(t){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const e=ze(this.currentSighting,t);e?.lat!==void 0&&e.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:e.lat,lng:e.lng},Ue.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?l0(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?ul(this.currentSighting.milestones):[]){const a=ze(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===s})}this.observerMapRenderer.paint({bounds:this.observerMapViewBounds,imagery:this.observerMapImagery,path:this.observerPath,position:e?.lat!==void 0&&e.lng!==void 0?{lat:e.lat,lng:e.lng}:void 0,headingDeg:e?.headingDeg===void 0?void 0:e.headingDeg+this.lookYawDeg,coneHalfAngleDeg:e?Ir.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(Ti.aspectOf(i)):void 0,markers:n,traces:(this.tracesShownState?this.currentSighting.traces:[]).map(r=>({kind:r.kind,points:r.points,color:r.color,label:this.said.read(r.title)})),decor:this.observerMapDecorAt(t),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(t){this.milestonesShown=t,this.milestoneMarks.hidden=!t,this.momentsBox.hidden=!t||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,ul(this.sighting.milestones).map(e=>e.t)),this.milestonesButton.setAttribute("aria-pressed",String(t)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintObserverMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0,this.momentsButton.title=this.messages.moments,Ue.setIcon(this.milestonesButton,this.milestonesShown?Zt.MILESTONES_ON:Zt.MILESTONES_OFF);const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=ze(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=tr(i,t),{lat:s,lng:r}=os(n.eastM,-n.northM,e.lat,e.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(t){const e=t===void 0?void 0:Math.max(0,Math.min(1,-t/12));e!==this.observerMapNightFraction&&(this.observerMapNightFraction=e,this.paintObserverMap(this.currentTime))}setLookOffset(t,e){t===this.lookYawDeg&&e===this.lookPitchDeg||(this.lookYawDeg=t,this.lookPitchDeg=e,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const t=this.gaitAt(this.currentTime),e=this.lookYawDeg+t.yawDeg,i=this.lookPitchDeg+t.pitchDeg;if(e===0&&i===0)return{x:0,y:0};const n=ze(this.currentSighting,this.currentTime),s=Ir.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(e),y:s.angleDegToRadiusPx(i)}}gaitAt(t){return qe.bodyAt(this.currentSighting,t,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(t){t!==this.mutedState&&(this.mutedState=t,!t&&this.volumeState===0&&(this.volumeState=Ue.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(t){this.setVolume(t)}setVolume(t){this.volumeState=Math.min(Math.max(t,0),1),this.mutedState=this.volumeState===0,this.applyLevel()}get level(){return this.mutedState?0:this.volumeState}applyLevel(){this.sightingAudio.setLevel(this.level),this.updateMuteButton(),this.dispatchEvent(new CustomEvent("mutedchange",{bubbles:!0,composed:!0,detail:{muted:this.mutedState,volume:this.volumeState}}))}toggleMuted(){this.hasSound&&(this.muted=!this.mutedState)}ambientSound;get hasSound(){return this.currentSighting.soundTrack.allKeyframes.length>0||this.ambientSound?.(this.currentSighting)===!0}updateMuteButton(){const t=!this.hasSound;this.miniMuteButton.hidden=t,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Ue.setIcon(this.miniMuteButton,this.mutedState?Zt.MUTED:Zt.VOLUME);const e=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=e,this.miniMuteButton.setAttribute("aria-label",e),this.muteButton.disabled=t,this.volumeInput.hidden=t,t){Ue.setIcon(this.muteButton,Zt.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Ue.setIcon(this.muteButton,this.mutedState?Zt.MUTED:Zt.VOLUME);const i=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=i,this.muteButton.setAttribute("aria-label",i),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Ue.setIcon(this.fullscreenButton,t?Zt.EXIT_FULLSCREEN:Zt.ENTER_FULLSCREEN),this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Ps(Ga.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=Tg(Ga.preferencesFor(this),Rg);if(t===this.messagesLanguage||t==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=t;const e=await iE(t);this.messagesLanguage===t&&this.applyMessages(e)}messagesLanguage;updateTimeLabelTitles(){const t=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,e=this.canSwitchTimeDisplay?` — ${t}`:"";this.timeStartLabel.title=this.messages.currentPosition+e,this.timeEndLabel.title=this.messages.duration+e,this.timePill.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(this.timePill.setAttribute("role","button"),this.timePill.setAttribute("tabindex","0")):(this.timePill.removeAttribute("role"),this.timePill.removeAttribute("tabindex"))}applyMessages(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const t=this.currentSighting.event,e=C2(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?Xp(t.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.paintMiniProgress(this.player.time),this.updateTimeLabelTitles()}formatPosition(t){if(this.realDurationMs===void 0)return pa(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?bv(xv(this.realStartMs+i)):pa(i)}formatElapsedAt(t){const e=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?pa(t):pa(e>0&&t<=e?t/e*this.realDurationMs:t)}formatRemaining(t){const e=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return pa(Math.max(0,e-t));const i=e>0&&t<=e?t/e*this.realDurationMs:t;return pa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?pa(this.currentSighting.timeline.duration):this.canShowClockTime?bv(xv(this.realStartMs+this.realDurationMs)):pa(this.realDurationMs)}}function xv(o){const t=new Date(o);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function bv(o){if(o.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return o.second?`${t(o.hour)}:${t(o.minute??0)}:${t(o.second)}`:`${t(o.hour)}:${t(o.minute??0)}`}function pa(o){const t=Math.round(o/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Kp="rr0-ufo";function Q2(){customElements.get(Kp)||customElements.define(Kp,Ue)}const CE="recordingissues",tx="minifiedreset";/**
|
|
2404
|
+
`);let e=zc.shared.get(t);return e||(e=this.fetchFirstAvailable(),zc.shared.set(t,e),e.then(i=>{i.length===0&&zc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.1")}`,e=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(e&&e!==d0?[e,d0]:[d0]).map(i=>i+t)}}class Oa{attribution="Roads © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Type autoroutier":{surface:"paved",widthM:11},"Route à 2 chaussées":{surface:"paved",widthM:7},"Route à 1 chaussée":{surface:"paved",widthM:5.5},"Rond-point":{surface:"paved",widthM:6},Bretelle:{surface:"paved",widthM:5},"Route empierrée":{surface:"gravel",widthM:3.5},Chemin:{surface:"dirt",widthM:3},"Piste cyclable":{surface:"paved",widthM:2.5}};static DEFAULT={surface:"paved",widthM:5};static KINDS={"Type autoroutier":"motorway","Route à 2 chaussées":"dual","Route à 1 chaussée":"road","Rond-point":"roundabout",Bretelle:"slip"};static DIRECTIONS={"Double sens":"both","Sens direct":"forward","Sens inverse":"backward"};platform;constructor(t={}){this.platform=new Ce(t)}static covers(t){return Ce.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRoads(t){return(await this.platform.roads(t)).flatMap((i,n)=>Oa.wayOf(i,n))}static wayOf(t,e){if(t.geometry.type!=="LineString")return[];const i=t.geometry.coordinates.map(([d,f])=>({lat:f,lng:d}));if(i.length<2)return[];const n=String(t.properties.nature??""),s=Oa.BY_NATURE[n]??Oa.DEFAULT,r=Number(t.properties.largeur_de_chaussee),a=Number(t.properties.nombre_de_voies),c=Number(t.properties.vitesse_moyenne_vl),h=Oa.DIRECTIONS[String(t.properties.sens_de_circulation??"")],l=Oa.KINDS[n],u=[t.properties.cpx_toponyme_route_nommee,t.properties.nom_voie_ban_gauche,t.properties.nom_voie_ban_droite].find(d=>typeof d=="string"&&d.length>0);return[{id:String(t.properties.cleabs??`ign-${e}`),...u?{name:u}:{},surface:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.widthM,...t.properties.urbain===!0?{urban:!0}:{},...l?{kind:l}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...h?{direction:h}:{},...Number.isFinite(c)&&c>0?{speedKmh:c}:{},points:i}]}}class SE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(t){if(Oa.covers(t))try{const e=await this.regional.getRoads(t);if(e.length>0)return e}catch{}return this.worldwide.getRoads(t)}}class kl{attribution="Water © IGN, BD TOPO (Licence Ouverte 2.0)";platform;constructor(t={}){this.platform=new Ce(t)}static covers(t){return Ce.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getWater(t){return(await this.platform.waterSurfaces(t)).flatMap((i,n)=>kl.surfacesOf(i,n))}static surfacesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="Polygon"?[n]:i==="MultiPolygon"?n:[],r=String(t.properties.cleabs??`ign-water-${e}`);return s.flatMap((a,c)=>{const h=a.map(l=>kl.open(l.map(u=>({lat:u[1],lng:u[0]})))).filter(l=>l.length>=3);return h.length>0?[{id:s.length>1?`${r}-${c}`:r,rings:h}]:[]})}static open(t){const e=t[0],i=t[t.length-1];return t.length>1&&e.lat===i.lat&&e.lng===i.lng?t.slice(0,-1):t}}class lo{attribution="Water © OpenStreetMap contributors";client;constructor(t={}){this.client=new ss(t)}async getWater(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:30];(way["natural"="water"](${e});way["waterway"="riverbank"](${e});)->.w;(relation["natural"="water"](${e});relation["waterway"="riverbank"](${e});)->.r;.w out geom;.r out body;way(r.r)(${e});out geom;`;return lo.surfacesFrom(await this.client.query(i))}static surfacesFrom(t){const e=t.elements??[],i=new Map;for(const r of e)r.type==="way"&&r.id!==void 0&&r.geometry&&i.set(r.id,r.geometry.map(a=>({lat:a.lat,lng:a.lon})));const n=[],s=new Set;for(const r of e){if(r.type!=="relation")continue;const a=h=>(r.members??[]).filter(l=>l.type==="way"&&l.role===h&&l.ref!==void 0&&i.has(l.ref)).map(l=>(s.add(l.ref),i.get(l.ref))),c=lo.rings(a("inner"));for(const[h,l]of lo.rings(a("outer")).entries()){const u=c.filter(d=>lo.contains(l,d[0]));n.push({id:`osm-r${r.id}-${h}`,rings:[l,...u]})}}for(const r of e)if(!(r.type!=="way"||!r.tags||r.id===void 0||s.has(r.id))&&!(r.tags.natural!=="water"&&r.tags.waterway!=="riverbank"))for(const a of lo.rings([i.get(r.id)??[]]))n.push({id:`osm-w${r.id}`,rings:[a]});return n}static rings(t){const e=(s,r)=>s.lat===r.lat&&s.lng===r.lng,i=t.filter(s=>s.length>=2).map(s=>[...s]),n=[];for(;i.length>0;){let s=i.pop(),r=!0;for(;!e(s[0],s[s.length-1])&&r;){r=!1;for(let a=0;a<i.length;a++){const c=i[a],h=s[s.length-1];if(e(h,c[0]))s=[...s,...c.slice(1)];else if(e(h,c[c.length-1]))s=[...s,...[...c].reverse().slice(1)];else continue;i.splice(a,1),r=!0;break}}s.length>=4&&e(s[0],s[s.length-1])&&n.push(s.slice(0,-1))}return n}static contains(t,e){let i=!1;for(let n=0,s=t.length-1;n<t.length;s=n++){const r=t[n],a=t[s];r.lat>e.lat!=a.lat>e.lat&&e.lng<(a.lng-r.lng)*(e.lat-r.lat)/(a.lat-r.lat)+r.lng&&(i=!i)}return i}}class EE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Water © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere";async getWater(t){if(kl.covers(t))try{const e=await this.regional.getWater(t);if(e.length>0)return e}catch{}return this.worldwide.getWater(t)}}const f0="https://ufoathome.org/water/index.json";class Bc{attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Bc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Water © OpenStreetMap contributors"}async getWater(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getWater(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.surfaces)?(this.attributionRead=s.attribution,s.surfaces):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const t=this.indexUrls.join(`
|
|
2405
|
+
`);let e=Bc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Bc.shared.set(t,e),e.then(i=>{i.length===0&&Bc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.1")}`,e=typeof location>"u"?void 0:new URL("/water/index.json",location.href).href;return(e&&e!==f0?[e,f0]:[f0]).map(i=>i+t)}}class es{constructor(t){this.water=t}static CACHE_NAME="rr0-water";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static asked=new Map;get attribution(){return this.water.attribution}async getWater(t){const e=es.key(t);let i=es.asked.get(e);return i===void 0&&(i=this.recalled(e,t),es.asked.set(e,i),i.catch(()=>es.asked.delete(e))),structuredClone(await i)}static forget(){es.asked.clear()}static key(t){return`v${es.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}async recalled(t,e){const i=await es.openCache(),n=es.request(t);if(i)try{const r=await i.match(n);if(r){const{savedAt:a,surfaces:c}=await r.json();if(Date.now()-a<es.MAX_AGE_MS&&Array.isArray(c))return c;await i.delete(n)}}catch{}const s=await this.water.getWater(e);return i&&es.store(i,n,s),s}static async store(t,e,i){try{const n={savedAt:Date.now(),surfaces:i};await t.put(e,new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}}));const s=await t.keys();for(const r of s.slice(0,Math.max(0,s.length-es.MAX_STORED)))await t.delete(r)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(es.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__water__/${encodeURIComponent(t)}`)}}class Pa{attribution="Railways © IGN, BD TOPO (Licence Ouverte 2.0), as drawn today";contemporary=!0;static BY_NATURE={"Voie ferrée principale":{kind:"rail"},LGV:{kind:"rail",highSpeed:!0},"Voie de service":{kind:"rail",service:!0},Métro:{kind:"subway"},Tramway:{kind:"tram"},"Transport urbain":{kind:"light_rail"},"Funiculaire ou crémaillère":{kind:"funicular"}};static GAUGE_MM={Normale:1435,Etroite:1e3,Étroite:1e3,Large:1668};static NO_ALTITUDE=-1e3;platform;constructor(t={}){this.platform=new Ce(t)}static covers(t){return Ce.covers((t.south+t.north)/2,(t.west+t.east)/2)}async getRailways(t){return(await this.platform.railways(t)).flatMap((i,n)=>Pa.linesOf(i,n))}static linesOf(t,e){const{type:i,coordinates:n}=t.geometry,s=i==="LineString"?[n]:i==="MultiLineString"?n:[],r=Pa.BY_NATURE[String(t.properties.nature??"")];if(!r)return[];const a=String(t.properties.cleabs??`ign-rail-${e}`),c=Number(t.properties.nombre_de_voies),h=Number(t.properties.position_par_rapport_au_sol),l=t.properties.cpx_toponyme,u=Pa.GAUGE_MM[String(t.properties.largeur??"")]??1435,d=Pa.electrificationOf(r.kind,u,t.properties.electrifie);return s.flatMap((f,p)=>{const g=f.map(m=>({lat:m[1],lng:m[0],...m.length>2&&Number.isFinite(m[2])&&m[2]>Pa.NO_ALTITUDE?{altitudeM:m[2]}:{}}));return g.length<2?[]:[{id:s.length>1?`${a}-${p}`:a,...typeof l=="string"&&l.length>0?{name:l}:{},kind:r.kind,...r.service?{service:!0}:{},...r.highSpeed?{highSpeed:!0}:{},gaugeMm:u,tracks:Number.isInteger(c)&&c>0?c:1,...d?{electrification:d}:{},level:Number.isFinite(h)?h:0,points:g}]})}static electrificationOf(t,e,i){if(i===!1)return"none";if(i===!0){if(t==="subway")return"third_rail";if(!(t==="funicular"||e<1435))return"overhead"}}}class Mn{static NEAR_M=15;static ALIGNED_DEG=30;static SAMPLE_M=10;static ROUTES="train|subway|light_rail|tram|monorail";static KINDS="rail|light_rail|subway|tram|narrow_gauge|funicular|preserved";client;constructor(t={}){this.client=new ss(t)}async named(t,e){if(t.length===0)return[...t];const i=`${e.south},${e.west},${e.north},${e.east}`,n=`[out:json][timeout:120];way["railway"~"^(${Mn.KINDS})$"](${i})->.w;.w out tags geom;rel(bw.w)["route"~"^(${Mn.ROUTES})$"];out body;`;return Mn.apply(t,await this.client.query(n),e)}static apply(t,e,i){const n={lat:(i.north+i.south)/2,lng:(i.east+i.west)/2},s=Mn.ways(e,n);return s.length===0?[...t]:t.map(r=>{const a=r.points.map(v=>oe(v.lat,v.lng,n.lat,n.lng)),c=new Map,h=new Map,l=new Map;let u=0;const d=s.filter(v=>v.service===!!r.service);for(const v of Mn.samples(a)){u++;const y=Mn.waysAt(d,v);if(y.length===0)continue;const[x]=y;x.name&&c.set(x.name,(c.get(x.name)??0)+1),x.voltageV&&h.set(x.voltageV,(h.get(x.voltageV)??0)+1);for(const M of new Set(y.flatMap(b=>b.services)))l.set(M,(l.get(M)??0)+1)}const f=v=>[...v.entries()].sort((y,x)=>x[1]-y[1])[0]?.[0],p=r.name??f(c),g=r.voltageV??(r.electrification==="none"?void 0:f(h)),m=[...l.entries()].filter(([,v])=>v*4>=u).sort((v,y)=>y[1]-v[1]||v[0].localeCompare(y[0])).map(([v])=>v);return{...r,...p?{name:p}:{},...g?{voltageV:g}:{},...m.length>0?{services:m}:{}}})}static serviceOf(t){const e=t.name?.split(" : ")[0].replace(/\s*\([^)]*\)\s*$/,"").trim();return e||[t.network,t.ref].filter(Boolean).join(" ")||void 0}static servicesByWay(t){const e=new Map;for(const i of t.elements??[]){if(i.type!=="relation"||!i.tags)continue;const n=Mn.serviceOf(i.tags);if(n)for(const s of i.members??[]){if(s.type!=="way"||s.ref===void 0)continue;const r=e.get(s.ref)??new Set;r.add(n),e.set(s.ref,r)}}return e}static voltageOf(t){const e=Number.parseInt((t.voltage??"").split(";")[0],10);return Number.isFinite(e)&&e>0?e:void 0}static ways(t,e){const i=Mn.servicesByWay(t),n=[];for(const s of t.elements??[]){if(s.type!=="way"||!s.geometry||s.geometry.length<2)continue;const r=s.tags??{},a=Mn.voltageOf(r);n.push({service:!!r.service||r.usage==="industrial",...r.name?{name:r.name}:{},...a?{voltageV:a}:{},services:[...i.get(s.id??-1)??[]],path:s.geometry.map(c=>oe(c.lat,c.lon,e.lat,e.lng))})}return n}static samples(t){const e=[];for(let i=0;i<t.length-1;i++){const n=Math.hypot(t[i+1].x-t[i].x,t[i+1].z-t[i].z);if(n<1e-6)continue;const s=(t[i+1].x-t[i].x)/n,r=(t[i+1].z-t[i].z)/n;for(let a=Mn.SAMPLE_M/2;a<n;a+=Mn.SAMPLE_M)e.push({x:t[i].x+s*a,z:t[i].z+r*a,dx:s,dz:r})}return e}static waysAt(t,e){const i=Math.cos(Mn.ALIGNED_DEG*Math.PI/180),n=[];for(const s of t){let r;for(let a=0;a<s.path.length-1;a++){const c=s.path[a],h=s.path[a+1],l=h.x-c.x,u=h.z-c.z,d=Math.hypot(l,u);if(d<1e-6||Math.abs((l*e.dx+u*e.dz)/d)<i)continue;const f=Math.max(0,Math.min(1,((e.x-c.x)*l+(e.z-c.z)*u)/(d*d))),p=Math.hypot(e.x-(c.x+l*f),e.z-(c.z+u*f));p<=Mn.NEAR_M&&(r===void 0||p<r)&&(r=p)}r!==void 0&&n.push({way:s,distance:r})}return n.sort((s,r)=>s.distance-r.distance).map(({way:s})=>s)}}class Hc{attribution="Railways © OpenStreetMap contributors, as surveyed today";contemporary=!0;static KINDS=["rail","light_rail","tram","subway","narrow_gauge","funicular","preserved"];client;constructor(t={}){this.client=new ss(t)}async getRailways(t){const e=`${t.south},${t.west},${t.north},${t.east}`,i=`[out:json][timeout:25];way["railway"~"^(${Hc.KINDS.join("|")})$"](${e})->.w;.w out tags geom;rel(bw.w)["route"~"^(${Mn.ROUTES})$"];out body;`;return this.linesFrom(await this.client.query(i))}linesFrom(t){const e=[],i=Mn.servicesByWay(t);for(const n of t.elements??[]){const s=n.geometry,r=n.tags;if(n.type==="relation"||!r||!s||s.length<2)continue;const a=[...i.get(n.id??-1)??[]].sort(),c=Mn.voltageOf(r),h=Hc.kindOf(r),l=Number.parseInt((r.gauge??"").split(";")[0],10),u=Number.parseInt(r.tracks??"",10),d=Hc.electrificationOf(r.electrified),f=r.highspeed==="yes"||Number.parseInt(r.maxspeed??"",10)>=250;e.push({id:`osm-rail-${n.id??e.length}`,...r.name?{name:r.name}:{},...a.length>0?{services:a}:{},...c?{voltageV:c}:{},kind:h,...r.service||r.usage==="industrial"?{service:!0}:{},...f?{highSpeed:!0}:{},gaugeMm:Number.isFinite(l)&&l>300?l:r.railway==="narrow_gauge"?1e3:1435,tracks:Number.isFinite(u)&&u>0?u:1,...d?{electrification:d}:{},level:Hc.levelOf(r),points:s.map(p=>({lat:p.lat,lng:p.lon}))})}return e}static kindOf(t){switch(t.railway){case"tram":return"tram";case"subway":return"subway";case"light_rail":return"light_rail";case"funicular":return"funicular";default:return"rail"}}static electrificationOf(t){if(t!==void 0){if(t==="no")return"none";if(t==="contact_line"||t==="yes")return"overhead";if(t==="rail"||t==="4th_rail"||t==="ground-level_power_supply")return"third_rail"}}static levelOf(t){const e=Number.parseInt(t.layer??"",10);return t.tunnel&&t.tunnel!=="no"?Number.isFinite(e)&&e<0?e:-1:t.covered==="yes"&&t.location==="underground"?-1:t.bridge&&t.bridge!=="no"?Number.isFinite(e)&&e>0?e:1:0}}class AE{constructor(t,e){this.regional=t,this.worldwide=e}attribution="Railways © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRailways(t){if(!Pa.covers(t))return this.worldwide.getRailways(t);let e;try{if(e=await this.regional.getRailways(t),e.length>0)return e}catch{}try{return await this.worldwide.getRailways(t)}catch(i){if(e)return e;throw i}}}class Zi{constructor(t,e=Date.now){this.railways=t,this.now=e}static CACHE_NAME="rr0-railways";static MAX_AGE_MS=720*3600*1e3;static FORMAT=1;static MAX_STORED=400;static RETRY_AFTER_MS=300*1e3;static asked=new Map;static failedAt=-1/0;get attribution(){return this.railways.attribution}get contemporary(){return this.railways.contemporary}async getRailways(t){const e=Zi.key(t);let i=Zi.asked.get(e)??Zi.containing(t);if(i===void 0){const n=this.recalled(e,t);i={bounds:t,answer:n},Zi.asked.set(e,i),n.catch(()=>Zi.asked.delete(e))}return structuredClone(await i.answer)}static forget(){Zi.asked.clear(),Zi.failedAt=-1/0}static key(t){return`v${Zi.FORMAT}/${[t.north,t.south,t.east,t.west].map(e=>e.toFixed(5)).join("/")}`}static containing(t){for(const e of Zi.asked.values()){const i=e.bounds;if(i.north>=t.north&&i.south<=t.south&&i.east>=t.east&&i.west<=t.west)return e}}async recalled(t,e){const i=await Zi.openCache(),n=Zi.request(t);let s;if(i)try{const a=await i.match(n);if(a){const{savedAt:c,lines:h}=await a.json();if(Array.isArray(h)){if(this.now()-c<Zi.MAX_AGE_MS)return h;s=h}}}catch{}if(this.now()-Zi.failedAt<Zi.RETRY_AFTER_MS){if(s)return s;throw new Error("The railway survey failed a moment ago: not asked again yet")}let r;try{r=await this.railways.getRailways(e)}catch(a){if(Zi.failedAt=this.now(),s)return s;throw a}return i&&Zi.store(i,n,{savedAt:this.now(),lines:r}),r}static async store(t,e,i){try{await t.delete(e),await t.put(e,new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}}));const n=await t.keys();for(const s of n.slice(0,Math.max(0,n.length-Zi.MAX_STORED)))await t.delete(s)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(Zi.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__railways__/${encodeURIComponent(t)}`)}}const p0="https://ufoathome.org/railways/index.json";class Gc{contemporary=!0;attributionRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??Gc.defaultIndexUrls(),this.fallback=t.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Railways © OpenStreetMap contributors"}async getRailways(t){const e=await this.held(t);if(e)return e;if(!this.fallback)return[];const i=await this.fallback.getRailways(t);return this.attributionRead=this.fallback.attribution,i}async held(t){const i=(await this.load().catch(()=>[])).find(({entry:n})=>n.north>=t.north&&n.south<=t.south&&n.east>=t.east&&n.west<=t.west);if(i)try{const n=await this.fetchImpl(new URL(i.entry.file,i.indexUrl).href);if(!n.ok)return;const s=await n.json();return Array.isArray(s?.lines)?(this.attributionRead=s.attribution,s.lines):void 0}catch{return}}load(){if(this.index)return this.index;if(!this.sharing)return this.index=this.fetchFirstAvailable();const t=this.indexUrls.join(`
|
|
2406
|
+
`);let e=Gc.shared.get(t);return e||(e=this.fetchFirstAvailable(),Gc.shared.set(t,e),e.then(i=>{i.length===0&&Gc.shared.delete(t)})),this.index=e}async fetchFirstAvailable(){for(const t of this.indexUrls)try{const e=await this.fetchImpl(t);if(!e.ok)continue;const i=await e.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:t}))}catch{}return[]}static defaultIndexUrls(){const t=`?v=${encodeURIComponent("0.152.1")}`,e=typeof location>"u"?void 0:new URL("/railways/index.json",location.href).href;return(e&&e!==p0?[e,p0]:[p0]).map(i=>i+t)}}function J2(){return{elevation:_E(),imagery:j2(),roads:TE(),water:RE(),railways:IE()}}function _E(){return new xE(new Te,new ME)}function j2(){return new Z2}function TE(){return new zc({fallback:new SE(new Oa,new Ra)})}function RE(){return new Bc({fallback:new es(new EE(new kl,new lo))})}function IE(){return new Gc({fallback:new Zi(new AE(new Pa,new Hc))})}const DE=new Set,Lr="show-observer-map",Nr="hide-milestones",Io="minified";class Ue extends HTMLElement{static get observedAttributes(){return["src",Lr,Nr,Io]}shadow;stageElement;canvas;canvasRenderer;chromeCanvas;chromeRenderer;chromeResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>{this.chromeDirty&&this.refresh()});chromeDirty=!1;tooltip;toolbar;issuesBox;issuesButton;issuesPanel;playPauseButton;fullscreenButton;cornerButtons;observerMapButton;referencesButton;tracesButton;tracesShownState=!0;referenceOpacityInput;referencesShownState=!0;accountHidden=!1;referenceViews=new Map;referencesMenu;referenceOpacityTouched=!1;milestonesButton;observerMapPanel;observerMapCanvas;observerMapRenderer;mapZoomInButton;mapZoomOutButton;mapFitButton;observerMapView=new si;observerMapDrag;suppressObserverMapClick=!1;observerMapImageryTimer;observerPlacing=!1;seekInput;playbackFlash;milestoneMarks;milestoneCaption;timeStartLabel;timeEndLabel;timePill;muteButton;volumeInput;controlsRow;momentsBox;momentsButton;momentsCurrent;momentsMenu;moreButton;controlsRight;seekSegments;seekDot;playerTitleBox;seekPreview;seekPreviewCanvas;seekPreviewTitle;seekPreviewTime;observerPath;observerMapBounds;observerMapImagery;observerMapImageryBounds;observerMapImageryViewWidth=0;observerMapImageryLoading=!1;observerMapImageryCredit;observerMapImageryFailed=!1;creditShownExternally=!1;lookYawDeg=0;lookPitchDeg=0;milestonesShown=!0;currentSighting=Gf.create();issues=[];issueCheck=0;sightingAudio=new ZS;soundPreview;player;loopEnabled=!1;playbackBeforeClick;highlightedSourceIds=new Set;paintsShapes=!0;steadyObserver=!1;static LIVE_BODY_MAX_RATE=2;get steadyBody(){return this.steadyObserver||this.player.playbackState!=="playing"||this.player.playbackRate>Ue.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=B2;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const t=this.controlsRow,e=t.classList.contains("more-open"),i=()=>t.scrollWidth>t.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,t.classList.remove("narrow","more-open","nomoments","compact","tiny"),t.clientWidth>0&&i()){t.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;t.classList.add(s)}e&&t.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(t){this.controlsRow.classList.toggle("more-open",!t),this.updateMoreButton()}updateMoreButton(){const t=this.controlsRow.classList.contains("more-open");Ue.setIcon(this.moreButton,t?Zt.UNFOLDED:Zt.FOLDED);const e=t?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=e,this.moreButton.setAttribute("aria-label",e),this.moreButton.setAttribute("aria-expanded",String(t))}addControl(t){this.controlsRight.insertBefore(t,this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null),this.fitControls()}observerMapResizeObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.resizeObserverMap());resizeObserverMap(){this.observerMapPanel.hidden||(this.sizeObserverMapCanvas(),this.paintObserverMap(this.currentTime))}simulatedFullscreen=!1;styleBeforeSimulatedFullscreen;bodyOverflowBeforeSimulatedFullscreen;handleSimulatedFullscreenKey=t=>{t.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=t=>{const e=this.canvasPointFromEvent(t),i=e&&this.shapeAt(e.x,e.y),n=this.said.read(i?.shape.title);if(!n){this.tooltip.hidden=!0;return}this.tooltip.textContent=n,this.tooltip.hidden=!1;const s=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-s.left+12}px`,this.tooltip.style.top=`${t.clientY-s.top+12}px`};handleObserverMapPointerMove=t=>{if(this.dragObserverMap(t))return;const e=this.observerMapTargetFrom(t);if(!e){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(t,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(t,e.label)};showObserverMapTooltip(t,e){this.tooltip.textContent=e,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${t.clientX-i.left+12}px`,this.tooltip.style.top=`${t.clientY-i.top+12}px`}handleObserverMapClick=t=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const e=this.observerMapTargetFrom(t);if(!e){this.observerPlacing&&this.placeObserverFrom(t);return}if(e.kind==="milestone"&&e.t!==void 0){this.player.seek(e.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:e.lat,lng:e.lng,kind:e.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(t){const e=this.observerMapCanvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return this.observerMapRenderer.hitTest((t.clientX-e.left)/e.width*this.observerMapCanvas.width,(t.clientY-e.top)/e.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=t=>{t.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,moved:!1})};handleObserverMapPointerUp=t=>{const e=this.observerMapDrag;!e||e.pointerId!==t.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),e.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(t.pointerId)&&this.observerMapCanvas.releasePointerCapture(t.pointerId)))};dragObserverMap(t){const e=this.observerMapDrag;if(!e||e.pointerId!==t.pointerId)return!1;if(!e.moved){if(Math.hypot(t.clientX-e.startX,t.clientY-e.startY)<Ue.OBSERVER_MAP_DRAG_PX)return!1;e.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(t.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((t.clientX-e.lastX)/i.width,(t.clientY-e.lastY)/i.height),this.observerMapViewChanged()),e.lastX=t.clientX,e.lastY=t.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=t=>{t.preventDefault();const e=this.observerMapCanvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=t.deltaMode===0?t.deltaY:t.deltaY*40;this.zoomObserverMap((t.clientX-e.left)/e.width,(t.clientY-e.top)/e.height,Math.exp(-i*.002))};zoomObserverMap(t,e,i){this.observerMapView.zoomAt(t,e,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=si.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=si.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},Ue.OBSERVER_MAP_IMAGERY_DELAY_MS))}static OBSERVER_MAP_FOLLOW_MARGIN=.1;static OBSERVER_MAP_IMAGERY_DELAY_MS=300;get observerMapViewBounds(){return this.observerMapBounds&&this.observerMapView.boundsWithin(this.observerMapBounds)}placeObserverFrom(t){const e=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!e||i.width===0||i.height===0)return;const n=si.pointAt(e,(t.clientX-i.left)/i.width,(t.clientY-i.top)/i.height);this.dispatchEvent(new CustomEvent("observerplace",{detail:n,bubbles:!0,composed:!0}))}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${GS}</style>${HS}`,this.shadow.appendChild(t.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new gh(this.canvas.getContext("2d")),this.chromeCanvas=this.shadow.getElementById("chrome"),this.tooltip=this.shadow.getElementById("tooltip"),this.toolbar=this.shadow.getElementById("toolbar"),this.issuesBox=this.shadow.getElementById("issues"),this.issuesButton=this.shadow.getElementById("issues-button"),this.issuesPanel=this.shadow.getElementById("issues-panel"),this.issuesButton.addEventListener("click",a=>{a.stopPropagation(),this.issuesPanel.hidden=!this.issuesPanel.hidden,this.issuesButton.setAttribute("aria-expanded",String(!this.issuesPanel.hidden))}),this.playPauseButton=this.shadow.getElementById("play-pause"),this.fullscreenButton=this.shadow.getElementById("fullscreen"),this.cornerButtons=this.shadow.getElementById("corner-buttons"),this.observerMapButton=this.shadow.getElementById("observer-map"),this.referencesButton=this.shadow.getElementById("references"),this.tracesButton=this.shadow.getElementById("traces"),this.referenceOpacityInput=this.shadow.getElementById("reference-opacity"),this.referencesMenu=this.shadow.getElementById("references-menu"),this.milestonesButton=this.shadow.getElementById("milestones"),this.observerMapPanel=this.shadow.getElementById("observer-map-panel"),this.observerMapCanvas=this.shadow.getElementById("observer-map-canvas"),this.observerMapRenderer=new ho(this.observerMapCanvas.getContext("2d")),this.mapZoomInButton=this.shadow.getElementById("map-zoom-in"),this.mapZoomOutButton=this.shadow.getElementById("map-zoom-out"),this.mapFitButton=this.shadow.getElementById("map-fit"),this.seekInput=this.shadow.getElementById("seek"),this.playbackFlash=this.shadow.getElementById("playback-flash"),this.milestoneMarks=this.shadow.getElementById("milestone-marks"),this.milestoneCaption=this.shadow.getElementById("milestone-caption"),this.timeStartLabel=this.shadow.getElementById("time-start"),this.timeEndLabel=this.shadow.getElementById("time-end"),this.timePill=this.shadow.getElementById("time"),this.muteButton=this.shadow.getElementById("mute"),this.controlsRight=this.shadow.getElementById("controls-right"),this.seekSegments=this.shadow.getElementById("seek-segments"),this.seekDot=this.shadow.getElementById("seek-dot"),this.playerTitleBox=this.shadow.getElementById("player-title"),this.seekPreview=this.shadow.getElementById("seek-preview"),this.seekPreviewCanvas=this.shadow.getElementById("seek-preview-canvas"),this.seekPreviewTitle=this.shadow.getElementById("seek-preview-title"),this.seekPreviewTime=this.shadow.getElementById("seek-preview-time"),this.timePill.addEventListener("click",()=>this.toggleTimeDisplay()),this.timePill.addEventListener("keydown",a=>{a.key!=="Enter"&&a.key!==" "||(a.preventDefault(),this.toggleTimeDisplay())}),this.volumeInput=this.shadow.getElementById("volume"),this.controlsRow=this.shadow.querySelector(".controls"),this.momentsBox=this.shadow.getElementById("moments"),this.momentsButton=this.shadow.getElementById("moments-button"),this.momentsCurrent=this.shadow.getElementById("moments-current"),this.momentsMenu=this.shadow.getElementById("moments-menu"),this.momentsButton.addEventListener("click",()=>this.toggleMomentsMenu()),this.moreButton=this.shadow.getElementById("controls-more"),this.moreButton.addEventListener("click",()=>this.setControlsFolded(this.controlsRow.classList.contains("more-open"))),this.muteButton.addEventListener("click",()=>this.toggleMuted()),this.miniPlayed=this.shadow.getElementById("mini-played"),this.miniRemaining=this.shadow.getElementById("mini-remaining"),this.miniMuteButton=this.shadow.getElementById("mini-mute"),this.miniDot=this.shadow.getElementById("mini-dot"),this.miniScrubTime=this.shadow.getElementById("mini-scrub-time");const e=this.shadow.getElementById("mini-bar"),i=e.querySelector(".mini-track"),n=a=>{const c=i.getBoundingClientRect(),h=this.player.seekableDuration;if(c.width<=0||h<=0)return;const l=Math.min(Math.max((a.clientX-c.left)/c.width,0),1)*h;this.player.seek(l),this.miniScrubTime.textContent=this.formatElapsedAt(l),this.miniScrubTime.style.left=this.miniDot.style.left};let s=!1;e.addEventListener("pointerdown",a=>{a.button===0&&(a.stopPropagation(),e.setPointerCapture(a.pointerId),e.classList.add("scrubbing"),s=this.playRequested,this.pause(),this.miniScrubTime.hidden=!1,n(a))}),e.addEventListener("pointermove",a=>{e.hasPointerCapture(a.pointerId)&&n(a)});const r=a=>{e.classList.contains("scrubbing")&&(e.classList.remove("scrubbing"),e.hasPointerCapture(a.pointerId)&&e.releasePointerCapture(a.pointerId),this.miniScrubTime.hidden=!0,s&&this.play())};e.addEventListener("pointerup",r),e.addEventListener("pointercancel",r),e.addEventListener("click",a=>a.stopPropagation()),this.miniMuteButton.addEventListener("click",a=>{a.stopPropagation(),this.toggleMuted()}),this.stageElement.addEventListener("pointerenter",this.handleMinifiedEnter),this.stageElement.addEventListener("pointerleave",this.handleMinifiedLeave),this.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>{this.player.seek(this.snapSeekToMark(Number(this.seekInput.value))),this.announceReveal()}),this.seekInput.addEventListener("pointerdown",a=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(a),this.beginTouchScrub(a)}),this.seekInput.addEventListener("pointerup",a=>{this.seekSnapArmed=!1,this.endTouchScrub(a)}),this.seekInput.addEventListener("pointercancel",a=>this.endTouchScrub(a)),this.seekInput.addEventListener("pointermove",a=>{this.nameMarkUnder(a),this.hoverSeek(a),this.touchScrub(a)}),this.seekInput.addEventListener("pointerleave",()=>{this.seekInput.removeAttribute("title"),this.leaveSeek()}),this.seekInput.addEventListener("keydown",this.handleSeekKey),this.stageElement.addEventListener("pointerdown",()=>{this.handlePointerDown(),this.touchedStage()},!0);for(const a of["touchend","click"])this.stageElement.addEventListener(a,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",a=>{if(!(!this.enableClickToPlay||this.minified)){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}a.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",a=>{!this.enableClickToPlay||this.minified||(a.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),document.addEventListener("pointerdown",this.handleMomentsDismiss,!0),document.addEventListener("keydown",this.handleMomentsDismiss,!0),document.addEventListener("visibilitychange",this.handleVisibility),window.addEventListener("pagehide",this.handleHidden),document.addEventListener("pointerup",this.handlePointerRelease,!0),document.addEventListener("pointercancel",this.handlePointerRelease,!0),this.observerMapResizeObserver?.observe(this.observerMapPanel),this.chromeResizeObserver?.observe(this.chromeCanvas),this.controlsFitObserver?.observe(this.controlsRow),this.controlsFitObserver?.observe(this.controlsRow.querySelector(".controls-left")),typeof MutationObserver<"u"&&(this.controlsMutations=new MutationObserver(()=>this.fitControls()),this.controlsMutations.observe(this.controlsRight,{attributes:!0,attributeFilter:["hidden"],childList:!0,subtree:!0})),this.hostControls(void 0),this.player=this.createPlayer(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.refresh()}connectedCallback(){this.saidTexts=void 0,this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("fullscreenchange",this.handleFullscreenChange),document.removeEventListener("pointerdown",this.handleMomentsDismiss,!0),document.removeEventListener("keydown",this.handleMomentsDismiss,!0),document.removeEventListener("visibilitychange",this.handleVisibility),window.removeEventListener("pagehide",this.handleHidden),document.removeEventListener("pointerup",this.handlePointerRelease,!0),document.removeEventListener("pointercancel",this.handlePointerRelease,!0),window.clearTimeout(this.controlsIdleTimer),this.observerMapResizeObserver?.disconnect(),this.chromeResizeObserver?.disconnect(),this.controlsFitObserver?.disconnect(),this.controlsMutations?.disconnect(),this.exitSimulatedFullscreen(),this.sightingAudio.dispose()}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t===Lr&&this.applyObserverMapDefault(),t===Nr&&this.setMilestonesShown(!this.hasAttribute(Nr)),t===Io){const n=this.minified;this.stageElement.classList.toggle("minified",n),n&&e===null&&(this.muted=!0),this.updateStartState()}}get minified(){return this.hasAttribute(Io)}miniPlayed;miniRemaining;miniMuteButton;handleMinifiedEnter=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!0,this.play())};minifiedHovered=!1;handleMinifiedLeave=t=>{!this.minified||t.pointerType==="touch"||(this.minifiedHovered=!1,this.pause(),this.dispatchEvent(new CustomEvent(tx)))};started=!1;updateStartState(){this.playRequested&&(this.started=!0);const t=!this.started&&this.enableClickToPlay;this.stageElement.classList.toggle("unstarted",t),t&&!this.minified?this.canvas.title=this.messages.clickToPlay:this.canvas.removeAttribute("title")}async loadFromSrc(t){this.sightingData=await Ha.recording(t)}get sightingData(){return JS(this.currentSighting)}set sightingData(t){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=QS(t),this.observerMapFrozenSource&&(this.observerMapFrozen=this.observerMapFrozenSource(this.currentSighting.frozen)),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(t,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.started=!1,this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault(),this.minified&&this.minifiedHovered&&this.play()}set playerTitle(t){this.titleOverride=t,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const t=this.said.read(this.titleOverride)??this.said.read(this.currentSighting.observer?.title)??"";this.playerTitleBox.textContent=t,this.playerTitleBox.hidden=t===""}get recordingIssues(){return this.issues}async reportIssues(t,e){const i=++this.issueCheck;let n=[];try{const{default:s}=await Re(async()=>{const{default:r}=await import("./sightingSchema-Bc1JhWrZ.js");return{default:r}},[],import.meta.url);n=new Vs(s).issues(t)}catch{}i===this.issueCheck&&(this.issues=[...n,...e.loadIssues],vh.warn(this.issues,e.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(CE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const t=this.issues.length;this.issuesBox.hidden=t===0,this.shadow.getElementById("issues-count").textContent=String(t);const e=this.messages.recordingIssues.replace("{count}",String(t));this.issuesButton.title=e,this.issuesButton.setAttribute("aria-label",e),this.shadow.getElementById("issues-title").textContent=e,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=vh.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(t){this.soundPreview=t,this.sightingAudio.resume(),this.sightingAudio.setSound(t)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(t){this.player.seek(t)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(t){t!==this.loopEnabled&&this.toggleLoop()}play(){if(!(this.player.seekableDuration<=0||this.playbackState==="playing")){if(this.clockHeld){this.playAfterHold=!0,this.announcePlayRequest();return}this.togglePlayPause()}}get playRequested(){return this.playbackState==="playing"||this.playAfterHold}announcePlayRequest(){this.announceReveal(),this.dispatchEvent(new CustomEvent("playrequest"))}announceReveal(){this.started=!0,this.updateStartState(),this.dispatchEvent(new CustomEvent("revealrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(t){if(t!==this.clockHeld){if(this.clockHeld=t,t){if(this.playbackState!=="playing")return;this.playAfterHold=!0,this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton();return}this.playAfterHold&&(this.playAfterHold=!1,!(this.player.seekableDuration<=0||this.playbackState==="playing")&&(this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton()))}}pause(){this.playAfterHold=!1,this.playbackState==="playing"&&this.togglePlayPause()}get positionLabel(){return this.timeStartLabel.textContent??""}get durationLabel(){return this.timeEndLabel.textContent??""}get showingClockTime(){return this.canShowClockTime}get canSwitchTimeDisplay(){return this.realStartMs!==void 0}toggleTimeDisplay(){this.canSwitchTimeDisplay&&(this.showClockTime=!this.showClockTime,this.updateTimeLabels(),this.updateTimeLabelTitles(),this.dispatchEvent(new CustomEvent("timedisplaychange",{bubbles:!0,composed:!0})))}get canShowClockTime(){return this.realStartMs!==void 0&&this.showClockTime}set showToolbar(t){this.toolbar.classList.toggle("hidden",!t),t?this.controlsRight.appendChild(this.fullscreenButton):this.cornerButtons.appendChild(this.fullscreenButton)}get playbackState(){return this.player.playbackState}get selectedSourceIds(){return this.highlightedSourceIds}get durationSeconds(){return this.currentSighting.event.durationSeconds}set durationSeconds(t){this.currentSighting.event.durationSeconds=t,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(t){const e=new Set(t);e.size===this.highlightedSourceIds.size&&[...e].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=e,this.refresh())}hasVisibleShapeAt(t,e){return this.shapeAt(t,e)!==void 0}refresh(){this.applyFrameFormat(),this.updateMuteButton(),this.updateTimeLabels(),this.seekInput.max=String(this.player.seekableDuration),this.refreshMilestoneMarks(),this.updateMilestonesButton(),this.updateObserverMap(),this.updateReferences(),this.updateTracesButton(),this.player.seek(this.player.time)}repaintOverlay(){this.quietFrame=!0;try{this.player.seek(this.player.time)}finally{this.quietFrame=!1}}quietFrame=!1;hostControls(t){const e=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(t)for(const i of e)t.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of e)this.controlsRight.insertBefore(n,i)}}get referencesShown(){return this.referencesShownState}get referenceOpacity(){return Number(this.referenceOpacityInput.value)}get severalReferences(){return this.currentSighting.references.length>1}toggleReferences(){if(this.severalReferences){this.toggleReferencesMenu();return}this.referencesShownState=!this.referencesShownState,this.updateReferencesButton(),this.dispatchReferenceView()}updateReferences(){const t=this.currentSighting.references;!this.referenceOpacityTouched&&t.length>0&&(this.referenceOpacityInput.value=String(t[0].opacity));for(const e of[...this.referenceViews.keys()])t.some(i=>i.id===e)||this.referenceViews.delete(e);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(t){let e=this.referenceViews.get(t.id);return e||(e={shown:!0,opacity:t.opacity},this.referenceViews.set(t.id,e)),e}toggleReferencesMenu(){this.referencesMenu.hidden?this.openReferencesMenu():this.closeReferencesMenu()}openReferencesMenu(){this.renderReferencesMenu(),this.referencesMenu.hidden=!1,this.placeReferencesMenu(),this.referencesButton.setAttribute("aria-expanded","true"),document.addEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.addEventListener("keydown",this.handleReferencesMenuKey,!0)}closeReferencesMenu(){this.referencesMenu.hidden||(this.referencesMenu.hidden=!0,this.referencesButton.setAttribute("aria-expanded","false"),document.removeEventListener("pointerdown",this.handleReferencesMenuOutside,!0),document.removeEventListener("keydown",this.handleReferencesMenuKey,!0))}handleReferencesMenuOutside=t=>{const e=t.composedPath();e.includes(this.referencesMenu)||e.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=t=>{t.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const t=this.referencesButton.getBoundingClientRect(),e=this.referencesMenu,i=4;e.style.bottom=`${Math.max(i,window.innerHeight-t.top+i)}px`,e.style.top="auto";const n=e.getBoundingClientRect().width;e.style.left=`${Math.max(i,Math.min(t.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const t=this.currentSighting.references.map(e=>{const i=this.viewOfReference(e),n=this.said.read(e.title)??e.id,s=document.createElement("div");s.className="reference-row";const r=document.createElement("label"),a=document.createElement("input");a.type="checkbox",a.checked=i.shown;const c=document.createElement("span");c.textContent=n,c.title=n,r.append(a,c);const h=document.createElement("input");return h.type="range",h.min="0",h.max="1",h.step="0.05",h.value=String(i.opacity),h.title=this.messages.referenceOpacity,h.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),h.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,h.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),h.addEventListener("input",()=>{i.opacity=Number(h.value),this.dispatchReferenceView()}),s.append(r,h),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...t)}updateReferencesButton(){const t=this.currentSighting.references.length>0,e=this.severalReferences,i=e?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!t,this.referenceOpacityInput.hidden=!t||!this.referencesShownState||e,this.referencesButton.setAttribute("aria-pressed",String(i)),e?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),Ue.setIcon(this.referencesButton,i?Zt.PICTURES_ON:Zt.PICTURES_OFF);const n=e?this.messages.referencesMenu:this.referencesShownState?this.messages.hideReferences:this.messages.showReferences;this.referencesButton.title=n,this.referencesButton.setAttribute("aria-label",n),this.referenceOpacityInput.title=this.messages.referenceOpacity,this.referenceOpacityInput.setAttribute("aria-label",this.messages.referenceOpacity)}get tracesShown(){return this.tracesShownState}toggleTraces(){this.tracesShownState=!this.tracesShownState,this.updateTracesButton(),this.updateObserverMap(),this.dispatchEvent(new CustomEvent("traceview",{detail:{shown:this.tracesShown}}))}updateTracesButton(){this.tracesButton.hidden=this.currentSighting.traces.length===0,this.tracesButton.setAttribute("aria-pressed",String(this.tracesShownState)),Ue.setIcon(this.tracesButton,this.tracesShownState?Zt.TRACES_ON:Zt.TRACES_OFF);const t=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=t,this.tracesButton.setAttribute("aria-label",t)}dispatchReferenceView(){const t=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(e=>[e.id,{...this.viewOfReference(e)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:t}}))}refreshMilestoneMarks(){const t=this.player.seekableDuration,e=t>0?ul(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...e.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/t,0),1)*100}%`;const s=this.said.read(i.label)??"",r=this.said.read(i.note),a=r?`${s} — ${r}`:s;return n.title=a,n.setAttribute("aria-label",a),n.dataset.t=String(i.t),n.addEventListener("click",()=>this.player.seek(i.t)),n})),this.refreshSeekSegments(t,e.map(i=>i.t)),this.refreshMomentsPicker(e)}refreshMomentsPicker(t){const e=this.milestonesShown&&t.length>0;this.momentsBox.hidden=!e,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...t.map(i=>{const n=document.createElement("li"),s=document.createElement("button");s.type="button",s.dataset.t=String(i.t);const r=this.said.read(i.label)??"",a=this.said.read(i.note);return s.textContent=a?`${r} — ${a}`:r,s.addEventListener("click",()=>{this.player.seek(i.t),this.closeMomentsMenu()}),n.appendChild(s),n})),this.momentsButton.title=this.messages.moments,this.showCurrentMoment(void 0)}showCurrentMoment(t){const i=(t?this.said.read(t.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=t!==void 0&&Number(n.dataset.t)===t.t;n.getAttribute("aria-current")==="true"!==s&&n.setAttribute("aria-current",String(s))}}toggleMomentsMenu(){this.momentsMenu.hidden?(this.momentsMenu.hidden=!1,this.momentsButton.setAttribute("aria-expanded","true")):this.closeMomentsMenu()}closeMomentsMenu(){this.momentsMenu.hidden=!0,this.momentsButton.setAttribute("aria-expanded","false")}handleMomentsDismiss=t=>{if(!this.momentsMenu.hidden){if(t instanceof KeyboardEvent){t.key==="Escape"&&this.closeMomentsMenu();return}t.composedPath().some(e=>e===this.momentsMenu||e===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(t,e){const n=[0,...this.milestonesShown&&t>0?[...new Set(e.filter(r=>r>0&&r<t))].sort((r,a)=>r-a):[],Math.max(t,0)];this.seekSegmentList=[];const s=[];for(let r=0;r<n.length-1;r++){const a=document.createElement("div");a.className="seek-segment",a.style.flexGrow=String(Math.max(n[r+1]-n[r],1));const c=document.createElement("i");c.className="seek-hover";const h=document.createElement("i");h.className="seek-played",a.append(c,h),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:h,hover:c})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(t,e){const i=t.end-t.start,n=i>0?(e-t.start)/i:e>=t.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintMiniProgress(t){const e=this.player.seekableDuration,i=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`;this.miniPlayed.style.width=i,this.miniDot.style.left=i,this.miniRemaining.textContent=this.formatRemaining(t)}miniDot;miniScrubTime;paintSeekProgress(t){for(const i of this.seekSegmentList)i.played.style.width=Ue.fillOf(i,t);const e=this.player.seekableDuration;this.seekDot.style.left=`${e>0?Math.min(Math.max(t/e,0),1)*100:0}%`}hoverSeek(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((f,p)=>{f.hover.style.width=Ue.fillOf(f,s),f.element.classList.toggle("hovered",s>=f.start&&(s<f.end||p===r))});const a=this.milestonesShown?this.sighting.milestones:[],c=a.length>0?l0(a,s):void 0,h=c?this.said.read(c.label)??"":"",l=c?this.said.read(c.note):void 0,u=l?`${h} — ${l}`:h;this.seekPreviewTitle.textContent=u,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const d=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*e.width-d/2,0),Math.max(e.width-d,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const t of this.seekSegmentList)t.hover.style.width="0",t.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(t){const e=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=e===void 0,e?.(t,this.seekPreviewCanvas)}paintChrome(t){const e=this.chromeCanvas.getContext("2d"),i=this.overlayPainter!==void 0||this.selectionShown;if(!i&&!this.chromeDirty)return;const n=this.chromeCanvas.clientWidth,s=this.chromeCanvas.clientHeight;if(!e||typeof e.setTransform!="function"||n===0||s===0){t(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),c=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==c&&(this.chromeCanvas.height=c),e.setTransform(1,0,0,1,0,0),e.clearRect(0,0,a,c),this.chromeDirty=!1,i&&(e.setTransform(a/this.canvas.width,0,0,c/this.canvas.height,0,0),this.chromeRenderer??=new gh(e),this.chromeDirty=!0,t(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(t){if(t.pointerType!=="mouse"){this.scrubbingPointer=t.pointerId;try{this.seekInput.setPointerCapture(t.pointerId)}catch{}this.seekToPointer(t)}}touchScrub(t){t.pointerId===this.scrubbingPointer&&this.seekToPointer(t)}endTouchScrub(t){t.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(t))}seekToPointer(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=Math.min(Math.max((t.clientX-e.left)/e.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(t){const e=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(e<=0||i<=0)return;const n=Ue.MARK_SNAP_PX/i*e;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-t)>n||(!s||Math.abs(a-t)<Math.abs(s.t-t))&&(s={t:a,name:r.title})}return s}snapSeekToMark(t){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(t)?.t??t):t}nameMarkUnder(t){const e=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(e.width<=0||i<=0)return;const n=(t.clientX-e.left)/e.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(t){const e=this.milestonesShown&&this.sighting.milestones.length>0?l0(this.sighting.milestones,t):void 0;if(this.milestoneCaption.hidden=e===void 0,this.showCurrentMoment(e),!e)return;const i=document.createElement("b");i.textContent=this.said.read(e.label)??"";const n=this.said.read(e.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(t){const e=this.exposureTimes(t),i=1/e.length;return e.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(t=this.currentTime){const e=qs.windowEndingAt(t,this.currentSighting.exposure??0);if(e.ms<Ue.SHORTEST_VISIBLE_EXPOSURE_MS)return[t];const i=Math.min(Ue.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(e.ms/Ue.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(e.fromMs,e.ms)/Ue.EXPOSURE_STEP_PX),s=Math.min(Ue.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(e.fromMs+e.ms*a/(s-1));return r}travelPxOver(t,e){const i=this.shapesAt(t),n=this.shapesAt(t+e);let s=0;for(const[r,a]of i){const c=n.get(r);if(!c)continue;const h=c.bounds.x+c.bounds.width/2-(a.bounds.x+a.bounds.width/2),l=c.bounds.y+c.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(h,l))}return s}shapeAt(t,e,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,t,e,i);if(s)return s}}shapesAt(t){const e=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(t,i);n&&e.set(i,n)}return e}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const t=Ti.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===t)return;this.canvas.width=t,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${t} / ${this.canvas.height}`)}canvasPointFromEvent(t){const e=this.canvas.getBoundingClientRect();if(!(e.width===0||e.height===0))return{x:(t.clientX-e.left)/e.width*this.canvas.width,y:(t.clientY-e.top)/e.height*this.canvas.height}}onFrame(t,e){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:DE;this.canvasRenderer.setStarPoints(Ti.starPointsOf(this.sighting.instrument,ze(this.sighting,t)?.fNumber));const n=(ze(this.sighting,t)?.rollDeg??0)+this.gaitAt(t).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(t),r=this.frameShift;if(this.paintsShapes)for(const c of s)for(const[,h]of c.shapes){const l=c.share,u=l===1?h:{...h,transparency:1-(1-h.transparency)*l};this.canvasRenderer.paintShape(this.shifted(u,r))}for(const[c,h]of s[0].shapes)!this.selectionShown||!i.has(c)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...h,selected:!0}):this.canvasRenderer.paintMemberOutline(h):this.canvasRenderer.paintSelectionOnly(this.shifted(h,r)));const a=this.selectionShown&&i.size>1?ys.groupBoundsFor([...e].filter(([c])=>i.has(c)).map(([,c])=>c.bounds)):void 0;this.chromeDraw=c=>{a&&c.paintGroupHandles(a),this.overlayPainter?.(c)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(c=>[...c.shapes.values()].filter(h=>h.transparency<1).map(h=>this.shifted(h,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(t),this.paintSeekProgress(t),this.minified&&this.paintMiniProgress(t),this.timeStartLabel.textContent=this.formatPosition(t),this.showMilestoneAt(t),this.paintObserverMap(t),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(O2(this.currentSighting,t))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),!this.quietFrame&&this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:t}}))}shifted(t,e){return e.x===0&&e.y===0?t:{...t,bounds:{...t.bounds,x:t.bounds.x+e.x,y:t.bounds.y+e.y}}}createPlayer(){const t=new VS(this.currentSighting.timeline,(e,i)=>this.onFrame(e,i));return t.loop=this.loopEnabled,t.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},t}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=t=>{t.key.toLowerCase()!=="f"||t.altKey||t.ctrlKey||t.metaKey||!this.enableClickToPlay||t.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(t.preventDefault(),this.toggleFullscreen())};handleSeekKey=t=>{if(t.altKey||t.ctrlKey||t.metaKey)return;const e=t.key==="ArrowLeft"?-1:t.key==="ArrowRight"?1:0;if(e){t.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+e*Ue.SEEK_KEY_STEP_MS)))}else t.key===" "&&(t.preventDefault(),this.togglePlayPause())};togglePlayPause(){if(!(this.player.seekableDuration<=0)){if(this.player.playbackState==="playing")this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh();else if(this.clockHeld){this.playAfterHold=!this.playAfterHold,this.playAfterHold&&this.announcePlayRequest();return}else this.announcePlayRequest(),this.sightingAudio.resume(),this.player.play();this.updatePlayPauseButton(),this.flashPlayback()}}flashPlayback(){const t=this.playbackFlash;t.innerHTML=this.player.playbackState==="playing"?Zt.PLAY:Zt.PAUSE,t.classList.remove("flashing"),t.offsetWidth,t.classList.add("flashing")}static icons=new WeakMap;static setIcon(t,e){Ue.icons.get(t)!==e&&(Ue.icons.set(t,e),t.innerHTML=e)}set captionHeld(t){this.stageElement.classList.toggle("caption-held",t)}set controlsHeld(t){this.stageElement.classList.toggle("controls-held",t)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(t){this.quietControlsValue=t,this.stageElement.classList.toggle("quiet",t)}tapRevealedOnly=!1;get hoverless(){return typeof matchMedia=="function"&&matchMedia("(hover: none)").matches}touchedStage(){if(!this.hoverless)return;this.player.playbackState==="playing"&&!this.stageElement.classList.contains("touched")&&(this.tapRevealedOnly=!0),this.revealControls()}pointerHeld=!1;handlePointerDown=()=>{this.pointerHeld=!0};resumeAfterScrub=!1;suspendForScrub(){this.player.playbackState==="playing"&&(this.resumeAfterScrub=!0,this.stopPlaying())}stopPlaying(){this.player.pause(),this.soundPreview=void 0,this.sightingAudio.silence(),this.refresh(),this.updatePlayPauseButton()}resumeFromScrub(){this.resumeAfterScrub&&(this.resumeAfterScrub=!1,this.sightingAudio.resume(),this.player.play(),this.updatePlayPauseButton())}handleHidden=()=>{this.player.playbackState==="playing"&&this.stopPlaying(),this.resumeAfterScrub=!1};handleVisibility=()=>{document.visibilityState==="hidden"&&this.handleHidden()};handlePointerRelease=()=>{this.resumeAfterScrub&&window.setTimeout(()=>this.resumeFromScrub(),0),this.pointerHeld&&(this.pointerHeld=!1,this.hoverless&&this.stageElement.classList.contains("touched")&&this.revealControls())};revealControls(){this.stageElement.classList.add("touched"),window.clearTimeout(this.controlsIdleTimer),this.player.playbackState==="playing"&&(this.pointerHeld||!this.momentsMenu.hidden||(this.controlsIdleTimer=window.setTimeout(()=>{this.stageElement.classList.remove("touched"),this.tapRevealedOnly=!1},Ue.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const t=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!t),t!==this.wasPlaying&&t&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=t,this.updateStartState(),Ue.setIcon(this.playPauseButton,t?Zt.PAUSE:Zt.PLAY);const e=this.player.seekableDuration>0;this.playPauseButton.disabled=!e;const i=e?t?this.messages.pause:this.messages.play:this.messages.noDuration;this.playPauseButton.title=i,this.playPauseButton.setAttribute("aria-label",i)}toggleLoop(){this.loopEnabled=!this.loopEnabled,this.player.loop=this.loopEnabled}restorePlayback(){const t=this.playbackBeforeClick;t&&(this.currentTime=t.time,t.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(t=>{console.error("<rr0-ufo>: requestFullscreen() failed —",t)})}enterSimulatedFullscreen(){const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=t.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const e=t.style;e.setProperty("position","fixed"),e.setProperty("inset","0"),e.setProperty("margin","0"),e.setProperty("max-width","none"),e.setProperty("max-height","none"),e.setProperty("aspect-ratio","auto"),e.setProperty("z-index","2147483647"),e.setProperty("background","#000"),e.setProperty("width","100vw"),e.setProperty("width","100dvw"),e.setProperty("height","100vh"),e.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const t=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?t.setAttribute("style",this.styleBeforeSimulatedFullscreen):t.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const t=this.observerMapPanel.hidden;this.observerMapAsked=t,this.setObserverMapOpen(t),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:t}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const t=this.getAttribute(Lr),e=t===null?this.sighting.observerMap??this.observerPath?.travels===!0:t!=="false";this.setObserverMapOpen(e&&this.observerPath!==void 0)}setObserverMapOpen(t){this.observerMapPanel.hidden=!t,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(t)),this.updateObserverMapButton(),t&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const t=!this.observerMapPanel.hidden;Ue.setIcon(this.observerMapButton,t?Zt.MAP_ON:Zt.MAP_OFF);const e=t?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=e,this.observerMapButton.setAttribute("aria-label",e);const i=[[this.mapZoomInButton,this.messages.zoomMapIn],[this.mapZoomOutButton,this.messages.zoomMapOut],[this.mapFitButton,this.messages.fitMap]];for(const[n,s]of i)n.title=s,n.setAttribute("aria-label",s)}updateObserverMap(){const t=this.observerPath!==void 0;if(this.observerPath=eh.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!t&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const e=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=si.fitted(this.observerPath,e);(!this.observerMapBounds||!this.sameGround(this.observerMapBounds,i))&&(this.observerMapBounds&&this.observerMapView.refit(this.observerMapBounds,i),this.observerMapBounds=i,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||this.loadObserverMapImagery())}sameGround(t,e){const i=Math.abs(t.east-t.west)/20;return Math.abs(t.north-e.north)<i&&Math.abs(t.south-e.south)<i&&Math.abs(t.west-e.west)<i&&Math.abs(t.east-e.east)<i}async loadObserverMapImagery(){const t=this.observerMapViewBounds;if(!t||this.observerMapPanel.hidden||this.observerMapImageryLoading||(this.observerMapFrozenImagery?this.observerMapImageryBounds!==void 0:!this.observerMapImageryNeededFor(t)))return;const e=this.observerMapView.changed,i=e?si.expand(t,Ue.OBSERVER_MAP_IMAGERY_AHEAD):t,n=si.IMAGERY_PX*(e?1+2*Ue.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=t.east-t.west,this.observerMapImageryLoading=!0;const s=this.observerMapFrozenImagery,r=s?void 0:j2();try{const a=r?await r.getImageryTexture(i,{width:n,height:n}):await s.getImagery();if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=a,this.observerMapImageryCredit=(r??s).attribution,this.observerMapImageryFailed=!1}catch{if(this.observerMapImageryBounds!==i)return;this.observerMapImageryFailed=this.observerMapImagery===void 0}finally{this.observerMapImageryBounds===i&&(this.observerMapImageryLoading=!1)}this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}static OBSERVER_MAP_IMAGERY_AHEAD=.5;static OBSERVER_MAP_IMAGERY_LOOKAHEAD=.25;observerMapImageryNeededFor(t){const e=this.observerMapImageryBounds;if(!e)return!0;const i=this.observerMapImagery?.bounds??e,n=this.observerMapView.changed?si.expand(t,Ue.OBSERVER_MAP_IMAGERY_LOOKAHEAD):t,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=t.east-t.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}set observerMapFrozen(t){t!==this.observerMapFrozenImagery&&(this.observerMapFrozenImagery=t,this.observerMapImagery=void 0,this.observerMapImageryCredit=void 0,this.observerMapImageryFailed=!1,this.observerMapImageryBounds=void 0,this.observerMapImageryLoading=!1,this.observerMapPanel.hidden||(this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime)))}get observerMapFrozen(){return this.observerMapFrozenImagery}observerMapFrozenImagery;observerMapFrozenSource;get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(t){this.mapSceneBounds=t.map(e=>({x:e.x*this.canvas.width,y:e.y*this.canvas.height,width:e.width*this.canvas.width,height:e.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const t=this.observerMapBoxPx;if(!t)return;const e=[...this.mapShapeBounds,...this.mapSceneBounds],i=(h,l,u)=>{for(const d of e)if(!(d.x+d.width<h-u||d.x>l+u)&&!(d.y>t.bottom+u||d.y+d.height<t.top-u))return!0;return!1},n=[this.canvas.width-t.width,this.canvas.width],s=[0,t.width],r=Ue.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),c=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&c&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(c||!i(n[0],n[1],r))&&this.observerMapPanel.classList.remove("on-the-left");return}i(n[0],n[1],0)&&!i(s[0],s[1],0)&&this.observerMapPanel.classList.add("on-the-left")}observerMapBoxPx;static OBSERVER_MAP_CLEARANCE_PX=24;sizeObserverMapCanvas(){const t=this.observerMapPanel.clientWidth;if(t===0)return;const e=Math.round(t*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==e&&(this.observerMapCanvas.width=e,this.observerMapCanvas.height=e)}measureObserverMapBox(){const t=this.observerMapPanel.getBoundingClientRect(),e=this.canvas.getBoundingClientRect();if(e.width===0||e.height===0)return;const i=this.canvas.width/e.width,n=this.canvas.height/e.height;this.observerMapBoxPx={width:t.width*i,top:(t.top-e.top)*n,bottom:(t.bottom-e.top)*n}}paintObserverMap(t){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const e=ze(this.currentSighting,t);e?.lat!==void 0&&e.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:e.lat,lng:e.lng},Ue.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?l0(this.currentSighting.milestones,t):void 0;for(const r of this.milestonesShown?ul(this.currentSighting.milestones):[]){const a=ze(this.currentSighting,r.t);a?.lat===void 0||a.lng===void 0||n.push({label:this.said.read(r.label)??"",note:this.said.read(r.note),t:r.t,lat:a.lat,lng:a.lng,current:r===s})}this.observerMapRenderer.paint({bounds:this.observerMapViewBounds,imagery:this.observerMapImagery,path:this.observerPath,position:e?.lat!==void 0&&e.lng!==void 0?{lat:e.lat,lng:e.lng}:void 0,headingDeg:e?.headingDeg===void 0?void 0:e.headingDeg+this.lookYawDeg,coneHalfAngleDeg:e?Ir.of(i,this.canvas.height,e.fovDeg).halfWidthAngleDeg(Ti.aspectOf(i)):void 0,markers:n,traces:(this.tracesShownState?this.currentSighting.traces:[]).map(r=>({kind:r.kind,points:r.points,color:r.color,label:this.said.read(r.title)})),decor:this.observerMapDecorAt(t),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(t){this.milestonesShown=t,this.milestoneMarks.hidden=!t,this.momentsBox.hidden=!t||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,ul(this.sighting.milestones).map(e=>e.t)),this.milestonesButton.setAttribute("aria-pressed",String(t)),this.updateMilestonesButton(),this.showMilestoneAt(this.currentTime),this.paintObserverMap(this.currentTime)}updateMilestonesButton(){this.milestonesButton.hidden=this.currentSighting.milestones.length===0,this.momentsButton.title=this.messages.moments,Ue.setIcon(this.milestonesButton,this.milestonesShown?Zt.MILESTONES_ON:Zt.MILESTONES_OFF);const t=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=t,this.milestonesButton.setAttribute("aria-label",t)}observerMapDecorAt(t){const e=ze(this.currentSighting,0);return e?.lat===void 0||e.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=tr(i,t),{lat:s,lng:r}=os(n.eastM,-n.northM,e.lat,e.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(t){const e=t===void 0?void 0:Math.max(0,Math.min(1,-t/12));e!==this.observerMapNightFraction&&(this.observerMapNightFraction=e,this.paintObserverMap(this.currentTime))}setLookOffset(t,e){t===this.lookYawDeg&&e===this.lookPitchDeg||(this.lookYawDeg=t,this.lookPitchDeg=e,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const t=this.gaitAt(this.currentTime),e=this.lookYawDeg+t.yawDeg,i=this.lookPitchDeg+t.pitchDeg;if(e===0&&i===0)return{x:0,y:0};const n=ze(this.currentSighting,this.currentTime),s=Ir.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(e),y:s.angleDegToRadiusPx(i)}}gaitAt(t){return qe.bodyAt(this.currentSighting,t,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(t){t!==this.mutedState&&(this.mutedState=t,!t&&this.volumeState===0&&(this.volumeState=Ue.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(t){this.setVolume(t)}setVolume(t){this.volumeState=Math.min(Math.max(t,0),1),this.mutedState=this.volumeState===0,this.applyLevel()}get level(){return this.mutedState?0:this.volumeState}applyLevel(){this.sightingAudio.setLevel(this.level),this.updateMuteButton(),this.dispatchEvent(new CustomEvent("mutedchange",{bubbles:!0,composed:!0,detail:{muted:this.mutedState,volume:this.volumeState}}))}toggleMuted(){this.hasSound&&(this.muted=!this.mutedState)}ambientSound;get hasSound(){return this.currentSighting.soundTrack.allKeyframes.length>0||this.ambientSound?.(this.currentSighting)===!0}updateMuteButton(){const t=!this.hasSound;this.miniMuteButton.hidden=t,this.miniMuteButton.setAttribute("aria-pressed",String(this.mutedState)),Ue.setIcon(this.miniMuteButton,this.mutedState?Zt.MUTED:Zt.VOLUME);const e=this.mutedState?this.messages.unmute:this.messages.mute;if(this.miniMuteButton.title=e,this.miniMuteButton.setAttribute("aria-label",e),this.muteButton.disabled=t,this.volumeInput.hidden=t,t){Ue.setIcon(this.muteButton,Zt.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}Ue.setIcon(this.muteButton,this.mutedState?Zt.MUTED:Zt.VOLUME);const i=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=i,this.muteButton.setAttribute("aria-label",i),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const t=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;Ue.setIcon(this.fullscreenButton,t?Zt.EXIT_FULLSCREEN:Zt.ENTER_FULLSCREEN),this.fullscreenButton.title=t?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new Ps(Ga.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const t=Tg(Ga.preferencesFor(this),Rg);if(t===this.messagesLanguage||t==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=t;const e=await iE(t);this.messagesLanguage===t&&this.applyMessages(e)}messagesLanguage;updateTimeLabelTitles(){const t=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,e=this.canSwitchTimeDisplay?` — ${t}`:"";this.timeStartLabel.title=this.messages.currentPosition+e,this.timeEndLabel.title=this.messages.duration+e,this.timePill.classList.toggle("switchable",this.canSwitchTimeDisplay),this.canSwitchTimeDisplay?(this.timePill.setAttribute("role","button"),this.timePill.setAttribute("tabindex","0")):(this.timePill.removeAttribute("role"),this.timePill.removeAttribute("tabindex"))}applyMessages(t){this.messages=t,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const t=this.currentSighting.event,e=C2(t);this.realDurationMs=e!==void 0&&e>0?e:void 0,this.realStartMs=t.time?Xp(t.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.paintMiniProgress(this.player.time),this.updateTimeLabelTitles()}formatPosition(t){if(this.realDurationMs===void 0)return pa(t);const e=this.currentSighting.timeline.duration,i=e>0&&t<=e?t/e*this.realDurationMs:t;return this.canShowClockTime?bv(xv(this.realStartMs+i)):pa(i)}formatElapsedAt(t){const e=this.currentSighting.timeline.duration;return this.realDurationMs===void 0?pa(t):pa(e>0&&t<=e?t/e*this.realDurationMs:t)}formatRemaining(t){const e=this.currentSighting.timeline.duration;if(this.realDurationMs===void 0)return pa(Math.max(0,e-t));const i=e>0&&t<=e?t/e*this.realDurationMs:t;return pa(Math.max(0,this.realDurationMs-i))}formatEndOfTimeline(){return this.realDurationMs===void 0?pa(this.currentSighting.timeline.duration):this.canShowClockTime?bv(xv(this.realStartMs+this.realDurationMs)):pa(this.realDurationMs)}}function xv(o){const t=new Date(o);return{hour:t.getUTCHours(),minute:t.getUTCMinutes(),second:t.getUTCSeconds()}}function bv(o){if(o.hour===void 0)return"0:00";const t=e=>String(e).padStart(2,"0");return o.second?`${t(o.hour)}:${t(o.minute??0)}:${t(o.second)}`:`${t(o.hour)}:${t(o.minute??0)}`}function pa(o){const t=Math.round(o/1e3),e=Math.floor(t/60),i=t%60;return`${e}:${String(i).padStart(2,"0")}`}const Kp="rr0-ufo";function Q2(){customElements.get(Kp)||customElements.define(Kp,Ue)}const CE="recordingissues",tx="minifiedreset";/**
|
|
2407
2407
|
* @license
|
|
2408
2408
|
* Copyright 2010-2026 Three.js Authors
|
|
2409
2409
|
* SPDX-License-Identifier: MIT
|
|
@@ -8491,7 +8491,7 @@ uniform float uWindowLuminance;
|
|
|
8491
8491
|
varying float vLitRank;
|
|
8492
8492
|
${h.fragmentShader.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
|
|
8493
8493
|
totalEmissiveRadiance *= step(vLitRank, uLitShare) * uWindowLuminance * ${ut.WINDOW_VARIETY_GLSL};`)}`},a.customProgramCacheKey=()=>"facade-lit-windows";const c=new yt(r,a);return c.castShadow=!0,c.receiveShadow=!0,e.add(c),e}static CLOSED_AT_NIGHT_SHARE=.2;static litWindowShare={value:0};static WINDOW_LUMINANCE_CD_M2=15;static ROOM_LIGHT_K=2900;static COLD_ROOM_LIGHT_K=4e3;static windowLuminance={value:0};static get WINDOW_VARIETY_GLSL(){const t=n=>`vec3(${n.map(s=>s.toFixed(4)).join(", ")})`,e=lh.ofTemperature(ut.ROOM_LIGHT_K),i=lh.ofTemperature(ut.COLD_ROOM_LIGHT_K);return`(mix(0.35, 2.0, fract(vLitRank * 97.13) * fract(vLitRank * 97.13)) * mix(${t(e)}, ${t(i)}, step(0.86, fract(vLitRank * 53.71))))`}static setWindowLuminance(t){ut.windowLuminance.value=ut.WINDOW_LUMINANCE_CD_M2*t}static setLitWindowShare(t){ut.litWindowShare.value=Math.max(0,Math.min(1,t))}static build(t,e){const i=ut.hasFacade(t)?ut.buildFacade(t):t.kind==="building"?yy(t.floors??Jd,t.windows,t.observerSide,t.occupiedFloor,t.observerFacing):t.kind==="tree"?by():t.kind==="shrub"?xy():t.kind==="bridge"?qC(t):t.kind==="wire"?ZC(t):t.kind==="wall"?Ji.build(t):t.kind==="crop"?Sy():t.kind==="terrace"?s6():t.kind==="mound"?Ey():t.kind==="streetlight"?Ay(e,t.lamp?.mount,t.lamp):t.kind==="trafficlight"?be.trafficLight(fe.isPedestrian(t.lights)):t.kind==="crossing"?be.crossing(ut.sizeOf(t).widthM,ut.sizeOf(t).lengthM):t.kind==="roadsign"?be.roadSign(t.sign):t.kind==="vehicle"?_y(e,t.windows,t.observerSide,t.observerFacing):t.kind==="aircraft"?Oy():t.kind==="entity"?Dy():Mg();t.color&&this.paint(i,t.color);const n=this.scaleFor(t),s=new Ne;return t.kind==="building"&&t.roof&&this.addRoof(s,t),i.name=ut.BODY_NAME,i.scale.copy(n),s.add(i),t.headingDeg!==void 0&&(s.rotation.y=-t.headingDeg*cp),this.addLights(s,t.lights),ut.fitLights(s,t,t.sizeM??{}),s}static scaleFor(t){const e=t.sizeM;if(!e||ut.hasFacade(t)||t.kind==="bridge"||t.kind==="wire"||t.kind==="terrace"||t.kind==="wall"||t.kind==="crossing")return new T(1,1,1);const i=this.naturalSize(t.kind,t.floors);return new T(e.widthM===void 0?1:dp(e.widthM,i.widthM),e.heightM===void 0?1:dp(t.kind==="building"?this.wallHeightOf(t,e.heightM):e.heightM,i.heightM),e.lengthM===void 0?1:dp(e.lengthM,i.lengthM))}static naturalSize(t,e){const i=t==="building"?Math.max(1,(e??Jd)+1):0;if(t==="bridge")return pi.NATURAL_SIZE;if(t==="wire")return No.NATURAL_SIZE;if(t==="terrace"||t==="wall")return{widthM:1,lengthM:1,heightM:1};if(t==="crossing")return{widthM:6,lengthM:2.5,heightM:be.CROSSING_LIFT_M};const n=`${t}:${i}`,s=Ty.get(n);if(s)return s;const r=t==="building"?yy(i-1,void 0,void 0,void 0):t==="tree"?by():t==="shrub"?xy():t==="crop"?Sy():t==="mound"?Ey():t==="streetlight"?Ay(!1):t==="trafficlight"?be.trafficLight(!1):t==="roadsign"?be.roadSign(void 0):t==="vehicle"?_y(!1,void 0,void 0):t==="aircraft"?Oy():t==="entity"?Dy():Mg(),a=new Xi().setFromObject(r),c={widthM:a.max.x-a.min.x,heightM:a.max.y-a.min.y,lengthM:a.max.z-a.min.z};return this.dispose(r),Ty.set(n,c),c}static usesModel(t){return jd(t)!==void 0&&!(t.observerSide!==void 0&&mh(t.kind))}static applyModel(t,e,i,n={}){const s=this.bodyOf(t),r=new Ne;r.name=ut.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*cp,i.updateMatrixWorld(!0);const a=new Xi().setFromObject(i),c={lengthM:a.max.z-a.min.z,heightM:a.max.y-a.min.y,widthM:a.max.x-a.min.x},h=e.kind==="tree"&&e.sizeM?.heightM!==void 0?{heightM:e.sizeM.heightM}:e.sizeM,l=Ry(h,c)??Ry(n.depictedSizeM,c)??1;i.scale.multiplyScalar(l);const u=a.getCenter(new T).multiplyScalar(l);i.position.x-=u.x,i.position.z-=u.z,i.position.y-=e.kind==="aircraft"?u.y:a.min.y*l,i.traverse(d=>{d instanceof yt&&(d.castShadow=!0,d.receiveShadow=!0)}),r.add(i),e.kind==="tree"&&r.add(ut.trunkShadow(c.heightM*l)),s.parent?(s.parent.add(r),s.removeFromParent()):t.add(r),this.dispose(s),ut.fitLights(t,e,{widthM:c.widthM*l,heightM:c.heightM*l,lengthM:c.lengthM*l})}static fitLights(t,e,i){const n=Qd.byId(qc.rigOf(e)||void 0)?.referenceSizeM;if(!n||!e.lights)return;const s=(l,u)=>l===void 0||u===0?1:l/u,r=s(i.widthM,n.widthM),a=s(i.heightM,n.heightM),c=s(i.lengthM,n.lengthM),h=new Map(e.lights.map(l=>[l.id,l.offsetM]));t.traverse(l=>{const u=l.userData.lightId,d=u===void 0?void 0:h.get(u);d&&l.position.set(d.x*r,d.y*a,d.z*c)})}static trunkShadow(t){ut.trunkProxy??={geometry:new kn(1,1.15,1,8),material:new ls({colorWrite:!1,depthWrite:!1})};const e=new yt(ut.trunkProxy.geometry,ut.trunkProxy.material),i=Math.min(.3,Math.max(.12,t*.035)),n=t*.45;return e.scale.set(i,n,i),e.position.y=n/2,e.castShadow=!0,e.receiveShadow=!1,e.userData.sharedModel=!0,e.name="trunk-shadow",e}static trunkProxy;static sizeOf(t){const e=this.naturalSize(t.kind,t.floors);return{widthM:t.sizeM?.widthM??e.widthM,lengthM:t.sizeM?.lengthM??e.lengthM,heightM:t.sizeM?.heightM??e.heightM}}static addLights(t,e){for(const i of e??[]){const n=BC(i.color),s=fe.figureOf(i),r=s?be.pedestrianFigure(s,1.8*(i.radiusM??hp)):new Yi(i.radiusM??hp,8,6),a=Ge(t,r,n,i.offsetM.y,!0);a.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),a.userData={emissive:!0,lightId:i.id,lightColor:n},a.visible=!1;const c=a.material;rb.apply(c),c.transparent=!0,c.depthWrite=!1,c.fog=!1}}static setLights(t,e,i,n,s=0,r=1,a=LC,c=[1,1,1],h){if(!e||e.length===0)return;const l=new Map(e.map(d=>[d.id,d]));let u;h&&e.some(d=>d.beamDeg!==void 0)&&(t.updateWorldMatrix(!0,!1),u=t.worldToLocal(ut.eyeScratch.copy(h)));for(const d of t.children){if(!(d instanceof yt))continue;const f=d.userData.lightId;if(!f)continue;const p=l.get(f);if(!p)continue;const g=s>0?k2(p,i,i+s):wS(p,i)?1:0,m=u&&p.beamDeg!==void 0?ut.beamShare(p.beamDeg,d.position,u):1;d.visible=g>0&&m>0;const v=p.radiusM??hp,y=Math.max(1,n*a/v),x=v*y,M=r/(Math.PI*x*x),b=d.material,S=d.userData.lightColor;if(S){const _=g*m*NC*(p.intensity??1)*M,w=[S[0]*_*c[0],S[1]*_*c[1],S[2]*_*c[2]],A=Math.min(1,vy/Math.max(w[0],w[1],w[2],1e-30));b.color.setRGB(w[0]*A,w[1]*A,w[2]*A)}d.scale.setScalar(y)}}static eyeScratch=new T;static beamShare(t,e,i){const n=i.x-e.x,s=i.y-e.y,r=i.z-e.z,a=Math.hypot(n,s,r);if(a===0)return 1;const c=-r/a;if(c<=0)return 0;const h=Math.log(.5)/Math.log(Math.cos(t*Math.PI/180));return Math.pow(c,h)}static setLit(t,e,i,n=1,s){const[r,a,c]=e==="streetlight"?[kC*ut.lampShare(s),UC,ut.lampHue(s)]:[FC,zC,Ob],h=i?r*n/(Math.PI*a*a):0,l=Math.min(1,vy/Math.max(c[0]*h,c[1]*h,c[2]*h,1e-30)),u=[c[0]*h*l,c[1]*h*l,c[2]*h*l];t.traverse(d=>{const f=d.userData;!(d instanceof yt)||!f.emissive||f.lightId||(d.material instanceof Fs?d.material.emissive.setRGB(...u):d.material.color.setRGB(...u))})}static REFERENCE_LUMENS=1e4;static lampShare(t){return t?.lumens?t.lumens/ut.REFERENCE_LUMENS:1}static lampHue(t){return t?.colorTemperatureK?lh.ofTemperature(t.colorTemperatureK):GC}static dispose(t){t.traverse(e=>{if(!(e instanceof yt))return;if(e.userData.sharedModel){for(const n of e.userData.tintedMaterials??[])n.dispose();return}e.geometry.dispose();const i=e.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const pp="https://ufoathome.org/models/index.json";class Al{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;static shared=new Map;sharing;constructor(t={}){this.sharing=!t.fetchImpl,this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.indexUrls=t.indexUrls??c6()}async entries(t){const e=await this.load();return t?e.filter(i=>[i.kind].flat().includes(t)):e}async entry(t){return(await this.load()).find(e=>e.id===t)}load(){if(this.loading)return this.loading;if(!this.sharing)return this.loading=this.fetchFirstAvailable();const t=this.indexUrls.join(`
|
|
8494
|
-
`);let e=Al.shared.get(t);return e||(e=this.fetchFirstAvailable(),Al.shared.set(t,e),e.then(i=>{i.length===0&&Al.shared.delete(t)})),this.loading=e}async fetchFirstAvailable(){for(const t of this.indexUrls){const e=await this.fetchIndex(t);if(e)return e}return[]}async fetchIndex(t){try{const e=await this.fetchImpl(t);if(!e.ok)return;const i=await e.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,t).href})):void 0}catch{return}}}function c6(){const o=`?v=${encodeURIComponent("0.152.
|
|
8494
|
+
`);let e=Al.shared.get(t);return e||(e=this.fetchFirstAvailable(),Al.shared.set(t,e),e.then(i=>{i.length===0&&Al.shared.delete(t)})),this.loading=e}async fetchFirstAvailable(){for(const t of this.indexUrls){const e=await this.fetchIndex(t);if(e)return e}return[]}async fetchIndex(t){try{const e=await this.fetchImpl(t);if(!e.ok)return;const i=await e.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,t).href})):void 0}catch{return}}}function c6(){const o=`?v=${encodeURIComponent("0.152.1")}`,t=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(t&&t!==pp?[t,pp]:[pp]).map(e=>e+o)}const h6=[{id:"ufoathome",name:"UFO@home",credit:"3D models re-hosted by UFO@home, each under its own author's licence",creditUrl:"https://ufoathome.org/models/",create:()=>new Al}];async function mp(o){const{GLTFLoader:t}=await Re(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-BGUT3v5v.js");return{GLTFLoader:i}},[],import.meta.url),e=new t;return new Promise((i,n)=>{e.load(o,s=>i(Object.assign(s.scene,{animations:s.animations})),void 0,s=>n(new Error(`Could not load 3D model ${o}: ${s instanceof Error?s.message:String(s)}`)))})}const zb=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class xs{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(t,e){this.mesh=new yt(new Un(2,2),new Ee({uniforms:{uColor:{value:new st(0,0,0)},uRadius:{value:1}},vertexShader:xs.VERTEX,fragmentShader:xs.FRAGMENT,transparent:!0,depthWrite:!1,blending:on,toneMapped:!1})),this.mesh.name=t,this.mesh.frustumCulled=!1,this.mesh.renderOrder=e,this.mesh.visible=!1}shine(t,e,i){this.mesh.visible=!0,this.mesh.position.set(t.x,t.y,t.z),this.mesh.material.uniforms.uRadius.value=e,this.mesh.material.uniforms.uColor.value.setRGB(i[0],i[1],i[2])}hide(){this.mesh.visible=!1}dispose(){this.mesh.geometry.dispose(),this.mesh.material.dispose()}static spread(t,e,i,n){const s=Math.max(t,n*xs.MIN_ANGLE_RAD),r=xs.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(xs.MAX_SHARE,e/r)}}static conserving(t){return Math.sqrt(t/(xs.MAX_SHARE*xs.FILL*Math.PI))}static VERTEX=`
|
|
8495
8495
|
uniform float uRadius;
|
|
8496
8496
|
varying vec2 vOffset;
|
|
8497
8497
|
void main() {
|
|
@@ -9433,6 +9433,6 @@ ${ri.generation}`;return this.frozenMap?.key!==i&&(this.frozenMap={key:i,imagery
|
|
|
9433
9433
|
<button id="copy" class="share-copy" type="button">Copy</button>
|
|
9434
9434
|
</div>
|
|
9435
9435
|
</dialog>
|
|
9436
|
-
`;class uh extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(uh.TAG)||customElements.define(uh.TAG,uh)}subject;messages=yg;languageToken=0;shadow;dialog;linkField;copyButton;linkBox;embedBox;linkOption;embedOption;freeze;embedMarkup;noteElement;codeEditor;codeLoading;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.shadow.innerHTML=qO;const t=e=>this.shadow.getElementById(e);this.dialog=t("dialog"),this.linkField=t("link"),this.copyButton=t("copy"),this.linkBox=t("link-box"),this.embedBox=t("embed-box"),this.linkOption=t("link-option"),this.embedOption=t("embed-option"),this.freeze=t("freeze"),this.embedMarkup=t("embed-markup"),this.noteElement=t("note"),t("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",e=>{e.target===this.dialog&&this.close()}),this.linkOption.addEventListener("click",()=>this.show("link")),this.embedOption.addEventListener("click",()=>this.show("embed")),this.freeze.addEventListener("change",()=>this.refresh()),this.copyButton.addEventListener("click",()=>void(this.embedBox.hidden?this.copy(this.linkField.value,this.linkField):this.copy(this.codeEditor?.text??this.embedMarkup.value,this.embedMarkup))),this.applyMessages()}async useLanguage(t){const e=++this.languageToken,i=t==="en"?yg:await aE(t);if(e===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(t){this.noteElement.textContent=t??"",this.noteElement.hidden=t===void 0}get isOpen(){return this.dialog.open||this.dialog.hasAttribute("open")}open(){this.refresh(),this.show("link"),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open",""),this.fitLink(),this.linkField.select()}close(){typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}refresh(){const t=this.subject;if(!t)return;const e=this.freeze.checked;this.linkField.value=e?Tr.frozenLink(t.link(),"0.152.
|
|
9437
|
-
${t.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const t=this.messages,e=(i,n)=>{this.shadow.getElementById(i).textContent=n};e("title",t.share),e("link-label",t.link),e("embed-label",t.embed),e("copy",t.copy),e("freeze-label",t.freeze.replace("{version}","0.152.0")),this.freeze.parentElement.title=t.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",t.close),this.linkField.setAttribute("aria-label",t.link)}show(t){this.linkBox.hidden=t!=="link",this.embedBox.hidden=t!=="embed",this.linkOption.setAttribute("aria-pressed",String(t==="link")),this.embedOption.setAttribute("aria-pressed",String(t==="embed")),t==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=Re(async()=>{const{ShareCodeEditor:t}=await import("./ShareCodeEditor-C53SBK2N.js");return{ShareCodeEditor:t}},[],import.meta.url).then(({ShareCodeEditor:t})=>{this.codeEditor=new t(this.shadow.getElementById("embed-code"),this.embedMarkup.value,e=>{this.embedMarkup.value=e},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(t,e){try{await navigator.clipboard.writeText(t),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{e.select()}}}class yn{static PLAIN=/^\d+(?:[.,]\d+)?$/;static COLONS=/^(?:(\d+):)?(\d{1,2}):(\d{1,2}(?:[.,]\d+)?)$/;static UNITS=/^(?:(\d+(?:[.,]\d+)?)h)?(?:(\d+(?:[.,]\d+)?)m)?(?:(\d+(?:[.,]\d+)?)s)?$/i;static CLOCK=/^(?:(\d{4})-(\d{2})-(\d{2})[T ])?T?(\d{1,2}):(\d{2})(?::(\d{2}(?:[.,]\d+)?))?$/;static num(t){return t===void 0?0:Number(t.replace(",","."))}static delta(t){const e=(t??"").trim();if(e==="")return;if(yn.PLAIN.test(e))return yn.num(e);const i=yn.COLONS.exec(e);if(i){const[,s,r,a]=i;return Number(r)>=60||yn.num(a)>=60?void 0:yn.num(s)*3600+Number(r)*60+yn.num(a)}const n=yn.UNITS.exec(e);return n&&(n[1]!==void 0||n[2]!==void 0||n[3]!==void 0)?yn.num(n[1])*3600+yn.num(n[2])*60+yn.num(n[3]):/^P/i.test(e)?th.seconds(e.toUpperCase()):void 0}static isClock(t){return yn.clock(t)!==void 0}static clock(t){const e=yn.CLOCK.exec((t??"").trim());if(!e)return;const[,i,n,s,r,a,c]=e,h={hour:Number(r),minute:Number(a),second:yn.num(c)};if(!(h.hour>=24||h.minute>=60||h.second>=60)){if(i!==void 0){const l={year:Number(i),month:Number(n),day:Number(s)};if(l.month<1||l.month>12||l.day<1||l.day>31)return;h.date=l}return h}}static elapsedSince(t,e){if(!t||t.hour===void 0||t.minute===void 0)return;const i=t.hour*3600+t.minute*60+(t.second??0),n=e.hour*3600+e.minute*60+e.second;if(e.date){if(t.year===void 0||t.month===void 0||t.day===void 0)return;const r=Date.UTC(e.date.year,e.date.month-1,e.date.day)/1e3+n,a=Date.UTC(t.year,t.month-1,t.day)/1e3+i;return Math.max(0,r-a)}let s=n-i;return s<=-43200&&(s+=86400),Math.max(0,s)}}Yb();uh.register();const Dd=ql.home(),ud="compare-account",Bp="start-time",v2="start-clock",il="observer",dd="case",fd="account",pd="variant-",Hp=`${Dd}/edit/`;class dh extends HTMLElement{static get observedAttributes(){return["src","show-labels",Bp,v2,il,Lr,Nr,ud]}shadow;sceneElement;toolbarElement;accountElement;accountPrefix;observerText;observerSelect;infoButton;infoPanel;infoAppLink;editLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;shareButton;shareDialog;shareStartOn;shareStart;shareScopeRow;shareScopeLabel;shareScope;shareOpensRow;shareOpensLabel;shareOpens;shareStartLabel;shareOptions;labelsToggle;paramSummary;summaryBuilder=new Ll(hl,new Lf,new Ps(["en"]),new gd({}),{messages:hl,locale:"en"});summarySignature="";assessmentEntries=[];assessmentToken=0;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];caseSource;interpretationChoice;interpretationLabel;interpretationSelect;confrontationElement;confrontationHeading;confrontationList;compareButton;variantChips;variantMoved;interpretationLoaders=new Map;interpretationToken=0;offeredFor;currentSrc;infoOpen=!1;creditsOpen=!1;labelsShown=!1;language="en";messages=hl;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${iw}</style>${ew}`,this.shadow.appendChild(t.content.cloneNode(!0)),customElements.upgrade(this.shadow),this.sceneElement=document.createElement(kf),this.forwardPlayerAttributes(),this.sceneElement.ufoElement.creditShownExternally=!0,this.sceneElement.ownCredits=!1,this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.accountElement=this.shadow.getElementById("account"),this.accountPrefix=this.shadow.getElementById("account-prefix"),this.observerText=this.shadow.getElementById("observer-text"),this.observerSelect=this.shadow.getElementById("observer"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.editLink=this.shadow.getElementById("edit-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.labelsToggle=this.shadow.getElementById("info-labels-toggle"),this.paramSummary=this.shadow.getElementById("param-summary"),this.labelsToggle.addEventListener("click",()=>{this.showLabels=!this.showLabels}),this.shareButton=document.createElement("button"),this.shareButton.type="button",this.shareButton.id="share-button",this.shareButton.setAttribute("aria-haspopup","dialog"),this.shareButton.innerHTML=Zt.SHARE,this.sceneElement.ufoElement.addControl(this.shareButton),this.shareDialog=this.shadow.getElementById("share-dialog"),this.shareDialog.subject=this.shareSubject,this.shareStartOn=this.shadow.getElementById("share-start-on"),this.shareStart=this.shadow.getElementById("share-start"),this.shareStartLabel=this.shadow.getElementById("share-start-label"),this.shareScopeRow=this.shadow.getElementById("share-scope-row"),this.shareScopeLabel=this.shadow.getElementById("share-scope-label"),this.shareScope=this.shadow.getElementById("share-scope"),this.shareOpensRow=this.shadow.getElementById("share-opens-row"),this.shareOpensLabel=this.shadow.getElementById("share-opens-label"),this.shareOpens=this.shadow.getElementById("share-opens");const e=i=>({input:this.shadow.getElementById(`share-opt-${i}`),label:this.shadow.getElementById(`share-opt-${i}-label`)});this.shareOptions={labels:e("labels"),map:e("map"),milestones:e("milestones"),compare:e("compare")},this.interpretationChoice=this.shadow.getElementById("interpretation-choice"),this.interpretationLabel=this.shadow.getElementById("interpretation-label"),this.interpretationSelect=this.shadow.getElementById("interpretation"),this.confrontationElement=this.shadow.getElementById("confrontation"),this.confrontationHeading=this.shadow.getElementById("confrontation-heading"),this.confrontationList=this.shadow.getElementById("confrontation-list"),this.compareButton=this.shadow.getElementById("compare-account"),this.variantChips=this.shadow.getElementById("variant-chips"),this.variantMoved=this.shadow.getElementById("variant-moved"),this.compareButton.addEventListener("click",()=>this.setComparing(!this.sceneElement.compareAccount)),this.observerSelect.addEventListener("change",()=>this.selectObserver(this.observerSelect.value)),this.interpretationSelect.addEventListener("change",()=>void this.chooseInterpretation(this.interpretationSelect.value)),this.sceneElement.addEventListener($b,i=>this.showConfrontation(i.detail)),this.sceneElement.ufoElement.addEventListener("timeupdate",()=>this.refreshParamSummary()),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",i=>{i.newState==="open"&&(this.populateInfoPanel(),this.bringInfoButtonIntoView())}),this.infoPanel.addEventListener("toggle",i=>this.syncInfoOpen(i.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.shareButton.addEventListener("click",()=>this.openShare());for(const i of[this.shareStartOn,this.shareStart,...Object.values(this.shareOptions).map(n=>n.input)])i.addEventListener("input",()=>this.refreshShareLinks());for(const i of[this.shareScope,this.shareOpens])i.addEventListener("change",()=>this.refreshShareLinks());this.isConnected&&this.loadLocaleMessages()}get scene(){return this.sceneElement}async loadLocaleMessages(){const t=++this.localeToken,e=Ga.preferencesFor(this);this.preferences=e;const i=Tg(e,Rg),[n,s,r]=i==="en"?[hl,{},void 0]:await Promise.all([sE(i),oE(i),z2(i)]);if(t!==this.localeToken)return;const a=i!==this.language;this.language=i,this.messages=n,this.tags=new gd(s),this.said=new Ps(e),this.summaryBuilder=new Ll(this.messages,new Lf(r),this.said,this.tags,{messages:this.messages,locale:i}),this.accountPrefix.textContent=this.messages.accountBy,this.interpretationLabel.textContent=this.messages.interpretation,this.confrontationHeading.textContent=this.messages.confrontation;const c=this.entries.find(h=>h.src===this.currentSrc);c&&this.offerInterpretations(c),this.updateCompareButton(),this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.syncLabelsToggle(),this.refreshParamSummary(),a&&this.currentSrc&&this.runAssessments(),this.shareButton.title=this.messages.share,this.shareButton.setAttribute("aria-label",this.messages.share),this.shareStartLabel.textContent=this.messages.shareStartAt,this.shareScopeLabel.textContent=this.messages.shareScope,this.shareOpensLabel.textContent=this.messages.shareOpensOn,this.shareOptions.labels.label.textContent=this.messages.shareOptionLabels,this.shareOptions.map.label.textContent=this.messages.shareOptionMap,this.shareOptions.milestones.label.textContent=this.messages.shareOptionMilestones,this.shareOptions.compare.label.textContent=this.messages.shareOptionCompare,this.shareStart.setAttribute("aria-label",this.messages.shareStartAt),this.shareDialog.useLanguage(i),this.infoOpen&&this.populateInfoPanel(),this.updateAccountLine()}preferences=[];localeToken=0;said=new Ps(["en"]);tags=new gd({});connectedCallback(){Ga.preferencesFor(this).join()!==this.preferences.join()&&this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t==="show-labels"&&this.applyLabels(this.hasAttribute("show-labels")),(t===Lr||t===Nr)&&this.forwardPlayerAttributes(),t===il&&this.entries.length>1){const n=this.entryAsked(this.entries);n&&n.src!==this.currentSrc&&this.selectObserver(n.src)}t===ud&&this.setComparing(this.hasAttribute(ud))}forwardPlayerAttributes(){for(const t of[Lr,Nr]){const e=this.getAttribute(t);e===null?this.sceneElement.removeAttribute(t):this.sceneElement.setAttribute(t,e)}}async loadFromSrc(t){this.startPending=!0;const e=Ha.recording(t);this.sceneElement.holdForNewScene(e);const i=await e;if(Array.isArray(i))throw new Error(`${t} is a bare list of recordings, which is no longer read: list them as the sighting events of a case.json`);if(sn.isCase(i)){sn.check(i);const n=sn.sightingUrls(i,new URL(t,location.href).href);if(n.length===0)throw new Error(`${t} is a case with no sighting event: no recording to show`);await this.loadObserverUrls(n,{json:i,url:new URL(t,location.href).href})}else this.setEntries([{src:t,sighting:i}],void 0)}get sightingData(){return this.entries.find(t=>t.src===this.currentSrc)?.sighting}set sightingData(t){this.startPending=!0,this.currentSrc="",this.setEntries([{src:"",sighting:t}],void 0)}seekTo(t,e){const i=this.caseSource,n=e===void 0?void 0:this.entries.find(s=>{const r=this.plain(s).id;return(i?sn.accountIds(i.json,i.url,s.src,r):[r]).includes(e)});n&&n.src!==this.currentSrc&&this.selectObserver(n.src),this.sceneElement.ufoElement.currentTime=Math.max(0,t)*1e3}get observerUrls(){return this.entries.map(t=>t.src)}set observerUrls(t){this.loadObserverUrls(t)}async loadObserverUrls(t,e){const i=await Promise.all(t.map(async n=>({src:n,sighting:await Ha.recording(n)})));this.setEntries(i,e)}reportCaseProblems(t,e){const{duplicateIds:i,unresolved:n}=sn.problems(t,e.map(s=>this.plain(s).id).filter(s=>s!==void 0));for(const s of i)console.warn(`The case ${t.id??""} gives the id "${s}" to more than one event: a reference to it is ambiguous.`);for(const{reading:s,reference:r}of n)console.warn(`The reading ${s} of the case ${t.id??""} is "interpretationOf" "${r}", which no event of the case has as its id, nor any recording it lists.`)}setEntries(t,e){this.entries=t,this.caseSource=e,e&&this.reportCaseProblems(e.json,t),this.toolbarElement.hidden=t.length===0;const i=t.length>1;this.observerSelect.hidden=!i,this.observerText.hidden=i,this.observerSelect.innerHTML="";const n=t.map((r,a)=>this.observerDisplayName(this.plain(r).observer)??this.caseTitleOf(r)??this.messages.unnamedObserver.replace("{n}",String(a+1)));for(const[r,a]of t.entries()){const c=document.createElement("option");c.value=a.src;const h=n.filter(l=>l===n[r]).length>1;c.textContent=(h?this.caseTitleOf(a):void 0)??n[r],this.observerSelect.appendChild(c)}const s=t.find(r=>r.src===this.currentSrc)??this.entryAsked(t)??t[0];s?this.selectObserver(s.src):this.updateAccountLine()}entryAsked(t){const e=this.getAttribute(il)?.trim();if(!e)return;const i=t.find(s=>this.plain(s).observer?.id===e);if(i)return i;const n=t.find(s=>s.src.split("/").pop()===e.split("/").pop());return n||(/^\d+$/.test(e)?t[Number(e)-1]:void 0)}observerKeyOf(t){return this.plain(t).observer?.id??String(this.entries.indexOf(t)+1)}sharedEntry(){const t=this.shareScope.value;if(!(!this.caseSource||t===dd))return this.entries.find(e=>e.src===t)}get sharesCase(){return this.caseSource!==void 0&&!this.shareScopeRow.hidden&&this.shareScope.value===dd}editorUrl(){if(!this.currentSrc)return Hp;const t=new URL(this.currentSrc,location.href),e=this.caseSource;return e?`${Hp}?file=${encodeURIComponent(e.url)}&track=${encodeURIComponent(this.shownTrackUrl()??t.href)}`:`${Hp}?file=${encodeURIComponent(t.href)}`}get editorHref(){return this.editorUrl()}shownTrackUrl(){const t=this.caseSource,e=this.entries.find(s=>s.src===this.currentSrc),i=/^case-(\d+)$/.exec(this.interpretationSelect.value);if(!t||!e||!i)return;const n=sn.interpretationEvents(t.json,sn.accountIds(t.json,t.url,e.src,this.plain(e).id))[Number(i[1])];return n?.url?new URL(n.url,t.url).href:void 0}shareSubject={module:"rr0-sighting",link:()=>this.playUrl(),element:()=>this.replayElement()};replayElement(){const t=this.sharedAddress(),i=[...t.observer?[[il,t.observer]]:[],...this.replayAttributes()].map(([n,s])=>s===""?` ${n}`:` ${n}="${s}"`).join("");return`<rr0-sighting src="${t.src}"${i}></rr0-sighting>`}playUrl(){const t=this.sharedAddress(),e=[...t.observer?[`${il}=${encodeURIComponent(t.observer)}`]:[],...this.replayQuery()].join("&");return t.src?`${Dd}/play/?file=${encodeURIComponent(t.src)}${e&&"&"+e}`:`${Dd}/play/${e&&"?"+e}`}sharedAddress(){const t=e=>e?new URL(e,location.href).href:"";if(this.sharesCase){const e=this.entries.find(i=>i.src===this.shareOpens.value)??this.entries.find(i=>i.src===this.currentSrc);return{src:this.caseSource.url,observer:e?this.observerKeyOf(e):void 0}}return{src:t(this.sharedEntry()?.src??this.currentSrc??"")}}replayAttributes(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push([Bp,String(this.shareStartSeconds)]),t.labels.input.checked&&e.push(["show-labels",""]),t.map.input.checked&&e.push([Lr,""]),t.milestones.input.checked||e.push([Nr,""]),t.compare.input.checked&&e.push([ud,""]),e}replayQuery(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push(`d=${this.shareStartSeconds}`),t.labels.input.checked||e.push("labels=0"),t.map.input.checked&&e.push("map=1"),t.milestones.input.checked||e.push("moments=0"),t.compare.input.checked&&e.push("compare=1"),e}get shareStartSeconds(){const t=Math.floor(Number(this.shareStart.value));return this.shareStartOn.checked&&Number.isFinite(t)&&t>=0?t:void 0}refreshShareLinks(){this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.refresh()}openShare(){const t=this.sceneElement.ufoElement;this.shareStart.max=String(Math.floor(t.seekableDuration/1e3)),this.shareStart.value=String(Math.floor(t.currentTime/1e3)),this.shareStartOn.checked=!1,this.shareOptions.labels.input.checked=this.labelsShown,this.shareOptions.map.input.checked=t.observerMapOpen,this.shareOptions.milestones.input.checked=t.milestonesVisible,this.shareOptions.compare.input.checked=this.sceneElement.compareAccount,this.offerShareScope(),this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.open()}offerShareScope(){const t=this.caseSource!==void 0&&this.entries.length>1;if(this.shareScopeRow.hidden=!t,this.shareScope.innerHTML="",this.shareOpens.innerHTML="",!t)return;const e=(i,n,s)=>{const r=document.createElement("option");r.value=n,r.textContent=s,i.appendChild(r)};e(this.shareScope,dd,this.messages.shareScopeCase);for(const i of this.entries){const n=this.observerDisplayName(this.plain(i).observer)??this.caseTitleOf(i)??this.messages.unnamedObserver.replace("{n}",String(this.entries.indexOf(i)+1));e(this.shareScope,i.src,n),e(this.shareOpens,i.src,n)}this.shareScope.value=dd,this.shareOpens.value=this.currentSrc??this.entries[0].src}offerInterpretations(t){const e=this.offeredFor===t.sighting,i=this.interpretationSelect.value;this.offeredFor=t.sighting,this.interpretationToken++,this.interpretationLoaders=new Map,this.interpretationSelect.innerHTML="";const n=(u,d,f)=>{const p=document.createElement("option");p.value=u,p.textContent=d,this.interpretationSelect.appendChild(p),this.interpretationLoaders.set(u,f)},s=t===this.entries.find(u=>u.src===this.currentSrc),r=s?this.sceneElement.ufoElement.sighting.interpretation:void 0;n(fd,this.messages.account,()=>Promise.resolve(r));const a=this.caseSource;a&&sn.interpretationEvents(a.json,sn.accountIds(a.json,a.url,t.src,this.plain(t).id)).forEach((u,d)=>{const f=this.said.read(u.title)??`#${d+1}`,p=(u.by??[]).map(g=>this.agentName(g)).filter(Boolean).join(", ");n(`case-${d}`,p?this.messages.interpretationBy.replace("{title}",f).replace("{by}",p):f,()=>sn.interpretationOf(u,a.url,g=>Ha.recording(g)))});const c=s?this.keptVariants(t):[];for(const{index:u,kept:d}of c)n(`${pd}${u}`,`${this.variantLabel(d)} (${this.messages.verdicts[d.variant.verdict]})`,()=>Promise.resolve(d.bodies.length>0?d:void 0));const l=e&&[...this.interpretationSelect.options].some(u=>u.value===i)?i:fd;this.interpretationSelect.value=l,l===fd?this.sceneElement.interpretation!==r&&(this.sceneElement.interpretation=r):this.sceneElement.interpretation||this.chooseInterpretation(l),this.interpretationChoice.hidden=this.interpretationSelect.options.length<2,this.showConfrontation(this.sceneElement.confrontation),this.updateCompareButton(),this.showVariants(c)}keptVariants(t){const e={consolidated:0,contested:1,incompatible:2};return(t.sighting.variants??[]).map((i,n)=>({index:n,kept:i})).filter(({kept:i})=>i.variant).sort((i,n)=>e[i.kept.variant.verdict]-e[n.kept.variant.verdict]||i.kept.variant.cost-n.kept.variant.cost)}variantLabel(t){return this.messages.variant.replace("{name}",t.variant.label??t.variant.candidate)}showVariants(t){if(this.variantChips.innerHTML="",this.variantChips.hidden=t.length===0,t.length===0){this.showVariantMoved();return}const e=(i,n,s)=>{const r=document.createElement("button");r.type="button",r.dataset.value=i,s&&(r.dataset.verdict=s,r.title=this.messages.verdicts[s],r.append(Object.assign(document.createElement("span"),{className:"dot"}))),r.append(n),r.addEventListener("click",()=>{this.interpretationSelect.value!==i&&(this.interpretationSelect.value=i,this.chooseInterpretation(i))}),this.variantChips.append(r)};e(fd,this.messages.account);for(const{index:i,kept:n}of t)e(`${pd}${i}`,n.variant.label??n.variant.candidate,n.variant.verdict);this.showVariantMoved()}showVariantMoved(){const t=this.interpretationSelect.value;for(const s of this.variantChips.querySelectorAll("button"))s.setAttribute("aria-pressed",String(s.dataset.value===t));this.variantMoved.innerHTML="";const e=t.startsWith(pd)?Number(t.slice(pd.length)):-1,i=this.sceneElement.ufoElement.sighting.variants?.[e]?.variant;if(this.variantMoved.hidden=!i||i.moved.length+(i.readings?.length??0)===0,!i)return;const n=new Intl.NumberFormat(this.language,{maximumFractionDigits:1});for(const s of i.moved){const[r,a]=s.field==="time"?["0 min",`${s.variant>0?"+":""}${n.format(s.variant)} min`]:s.field==="duration"?[`${n.format(s.stated)} s`,`${n.format(s.variant)} s`]:[`${n.format(s.stated)}°`,`${n.format(s.variant)}°`],c=document.createElement("span");c.append(`${this.messages.variantFields[s.field]}${this.colon}`,Object.assign(document.createElement("s"),{textContent:r})," → ",Object.assign(document.createElement("b"),{textContent:a})),this.variantMoved.append(c)}for(const s of i.readings??[]){const r=this.messages.variantReadings[s.reading];r&&this.variantMoved.append(Object.assign(document.createElement("span"),{className:"reading",textContent:r}))}}setComparing(t){this.sceneElement.compareAccount=t,this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation)}updateCompareButton(){const t=this.sceneElement.compareAccount;this.compareButton.hidden=!this.sceneElement.interpretation,this.compareButton.setAttribute("aria-pressed",String(t));const e=t?this.messages.hideComparison:this.messages.showComparison;this.compareButton.title=e,this.compareButton.setAttribute("aria-label",e)}static DATE_LOCALES={en:"en-US",fr:"fr-FR",es:"es-ES",it:"it-IT"};get colon(){return this.language==="fr"?" : ":": "}async chooseInterpretation(t){const e=++this.interpretationToken,i=this.interpretationLoaders.get(t),n=i?await i().catch(s=>{console.warn(`<rr0-sighting>: could not read interpretation "${t}":`,s)}):void 0;e===this.interpretationToken&&(this.sceneElement.interpretation=n,this.editLink.href=this.editorUrl(),this.dispatchEvent(new CustomEvent("interpretationchange",{detail:{track:this.shownTrackUrl()}})),this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation),this.showVariantMoved())}agentName(t){if("people"in t){const[e,...i]=t.people.replace(/([a-z])([A-Z])/g,"$1 $2").split(" ");return[...i,e].join(" ")}return"org"in t?t.org.replace(/([a-z])([A-Z])/g,"$1 $2"):this.observerDisplayName(t)??""}showConfrontation(t){this.confrontationList.innerHTML="",this.confrontationElement.hidden=!this.sceneElement.interpretation||!this.sceneElement.compareAccount;const e=new Intl.NumberFormat(this.language,{maximumFractionDigits:1,minimumFractionDigits:1}),i=new Intl.NumberFormat(this.language,{maximumFractionDigits:2,minimumFractionDigits:2});for(const n of t){const s=document.createElement("li");s.append(`${this.said.read(n.title)??n.sourceId}${this.colon}`);const r=[];n.separationDeg!==void 0&&r.push([this.messages.confrontationDirection.replace("{deg}",e.format(n.separationDeg)),n.disagreements.includes("direction")]),n.widthRatio!==void 0&&r.push([this.messages.confrontationWidth.replace("{ratio}",i.format(n.widthRatio)),n.disagreements.includes("width")]),n.heightRatio!==void 0&&r.push([this.messages.confrontationHeight.replace("{ratio}",i.format(n.heightRatio)),n.disagreements.includes("height")]),r.forEach(([a,c],h)=>{h>0&&s.append(" · ");const l=document.createElement("span");l.textContent=a,c&&(l.className="disagrees"),s.append(l)}),this.confrontationList.appendChild(s)}}startPending=!1;startSeconds(t){const e=yn.clock(this.getAttribute(v2));return(e?yn.elapsedSince(this.plain(t).time,e):void 0)??yn.delta(this.getAttribute(Bp))}selectObserver(t){const e=this.entries.find(n=>n.src===t);if(!e)return;this.currentSrc=t,this.observerSelect.value=t,this.sceneElement.documentUrl=e.src?new URL(e.src,location.href).href:void 0;const i=!this.sceneElement.ufoElement.playRequested;if(e.sighting.image?this.sceneElement.showPoster(e.sighting.image,e.src?new URL(e.src,location.href).href:void 0,i):this.sceneElement.showPoster(this.caseSource?.json.image,this.caseSource?.url,i),this.sceneElement.holdForNewScene(),this.sceneElement.sightingData=e.sighting,this.startPending){this.startPending=!1;const n=this.startSeconds(e);n!==void 0&&(this.sceneElement.ufoElement.currentTime=Math.max(0,n)*1e3)}this.offerInterpretations(e),this.updateAccountLine(),this.refreshParamSummary(),this.runAssessments(),this.infoOpen&&this.populateInfoPanel(),this.dispatchEvent(new CustomEvent(ZO,{detail:{src:t}}))}async runAssessments(){const t=++this.assessmentToken,e=await new PS(this.messages).read(this.sceneElement.ufoElement.sighting);t===this.assessmentToken&&(this.assessmentEntries=e.entries,this.refreshParamSummary())}updateAccountLine(){const t=this.entries.find(n=>n.src===this.currentSrc),e=t?this.observerDisplayName(this.plain(t).observer):void 0,i=e!==void 0||this.entries.length>1;this.accountElement.hidden=!i,this.observerText.textContent=e??"",this.editLink.hidden=!this.currentSrc,this.editLink.href=this.editorUrl(),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation)}caseTitleOf(t){const e=this.caseSource;if(!e)return;const i=e.json.events?.find(n=>n.url!==void 0&&!n.interpretationOf&&new URL(n.url,e.url).href===new URL(t.src,location.href).href);return i?this.said.read(i.title):void 0}observerDisplayName(t){if(!t)return;const e=[...t.firstNames??[],t.lastName].filter(Boolean).join(" ");return this.said.read(t.title)||e||t.id}plainRecordings=new WeakMap;plain(t){return this.stripped(t).recording}stripped(t){let e=this.plainRecordings.get(t.sighting);return e||(e=Kn.strip(t.sighting),this.plainRecordings.set(t.sighting,e)),e}basisOf(t,e){const i=this.stripped(t).provenance,n={measured:-1,stated:0,derived:1,assumed:2},s=i.paths().filter(c=>e.some(h=>c===h||c.startsWith(`${h}.`))).map(c=>i.at(c)),r=s.reduce((c,h)=>n[h.basis]>n[c]?h.basis:c,"stated"),a=s.filter(c=>c.basis===r&&c.rationale).map(c=>c.rationale);return{basis:r,rationales:a}}formatDate(t){const e=t.place?.[0],i=ao(t.time??{},e?.lng??0,t.utcOffsetHours);if(!i)return;const n=i.getTime()+this.utcOffsetHoursOf(t,e?.lng??0)*36e5;if(Number.isFinite(n))return new Intl.DateTimeFormat(dh.DATE_LOCALES[this.language],{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(n))}utcOffsetHoursOf(t,e){return t.utcOffsetHours??Math.round(e/15)}formatLocation(t){const e=t.place?.[0];if(e)return`${e.lat.toFixed(4)}, ${e.lng.toFixed(4)}`}toggleInfoPanel(){const t=!this.infoOpen;if(this.supportsPopover){const e=this.infoPanel.matches(":popover-open");t&&!e?this.infoPanel.showPopover():!t&&e&&this.infoPanel.hidePopover();return}t&&this.bringInfoButtonIntoView(),this.syncInfoOpen(t),this.infoPanel.hidden=!t,t?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}bringInfoButtonIntoView(){const t=this.infoButton.getBoundingClientRect(),e=window.innerHeight||document.documentElement.clientHeight;t.top>=0&&t.bottom<=e||this.infoButton.scrollIntoView({block:"center"})}syncInfoOpen(t){t!==this.infoOpen&&(this.infoOpen=t,this.infoButton.setAttribute("aria-expanded",String(t)),t?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=t=>{const e=t.composedPath();!e.includes(this.infoPanel)&&!e.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}revealInPanel(t){t.scrollIntoView?.({block:"nearest"})}get showLabels(){return this.labelsShown}set showLabels(t){this.toggleAttribute("show-labels",t)}applyLabels(t){this.labelsShown=t,this.syncLabelsToggle(),this.refreshParamSummary(),this.populateInfoPanel()}syncLabelsToggle(){this.labelsToggle.textContent=this.labelsShown?this.messages.hideLabels:this.messages.showLabels,this.labelsToggle.setAttribute("aria-pressed",String(this.labelsShown))}refreshParamSummary(){if(this.paramSummary.hidden=!this.labelsShown,!this.labelsShown){this.paramSummary.replaceChildren(),this.summarySignature="";return}const t=this.sceneElement.ufoElement.sighting,e=[...this.summaryBuilder.entriesFor(t,this.sceneElement.ufoElement.currentTime,{roadGradeDeg:this.sceneElement.roadGradeDeg}),...this.assessmentEntries],i=e.map(r=>`${r.field}=${r.label}=${r.value}${r.unit}${r.full??""}${r.fromSource?"*":""}`).join("|");if(i===this.summarySignature)return;this.summarySignature=i;const n=[];let s;for(const r of e){s&&s.group!==r.group&&(s=void 0);const a=r.group==="summary"?this.messages.summaryGroup:r.group==="observer"?this.messages.observerGroup:r.group in this.messages.summaryGroups?this.messages.summaryGroups[r.group]:r.group==="assessment"?this.messages.assessmentGroup:void 0;if(a!==void 0&&!s){const h=document.createElement("span");h.className="param-nest";const l=document.createElement("span");l.className="param-nest-label",l.textContent=a,h.append(l),s={group:r.group,element:h},n.push(h)}const c=this.paramItem(r);s?s.element.append(c):n.push(c)}this.paramSummary.replaceChildren(...n),this.syncDescription(e)}openDescription;syncDescription(t){this.openDescription!==void 0&&!t.some(e=>e.full===this.openDescription)&&(this.openDescription=void 0),x2.sync(this.paramSummary,this.openDescription,this.messages.summaryDescription,this.messages.closeDescription,()=>{this.openDescription=void 0,this.syncDescription(t)})}paramItem(t){const e=document.createElement("span");if(e.className=t.fromSource?"param-label from-source":"param-label",t.full!==void 0){e.classList.add("describable"),e.tabIndex=0,e.setAttribute("role","button");const s=()=>{this.openDescription=t.full,this.syncDescription([t])};e.addEventListener("click",s),e.addEventListener("keydown",r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),s())})}const i=document.createElement("span");if(i.className="param-label-label",i.textContent=`${t.label} `,e.append(i),t.color!==void 0){const s=document.createElement("span");s.className="param-label-swatch",s.style.background=t.color,e.append(s)}const n=document.createElement("span");return n.className="param-label-value",n.textContent=t.unit===""?t.value:`${t.value} ${t.unit}`,e.append(n),e}populateInfoPanel(){const t=this.entries.find(e=>e.src===this.currentSrc);if(this.infoObservationList.innerHTML="",t){const e=this.caseSource&&(this.caseSource.json.title??this.caseSource.json.id);if(e&&this.appendInfoRow(this.infoObservationList,this.messages.case,e),!this.labelsShown){const s=this.formatDate(this.plain(t));s&&this.appendInfoRow(this.infoObservationList,this.messages.date,s,this.basisOf(t,dh.DATE_PATHS));const r=this.formatLocation(this.plain(t));r&&this.appendInfoRow(this.infoObservationList,this.messages.location,r,this.basisOf(t,dh.PLACE_PATHS))}const i=this.said.read(this.plain(t).description);i&&!this.labelsShown&&this.appendInfoRow(this.infoObservationList,this.messages.description,i);for(const s of this.plain(t).sources??[])this.appendInfoSource(this.infoObservationList,this.messages.source,s);const n=this.plain(t).tags;!this.labelsShown&&n&&n.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,n.map(s=>this.tags.name(s)).join(", "))}this.infoAppLink.href=Dd,this.infoAppLink.textContent="UFO@home v0.152.0",gn.fill(this.infoCreditsList,this.sceneElement)}appendInfoSource(t,e,i){const n=document.createElement("dt");n.textContent=e;const s=document.createElement("dd"),r=i.title??i.url??"";if(i.url&&/^https?:\/\//i.test(i.url)){const c=document.createElement("a");c.href=i.url,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r,s.appendChild(c)}else s.append(r);const a=[i.authors?.join(", "),i.publication?.publisher,i.publication?.time,i.index].filter(Boolean);a.length>0&&s.append(`, ${a.join(", ")}`),t.append(n,s)}static DATE_PATHS=["time","utcOffsetHours","timeZone"];static PLACE_PATHS=["place.0"];appendInfoRow(t,e,i,n){const s=document.createElement("dt");s.textContent=e;const r=document.createElement("dd");if(r.textContent=i,n){const a=document.createElement("span");a.className=`basis basis-${n.basis}`,a.textContent=this.messages.basis[n.basis],n.rationales.length>0&&(a.title=n.rationales.join(`
|
|
9436
|
+
`;class uh extends HTMLElement{static TAG="rr0-share-dialog";static register(){customElements.get(uh.TAG)||customElements.define(uh.TAG,uh)}subject;messages=yg;languageToken=0;shadow;dialog;linkField;copyButton;linkBox;embedBox;linkOption;embedOption;freeze;embedMarkup;noteElement;codeEditor;codeLoading;constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.shadow.innerHTML=qO;const t=e=>this.shadow.getElementById(e);this.dialog=t("dialog"),this.linkField=t("link"),this.copyButton=t("copy"),this.linkBox=t("link-box"),this.embedBox=t("embed-box"),this.linkOption=t("link-option"),this.embedOption=t("embed-option"),this.freeze=t("freeze"),this.embedMarkup=t("embed-markup"),this.noteElement=t("note"),t("close").addEventListener("click",()=>this.close()),this.dialog.addEventListener("click",e=>{e.target===this.dialog&&this.close()}),this.linkOption.addEventListener("click",()=>this.show("link")),this.embedOption.addEventListener("click",()=>this.show("embed")),this.freeze.addEventListener("change",()=>this.refresh()),this.copyButton.addEventListener("click",()=>void(this.embedBox.hidden?this.copy(this.linkField.value,this.linkField):this.copy(this.codeEditor?.text??this.embedMarkup.value,this.embedMarkup))),this.applyMessages()}async useLanguage(t){const e=++this.languageToken,i=t==="en"?yg:await aE(t);if(e===this.languageToken)return this.messages=i,this.applyMessages(),i}set note(t){this.noteElement.textContent=t??"",this.noteElement.hidden=t===void 0}get isOpen(){return this.dialog.open||this.dialog.hasAttribute("open")}open(){this.refresh(),this.show("link"),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open",""),this.fitLink(),this.linkField.select()}close(){typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}refresh(){const t=this.subject;if(!t)return;const e=this.freeze.checked;this.linkField.value=e?Tr.frozenLink(t.link(),"0.152.1"):t.link(),this.fitLink();const n=`<script type="module" src="${e?Tr.frozen(t.module,"0.152.1"):Tr.current(t.module,import.meta.url,ql.home())}"><\/script>
|
|
9437
|
+
${t.element()}`;this.embedMarkup.value=n,this.codeEditor&&(this.codeEditor.text=n)}applyMessages(){const t=this.messages,e=(i,n)=>{this.shadow.getElementById(i).textContent=n};e("title",t.share),e("link-label",t.link),e("embed-label",t.embed),e("copy",t.copy),e("freeze-label",t.freeze.replace("{version}","0.152.1")),this.freeze.parentElement.title=t.freezeHint,this.shadow.getElementById("close").setAttribute("aria-label",t.close),this.linkField.setAttribute("aria-label",t.link)}show(t){this.linkBox.hidden=t!=="link",this.embedBox.hidden=t!=="embed",this.linkOption.setAttribute("aria-pressed",String(t==="link")),this.embedOption.setAttribute("aria-pressed",String(t==="embed")),t==="embed"?this.loadCodeEditor():this.fitLink()}fitLink(){this.linkField.style.height="auto",this.linkField.style.height=`${this.linkField.scrollHeight}px`}loadCodeEditor(){this.codeLoading??=Re(async()=>{const{ShareCodeEditor:t}=await import("./ShareCodeEditor-C53SBK2N.js");return{ShareCodeEditor:t}},[],import.meta.url).then(({ShareCodeEditor:t})=>{this.codeEditor=new t(this.shadow.getElementById("embed-code"),this.embedMarkup.value,e=>{this.embedMarkup.value=e},this.messages.embed),this.embedMarkup.hidden=!0}).catch(()=>{this.codeLoading=void 0})}async copy(t,e){try{await navigator.clipboard.writeText(t),this.copyButton.textContent=this.messages.copied,window.setTimeout(()=>this.copyButton.textContent=this.messages.copy,1500)}catch{e.select()}}}class yn{static PLAIN=/^\d+(?:[.,]\d+)?$/;static COLONS=/^(?:(\d+):)?(\d{1,2}):(\d{1,2}(?:[.,]\d+)?)$/;static UNITS=/^(?:(\d+(?:[.,]\d+)?)h)?(?:(\d+(?:[.,]\d+)?)m)?(?:(\d+(?:[.,]\d+)?)s)?$/i;static CLOCK=/^(?:(\d{4})-(\d{2})-(\d{2})[T ])?T?(\d{1,2}):(\d{2})(?::(\d{2}(?:[.,]\d+)?))?$/;static num(t){return t===void 0?0:Number(t.replace(",","."))}static delta(t){const e=(t??"").trim();if(e==="")return;if(yn.PLAIN.test(e))return yn.num(e);const i=yn.COLONS.exec(e);if(i){const[,s,r,a]=i;return Number(r)>=60||yn.num(a)>=60?void 0:yn.num(s)*3600+Number(r)*60+yn.num(a)}const n=yn.UNITS.exec(e);return n&&(n[1]!==void 0||n[2]!==void 0||n[3]!==void 0)?yn.num(n[1])*3600+yn.num(n[2])*60+yn.num(n[3]):/^P/i.test(e)?th.seconds(e.toUpperCase()):void 0}static isClock(t){return yn.clock(t)!==void 0}static clock(t){const e=yn.CLOCK.exec((t??"").trim());if(!e)return;const[,i,n,s,r,a,c]=e,h={hour:Number(r),minute:Number(a),second:yn.num(c)};if(!(h.hour>=24||h.minute>=60||h.second>=60)){if(i!==void 0){const l={year:Number(i),month:Number(n),day:Number(s)};if(l.month<1||l.month>12||l.day<1||l.day>31)return;h.date=l}return h}}static elapsedSince(t,e){if(!t||t.hour===void 0||t.minute===void 0)return;const i=t.hour*3600+t.minute*60+(t.second??0),n=e.hour*3600+e.minute*60+e.second;if(e.date){if(t.year===void 0||t.month===void 0||t.day===void 0)return;const r=Date.UTC(e.date.year,e.date.month-1,e.date.day)/1e3+n,a=Date.UTC(t.year,t.month-1,t.day)/1e3+i;return Math.max(0,r-a)}let s=n-i;return s<=-43200&&(s+=86400),Math.max(0,s)}}Yb();uh.register();const Dd=ql.home(),ud="compare-account",Bp="start-time",v2="start-clock",il="observer",dd="case",fd="account",pd="variant-",Hp=`${Dd}/edit/`;class dh extends HTMLElement{static get observedAttributes(){return["src","show-labels",Bp,v2,il,Lr,Nr,ud]}shadow;sceneElement;toolbarElement;accountElement;accountPrefix;observerText;observerSelect;infoButton;infoPanel;infoAppLink;editLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;shareButton;shareDialog;shareStartOn;shareStart;shareScopeRow;shareScopeLabel;shareScope;shareOpensRow;shareOpensLabel;shareOpens;shareStartLabel;shareOptions;labelsToggle;paramSummary;summaryBuilder=new Ll(hl,new Lf,new Ps(["en"]),new gd({}),{messages:hl,locale:"en"});summarySignature="";assessmentEntries=[];assessmentToken=0;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];caseSource;interpretationChoice;interpretationLabel;interpretationSelect;confrontationElement;confrontationHeading;confrontationList;compareButton;variantChips;variantMoved;interpretationLoaders=new Map;interpretationToken=0;offeredFor;currentSrc;infoOpen=!1;creditsOpen=!1;labelsShown=!1;language="en";messages=hl;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const t=document.createElement("template");t.innerHTML=`<style>${iw}</style>${ew}`,this.shadow.appendChild(t.content.cloneNode(!0)),customElements.upgrade(this.shadow),this.sceneElement=document.createElement(kf),this.forwardPlayerAttributes(),this.sceneElement.ufoElement.creditShownExternally=!0,this.sceneElement.ownCredits=!1,this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.accountElement=this.shadow.getElementById("account"),this.accountPrefix=this.shadow.getElementById("account-prefix"),this.observerText=this.shadow.getElementById("observer-text"),this.observerSelect=this.shadow.getElementById("observer"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.editLink=this.shadow.getElementById("edit-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.labelsToggle=this.shadow.getElementById("info-labels-toggle"),this.paramSummary=this.shadow.getElementById("param-summary"),this.labelsToggle.addEventListener("click",()=>{this.showLabels=!this.showLabels}),this.shareButton=document.createElement("button"),this.shareButton.type="button",this.shareButton.id="share-button",this.shareButton.setAttribute("aria-haspopup","dialog"),this.shareButton.innerHTML=Zt.SHARE,this.sceneElement.ufoElement.addControl(this.shareButton),this.shareDialog=this.shadow.getElementById("share-dialog"),this.shareDialog.subject=this.shareSubject,this.shareStartOn=this.shadow.getElementById("share-start-on"),this.shareStart=this.shadow.getElementById("share-start"),this.shareStartLabel=this.shadow.getElementById("share-start-label"),this.shareScopeRow=this.shadow.getElementById("share-scope-row"),this.shareScopeLabel=this.shadow.getElementById("share-scope-label"),this.shareScope=this.shadow.getElementById("share-scope"),this.shareOpensRow=this.shadow.getElementById("share-opens-row"),this.shareOpensLabel=this.shadow.getElementById("share-opens-label"),this.shareOpens=this.shadow.getElementById("share-opens");const e=i=>({input:this.shadow.getElementById(`share-opt-${i}`),label:this.shadow.getElementById(`share-opt-${i}-label`)});this.shareOptions={labels:e("labels"),map:e("map"),milestones:e("milestones"),compare:e("compare")},this.interpretationChoice=this.shadow.getElementById("interpretation-choice"),this.interpretationLabel=this.shadow.getElementById("interpretation-label"),this.interpretationSelect=this.shadow.getElementById("interpretation"),this.confrontationElement=this.shadow.getElementById("confrontation"),this.confrontationHeading=this.shadow.getElementById("confrontation-heading"),this.confrontationList=this.shadow.getElementById("confrontation-list"),this.compareButton=this.shadow.getElementById("compare-account"),this.variantChips=this.shadow.getElementById("variant-chips"),this.variantMoved=this.shadow.getElementById("variant-moved"),this.compareButton.addEventListener("click",()=>this.setComparing(!this.sceneElement.compareAccount)),this.observerSelect.addEventListener("change",()=>this.selectObserver(this.observerSelect.value)),this.interpretationSelect.addEventListener("change",()=>void this.chooseInterpretation(this.interpretationSelect.value)),this.sceneElement.addEventListener($b,i=>this.showConfrontation(i.detail)),this.sceneElement.ufoElement.addEventListener("timeupdate",()=>this.refreshParamSummary()),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",i=>{i.newState==="open"&&(this.populateInfoPanel(),this.bringInfoButtonIntoView())}),this.infoPanel.addEventListener("toggle",i=>this.syncInfoOpen(i.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.shareButton.addEventListener("click",()=>this.openShare());for(const i of[this.shareStartOn,this.shareStart,...Object.values(this.shareOptions).map(n=>n.input)])i.addEventListener("input",()=>this.refreshShareLinks());for(const i of[this.shareScope,this.shareOpens])i.addEventListener("change",()=>this.refreshShareLinks());this.isConnected&&this.loadLocaleMessages()}get scene(){return this.sceneElement}async loadLocaleMessages(){const t=++this.localeToken,e=Ga.preferencesFor(this);this.preferences=e;const i=Tg(e,Rg),[n,s,r]=i==="en"?[hl,{},void 0]:await Promise.all([sE(i),oE(i),z2(i)]);if(t!==this.localeToken)return;const a=i!==this.language;this.language=i,this.messages=n,this.tags=new gd(s),this.said=new Ps(e),this.summaryBuilder=new Ll(this.messages,new Lf(r),this.said,this.tags,{messages:this.messages,locale:i}),this.accountPrefix.textContent=this.messages.accountBy,this.interpretationLabel.textContent=this.messages.interpretation,this.confrontationHeading.textContent=this.messages.confrontation;const c=this.entries.find(h=>h.src===this.currentSrc);c&&this.offerInterpretations(c),this.updateCompareButton(),this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.syncLabelsToggle(),this.refreshParamSummary(),a&&this.currentSrc&&this.runAssessments(),this.shareButton.title=this.messages.share,this.shareButton.setAttribute("aria-label",this.messages.share),this.shareStartLabel.textContent=this.messages.shareStartAt,this.shareScopeLabel.textContent=this.messages.shareScope,this.shareOpensLabel.textContent=this.messages.shareOpensOn,this.shareOptions.labels.label.textContent=this.messages.shareOptionLabels,this.shareOptions.map.label.textContent=this.messages.shareOptionMap,this.shareOptions.milestones.label.textContent=this.messages.shareOptionMilestones,this.shareOptions.compare.label.textContent=this.messages.shareOptionCompare,this.shareStart.setAttribute("aria-label",this.messages.shareStartAt),this.shareDialog.useLanguage(i),this.infoOpen&&this.populateInfoPanel(),this.updateAccountLine()}preferences=[];localeToken=0;said=new Ps(["en"]);tags=new gd({});connectedCallback(){Ga.preferencesFor(this).join()!==this.preferences.join()&&this.loadLocaleMessages();const t=this.getAttribute("src");t&&this.loadFromSrc(t)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(t,e,i){if(t==="src"&&i&&i!==e&&this.isConnected&&this.loadFromSrc(i),t==="show-labels"&&this.applyLabels(this.hasAttribute("show-labels")),(t===Lr||t===Nr)&&this.forwardPlayerAttributes(),t===il&&this.entries.length>1){const n=this.entryAsked(this.entries);n&&n.src!==this.currentSrc&&this.selectObserver(n.src)}t===ud&&this.setComparing(this.hasAttribute(ud))}forwardPlayerAttributes(){for(const t of[Lr,Nr]){const e=this.getAttribute(t);e===null?this.sceneElement.removeAttribute(t):this.sceneElement.setAttribute(t,e)}}async loadFromSrc(t){this.startPending=!0;const e=Ha.recording(t);this.sceneElement.holdForNewScene(e);const i=await e;if(Array.isArray(i))throw new Error(`${t} is a bare list of recordings, which is no longer read: list them as the sighting events of a case.json`);if(sn.isCase(i)){sn.check(i);const n=sn.sightingUrls(i,new URL(t,location.href).href);if(n.length===0)throw new Error(`${t} is a case with no sighting event: no recording to show`);await this.loadObserverUrls(n,{json:i,url:new URL(t,location.href).href})}else this.setEntries([{src:t,sighting:i}],void 0)}get sightingData(){return this.entries.find(t=>t.src===this.currentSrc)?.sighting}set sightingData(t){this.startPending=!0,this.currentSrc="",this.setEntries([{src:"",sighting:t}],void 0)}seekTo(t,e){const i=this.caseSource,n=e===void 0?void 0:this.entries.find(s=>{const r=this.plain(s).id;return(i?sn.accountIds(i.json,i.url,s.src,r):[r]).includes(e)});n&&n.src!==this.currentSrc&&this.selectObserver(n.src),this.sceneElement.ufoElement.currentTime=Math.max(0,t)*1e3}get observerUrls(){return this.entries.map(t=>t.src)}set observerUrls(t){this.loadObserverUrls(t)}async loadObserverUrls(t,e){const i=await Promise.all(t.map(async n=>({src:n,sighting:await Ha.recording(n)})));this.setEntries(i,e)}reportCaseProblems(t,e){const{duplicateIds:i,unresolved:n}=sn.problems(t,e.map(s=>this.plain(s).id).filter(s=>s!==void 0));for(const s of i)console.warn(`The case ${t.id??""} gives the id "${s}" to more than one event: a reference to it is ambiguous.`);for(const{reading:s,reference:r}of n)console.warn(`The reading ${s} of the case ${t.id??""} is "interpretationOf" "${r}", which no event of the case has as its id, nor any recording it lists.`)}setEntries(t,e){this.entries=t,this.caseSource=e,e&&this.reportCaseProblems(e.json,t),this.toolbarElement.hidden=t.length===0;const i=t.length>1;this.observerSelect.hidden=!i,this.observerText.hidden=i,this.observerSelect.innerHTML="";const n=t.map((r,a)=>this.observerDisplayName(this.plain(r).observer)??this.caseTitleOf(r)??this.messages.unnamedObserver.replace("{n}",String(a+1)));for(const[r,a]of t.entries()){const c=document.createElement("option");c.value=a.src;const h=n.filter(l=>l===n[r]).length>1;c.textContent=(h?this.caseTitleOf(a):void 0)??n[r],this.observerSelect.appendChild(c)}const s=t.find(r=>r.src===this.currentSrc)??this.entryAsked(t)??t[0];s?this.selectObserver(s.src):this.updateAccountLine()}entryAsked(t){const e=this.getAttribute(il)?.trim();if(!e)return;const i=t.find(s=>this.plain(s).observer?.id===e);if(i)return i;const n=t.find(s=>s.src.split("/").pop()===e.split("/").pop());return n||(/^\d+$/.test(e)?t[Number(e)-1]:void 0)}observerKeyOf(t){return this.plain(t).observer?.id??String(this.entries.indexOf(t)+1)}sharedEntry(){const t=this.shareScope.value;if(!(!this.caseSource||t===dd))return this.entries.find(e=>e.src===t)}get sharesCase(){return this.caseSource!==void 0&&!this.shareScopeRow.hidden&&this.shareScope.value===dd}editorUrl(){if(!this.currentSrc)return Hp;const t=new URL(this.currentSrc,location.href),e=this.caseSource;return e?`${Hp}?file=${encodeURIComponent(e.url)}&track=${encodeURIComponent(this.shownTrackUrl()??t.href)}`:`${Hp}?file=${encodeURIComponent(t.href)}`}get editorHref(){return this.editorUrl()}shownTrackUrl(){const t=this.caseSource,e=this.entries.find(s=>s.src===this.currentSrc),i=/^case-(\d+)$/.exec(this.interpretationSelect.value);if(!t||!e||!i)return;const n=sn.interpretationEvents(t.json,sn.accountIds(t.json,t.url,e.src,this.plain(e).id))[Number(i[1])];return n?.url?new URL(n.url,t.url).href:void 0}shareSubject={module:"rr0-sighting",link:()=>this.playUrl(),element:()=>this.replayElement()};replayElement(){const t=this.sharedAddress(),i=[...t.observer?[[il,t.observer]]:[],...this.replayAttributes()].map(([n,s])=>s===""?` ${n}`:` ${n}="${s}"`).join("");return`<rr0-sighting src="${t.src}"${i}></rr0-sighting>`}playUrl(){const t=this.sharedAddress(),e=[...t.observer?[`${il}=${encodeURIComponent(t.observer)}`]:[],...this.replayQuery()].join("&");return t.src?`${Dd}/play/?file=${encodeURIComponent(t.src)}${e&&"&"+e}`:`${Dd}/play/${e&&"?"+e}`}sharedAddress(){const t=e=>e?new URL(e,location.href).href:"";if(this.sharesCase){const e=this.entries.find(i=>i.src===this.shareOpens.value)??this.entries.find(i=>i.src===this.currentSrc);return{src:this.caseSource.url,observer:e?this.observerKeyOf(e):void 0}}return{src:t(this.sharedEntry()?.src??this.currentSrc??"")}}replayAttributes(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push([Bp,String(this.shareStartSeconds)]),t.labels.input.checked&&e.push(["show-labels",""]),t.map.input.checked&&e.push([Lr,""]),t.milestones.input.checked||e.push([Nr,""]),t.compare.input.checked&&e.push([ud,""]),e}replayQuery(){const t=this.shareOptions,e=[];return this.shareStartSeconds!==void 0&&e.push(`d=${this.shareStartSeconds}`),t.labels.input.checked||e.push("labels=0"),t.map.input.checked&&e.push("map=1"),t.milestones.input.checked||e.push("moments=0"),t.compare.input.checked&&e.push("compare=1"),e}get shareStartSeconds(){const t=Math.floor(Number(this.shareStart.value));return this.shareStartOn.checked&&Number.isFinite(t)&&t>=0?t:void 0}refreshShareLinks(){this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.refresh()}openShare(){const t=this.sceneElement.ufoElement;this.shareStart.max=String(Math.floor(t.seekableDuration/1e3)),this.shareStart.value=String(Math.floor(t.currentTime/1e3)),this.shareStartOn.checked=!1,this.shareOptions.labels.input.checked=this.labelsShown,this.shareOptions.map.input.checked=t.observerMapOpen,this.shareOptions.milestones.input.checked=t.milestonesVisible,this.shareOptions.compare.input.checked=this.sceneElement.compareAccount,this.offerShareScope(),this.shareOpensRow.hidden=!this.sharesCase,this.shareDialog.open()}offerShareScope(){const t=this.caseSource!==void 0&&this.entries.length>1;if(this.shareScopeRow.hidden=!t,this.shareScope.innerHTML="",this.shareOpens.innerHTML="",!t)return;const e=(i,n,s)=>{const r=document.createElement("option");r.value=n,r.textContent=s,i.appendChild(r)};e(this.shareScope,dd,this.messages.shareScopeCase);for(const i of this.entries){const n=this.observerDisplayName(this.plain(i).observer)??this.caseTitleOf(i)??this.messages.unnamedObserver.replace("{n}",String(this.entries.indexOf(i)+1));e(this.shareScope,i.src,n),e(this.shareOpens,i.src,n)}this.shareScope.value=dd,this.shareOpens.value=this.currentSrc??this.entries[0].src}offerInterpretations(t){const e=this.offeredFor===t.sighting,i=this.interpretationSelect.value;this.offeredFor=t.sighting,this.interpretationToken++,this.interpretationLoaders=new Map,this.interpretationSelect.innerHTML="";const n=(u,d,f)=>{const p=document.createElement("option");p.value=u,p.textContent=d,this.interpretationSelect.appendChild(p),this.interpretationLoaders.set(u,f)},s=t===this.entries.find(u=>u.src===this.currentSrc),r=s?this.sceneElement.ufoElement.sighting.interpretation:void 0;n(fd,this.messages.account,()=>Promise.resolve(r));const a=this.caseSource;a&&sn.interpretationEvents(a.json,sn.accountIds(a.json,a.url,t.src,this.plain(t).id)).forEach((u,d)=>{const f=this.said.read(u.title)??`#${d+1}`,p=(u.by??[]).map(g=>this.agentName(g)).filter(Boolean).join(", ");n(`case-${d}`,p?this.messages.interpretationBy.replace("{title}",f).replace("{by}",p):f,()=>sn.interpretationOf(u,a.url,g=>Ha.recording(g)))});const c=s?this.keptVariants(t):[];for(const{index:u,kept:d}of c)n(`${pd}${u}`,`${this.variantLabel(d)} (${this.messages.verdicts[d.variant.verdict]})`,()=>Promise.resolve(d.bodies.length>0?d:void 0));const l=e&&[...this.interpretationSelect.options].some(u=>u.value===i)?i:fd;this.interpretationSelect.value=l,l===fd?this.sceneElement.interpretation!==r&&(this.sceneElement.interpretation=r):this.sceneElement.interpretation||this.chooseInterpretation(l),this.interpretationChoice.hidden=this.interpretationSelect.options.length<2,this.showConfrontation(this.sceneElement.confrontation),this.updateCompareButton(),this.showVariants(c)}keptVariants(t){const e={consolidated:0,contested:1,incompatible:2};return(t.sighting.variants??[]).map((i,n)=>({index:n,kept:i})).filter(({kept:i})=>i.variant).sort((i,n)=>e[i.kept.variant.verdict]-e[n.kept.variant.verdict]||i.kept.variant.cost-n.kept.variant.cost)}variantLabel(t){return this.messages.variant.replace("{name}",t.variant.label??t.variant.candidate)}showVariants(t){if(this.variantChips.innerHTML="",this.variantChips.hidden=t.length===0,t.length===0){this.showVariantMoved();return}const e=(i,n,s)=>{const r=document.createElement("button");r.type="button",r.dataset.value=i,s&&(r.dataset.verdict=s,r.title=this.messages.verdicts[s],r.append(Object.assign(document.createElement("span"),{className:"dot"}))),r.append(n),r.addEventListener("click",()=>{this.interpretationSelect.value!==i&&(this.interpretationSelect.value=i,this.chooseInterpretation(i))}),this.variantChips.append(r)};e(fd,this.messages.account);for(const{index:i,kept:n}of t)e(`${pd}${i}`,n.variant.label??n.variant.candidate,n.variant.verdict);this.showVariantMoved()}showVariantMoved(){const t=this.interpretationSelect.value;for(const s of this.variantChips.querySelectorAll("button"))s.setAttribute("aria-pressed",String(s.dataset.value===t));this.variantMoved.innerHTML="";const e=t.startsWith(pd)?Number(t.slice(pd.length)):-1,i=this.sceneElement.ufoElement.sighting.variants?.[e]?.variant;if(this.variantMoved.hidden=!i||i.moved.length+(i.readings?.length??0)===0,!i)return;const n=new Intl.NumberFormat(this.language,{maximumFractionDigits:1});for(const s of i.moved){const[r,a]=s.field==="time"?["0 min",`${s.variant>0?"+":""}${n.format(s.variant)} min`]:s.field==="duration"?[`${n.format(s.stated)} s`,`${n.format(s.variant)} s`]:[`${n.format(s.stated)}°`,`${n.format(s.variant)}°`],c=document.createElement("span");c.append(`${this.messages.variantFields[s.field]}${this.colon}`,Object.assign(document.createElement("s"),{textContent:r})," → ",Object.assign(document.createElement("b"),{textContent:a})),this.variantMoved.append(c)}for(const s of i.readings??[]){const r=this.messages.variantReadings[s.reading];r&&this.variantMoved.append(Object.assign(document.createElement("span"),{className:"reading",textContent:r}))}}setComparing(t){this.sceneElement.compareAccount=t,this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation)}updateCompareButton(){const t=this.sceneElement.compareAccount;this.compareButton.hidden=!this.sceneElement.interpretation,this.compareButton.setAttribute("aria-pressed",String(t));const e=t?this.messages.hideComparison:this.messages.showComparison;this.compareButton.title=e,this.compareButton.setAttribute("aria-label",e)}static DATE_LOCALES={en:"en-US",fr:"fr-FR",es:"es-ES",it:"it-IT"};get colon(){return this.language==="fr"?" : ":": "}async chooseInterpretation(t){const e=++this.interpretationToken,i=this.interpretationLoaders.get(t),n=i?await i().catch(s=>{console.warn(`<rr0-sighting>: could not read interpretation "${t}":`,s)}):void 0;e===this.interpretationToken&&(this.sceneElement.interpretation=n,this.editLink.href=this.editorUrl(),this.dispatchEvent(new CustomEvent("interpretationchange",{detail:{track:this.shownTrackUrl()}})),this.updateCompareButton(),this.showConfrontation(this.sceneElement.confrontation),this.showVariantMoved())}agentName(t){if("people"in t){const[e,...i]=t.people.replace(/([a-z])([A-Z])/g,"$1 $2").split(" ");return[...i,e].join(" ")}return"org"in t?t.org.replace(/([a-z])([A-Z])/g,"$1 $2"):this.observerDisplayName(t)??""}showConfrontation(t){this.confrontationList.innerHTML="",this.confrontationElement.hidden=!this.sceneElement.interpretation||!this.sceneElement.compareAccount;const e=new Intl.NumberFormat(this.language,{maximumFractionDigits:1,minimumFractionDigits:1}),i=new Intl.NumberFormat(this.language,{maximumFractionDigits:2,minimumFractionDigits:2});for(const n of t){const s=document.createElement("li");s.append(`${this.said.read(n.title)??n.sourceId}${this.colon}`);const r=[];n.separationDeg!==void 0&&r.push([this.messages.confrontationDirection.replace("{deg}",e.format(n.separationDeg)),n.disagreements.includes("direction")]),n.widthRatio!==void 0&&r.push([this.messages.confrontationWidth.replace("{ratio}",i.format(n.widthRatio)),n.disagreements.includes("width")]),n.heightRatio!==void 0&&r.push([this.messages.confrontationHeight.replace("{ratio}",i.format(n.heightRatio)),n.disagreements.includes("height")]),r.forEach(([a,c],h)=>{h>0&&s.append(" · ");const l=document.createElement("span");l.textContent=a,c&&(l.className="disagrees"),s.append(l)}),this.confrontationList.appendChild(s)}}startPending=!1;startSeconds(t){const e=yn.clock(this.getAttribute(v2));return(e?yn.elapsedSince(this.plain(t).time,e):void 0)??yn.delta(this.getAttribute(Bp))}selectObserver(t){const e=this.entries.find(n=>n.src===t);if(!e)return;this.currentSrc=t,this.observerSelect.value=t,this.sceneElement.documentUrl=e.src?new URL(e.src,location.href).href:void 0;const i=!this.sceneElement.ufoElement.playRequested;if(e.sighting.image?this.sceneElement.showPoster(e.sighting.image,e.src?new URL(e.src,location.href).href:void 0,i):this.sceneElement.showPoster(this.caseSource?.json.image,this.caseSource?.url,i),this.sceneElement.holdForNewScene(),this.sceneElement.sightingData=e.sighting,this.startPending){this.startPending=!1;const n=this.startSeconds(e);n!==void 0&&(this.sceneElement.ufoElement.currentTime=Math.max(0,n)*1e3)}this.offerInterpretations(e),this.updateAccountLine(),this.refreshParamSummary(),this.runAssessments(),this.infoOpen&&this.populateInfoPanel(),this.dispatchEvent(new CustomEvent(ZO,{detail:{src:t}}))}async runAssessments(){const t=++this.assessmentToken,e=await new PS(this.messages).read(this.sceneElement.ufoElement.sighting);t===this.assessmentToken&&(this.assessmentEntries=e.entries,this.refreshParamSummary())}updateAccountLine(){const t=this.entries.find(n=>n.src===this.currentSrc),e=t?this.observerDisplayName(this.plain(t).observer):void 0,i=e!==void 0||this.entries.length>1;this.accountElement.hidden=!i,this.observerText.textContent=e??"",this.editLink.hidden=!this.currentSrc,this.editLink.href=this.editorUrl(),this.editLink.title=this.messages.editThisObservation,this.editLink.setAttribute("aria-label",this.messages.editThisObservation)}caseTitleOf(t){const e=this.caseSource;if(!e)return;const i=e.json.events?.find(n=>n.url!==void 0&&!n.interpretationOf&&new URL(n.url,e.url).href===new URL(t.src,location.href).href);return i?this.said.read(i.title):void 0}observerDisplayName(t){if(!t)return;const e=[...t.firstNames??[],t.lastName].filter(Boolean).join(" ");return this.said.read(t.title)||e||t.id}plainRecordings=new WeakMap;plain(t){return this.stripped(t).recording}stripped(t){let e=this.plainRecordings.get(t.sighting);return e||(e=Kn.strip(t.sighting),this.plainRecordings.set(t.sighting,e)),e}basisOf(t,e){const i=this.stripped(t).provenance,n={measured:-1,stated:0,derived:1,assumed:2},s=i.paths().filter(c=>e.some(h=>c===h||c.startsWith(`${h}.`))).map(c=>i.at(c)),r=s.reduce((c,h)=>n[h.basis]>n[c]?h.basis:c,"stated"),a=s.filter(c=>c.basis===r&&c.rationale).map(c=>c.rationale);return{basis:r,rationales:a}}formatDate(t){const e=t.place?.[0],i=ao(t.time??{},e?.lng??0,t.utcOffsetHours);if(!i)return;const n=i.getTime()+this.utcOffsetHoursOf(t,e?.lng??0)*36e5;if(Number.isFinite(n))return new Intl.DateTimeFormat(dh.DATE_LOCALES[this.language],{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(n))}utcOffsetHoursOf(t,e){return t.utcOffsetHours??Math.round(e/15)}formatLocation(t){const e=t.place?.[0];if(e)return`${e.lat.toFixed(4)}, ${e.lng.toFixed(4)}`}toggleInfoPanel(){const t=!this.infoOpen;if(this.supportsPopover){const e=this.infoPanel.matches(":popover-open");t&&!e?this.infoPanel.showPopover():!t&&e&&this.infoPanel.hidePopover();return}t&&this.bringInfoButtonIntoView(),this.syncInfoOpen(t),this.infoPanel.hidden=!t,t?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}bringInfoButtonIntoView(){const t=this.infoButton.getBoundingClientRect(),e=window.innerHeight||document.documentElement.clientHeight;t.top>=0&&t.bottom<=e||this.infoButton.scrollIntoView({block:"center"})}syncInfoOpen(t){t!==this.infoOpen&&(this.infoOpen=t,this.infoButton.setAttribute("aria-expanded",String(t)),t?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=t=>{const e=t.composedPath();!e.includes(this.infoPanel)&&!e.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}revealInPanel(t){t.scrollIntoView?.({block:"nearest"})}get showLabels(){return this.labelsShown}set showLabels(t){this.toggleAttribute("show-labels",t)}applyLabels(t){this.labelsShown=t,this.syncLabelsToggle(),this.refreshParamSummary(),this.populateInfoPanel()}syncLabelsToggle(){this.labelsToggle.textContent=this.labelsShown?this.messages.hideLabels:this.messages.showLabels,this.labelsToggle.setAttribute("aria-pressed",String(this.labelsShown))}refreshParamSummary(){if(this.paramSummary.hidden=!this.labelsShown,!this.labelsShown){this.paramSummary.replaceChildren(),this.summarySignature="";return}const t=this.sceneElement.ufoElement.sighting,e=[...this.summaryBuilder.entriesFor(t,this.sceneElement.ufoElement.currentTime,{roadGradeDeg:this.sceneElement.roadGradeDeg}),...this.assessmentEntries],i=e.map(r=>`${r.field}=${r.label}=${r.value}${r.unit}${r.full??""}${r.fromSource?"*":""}`).join("|");if(i===this.summarySignature)return;this.summarySignature=i;const n=[];let s;for(const r of e){s&&s.group!==r.group&&(s=void 0);const a=r.group==="summary"?this.messages.summaryGroup:r.group==="observer"?this.messages.observerGroup:r.group in this.messages.summaryGroups?this.messages.summaryGroups[r.group]:r.group==="assessment"?this.messages.assessmentGroup:void 0;if(a!==void 0&&!s){const h=document.createElement("span");h.className="param-nest";const l=document.createElement("span");l.className="param-nest-label",l.textContent=a,h.append(l),s={group:r.group,element:h},n.push(h)}const c=this.paramItem(r);s?s.element.append(c):n.push(c)}this.paramSummary.replaceChildren(...n),this.syncDescription(e)}openDescription;syncDescription(t){this.openDescription!==void 0&&!t.some(e=>e.full===this.openDescription)&&(this.openDescription=void 0),x2.sync(this.paramSummary,this.openDescription,this.messages.summaryDescription,this.messages.closeDescription,()=>{this.openDescription=void 0,this.syncDescription(t)})}paramItem(t){const e=document.createElement("span");if(e.className=t.fromSource?"param-label from-source":"param-label",t.full!==void 0){e.classList.add("describable"),e.tabIndex=0,e.setAttribute("role","button");const s=()=>{this.openDescription=t.full,this.syncDescription([t])};e.addEventListener("click",s),e.addEventListener("keydown",r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),s())})}const i=document.createElement("span");if(i.className="param-label-label",i.textContent=`${t.label} `,e.append(i),t.color!==void 0){const s=document.createElement("span");s.className="param-label-swatch",s.style.background=t.color,e.append(s)}const n=document.createElement("span");return n.className="param-label-value",n.textContent=t.unit===""?t.value:`${t.value} ${t.unit}`,e.append(n),e}populateInfoPanel(){const t=this.entries.find(e=>e.src===this.currentSrc);if(this.infoObservationList.innerHTML="",t){const e=this.caseSource&&(this.caseSource.json.title??this.caseSource.json.id);if(e&&this.appendInfoRow(this.infoObservationList,this.messages.case,e),!this.labelsShown){const s=this.formatDate(this.plain(t));s&&this.appendInfoRow(this.infoObservationList,this.messages.date,s,this.basisOf(t,dh.DATE_PATHS));const r=this.formatLocation(this.plain(t));r&&this.appendInfoRow(this.infoObservationList,this.messages.location,r,this.basisOf(t,dh.PLACE_PATHS))}const i=this.said.read(this.plain(t).description);i&&!this.labelsShown&&this.appendInfoRow(this.infoObservationList,this.messages.description,i);for(const s of this.plain(t).sources??[])this.appendInfoSource(this.infoObservationList,this.messages.source,s);const n=this.plain(t).tags;!this.labelsShown&&n&&n.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,n.map(s=>this.tags.name(s)).join(", "))}this.infoAppLink.href=Dd,this.infoAppLink.textContent="UFO@home v0.152.1",gn.fill(this.infoCreditsList,this.sceneElement)}appendInfoSource(t,e,i){const n=document.createElement("dt");n.textContent=e;const s=document.createElement("dd"),r=i.title??i.url??"";if(i.url&&/^https?:\/\//i.test(i.url)){const c=document.createElement("a");c.href=i.url,c.target="_blank",c.rel="noopener noreferrer",c.textContent=r,s.appendChild(c)}else s.append(r);const a=[i.authors?.join(", "),i.publication?.publisher,i.publication?.time,i.index].filter(Boolean);a.length>0&&s.append(`, ${a.join(", ")}`),t.append(n,s)}static DATE_PATHS=["time","utcOffsetHours","timeZone"];static PLACE_PATHS=["place.0"];appendInfoRow(t,e,i,n){const s=document.createElement("dt");s.textContent=e;const r=document.createElement("dd");if(r.textContent=i,n){const a=document.createElement("span");a.className=`basis basis-${n.basis}`,a.textContent=this.messages.basis[n.basis],n.rationales.length>0&&(a.title=n.rationales.join(`
|
|
9438
9438
|
`)),r.append(" ",a)}t.appendChild(s),t.appendChild(r)}}const M2="rr0-sighting",ZO="observerchange",y2="rr0-eyeobserver";class JO extends dh{}function jO(){Yb(),uh.register(),customElements.get(M2)||customElements.define(M2,dh),customElements.get(y2)||customElements.define(y2,JO)}jO();export{wn as $,Uo as A,ue as B,st as C,Uc as D,rs as E,le as F,Ne as G,Sd as H,dP as I,qa as J,Hh as K,$p as L,V3 as M,ls as N,Jn as O,Nm as P,Wt as Q,Tt as R,Dl as S,xn as T,B3 as U,Gs as V,oP as W,an as X,on as Y,lP as Z,Xo as _,$n as a,fn as a0,we as a1,wi as a2,Yi as a3,Un as a4,Si as a5,TO as a6,y1 as a7,QO as a8,eP as a9,Ex as aA,aP as aB,Zn as aC,Ss as aD,Sx as aE,vM as aF,QA as aG,d6 as aH,af as aI,Pm as aJ,zx as aK,Zg as aL,Jg as aM,Pe as aN,Xa as aO,Jl as aP,tP as aa,jl as ab,uP as ac,cP as ad,hf as ae,Hx as af,gf as ag,sP as ah,jn as ai,Jv as aj,hP as ak,fP as al,bx as am,ws as an,hu as ao,v0 as ap,QE as aq,We as ar,$a as as,im as at,Ni as au,Vr as av,r3 as aw,je as ax,nP as ay,rP as az,yt as b,qu as c,et as d,vl as e,Na as f,oe as g,he as h,Fs as i,pP as j,ff as k,os as l,Xi as m,ir as n,T as o,jS as p,Ee as q,tr as r,ao as s,Mr as t,bt as u,_e as v,mP as w,de as x,iP as y,gE as z};
|