@rr0/ufoathome 0.123.0 → 0.123.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.
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ContrailSystem-C1ugmbHe.js","./ContrailGrowth-CuAzwIoc.js","./trafficRuntime-XVgt3vom.js","./ModelThumbnails-B2MXsKrk.js","./ModelSource-C3dP1aBw.js","./ModelViewer-BltV6g37.js","./SightingFileEditor-C0NC8jbz.js","./sightingSchema-kkSSrggd.js","./BodyEditor-ChwDW_Ws.js","./BodyEditorMessages_en-C3VGB1gD.js","./LaunchEditor-BCbplrLt.js","./LaunchEditorMessages_en-j4RgQPZu.js","./InterviewEditorElement-CT26rBmp.js","./InterviewMessages_en-cs-wWpmz.js","./InterviewMedia-CvAxC62V.js","./interviewJson-CfwBPiuG.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ContrailSystem-C1ugmbHe.js","./ContrailGrowth-CuAzwIoc.js","./trafficRuntime-XVgt3vom.js","./ModelThumbnails-B2MXsKrk.js","./ModelSource-C3dP1aBw.js","./ModelViewer-BltV6g37.js","./SightingFileEditor-C0NC8jbz.js","./sightingSchema-kkSSrggd.js","./BodyEditor-ChwDW_Ws.js","./BodyEditorMessages_en-C3VGB1gD.js","./LaunchEditor-BCbplrLt.js","./LaunchEditorMessages_en-j4RgQPZu.js","./InterviewEditorElement-Dl2fhE44.js","./InterviewMessages_en-cs-wWpmz.js","./InterviewMedia-CvAxC62V.js","./interviewJson-CfwBPiuG.js"])))=>i.map(i=>d[i]);
2
2
  const Z2="modulepreload",j2=function(o,e){return new URL(o,e).href},vv={},_e=function(e,t,i){let n=Promise.resolve();if(t&&t.length>0){let r=function(h){return Promise.all(h.map(d=>Promise.resolve(d).then(u=>({status:"fulfilled",value:u}),u=>({status:"rejected",reason:u}))))};const a=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),c=l?.nonce||l?.getAttribute("nonce");n=r(t.map(h=>{if(h=j2(h,i),h in vv)return;vv[h]=!0;const d=h.endsWith(".css"),u=d?'[rel="stylesheet"]':"";if(!!i)for(let g=a.length-1;g>=0;g--){const m=a[g];if(m.href===h&&(!d||m.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${u}`))return;const f=document.createElement("link");if(f.rel=d?"stylesheet":Z2,d||(f.as="script"),f.crossOrigin="",f.href=h,c&&f.setAttribute("nonce",c),document.head.appendChild(f),d)return new Promise((g,m)=>{f.addEventListener("load",g),f.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${h}`)))})}))}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 e().catch(s)})};class Un{constructor(e){this.entries=e}static empty(){return new Un(new Map)}get size(){return this.entries.size}at(e){return this.entries.get(e)}paths(){return[...this.entries.keys()]}set(e,t){t.basis==="stated"&&t.rationale===void 0?this.entries.delete(e):this.entries.set(e,t)}clear(e){for(const t of this.entries.keys())(t===e||t.startsWith(`${e}.`))&&this.entries.delete(t)}static strip(e){const t=new Un(new Map);return{recording:Un.stripValue(e,[],t),provenance:t}}static restore(e,t){if(t.size===0)return e;const i=structuredClone(e);for(const n of t.paths()){const s=t.at(n),r=n.split("."),a=Un.holderOf(i,r);if(!a)continue;const l=r[r.length-1],c=a[l];c!==void 0&&(s.of!==void 0&&JSON.stringify(s.of)!==JSON.stringify(c)||(a[l]={value:c,...s.basis==="stated"?{}:{basis:s.basis},...s.rationale===void 0?{}:{rationale:s.rationale}}))}return i}static isWrapper(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&"value"in e}static stripValue(e,t,i){return Un.isWrapper(e)?(i.set(t.join("."),{basis:e.basis??"stated",...e.rationale===void 0?{}:{rationale:e.rationale},of:e.value}),Un.stripValue(e.value,t,i)):Array.isArray(e)?e.map((n,s)=>Un.stripValue(n,[...t,String(s)],i)):typeof e=="object"&&e!==null?Object.fromEntries(Object.entries(e).map(([n,s])=>[n,Un.stripValue(s,[...t,n],i)])):e}static holderOf(e,t){let i=e;for(const n of t.slice(0,-1)){if(typeof i!="object"||i===null)return;i=i[n]}return typeof i=="object"&&i!==null?i:void 0}}class Ci{static SIGHTING_EVENT="sighting";static INTERPRETATION_EVENT="interpretation";static INTERVIEW_EVENT="interview";static isCase(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&Array.isArray(e.events)&&!("timeline"in e)}static sightingUrls(e,t){return(e.events??[]).filter(i=>i.eventType===Ci.SIGHTING_EVENT&&!i.interpretationOf&&typeof i.url=="string"&&i.url!=="").map(i=>new URL(i.url,t).href)}static accountIds(e,t,i,n){const s=(e.events??[]).filter(r=>r.eventType===Ci.SIGHTING_EVENT&&r.id!==void 0&&typeof r.url=="string"&&i!==void 0&&new URL(r.url,t).href===i).map(r=>r.id);return n!==void 0&&s.push(n),s}static interpretationEvents(e,t){const i=[t].flat().filter(n=>!!n);return i.length===0?[]:(e.events??[]).filter(n=>n.eventType===Ci.INTERPRETATION_EVENT?n.sighting!==void 0&&i.includes(n.sighting):n.eventType!==Ci.SIGHTING_EVENT||n.interpretationOf===void 0?!1:[n.interpretationOf].flat().some(s=>i.includes(s))).map(n=>n)}static problems(e,t){const i=e.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 l=a.eventType===Ci.SIGHTING_EVENT?a.interpretationOf:a.eventType===Ci.INTERVIEW_EVENT?a.interviewOf:void 0;if(l!==void 0)for(const c of[l].flat())!n.has(c)&&!t.includes(c)&&r.push({reading:a.url??a.id??"",reference:c})}return{duplicateIds:[...s],unresolved:r}}static async interpretationOf(e,t,i){if(e.bodies||e.reentries||e.launches)return Ci.withModelsFrom(Un.strip({title:e.title,bodies:e.bodies??[],smoke:e.smoke,reentries:e.reentries,launches:e.launches}).recording,t);if(!e.url)return{title:e.title,bodies:[]};const n=new URL(e.url,t).href,s=await i(n),r="timeline"in s&&s.interpretation?s.interpretation:s;return Ci.withModelsFrom(Un.strip({title:e.title??r.title,bodies:r.bodies??[],smoke:r.smoke,reentries:r.reentries,launches:r.launches}).recording,n)}static withModelsFrom(e,t){return{...e,bodies:e.bodies.map(i=>i.model?.url?{...i,model:{...i.model,url:new URL(i.model.url,t).href}}:i)}}}class Ja extends Error{constructor(e,t,i){super(`${e}: ${t}${i===void 0?"":` (HTTP ${i})`}`),this.kind=e,this.url=t,this.status=i,this.name="SightingFetchError"}}class ho{static async json(e){const t=new URL(e,location.href);if(location.protocol==="https:"&&t.protocol==="http:")throw new Ja("mixed-content",e);let i;try{i=await fetch(e)}catch{throw await this.diagnose(e,t)}if(!i.ok)throw new Ja("status",e,i.status);try{return await i.json()}catch{throw new Ja("malformed",e)}}static async diagnose(e,t){if(t.origin===location.origin)return new Ja("unreachable",e);try{return await fetch(e,{mode:"no-cors"}),new Ja("cors",e)}catch{return new Ja("unreachable",e)}}}class zn{constructor(e){this.preferences=e}read(e){if(e===void 0||typeof e=="string")return e===""?void 0:e;for(const i of this.preferences){const n=e[i]??e[zn.base(i)];if(n)return n}const t=new Set(this.preferences.map(i=>zn.base(i)));for(const[i,n]of Object.entries(e))if(n&&t.has(zn.base(i)))return n;return Object.values(e).find(i=>i)??void 0}write(e,t,i){const n=t?.trim()?t.trim():void 0;if(e===void 0||typeof e=="string")return n;const s={...e},r=Object.keys(s).find(a=>a===i)??Object.keys(s).find(a=>zn.base(a)===zn.base(i))??i;return n===void 0?delete s[r]:s[r]=n,Object.keys(s).length===0?void 0:s}static base(e){return e.toLowerCase().split("-")[0]}}function yh(o,e){for(const t of o){const i=t.toLowerCase().split("-")[0];if(e.includes(i))return i}return"en"}class Is{static preferencesFor(e){const t=navigator.languages??[],i=this.declaredFor(e);return i?[i,...t]:t}static declaredFor(e){for(let t=e;t;){const i=t.closest("[lang]")?.getAttribute("lang")?.trim();if(i)return i;const n=t.getRootNode();t=n instanceof ShadowRoot?n.host:void 0}}}class Nn{static ISO=/^P(?:(\d+(?:[.,]\d+)?)W)?(?:(\d+(?:[.,]\d+)?)D)?(?:T(?:(\d+(?:[.,]\d+)?)H)?(?:(\d+(?:[.,]\d+)?)M)?(?:(\d+(?:[.,]\d+)?)S)?)?$/;static seconds(e){const t=e.trim().toUpperCase(),i=Nn.ISO.exec(t);if(!i||t==="P"||t.endsWith("T"))return;const[,n,s,r,a,l]=i,c=d=>d===void 0?0:Number(d.replace(",",".")),h=c(n)*604800+c(s)*86400+c(r)*3600+c(a)*60+c(l);return Number.isFinite(h)?h:void 0}static parse(e){let t=e.trim();if(t==="")return;const i=t.slice(-1),n="?~%".includes(i)?i:"";n!==""&&(t=t.slice(0,-1).trim());const s=t.split("/");if(s.length>2)return;const r=s.map(d=>Nn.seconds(d));if(r.some(d=>d===void 0))return;const[a,l]=r,c=Math.min(a,l??a),h=Math.max(a,l??a);return{doubt:n,minSeconds:c,maxSeconds:h,chosenSeconds:(c+h)/2}}static isExact(e){const t=Nn.parse(e);return t!==void 0&&t.doubt===""&&t.minSeconds===t.maxSeconds}static format(e){const t=Math.max(0,Math.round(e*10)/10),i=Math.floor(t/3600),n=Math.floor(t%3600/60),s=Math.round(t%60*10)/10;return`PT${`${i>0?`${i}H`:""}${n>0?`${n}M`:""}${s>0||i===0&&n===0?`${s}S`:""}`}`}static say(e){const t=Math.round(e*10)/10;if(t<60)return`${t} s`;const i=Math.floor(t/3600),n=Math.floor(t%3600/60),s=Math.round(t%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 mt{static MOON_ANGULAR_WIDTH_DEG=.5237;static CANVAS_WIDTH_PX=640;static CANVAS_HEIGHT_PX=360;static angularWidthDeg(e){return 2*Math.atan(e.sizeM/(2*e.distanceM))*180/Math.PI}static inMoons(e){return e/mt.MOON_ANGULAR_WIDTH_DEG}static lerpAngular(e,t,i){if(!(!e||!t))return{widthDeg:e.widthDeg+(t.widthDeg-e.widthDeg)*i,heightDeg:e.heightDeg+(t.heightDeg-e.heightDeg)*i}}static sizeMAt(e,t){return 2*e*Math.tan(t*Math.PI/360)}static distanceMAt(e,t){return e/(2*Math.tan(t*Math.PI/360))}}function J2(o,e,t){if(!o||!e)return t<1?o:e;const i=((e.azimuthDeg-o.azimuthDeg)%360+540)%360-180;return{azimuthDeg:((o.azimuthDeg+i*t)%360+360)%360,altitudeDeg:o.altitudeDeg+(e.altitudeDeg-o.altitudeDeg)*t}}function Q2(o,e="#39ff14"){return{kind:"oval",bounds:o,color:e,angle:0,transparency:0,haloScale:0,selected:!1}}function ex(o,e,t="#39ff14"){return{kind:"polygon",bounds:o,points:e,color:t,angle:0,transparency:0,haloScale:0,selected:!1}}function tx(o,e="#39ff14"){const{width:t,height:i}=o;return ex(o,[{x:0,y:0},{x:t,y:0},{x:t,y:i},{x:0,y:i}],e)}const ix={oval:Q2,polygon:tx};function yv(o,e){return{...ix[e.presetId](o,e.color),transparency:e.transparency,haloScale:e.haloScale,blur:e.blur,brightness:e.brightness}}function nx(o,e,t){const{bounds:i}=o;return e>=i.x&&e<=i.x+i.width&&t>=i.y&&t<=i.y+i.height}function MM(o,e,t){const i=o.bounds.width,n=o.bounds.height;return{...o,bounds:{x:e-i/2,y:t-n/2,width:i,height:n}}}function Jn(o,e,t){return o+(e-o)*t}function bv(o){const e=/^#([0-9a-f]{6})$/i.exec(o);if(!e)return;const t=parseInt(e[1],16);return[t>>16&255,t>>8&255,t&255]}function sx(o){return`#${o.map(e=>Math.round(e).toString(16).padStart(2,"0")).join("")}`}function rx(o,e,t){const i=bv(o),n=bv(e);return!i||!n?t<1?o:e:sx([Jn(i[0],n[0],t),Jn(i[1],n[1],t),Jn(i[2],n[2],t)])}function ax(o,e,t){const i={x:Jn(o.bounds.x,e.bounds.x,t),y:Jn(o.bounds.y,e.bounds.y,t),width:Jn(o.bounds.width,e.bounds.width,t),height:Jn(o.bounds.height,e.bounds.height,t)},n=Jn(o.angle,e.angle,t),s=Jn(o.transparency,e.transparency,t),r=Jn(o.haloScale,e.haloScale,t),a=Jn(o.blur??0,e.blur??0,t),l=Jn(o.brightness??0,e.brightness??0,t),c=rx(o.color,e.color,t),h=mt.lerpAngular(o.angular,e.angular,t),d=J2(o.aim,e.aim,t);return o.kind==="polygon"&&e.kind==="polygon"&&o.points.length===e.points.length?{...o,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:l,color:c,angular:h,aim:d,points:o.points.map((u,p)=>({x:Jn(u.x,e.points[p].x,t),y:Jn(u.y,e.points[p].y,t)}))}:{...t<1?o:e,bounds:i,angle:n,transparency:s,haloScale:r,blur:a,brightness:l,color:c,angular:h,aim:d}}class eo{static DEFAULT_COLOR="#e8e6df";static complete(e,t=[]){const i=new Map;return e.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 l=`timeline.keyframes.${s}.shapes.${a}.shape`,c=eo.completed(r,i.get(r.sourceId),l,t);return i.set(r.sourceId,c),{sourceId:r.sourceId,shape:c}})}))}static completed(e,t,i,n){const s=e.shape??{},r=t??eo.firstAppearance(s,i,n),a={...r};s.bounds&&t&&(t.aim||t.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 l=s.kind??r.kind??"oval",c={...a,...s,kind:l};if(l==="polygon"&&!c.points){n.push({kind:"defaulted",path:`${i}.points`,expected:"rectangle"});const{width:h,height:d}=c.bounds;return{...c,points:[{x:0,y:0},{x:h,y:0},{x:h,y:d},{x:0,y:d}]}}return c}static firstAppearance(e,t,i){return e.kind||i.push({kind:"defaulted",path:`${t}.kind`,expected:'"oval"'}),e.color||i.push({kind:"defaulted",path:`${t}.color`,expected:`"${eo.DEFAULT_COLOR}"`}),!e.bounds&&!e.aim&&i.push({kind:"unplaced",path:t}),!e.bounds&&!e.angular&&i.push({kind:"unsized",path:t}),{kind:e.kind??"oval",bounds:{...eo.NEUTRAL_BOUNDS},color:eo.DEFAULT_COLOR,angle:0,transparency:0,haloScale:0,selected:!1}}static NEUTRAL_BOUNDS={x:mt.CANVAS_WIDTH_PX/2,y:mt.CANVAS_HEIGHT_PX/2,width:1,height:1}}class xp{keyframes=[];order=[];groups=[];span=0;addKeyframe(e,t){const i=this.findInsertIndex(e);if(this.keyframes[i]?.t===e){const n=new Set(t.map(s=>s.sourceId));this.keyframes[i]={t:e,shapes:[...this.keyframes[i].shapes.filter(s=>!n.has(s.sourceId)),...t]}}else this.keyframes.splice(i,0,{t:e,shapes:[...t]});for(const n of t)this.order.includes(n.sourceId)||this.order.push(n.sourceId)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}getKeyframeAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t];return i?.t===e?i:void 0}getShapeAt(e,t){return this.getKeyframeAt(e)?.shapes.find(i=>i.sourceId===t)?.shape}getLatestShapeAt(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return n.shape}}getInterpolatedShapeAt(e,t){const i=this.findShapeAtOrBefore(e,t);if(i?.t===e)return i.shape;const n=this.findShapeAtOrAfter(e,t);return i?n?ax(i.shape,n.shape,(e-i.t)/(n.t-i.t)):i.shape:n?.shape}findShapeAtOrBefore(e,t){let i=this.findInsertIndex(e);for(this.keyframes[i]?.t!==e&&(i-=1);i>=0;i--){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}findShapeAtOrAfter(e,t){for(let i=this.findInsertIndex(e);i<this.keyframes.length;i++){const n=this.keyframes[i].shapes.find(s=>s.sourceId===t);if(n)return{t:this.keyframes[i].t,shape:n.shape}}}hitTest(e,t,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(e,s[r]);if(a&&nx(a,t,i))return{sourceId:s[r],shape:a}}}removeSource(e){for(let t=this.keyframes.length-1;t>=0;t--){const i=this.keyframes[t].shapes.filter(n=>n.sourceId!==e);i.length===0?this.keyframes.splice(t,1):i.length!==this.keyframes[t].shapes.length&&(this.keyframes[t]={t:this.keyframes[t].t,shapes:i})}this.order=this.order.filter(t=>t!==e),this.removeFromGroup(e)}group(e){if(!(e.length<2)){for(const t of e)this.removeFromGroup(t);this.groups.push([...e])}}ungroup(e){const t=this.groups.findIndex(i=>i.includes(e));t!==-1&&this.groups.splice(t,1)}groupMembers(e){return this.groups.find(t=>t.includes(e))}removeFromGroup(e){const t=this.groups.findIndex(n=>n.includes(e));if(t===-1)return;const i=this.groups[t].filter(n=>n!==e);i.length<2?this.groups.splice(t,1):this.groups[t]=i}bringToFront(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.push(e))}sendToBack(e){const t=this.order.indexOf(e);t!==-1&&(this.order.splice(t,1),this.order.unshift(e))}get duration(){const e=this.keyframes.length===0?0:this.keyframes[this.keyframes.length-1].t;return Math.max(e,this.span)}get hasSpan(){return this.span>0}setSpan(e){this.span=Math.max(0,e)}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(e,t){const i=new xp;for(const n of eo.complete(e.keyframes??[],t))i.addKeyframe(n.t,n.shapes);if(e.span!==void 0&&e.span>0&&(i.span=e.span),e.order){const n=i.order.filter(s=>!e.order.includes(s));i.order=[...e.order,...n]}return e.groups&&(i.groups=e.groups.map(n=>n.filter(s=>i.order.includes(s))).filter(n=>n.length>=2)),i}}function ox(o,e,t){return Math.max(e,Math.min(t,o))}function lx(o,e,t){const i=((e-o)%360+540)%360-180;return((o+i*t)%360+360)%360}function Jo(o,e,t){return o+(e-o)*t}function cx(o,e,t){return{lat:o.lat===void 0||e.lat===void 0?void 0:Jo(o.lat,e.lat,t),lng:o.lng===void 0||e.lng===void 0?void 0:Jo(o.lng,e.lng,t),elevationM:Jo(o.elevationM,e.elevationM,t),headingDeg:o.headingDeg===void 0||e.headingDeg===void 0?void 0:lx(o.headingDeg,e.headingDeg,t),pitchDeg:Jo(o.pitchDeg,e.pitchDeg,t),rollDeg:Jo(o.rollDeg??0,e.rollDeg??0,t),fovDeg:Jo(o.fovDeg,e.fovDeg,t),fNumber:o.fNumber,focusDistanceM:o.focusDistanceM,filter:o.filter}}class ko{static at(e,t,i,n,s){const r=e[i],l=e[i+1]-r;if(l<=0)return t[i];const c=ko.tangent(e,t,i,s),h=ko.tangent(e,t,i+1,s),d=(n-r)/l,u=d*d,p=u*d;return(2*p-3*u+1)*t[i]+(p-2*u+d)*l*c+(-2*p+3*u)*t[i+1]+(p-u)*l*h}static BRAKE_S=.8;static paced(e,t,i,n){if(!i&&!n)return e;const s=t>0?Math.min(.5,ko.BRAKE_S/t):.5;if(i&&n){const a=1/(1-s);return e<=s?a*e*e/(2*s):e>=1-s?1-a*(1-e)*(1-e)/(2*s):a*(e-s/2)}const r=a=>{const l=1/(1-s/2);if(a<=1-s)return l*a;const c=a-(1-s);return l*(1-s)+l*(c-c*c/(2*s))};return n?r(e):1-r(1-e)}static tangent(e,t,i,n){const s=e.length-1,r=p=>(t[p+1]-t[p])/(e[p+1]-e[p]||1);if(i===0)return n?0:r(0);if(i===s)return n?0:r(s-1);const a=r(i-1),l=r(i);if(a*l<=0)return 0;const c=e[i]-e[i-1],h=e[i+1]-e[i],d=2*h+c,u=h+2*c;return(d+u)/(d/a+u/l)}}class bh{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,pose:t}:this.keyframes.splice(i,0,{t:e,pose:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}getLatestPoseAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].pose:void 0}getInterpolatedPoseAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.pose;const n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.pose;if(!n)return i.pose;const s=cx(i.pose,n.pose,ox((e-i.t)/(n.t-i.t),0,1));return this.humanly(t-1,e,s)}humanly(e,t,i){const n=Math.max(0,e-1),s=Math.min(this.keyframes.length-1,e+2),r=this.keyframes.slice(n,s+1),a=e-n,l=r.map(M=>M.t),c=(M,y)=>{const x=r.map(S=>M(S.pose));if(!x.some(S=>S===void 0))return ko.at(l,x,a,t,y)},h=r.map(M=>M.pose.headingDeg);let d;if(h.every(M=>M!==void 0)){const M=[h[0]];for(let y=1;y<h.length;y++)M.push(M[y-1]+((h[y]-h[y-1])%360+540)%360-180);d=(ko.at(l,M,a,t,!0)%360+360)%360}const u=this.keyframes[e],p=this.keyframes[e+1],f=(M,y)=>M.lat===y.lat&&M.lng===y.lng&&M.elevationM===y.elevationM,g=!f(u.pose,p.pose),m=g&&e>0&&f(this.keyframes[e-1].pose,u.pose),v=g&&e+2<this.keyframes.length&&f(p.pose,this.keyframes[e+2].pose);let b;if(m||v){const M=ko.paced((t-u.t)/(p.t-u.t),(p.t-u.t)/1e3,m,v),y=(x,S)=>x===void 0||S===void 0?void 0:x+(S-x)*M;b={lat:y(u.pose.lat,p.pose.lat),lng:y(u.pose.lng,p.pose.lng),elevationM:y(u.pose.elevationM,p.pose.elevationM)}}return{...i,lat:b?b.lat:c(M=>M.lat,!1)??i.lat,lng:b?b.lng:c(M=>M.lng,!1)??i.lng,elevationM:b?b.elevationM:c(M=>M.elevationM,!1)??i.elevationM,headingDeg:d??i.headingDeg,pitchDeg:c(M=>M.pitchDeg,!0)??i.pitchDeg,rollDeg:c(M=>M.rollDeg??0,!0)??i.rollDeg,fovDeg:c(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(e){const t=new bh;for(const i of e.keyframes)t.addKeyframe(i.t,i.pose);return t}}class fa{static MAX_CHANGE_PER_S=.05;points;followed;constructor(e){let t="none",i=0;this.points=e.map(({t:n,weather:s})=>(s.precipitationType!=="none"&&(t=s.precipitationType,i=s.precipitationIntensity),{t:n,lastFalling:t,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(fa.follow(this.followed[n-1],s.intensity,r.intensity,(r.t-s.t)/1e3,(r.t-s.t)/1e3))}}at(e){if(this.points.length===0||e<this.points[0].t)return;let t=this.points.length-1;for(;t>0&&this.points[t].t>e;)t--;const i=this.points[t],n=this.points[t+1],s=n?fa.follow(this.followed[t],i.intensity,n.intensity,(n.t-i.t)/1e3,(e-i.t)/1e3):fa.follow(this.followed[t],i.intensity,i.intensity,1,(e-i.t)/1e3);return{type:fa.typeBetween(i,n,e,s),intensity:s,character:fa.characterBetween(i,n,e)}}static characterBetween(e,t,i){return e.type==="none"?t&&t.type!=="none"?t.intensity:e.lastFallingIntensity:!t||t.type==="none"?e.intensity:e.intensity+(t.intensity-e.intensity)*(i-e.t)/(t.t-e.t||1)}static typeBetween(e,t,i,n){return e.type==="none"?t&&t.type!=="none"&&i>e.t?t.type:n>0?e.lastFalling:"none":t&&t.type==="none"&&n<=0?"none":e.type}static follow(e,t,i,n,s){const r=fa.MAX_CHANGE_PER_S,a=n>0?(i-t)/n:0,l=d=>t+a*Math.min(Math.max(d,0),n);let c=e,h=0;for(let d=0;d<8&&h<s;d++){const u=l(h)-c;if(Math.abs(u)<1e-9){const M=h<n?a:0;if(Math.abs(M)<=r){const x=h<n?Math.min(s,n):s;c=l(x),h=x;continue}const y=Math.min(s,n);c+=Math.sign(M)*r*(y-h),h=y;continue}const p=Math.sign(u),f=h<n?a:0,g=r-p*f,m=g>0?h+Math.abs(u)/g:1/0,v=h<n?n:1/0,b=Math.min(s,m,v);c+=p*r*(b-h),h=b,b===m&&(c=l(h))}return Math.min(1,Math.max(0,c))}}const ag=1e3,gu=.65,wM=.05,Sp={cloudCover:0,cloudDarkness:0,precipitationType:"none",precipitationIntensity:0,windDirectionDeg:0,windSpeed:0,storm:!1};function Ca(o){if(o.cloudLayers!==void 0)return o.cloudLayers;const e=[],t=o.lowerCloudCover??o.cloudCover;return t>0&&e.push({id:"lower",type:"cumulus",baseM:o.cloudBaseM??ag,thicknessM:650,coverage:t,sizeM:1400,density:1,darkness:o.cloudDarkness}),(o.highCloudCover??0)>0&&e.push({id:"cirrus",type:"cirrus",baseM:8e3,thicknessM:400,coverage:o.highCloudCover,sizeM:2200,density:.35,darkness:o.cloudDarkness,iceCrystalAlignment:o.iceCrystalAlignment}),e}function hi(o,e,t){return o+(e-o)*t}function og(o,e,t){const i=((e-o)%360+540)%360-180;return((o+i*t)%360+360)%360}function hx(o,e,t){return Math.max(e,Math.min(t,o))}function dx(o=[],e=[],t){if(!(!o.length&&!e.length))return[...new Set([...o.map(i=>i.id),...e.map(i=>i.id)])].map(i=>{const n=o.find(l=>l.id===i),s=e.find(l=>l.id===i),r=n??{...s,density:0},a=s??{...n,density:0};return{...r,eastM:hi(r.eastM,a.eastM,t),northM:hi(r.northM,a.northM,t),baseM:hi(r.baseM,a.baseM,t),thicknessM:hi(r.thicknessM,a.thicknessM,t),widthM:hi(r.widthM,a.widthM,t),depthM:hi(r.depthM,a.depthM,t),rotationDeg:og(r.rotationDeg,a.rotationDeg,t),density:hi(r.density,a.density,t),darkness:hi(r.darkness??0,a.darkness??0,t)}})}function ux(o,e,t){if(o.cloudLayers===void 0&&e.cloudLayers===void 0)return;const i=Ca(o),n=Ca(e);return t>=1?n.map(r=>({...r})):[...new Set([...i.map(r=>r.id),...n.map(r=>r.id)])].map(r=>{const a=i.find(d=>d.id===r),l=n.find(d=>d.id===r),c=a??{...l,coverage:0},h=l??{...a,coverage:0};return{...c,instances:dx(a?.instances,l?.instances,t),baseM:hi(c.baseM,h.baseM,t),thicknessM:hi(c.thicknessM,h.thicknessM,t),coverage:hi(c.coverage,h.coverage,t),sizeM:hi(c.sizeM,h.sizeM,t),density:hi(c.density,h.density,t),darkness:hi(c.darkness??o.cloudDarkness,h.darkness??e.cloudDarkness,t),iceCrystalAlignment:c.iceCrystalAlignment===void 0||h.iceCrystalAlignment===void 0?void 0:hi(c.iceCrystalAlignment,h.iceCrystalAlignment,t),windSpeed:c.windSpeed===void 0&&h.windSpeed===void 0?void 0:hi(c.windSpeed??o.windSpeed,h.windSpeed??e.windSpeed,t),windDirectionDeg:c.windDirectionDeg===void 0&&h.windDirectionDeg===void 0?void 0:og(c.windDirectionDeg??o.windDirectionDeg,h.windDirectionDeg??e.windDirectionDeg,t)}})}function px(o,e,t){return{cloudLayers:ux(o,e,t),cloudCover:hi(o.cloudCover,e.cloudCover,t),cloudDarkness:hi(o.cloudDarkness,e.cloudDarkness,t),highCloudCover:o.highCloudCover===void 0||e.highCloudCover===void 0?void 0:hi(o.highCloudCover,e.highCloudCover,t),iceCrystalAlignment:o.iceCrystalAlignment===void 0||e.iceCrystalAlignment===void 0?void 0:hi(o.iceCrystalAlignment,e.iceCrystalAlignment,t),rareIceCrystals:o.rareIceCrystals===void 0||e.rareIceCrystals===void 0?void 0:hi(o.rareIceCrystals,e.rareIceCrystals,t),lowerCloudCover:o.lowerCloudCover===void 0||e.lowerCloudCover===void 0?void 0:hi(o.lowerCloudCover,e.lowerCloudCover,t),cloudBaseM:o.cloudBaseM===void 0||e.cloudBaseM===void 0?void 0:hi(o.cloudBaseM,e.cloudBaseM,t),relativeHumidity:o.relativeHumidity===void 0||e.relativeHumidity===void 0?void 0:hi(o.relativeHumidity,e.relativeHumidity,t),precipitationType:t<1?o.precipitationType:e.precipitationType,precipitationIntensity:hi(o.precipitationIntensity,e.precipitationIntensity,t),windDirectionDeg:og(o.windDirectionDeg,e.windDirectionDeg,t),windSpeed:hi(o.windSpeed,e.windSpeed,t),storm:t<1?o.storm:e.storm}}class Mh{keyframes=[];ramp;addKeyframe(e,t){this.ramp=void 0;const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,weather:t}:this.keyframes.splice(i,0,{t:e,weather:t})}clear(){this.ramp=void 0,this.keyframes.length=0}removeKeyframeAt(e){this.ramp=void 0;const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}getLatestWeatherAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].weather:void 0}getInterpolatedWeatherAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.weather;const n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];return i?n?px(i.weather,n.weather,hx((e-i.t)/(n.t-i.t),0,1)):i.weather:n?.weather}getActualWeatherAt(e){const t=this.getInterpolatedWeatherAt(e);if(!t)return;const i=(this.ramp??=new fa(this.keyframes)).at(e);if(!i)return t;const{type:n,intensity:s,character:r}=i,a=r>0?Math.min(1,s/r):n==="none"?0:1;return{...t,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(e){const t=new Mh;for(const i of e.keyframes)t.addKeyframe(i.t,{...Sp,...i.weather});return t}}class wh{keyframes=[];addKeyframe(e,t){const i=this.findInsertIndex(e);this.keyframes[i]?.t===e?this.keyframes[i]={t:e,sound:t}:this.keyframes.splice(i,0,{t:e,sound:t})}clear(){this.keyframes.length=0}removeKeyframeAt(e){const t=this.findInsertIndex(e);this.keyframes[t]?.t===e&&this.keyframes.splice(t,1)}getLatestSoundAt(e){let t=this.findInsertIndex(e);return this.keyframes[t]?.t!==e&&(t-=1),t>=0?this.keyframes[t].sound:void 0}getInterpolatedSoundAt(e){const t=this.findInsertIndex(e),i=this.keyframes[t]?.t===e?this.keyframes[t]:this.keyframes[t-1];if(i?.t===e)return i.sound;const n=this.keyframes[t]?.t===e?void 0:this.keyframes[t];if(!i)return n?.sound;if(!n)return i.sound;const s=(e-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(e){const t=new wh;for(const i of e.keyframes)t.addKeyframe(i.t,i.sound);return t}lerp(e,t,i){return{kind:i<1?e.kind:t.kind,volume:e.volume+(t.volume-e.volume)*i,pitchHz:e.pitchHz+(t.pitchHz-e.pitchHz)*i,src:i<1?e.src:t.src}}findInsertIndex(e){let t=0,i=this.keyframes.length;for(;t<i;){const n=t+i>>>1;this.keyframes[n].t<e?t=n+1:i=n}return t}}const fx=["none","hum","whistle","rumble","crackle"],mx=100,gx={kind:"none",volume:0,pitchHz:mx};class kl{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 kl.BODIES.map(e=>({id:e.id,category:"dslr",name:e.name,projection:"rectilinear",frame:{widthMm:e.widthMm,heightMm:e.heightMm,focalLengthMm:kl.DEFAULT_FOCAL_MM,focalRangeMm:kl.FOCAL_RANGE_MM},fNumber:8,fNumberRange:{min:1.4,max:22},exposureSeconds:1/250,exposureRangeSeconds:{min:1/8e3,max:3600},years:{from:e.year},apertureBlades:7,detailUm:e.pixelUm,medium:{kind:"sensor",iso:100}}))}static names(){return Object.fromEntries(kl.BODIES.map(e=>[e.id,e.name]))}}class Ls{static DEFAULT_EYEPIECE_MM=26;static DEFAULT_APPARENT_FIELD_DEG=52;static FIELD_STOP_MM=2*Ls.DEFAULT_EYEPIECE_MM*Math.tan(Ls.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 e=Ls.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}}:{}})),t=Ls.FIELD_STOP_MM,i=Ls.TELESCOPES.map(n=>({id:n.id,category:"telescope",name:n.name,projection:"rectilinear",frame:{widthMm:t*16/9,heightMm:t,focalLengthMm:n.focalLengthMm,focalRangeMm:{minMm:n.focalLengthMm*Ls.RANGE.min,maxMm:n.focalLengthMm*Ls.RANGE.max}},visualAid:{apertureMm:n.apertureMm,eyepieceFocalMm:Ls.DEFAULT_EYEPIECE_MM},...n.fromYear!==void 0?{years:{from:n.fromYear}}:{}}));return[...e,...i]}static names(){return Object.fromEntries(Ls.instruments().map(e=>[e.id,e.name]))}}const Jc=[{id:"eye",category:"eye",name:"Naked eye",flare:0,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}},{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}},...kl.instruments(),...Ls.instruments()];class Ut{static get default(){return Jc[0]}static byId(e){return Jc.find(t=>t.id===e)??this.default}static UNAIDED_FIELD_DEG=60;static UNAIDED_ASPECT=16/9;static fieldOfViewDeg(e){const t=e.frame;return t?2*Math.atan(t.heightMm/(2*t.focalLengthMm))*180/Math.PI:e.visualAid?.trueFieldDeg??Ut.UNAIDED_FIELD_DEG}static aspectOf(e){const t=e.frame;return t?t.widthMm/t.heightMm:Ut.UNAIDED_ASPECT}static frameWidthPx(e,t){return Math.round(t*Ut.aspectOf(e))}static CATEGORIES=["eye","camera","dslr","phone","binoculars","telescope"];static unavailability(e,t){const i=e.years;if(!(t===void 0||!i)){if(t<i.from)return{kind:"before",from:i.from};if(i.to!==void 0&&t>i.to)return{kind:"after",to:i.to}}}static availableAt(e){return e===void 0?Jc:Jc.filter(t=>!t.years||e>=t.years.from&&(t.years.to===void 0||e<=t.years.to))}static fieldOfViewDegAt(e,t){const i=e.frame;if(!(!i||t<=0))return 2*Math.atan(i.heightMm/(2*t))*180/Math.PI}static focalLengthMmFor(e,t){const i=e.frame;if(!(!i||t<=0||t>=180))return i.heightMm/(2*Math.tan(t*Math.PI/360))}static bladesShowing(e,t){const i=t??e.fNumber;if(i===void 0||e.apertureBlades===void 0)return 0;const n=e.fNumberRange;return!n||n.max<=n.min?1:Math.max(0,Math.min(1,(i-n.min)/(n.max-n.min)))}static LENS_FLARE_ARTIFACTS=1;static flareArtifactsOf(e){return e.flare??Ut.LENS_FLARE_ARTIFACTS}static starPointsOf(e){const t=e.apertureBlades;return t===void 0||t<3?0:t%2===0?t:t*2}}class Go extends Error{}class Ep{constructor(e){this.name=e}validate(e){return!0}}class xM extends Ep{min;max;constructor(e,t,i){super(e),this.min=t,this.max=i}validate(e){if(typeof e!="number")throw new Go(`${this.name} value must be a number, but was ${e}`);if(e<this.min||e>this.max)throw new Go(`${this.name} value must be >= ${this.min} and <= ${this.max}, but was ${e}`);return super.validate(e)}}class Xi{name;min;max;duration;subUnit;validator;constructor(e,t,i,n,s=new xM(e,t,i)){this.name=e,this.min=t,this.max=i,this.subUnit=n,this.duration=n?(n.max-n.min+1)*n.duration:1,this.validator=s}validate(e){return this.validator.validate(e)}[Symbol.iterator](){let e=this.min;return{next:()=>{const t={done:e>this.max,value:e};return e++,t}}}}class SM{millisecond;second;minute;hour;day;month;year}class vx extends SM{}class EM extends vx{millisecond=new Xi("millisecond",0,999,void 0);second=new Xi("second",0,59,this.millisecond);minute=new Xi("minute",0,59,this.second);hour=new Xi("hour",0,23,this.minute);day=new Xi("day",1,31,this.hour);month=new Xi("month",1,12,this.day);year=new Xi("year",0,9999,this.month)}const et=new EM;class yx extends xM{constructor(e=1,t=12){super("month",e,t)}}class vr{static instance=new vr;render(e){return e.value.toString()}}class An{unit;#e;constructor(e,t){this.unit=t,this.value=typeof e=="number"?e:e.value}get value(){return this.#e}set value(e){this.unit.validate(e),this.#e=e}get duration(){return this.value*this.unit.duration}#t(e){if(this.constructor.name!==e.constructor.name)throw new Ep(`${this.unit.name} "${this.toString()}" cannot be compared with ${e.unit?.name} "${e.toString()}"`)}compare(e){return this.#t(e),this.value-e.value}isEqual(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}previous(e=this.unit){const t=this.value-1;return new this.constructor(t,e)}next(e=this.unit){const t=this.value+1;return new this.constructor(t,e)}toString(e=vr.instance){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class ri{static#e=new Map;static register(e,t){ri.#e.set(e,t)}static get(e){const t=ri.#e.get(e);if(!t)throw new Go(`No default parser registered for ${e.name}: import "@rr0/time/defaults" or pass a parser to fromString()`);return t()}}class vu extends An{constructor(e=new Date().getFullYear(),t=et.year){super(e,t)}static fromString(e,t=ri.get(vu)){return new vu(t.parse(e))}}class Ir extends vr{static default=new Ir("0",2);constructor(e,t){super(),this.char=e,this.size=t}render(e){return super.render(e).padStart(this.size,this.char)}}class yu extends An{constructor(e=new Date().getMonth()+1,t=et.month){super(e,t)}static fromString(e,t=ri.get(yu)){return new yu(t.parse(e))}toString(e=Ir.default){return super.toString(e)}}class bu extends An{constructor(e=new Date().getDate(),t=et.day){super(e,t)}static fromString(e,t=ri.get(bu)){const i=t.parse(e);return new bu(i)}toString(e=Ir.default){return super.toString(e)}}class Mu extends An{constructor(e=new Date().getHours(),t=et.hour){super(e,t)}static fromString(e,t=ri.get(Mu)){return new Mu(t.parse(e))}toString(e=Ir.default){return super.toString(e)}}class wu extends An{constructor(e=new Date().getMinutes(),t=et.minute){super(e,t)}static fromString(e,t=ri.get(wu)){return new wu(t.parse(e))}toString(e=Ir.default){return super.toString(e)}}class xu extends An{constructor(e=new Date().getSeconds(),t=et.second){super(e,t)}static fromString(e,t=ri.get(xu)){return new xu(t.parse(e),et.second)}toString(e=Ir.default){return super.toString(e)}}class qo extends An{static renderer=new Ir("0",3);constructor(e,t=et.millisecond){super(e,t)}static parseFraction(e){return parseInt(e.padEnd(3,"0").substring(0,3),10)}toString(e=qo.renderer){return super.toString(e)}}class bx{render(e){return e.toString()}}class Mx extends bx{render(e){const t=e.value,i=Math.abs(t),n=Math.floor(i/60),s=i%60;if(n===0&&s===0)return"Z";{const r=t<0?"-":"+",a=n.toString().padStart(2,"0"),l=s>0?":"+s.toString().padEnd(2,"0"):"";return r+a+l}}}class oc{value;name="timeshift";renderer;constructor(e=0){this.value=e}static fromString(e,t=ri.get(oc),i=void 0){const n=t.parse(e,i);return new oc(n)}toString(e=new Mx){return e.render(this)}toSpec(){return{value:this.value}}toJSON(){return this.toSpec()}}class xn{static timeshift(e,t){return e+(xn.isDaylight(t)?60:0)}static isDaylight(e){const{year:t,month:i,day:n}=e,s=e.hour??12;if(![t,i,n].every(Number.isInteger))throw new RangeError("Daylight saving time depends on the year, month and day");const r=xn.rule(t);if(!r)return!1;const a=xn.rank(i,n,s);return a>=xn.rank(r.start.month,r.start.day,2)&&a<xn.rank(r.end.month,r.end.day,2)}static rule(e){if(e<1967)return;const t={month:10,day:xn.sunday(e,10,-1)};return e>=2007?{start:{month:3,day:xn.sunday(e,3,2)},end:{month:11,day:xn.sunday(e,11,1)}}:e>=1987?{start:{month:4,day:xn.sunday(e,4,1)},end:t}:e===1975?{start:{month:2,day:23},end:t}:e===1974?{start:{month:1,day:6},end:t}:{start:{month:4,day:xn.sunday(e,4,-1)},end:t}}static sunday(e,t,i){const n=new Date(Date.UTC(2e3,t-1,1));n.setUTCFullYear(e);const s=1+(7-n.getUTCDay())%7;if(i>0)return s+7*(i-1);const r=[31,xn.isLeap(e)?29:28,31,30,31,30,31,31,30,31,30,31][t-1];let a=s;for(;a+7<=r;)a+=7;return a}static isLeap(e){return e%4===0&&(e%100!==0||e%400===0)}static rank(e,t,i){return(e*100+t)*100+i}}const wx={name:"PST",timeshift:"-08",title:"Pacific Standard Time (US)"},xx={name:"PDT",timeshift:"-07",title:"Pacific Daylight Time (US)"},Sx={name:"MDT",timeshift:"-06",title:"Mountain Standard Time (US)"},Ex={name:"MST",timeshift:"-07",title:"Mountain Daylight Time (US)"},Ax={name:"PT",timeshift:o=>xn.timeshift(-480,o),title:"Pacific Time (US)"},Tx={name:"MT",timeshift:o=>xn.timeshift(-420,o),title:"Mountain Time (US)"},_x={name:"CT",timeshift:o=>xn.timeshift(-360,o),title:"Central Time (US)"},Ix={name:"ET",timeshift:o=>xn.timeshift(-300,o),title:"Eastern Time (US)"},Dx={name:"CWT",timeshift:"-05",title:"Central War Time (US)"},Rx={name:"CDT",timeshift:"-05",title:"Central Daylight Time"},Cx={name:"EST",timeshift:"-05",title:"Eastern Standard Time (US)"},kx={name:"EDT",timeshift:"-04",title:"Eastern Time (US)"},Lx={name:"AST",timeshift:"-04",title:"Atlantic Standard Time (US)"},Ox={name:"ADT",timeshift:"-03",title:"Atlantic Daylight Time (US)"},Px={name:"UTC",timeshift:"Z",title:"Coordinated Universal Time"},Nx={name:"Z",timeshift:"Z",title:"UTC"},Fx={name:"GMT",timeshift:"Z",title:"Greenwich Mean Time"},Ux={name:"BST",timeshift:"+01",title:"British Summer Time"},Bx={name:"CEST",timeshift:"+02",title:"Central European Summer Time"},zx={name:"CET",timeshift:"+01",title:"Central European Time"},Hx={name:"MSK",timeshift:"+03",title:"Moscow Time (RU)"},Gx={name:"IST",timeshift:"+05:30",title:"Indian Standard Time"},Vx={name:"BJT",timeshift:"+08",title:"Beijing Time"},Wx={name:"CST",timeshift:"-06",title:"Central Standard Time"},Xx={name:"JST",timeshift:"+09",title:"Japan Standard Time"},$x={name:"AEST",timeshift:"+10",title:"Australian Eastern Standard Time"},Yx={name:"NZST",timeshift:"+12",title:"New Zealand Standard Time"},qx={name:"LST",timeshift:"?",title:"Local Sideral Time"},Mv=[Ox,$x,Lx,Vx,Ux,Wx,Rx,zx,Bx,_x,Dx,kx,Cx,Ix,Fx,Gx,Xx,qx,Sx,Hx,Ex,Tx,Yx,xx,wx,Ax,Px,Nx];class Ap{static instance=new Ap;renderComponent(e,t){return e[t].toString()}renderSecond(e){return this.renderComponent(e,"second")+(e.millisecond?"."+e.millisecond.toString():"")}render(e){const t=[];e.year&&t.push(this.renderComponent(e,"year")),e.month&&t.push(this.renderComponent(e,"month")),e.day&&t.push(this.renderComponent(e,"day"));const i=[];e.hour&&i.push(this.renderComponent(e,"hour")),e.minute&&i.push(this.renderComponent(e,"minute")),e.second&&i.push(this.renderSecond(e));const n=t.join("-"),s=e.timeshift?e.timeshift.toString():"",r=i.join(":")+s;return n+(r.length>0?"T"+r:"")}}class Qa extends Go{constructor(e="method is abstract"){super(e)}}class lg{units;constructor(e){this.units=e}newYear(e){throw new Qa}newMonth(e){throw new Qa}newDay(e){throw new Qa}newHour(e){throw new Qa}newMinute(e){throw new Qa}newSecond(e){throw new Qa}}class Kx extends SM{millisecond=new Xi("milliseconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,void 0);second=new Xi("seconds",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.millisecond);minute=new Xi("minutes",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.second);hour=new Xi("hours",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.minutes);day=new Xi("days",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.hour);month=new Xi("months",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.day);year=new Xi("years",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const cg=new Kx;class hg{static instance=new hg;render(e){const t=uo.toSpec(e);let i="P";const n=t.years;n&&(i+=n.toString()+"Y");const s=t.months;s&&(i+=s.toString(vr.instance)+"MM");const r=t.days;r&&(i+=r.toString(vr.instance)+"D");const a=t.hours;a&&(i+=a.toString(vr.instance)+"H");const l=t.minutes;l&&(i+=l.toString(vr.instance)+"M");const c=t.seconds;return c&&(i+=c.toString(vr.instance)+"S"),i}}class uo extends An{constructor(e={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 e=="number"?e:+(e.years?e.years*et.year.duration:0)+(e.months?e.months*et.month.duration:0)+(e.days?e.days*et.day.duration:0)+(e.hours?e.hours*et.hour.duration:0)+(e.minutes?e.minutes*et.minute.duration:0)+(e.seconds?e.seconds*et.second.duration:0)},new Xi("millisecond",0,Number.MAX_SAFE_INTEGER,void 0))}static toSpec(e,t=jx){let i=typeof e=="number"?e:e.value;const n=i>0?1:-1;i=Math.abs(i);const s={},r=i/et.year.duration,a=Math.floor(r);a>0&&(s.years=t.newYear(n*a),i-=a*et.year.duration);const l=i/et.month.duration,c=Math.floor(l);c>0&&(s.months=t.newMonth(n*c),i-=c*et.month.duration);const h=i/et.day.duration,d=Math.floor(h);d>0&&(s.days=t.newDay(n*d),i-=d*et.day.duration);const u=i/et.hour.duration,p=Math.floor(u);p>0&&(s.hours=t.newHour(n*p),i-=p*et.hour.duration);const f=i/et.minute.duration,g=Math.floor(f);g>0&&(s.minutes=t.newMinute(n*g),i-=g*et.minute.duration);const m=i/et.second.duration,v=Math.floor(n*m);return v>0&&(s.seconds=t.newSecond(v)),s}static fromString(e,t=ri.get(uo)){return new uo(t.parse(e))}static between(e,t){const i=t.getTime(),n=e.getTime();return new uo(i-n)}toSpec(){return uo.toSpec(this)}toString(e=hg.instance){return e.render(this)}}class AM extends lg{constructor(e){super(e)}newYear(e){return new vu(e,this.units.year)}newMonth(e){return new yu(e,this.units.month)}newDay(e){return new bu(e,this.units.day)}newHour(e){return new Mu(e,this.units.hour)}newMinute(e){return new wu(e,this.units.minute)}newSecond(e){return new xu(e,this.units.second)}newMillisecond(e){return new qo(e,this.units.millisecond)}newTimeshift(e){return new oc(typeof e=="number"?e:e.value)}}const Zx=new AM(et),jx=new AM(cg);class Bs{#e;#t;#i;#n;#s;#r;#a;#o;constructor(e={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:Bs.timeshiftOf(new Date)}){this.year=e.year,this.month=e.month,this.day=e.day,this.hour=e.hour,this.minute=e.minute,this.second=e.second,this.millisecond=e.millisecond,this.timeshift=e.timeshift}get year(){return this.#e}set year(e){const t=typeof e=="number";this.#e&&t?this.#e.value=e:this.#e=t?this.factory.newYear(e):!e||e.start||e instanceof An?e:this.factory.newYear(e)}get month(){return this.#t}set month(e){const t=typeof e=="number";this.#t&&t?this.#t.value=e:this.#t=t?this.factory.newMonth(e):!e||e.start||e instanceof An?e:this.factory.newMonth(e)}get day(){return this.#i}set day(e){const t=typeof e=="number";this.#i&&t?this.#i.value=e:this.#i=t?this.factory.newDay(e):!e||e.start||e instanceof An?e:this.factory.newDay(e)}get hour(){return this.#n}set hour(e){const t=typeof e=="number";this.#n&&t?this.#n.value=e:this.#n=t?this.factory.newHour(e):!e||e.start||e instanceof An?e:this.factory.newHour(e)}get minute(){return this.#s}set minute(e){const t=typeof e=="number";this.#s&&t?this.#s.value=e:this.#s=t?this.factory.newMinute(e):!e||e.start||e instanceof An?e:this.factory.newMinute(e)}get second(){return this.#r}set second(e){const t=typeof e=="number";this.#r&&t?this.#r.value=e:this.#r=t?this.factory.newSecond(e):!e||e.start||e instanceof An?e:this.factory.newSecond(e)}get millisecond(){return this.#a}set millisecond(e){const t=typeof e=="number";this.#a&&t?this.#a.value=e:this.#a=t||e&&!(e instanceof An)?this.factory.newMillisecond(e):e}get timeshift(){return this.#o}set timeshift(e){const t=typeof e=="number";this.#o&&t?this.#o.value=e:this.#o=t||e&&!(e instanceof oc)?this.factory.newTimeshift(e):e}get factory(){return Zx}static fromString(e,t=ri.get(Bs)){const{year:i,month:n,day:s,hour:r,minute:a,second:l,millisecond:c,timeshift:h}=t.parse(e);return new Bs({year:i,month:n,day:s,hour:r,minute:a,second:l,millisecond:c,timeshift:h})}static timeshiftOf(e){return-e.getTimezoneOffset()||0}static fromDate(e){return new Bs({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:Bs.timeshiftOf(e)})}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return Bs.fromString(i)}#l(e){if(this.constructor.name!==e.constructor.name)throw new Ep(`Date "${this.toString()}" cannot be compared with "${e.toString()}"`)}compare(e){return this.#l(e),this.getTime()-e.getTime()}delta(e){const t=this.compare(e);return new uo(t)}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(e){return this.compare(e)===0}isBefore(e){return this.compare(e)<0}isAfter(e){return this.compare(e)>0}clone(){return new Bs(this.toSpec())}previous(){let e=this.clone();try{e.second=this.second.previous()}catch{try{e.minute=this.minute.previous()}catch{try{e.hour=this.hour.previous()}catch{try{e.day=this.day.previous()}catch{try{e.month=this.month.previous()}catch{e.year=this.year.previous()}}}}}return e}next(){let e=this.clone();try{e.second=this.second.next()}catch{try{e.minute=this.minute.next()}catch{try{e.hour=this.hour.next()}catch{try{e.day=this.day.next()}catch{try{e.month=this.month.next()}catch{e.year=this.year.next()}}}}}return e}toString(e=Ap.instance){return e.render(this)}toSpec(){const e={},t=this.year?.toSpec();t&&(e.year=t);const i=this.month?.toSpec();i&&(e.month=i);const n=this.day?.toSpec();n&&(e.day=n);const s=this.hour?.toSpec();s&&(e.hour=s);const r=this.minute?.toSpec();r&&(e.minute=r);const a=this.second?.toSpec();a&&(e.second=a);const l=this.millisecond?.toSpec();l&&(e.millisecond=l);const c=this.timeshift?.toSpec();return c&&(e.timeshift=c),e}toJSON(){return this.toSpec()}}class Fh extends vr{static instance=new Fh(Ir.default);constructor(e){super(),this.valueRenderer=e}render(e){return(this.valueRenderer?this.valueRenderer.render(e):super.render(e))+this.qualifier(e)}qualifier(e){return e.uncertain?e.approximate?"%":"?":e.approximate?"~":""}}class Ko extends An{#e;#t;constructor(e,t){super(e,t),this.#e=e.uncertain||!1,this.#t=e.approximate||!1}get uncertain(){return this.#e}set uncertain(e){return this.#e=e}get approximate(){return this.#t}set approximate(e){return this.#t=e}isCertainAndPrecise(){return!this.approximate&&!this.uncertain}isEqual(e){return this.isCertainAndPrecise()&&super.isEqual(e)}isBefore(e){return this.isCertainAndPrecise()&&super.isBefore(e)}isAfter(e){return this.isCertainAndPrecise()&&super.isAfter(e)}toString(e=Fh.instance){return super.toString(e)}toSpec(){return{...super.toSpec(),uncertain:this.uncertain,approximate:this.approximate}}toJSON(){return this.toSpec()}}class TM extends EM{year=new Xi("year",-9999,9999,this.month);yearExtended=new Xi("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Qd=new TM;class po extends Ko{constructor(e,t=Qd.year){super(e,t)}static fromString(e,t=Qd.year,i=ri.get(po)){const n=i.parse(e),s=n.value.start;if(e.startsWith("Y")&&(t=Qd.yearExtended),s!==void 0){const r=new po(Object.assign({...n},{value:Math.max(s,t.min)})),a=new po(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new po(n,t)}}class _M extends Ep{monthValidator=new yx;validate(e){switch(e){case 21:case 22:case 23:case 24:return!0;default:return this.monthValidator.validate(e)}}}class fo extends Ko{constructor(e,t=new Xi(et.month.name,1,24,et.day,new _M)){super(e,t)}static fromString(e,t=ri.get(fo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=et.month;const r=new fo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new fo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new fo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class mo extends Ko{constructor(e,t=et.day){super(e,t)}static fromString(e,t=ri.get(mo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=et.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(e){return super.toString(e).padStart(2,"0")}}class go extends Ko{constructor(e,t=et.hour){super(e,t)}static fromString(e,t=ri.get(go)){const i=t.parse(e),n=i.value.start;if(n!==void 0){let s=et.hour;const r=new go(Object.assign({...i},{value:Math.max(n,s.min)})),a=new go(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new go(i)}}class vo extends Ko{constructor(e,t=et.minute){super(e,t)}static fromString(e,t=ri.get(vo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.minute,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(e=Fh.instance){return super.toString(e)}}class yo extends Ko{constructor(e,t=et.second){super(e,t)}static fromString(e,t=ri.get(yo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.second,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 lc extends oc{static fromString(e,t=ri.get(lc),i=void 0){return new lc(t.parse(e,i))}}class IM extends lg{constructor(e){super(e)}newYear(e){return new po(e,this.units.year)}newMonth(e){return new fo(e,this.units.month)}newDay(e){return new mo(e,this.units.day)}newHour(e){return new go(e,this.units.hour)}newMinute(e){return new vo(e,this.units.minute)}newSecond(e){return new yo(e,this.units.second)}newMillisecond(e){return new qo(e,this.units.millisecond)}newTimeshift(e){return new lc(typeof e=="number"?e:e.value)}}const Jx=new IM(Qd);new IM(cg);class to extends Bs{constructor(e){super(e)}get factory(){return Jx}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(e){return new to({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:Bs.timeshiftOf(e)})}static fromString(e,t=ri.get(to)){const i=t.parse(e);return new to(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return to.fromString(i)}clone(){return new to(this.toSpec())}}class Mc extends Ko{uncertainComponent;approximateComponent;constructor(e,t){super(e,t),this.uncertainComponent=e.uncertainComponent||!1,this.approximateComponent=e.approximateComponent||!1}get uncertain(){return super.uncertain||this.uncertainComponent}set uncertain(e){return super.uncertain=e}get approximate(){return super.approximate||this.approximateComponent}set approximate(e){return super.approximate=e}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 Qx extends TM{year=new Xi("year",Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,this.month)}const Am=new Qx;class bo extends Mc{constructor(e,t=Am.year){super(e,t)}static fromString(e,t=Am.year,i=ri.get(bo)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new bo(Object.assign({...n},{value:Math.max(s,t.min)})),a=new bo(Object.assign({...n},{value:Math.min(n.value.end,t.max)})),l={start:r,end:a},c=n.value.estimate;return c&&(l.estimate=c),l}else return new bo(n)}}class eS extends _M{validate(e){switch(e){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(e)}}}class Mo extends Mc{constructor(e,t=new Xi(et.month.name,1,41,et.day,new eS)){super(e,t)}static fromString(e,t=ri.get(Mo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.month,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(e){return super.toString(e).padStart(2,"0")}}class wo extends Mc{constructor(e,t=et.day){super(e,t)}static fromString(e,t=ri.get(wo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.day,r=new wo(Object.assign({...i},{value:Math.max(n,s.min)})),a=new wo(Object.assign({...i},{value:Math.min(i.value.end,s.max)}));return{start:r,end:a}}else return new wo(i)}toString(e){return super.toString(e).padStart(2,"0")}}class xo extends Mc{constructor(e,t=et.hour){super(e,t)}static fromString(e,t=ri.get(xo)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.hour,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)}}class So extends Mc{constructor(e,t=et.minute){super(e,t)}static fromString(e,t=ri.get(So)){const i=t.parse(e),n=i.value.start;if(n!==void 0){const s=et.minute,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)}}class Eo extends Mc{constructor(e,t=et.second){super(e,t)}static fromString(e,t=et.second,i=ri.get(Eo)){const n=i.parse(e),s=n.value.start;if(s!==void 0){const r=new Eo(Object.assign({...n},{value:Math.max(s,t.min)})),a=new Eo(Object.assign({...n},{value:Math.min(n.value.end,t.max)}));return{start:r,end:a}}else return new Eo(n,t)}}class DM extends lc{}class tS extends Fh{qualifier(){return""}}class ma extends Ap{static instance=new ma;static valueRenderer=new tS(Ir.default);static names=["year","month","day","hour","minute","second"];static qualifier(e,t){return e?t?"%":"?":t?"~":""}renderComponent(e,t){const i=e[t],n=ma.names.slice(ma.names.indexOf(t)+1).map(a=>e[a]).filter(Boolean),s=ma.qualifier(i.uncertainComponent,i.approximateComponent),r=ma.qualifier(i.uncertainGroup&&!i.uncertainComponent&&!n.some(a=>a.uncertain),i.approximateGroup&&!i.approximateComponent&&!n.some(a=>a.approximate));return s+i.toString(ma.valueRenderer)+r}}class RM extends lg{constructor(e){super(e)}newYear(e){return new bo(e,this.units.year)}newMonth(e){return new Mo(e,this.units.month)}newDay(e){return new wo(e,this.units.day)}newHour(e){return new xo(e,this.units.hour)}newMinute(e){return new So(e,this.units.minute)}newSecond(e){return new Eo(e,this.units.second)}newMillisecond(e){return new qo(e,this.units.millisecond)}newTimeshift(e){return new DM(typeof e=="number"?e:e.value)}}const iS=new RM(Am);new RM(cg);class io extends to{constructor(e){super(e)}toString(e=ma.instance){return super.toString(e)}get year(){return super.year}set year(e){super.year=e}get month(){return super.month}set month(e){super.month=e}get factory(){return iS}static fromDate(e){return new io({year:e.getFullYear(),month:e.getMonth()+1,day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),timeshift:Bs.timeshiftOf(e)})}static fromString(e,t=ri.get(io)){const i=t.parse(e);return new io(i)}static newInstance(){const e=new Date().toISOString(),t=e.indexOf("."),i=e.substring(0,t)+e.substring(t+4);return io.fromString(i)}clone(){return new io(this.toSpec())}}class Tp{regExp;constructor(e,t){this.name=e,this.regExp=new RegExp(`^(?:${t})$`)}regexGroups(e){const t=this.regExp.exec(e);if(!t)throw new Go(`Invalid ${this.name} "${e}"`);return t.groups}parseGroups(e){throw new Qa(`${this.constructor.name} is abstract`)}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}class dg extends Tp{constructor(e,t){super(e,t)}static read(e){return{value:e?parseInt(e,10):void 0}}parseGroups(e){return dg.read(e[this.name])}parse(e){if(e.startsWith("-"))throw new Go(`${this.name} cannot be negative`);return super.parse(e)}}class oe{static groupName(...e){return e.reduce((t,i)=>t?t+i.charAt(0).toUpperCase()+i.substring(1):i,"")}static group(e,...t){return`(?<${e}>${t.join("")})`}static optional(e){return e+"?"}static nonCapturingGroup(...e){return`(?:${e.join("")})`}static optionalGroup(e,...t){return oe.optional(oe.group(e,...t))}static optionalNonCapturingGroup(...e){return oe.optional(oe.nonCapturingGroup(...e))}static numberGroup(e,t,i,n="\\d"){return oe.group(e,`${i||""}[${n}]${t}`)}}const wv="timeshiftValue",xv="shiftHour",Sv="shiftMinute";class ug extends Tp{static format(e=""){return Mv.map(t=>t.name).join("|")+"|"+oe.nonCapturingGroup(oe.group(e+xv,oe.numberGroup(oe.groupName(e,wv),"{2}","[+-]")),oe.optionalNonCapturingGroup(":?",oe.numberGroup(oe.groupName(e,Sv),"{2}",void 0)))}constructor(){super(wv,ug.format())}parse(e,t){let i=0;const n=Mv.find(s=>s.name===e);if(n){if(typeof n.timeshift=="function")try{return n.timeshift(t??{})}catch(s){throw new Go(`The time zone ${e} depends on the date: ${s.message}`)}e=n.timeshift}if(e!=="Z"){const s=this.regexGroups(e),r=s[xv];r&&(i+=parseInt(r,10)*60);const a=s[Sv];a&&(i+=parseInt(a,10))}return i}}class xi extends dg{static uncertainGroup="uncertain";static approximateGroup="approx";static uncertainAndApproximateGroup=xi.uncertainGroup+xi.approximateGroup;constructor(e,t){super(e,t)}static qualifierFormat(e,t){return oe.optionalGroup(e,`\\${t}`)}static formatSuffix(e){return this.qualifierFormat(oe.groupName(xi.uncertainGroup,e),"?")+this.qualifierFormat(oe.groupName(xi.approximateGroup,e),"~")+this.qualifierFormat(oe.groupName(xi.uncertainAndApproximateGroup,e),"%")}static numberFormat(e,t,i){return oe.numberGroup(e,t,i,"\\dX")+this.formatSuffix(e)}getValueAndSign(e){let t=e[this.name],i;return t.charAt(0)==="-"?(i=-1,t=t.substring(1)):i=1,{valueStr:t,sign:i}}parseGroups(e){const{valueStr:t,sign:i}=this.getValueAndSign(e);let n=0,s;for(s=0;s<t.length;s++){const c=t[s];if(c==="X")break;n=n*10+parseInt(c,10)}if(s<t.length){let c=1;for(let u=0;u<t.length-s;u++)c*=10;const h=i*n*c,d=h+c-1;n={start:h,end:d}}else n*=i;const r=e[oe.groupName(xi.uncertainAndApproximateGroup,this.name)],a=e[oe.groupName(xi.approximateGroup,this.name)]||r,l=e[oe.groupName(xi.uncertainGroup,this.name)]||r;return{value:n,approximate:a?!!a:!1,uncertain:l?!!l:!1}}}const Ev="yearValue";class Su extends xi{constructor(){super(Ev,Su.format())}static format(e=""){return"Y?"+xi.numberFormat(oe.groupName(e,Ev),"+","[-]?")}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const Av="monthValue";class Eu extends xi{static format(e=""){return xi.numberFormat(oe.groupName(e,Av),"{1,2}",void 0)}constructor(){super(Av,Eu.format())}}const Tv="dayValue";class Au extends xi{static format(e=""){return xi.numberFormat(oe.groupName(e,Tv),"{1,2}",void 0)}constructor(){super(Tv,Au.format())}}const _v="hourValue";class Tu extends xi{static format(e=""){return xi.numberFormat(oe.groupName(e,_v),"{1,2}",void 0)}constructor(){super(_v,Tu.format())}}const Iv="minuteValue";class _u extends xi{static format(e=""){return xi.numberFormat(oe.groupName(e,Iv),"{1,2}",void 0)}constructor(){super(Iv,_u.format())}}const Dv="secondValue";class Iu extends xi{static format(e=""){return xi.numberFormat(oe.groupName(e,Dv),"{1,2}",void 0)}constructor(){super(Dv,Iu.format())}}class Du extends ug{}class Ki extends Tp{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(e=Ki.format()){super("date",e)}static format(e=""){return oe.group(oe.groupName(e,Ki.yearGroup),Su.format(e))+oe.optionalNonCapturingGroup("-",oe.group(oe.groupName(e,Ki.monthGroup),Eu.format(e)),oe.optionalNonCapturingGroup("-",oe.group(oe.groupName(e,Ki.dayGroup),Au.format(e)),oe.optionalNonCapturingGroup("[T ]",oe.group(oe.groupName(e,Ki.hourGroup),Tu.format(e)),":",oe.group(oe.groupName(e,Ki.minuteGroup),_u.format(e)),oe.optionalNonCapturingGroup(":",oe.group(oe.groupName(e,Ki.secondGroup),Iu.format(e)),oe.optionalNonCapturingGroup("[.,]",oe.group(oe.groupName(e,Ki.millisecondGroup),"\\d+"))),oe.optionalGroup(oe.groupName(e,Ki.timeshiftGroup),Du.format(e)))))}parseGroups(e){const t=e[Ki.millisecondGroup],i=t?qo.parseFraction(t):void 0,n=e[Ki.secondGroup],s=n?yo.fromString(n,new Iu):void 0,r=e[Ki.minuteGroup];let a;r&&(a=vo.fromString(r,new _u),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const l=e[Ki.hourGroup];let c;l&&(c=go.fromString(l,new Tu),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[Ki.dayGroup];let d;h&&(d=mo.fromString(h,new Au),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[Ki.monthGroup];let p;u&&(p=fo.fromString(u,new Eu),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[Ki.yearGroup];let g;f&&(g=po.fromString(f,void 0,new Su),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[Ki.timeshiftGroup],v=m?lc.fromString(m,new Du,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}class Bi extends xi{static uncertainGroup="uncertain1";static approximateGroup="approx1";static uncertainAndApproximateGroup=Bi.uncertainGroup+Bi.approximateGroup;constructor(e,t){super(e,t)}static numberFormat(e,t,i){return this.qualifierFormat(oe.groupName(Bi.uncertainGroup,e),"?")+this.qualifierFormat(oe.groupName(Bi.approximateGroup,e),"~")+this.qualifierFormat(oe.groupName(Bi.uncertainAndApproximateGroup,e),"%")+xi.numberFormat(e,t,i)}parseGroups(e){const t=super.parseGroups(e),i=e[oe.groupName(Bi.uncertainAndApproximateGroup,this.name)];return(e[oe.groupName(Bi.uncertainGroup,this.name)]||i)&&(t.uncertainComponent=!0),(e[oe.groupName(Bi.approximateGroup,this.name)]||i)&&(t.approximateComponent=!0),t}}const Ac="yearValue",Rv="exp",Cv="signif";class Ru extends Bi{constructor(){super(Ac,Ru.format())}static format(e=""){return"Y?"+oe.nonCapturingGroup(oe.group(oe.groupName(e,Rv),"[-]?\\d+E\\d+")+"|"+Bi.numberFormat(oe.groupName(e,Ac),"+","[-]?")+oe.optionalGroup(oe.groupName(e,Cv),"S\\d+"))}parseGroups(e){const t=e[Rv];if(t){const r=t.indexOf("E"),a=parseInt(t.substring(r+1),10),c=parseInt(t.substring(0,r),10)*Math.pow(10,a);e[Ac]=c.toString()}const i=e[Cv],n=e[Ac];if(i){const r=parseInt(i.substring(1),10),{valueStr:a,sign:l}=this.getValueAndSign(e);let c="";for(let h=0;h<a.length;h++)c+=h<r?a.charAt(h):"X";e[Ac]=(l<0?"-":"")+c}const s=super.parseGroups(e);return i&&(s.value.estimate=parseInt(n,10)),s}parse(e){const t=this.regexGroups(e);return this.parseGroups(t)}}const kv="monthValue";class Cu extends Bi{static format(e=""){return Bi.numberFormat(oe.groupName(e,kv),"{1,2}",void 0)}constructor(){super(kv,Cu.format())}}const Lv="dayValue";class ku extends Bi{static format(e=""){return Bi.numberFormat(oe.groupName(e,Lv),"{1,2}",void 0)}constructor(){super(Lv,ku.format())}}const Ov="hourValue";class Lu extends Bi{static format(e=""){return Bi.numberFormat(oe.groupName(e,Ov),"{1,2}",void 0)}constructor(){super(Ov,Lu.format())}}const Pv="secondValue";class Ou extends Bi{static format(e=""){return Bi.numberFormat(oe.groupName(e,Pv),"{1,2}",void 0)}constructor(){super(Pv,Ou.format())}}const Nv="minuteValue";class Pu extends Bi{static format(e=""){return Bi.numberFormat(oe.groupName(e,Nv),"{1,2}",void 0)}constructor(){super(Nv,Pu.format())}}class nS extends Du{}class Zi extends Tp{static yearGroup=Ki.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",Zi.format())}static format(e=""){return oe.group(oe.groupName(e,Zi.yearGroup),Ru.format(e))+oe.optionalNonCapturingGroup("-",oe.group(oe.groupName(e,Zi.monthGroup),Cu.format(e)),oe.optionalNonCapturingGroup("-",oe.group(oe.groupName(e,Zi.dayGroup),ku.format(e)),oe.optionalNonCapturingGroup("[T ]",oe.group(oe.groupName(e,Zi.hourGroup),Lu.format(e)),":",oe.group(oe.groupName(e,Zi.minuteGroup),Pu.format(e)),oe.optionalNonCapturingGroup(":",oe.group(oe.groupName(e,Zi.secondGroup),Ou.format(e)),oe.optionalNonCapturingGroup("[.,]",oe.group(oe.groupName(e,Zi.millisecondGroup),"\\d+"))),oe.optionalGroup(oe.groupName(e,Zi.timeshiftGroup),nS.format(e)))))}parseGroups(e){const t=e[Zi.millisecondGroup],i=t?qo.parseFraction(t):void 0,n=e[Zi.secondGroup];let s;n&&(s=Eo.fromString(n,void 0,new Ou),s.uncertain=s?.uncertain||!1,s.approximate=s?.approximate||!1);const r=e[Zi.minuteGroup];let a;r&&(a=So.fromString(r,new Pu),a.uncertain=a.uncertain||s?.uncertain||!1,a.approximate=a.approximate||s?.approximate||!1);const l=e[Zi.hourGroup];let c;l&&(c=xo.fromString(l,new Lu),c.uncertain=c.uncertain||a?.uncertain||!1,c.approximate=c.approximate||a?.approximate||!1);const h=e[Zi.dayGroup];let d;h&&(d=wo.fromString(h,new ku),d.uncertain=d.uncertain||c?.uncertain||!1,d.approximate=d.approximate||c?.approximate||!1);const u=e[Zi.monthGroup];let p;u&&(p=Mo.fromString(u,new Cu),p.uncertain=p.uncertain||d?.uncertain||!1,p.approximate=p.approximate||d?.approximate||!1);const f=e[Zi.yearGroup];let g;f&&(g=bo.fromString(f,void 0,new Ru),g.uncertain=g.uncertain||p?.uncertain||!1,g.approximate=g.approximate||p?.approximate||!1);const m=e[Zi.timeshiftGroup],v=m?DM.fromString(m,new Du,{year:g?.value,month:p?.value,day:d?.value,hour:c?.value}):void 0;return{year:g,month:p,day:d,hour:c,minute:a,second:s,millisecond:i,timeshift:v}}}const CM=["spring","summer","autumn","winter"],Tm=21,sS=32,rS=/^(?<hour>[01]?\d|2[0-3]):(?<minute>[0-5]\d)(?::(?<second>[0-5]\d))?[?~%]?$/;let aS;function oS(){return aS??=new Zi}function Qo(o){return typeof o?.value=="number"?o.value:void 0}function eu(o){const e=o.trim();if(/^\d{1,2}:/.test(e)){const r=rS.exec(e)?.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:e}:void 0}let t;try{t=io.fromString(e,oS())}catch{return}const i=Qo(t.year),n=Qo(t.month),s=n!==void 0&&n>=Tm&&n<=sS;if(!(t.timeshift||i!==void 0&&Math.abs(i)>9999)&&!(n!==void 0&&n>12&&!s)&&!(s&&(t.day||t.hour)))return{year:i,month:s?void 0:n,...s?{season:CM[(n-Tm)%4]}:{},day:Qo(t.day),hour:Qo(t.hour),minute:Qo(t.minute),second:Qo(t.second),raw:e}}function Ao(o){if(o.raw!==void 0)return o.raw;if(o.year===void 0){if(o.hour===void 0)return"";let t=`${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`;return o.second!==void 0&&(t+=`:${String(o.second).padStart(2,"0")}`),t}let e=String(o.year).padStart(4,"0");return o.season!==void 0?`${e}-${Tm+CM.indexOf(o.season)}`:(o.month===void 0||(e+=`-${String(o.month).padStart(2,"0")}`,o.day===void 0)||(e+=`-${String(o.day).padStart(2,"0")}`,o.hour===void 0)||(e+=`T${String(o.hour).padStart(2,"0")}:${String(o.minute??0).padStart(2,"0")}`,o.second!==void 0&&(e+=`:${String(o.second).padStart(2,"0")}`)),e)}function _m(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 Fv(o){return(((o.day??0)*24+(o.hour??0))*60+(o.minute??0))*6e4+(o.second??0)*1e3}const lS=["year","month","day","hour","minute"],cS=["day","hour","minute"];function Uv(o,e){return e.filter(t=>o[t]!==void 0).join(",")}function cc(o){if(o.durationSeconds!==void 0)return o.durationSeconds*1e3;const e=o.durationText===void 0?void 0:Nn.parse(o.durationText);if(e)return e.chosenSeconds*1e3;if(!o.time||!o.endTime)return;const t=o.time.year!==void 0&&o.endTime.year!==void 0,i=t?lS:cS,n=Uv(o.time,i);if(!(n===""||n!==Uv(o.endTime,i)))return t?_m(o.endTime)-_m(o.time):Fv(o.endTime)-Fv(o.time)}function hS(o){if(o.durationSeconds===void 0&&!(!o.time||!o.endTime))return cc(o)===void 0?"imprecise":void 0}class _p{constructor(e,t,i,n,s,r,a,l,c=[],h,d,u,p=[],f=[],g=[],m=[]){this.event=e,this.timeline=t,this.observerTrack=i,this.weatherTrack=n,this.soundTrack=s,this.observer=r,this.id=a,this.weather=l,this.decor=c,this.weatherSource=h,this.instrumentId=d,this.exposureSeconds=u,this.milestones=p,this.references=f,this.roads=g,this.traces=m}provenance=Un.empty();loadIssues=[];account;sources;interpretation;sway;lightPollution;observerMap;iso;vehicle;get observerCount(){return 1+this.decor.filter(e=>e.kind==="observer").length}get exposure(){return this.exposureSeconds??this.instrument.exposureSeconds}get instrument(){return Ut.byId(this.instrumentId)}static create(e,t,i){return new _p({eventType:"sighting",time:e,place:t},new xp,new bh,new Mh,new wh,i)}}const dS=0,uS=0;function ot(o,e){const t=o.observerTrack.getInterpolatedPoseAt(e);if(t)return t;const i=o.event.place?.[0];if(i)return{lat:i.lat,lng:i.lng,elevationM:dS,headingDeg:void 0,pitchDeg:uS,fovDeg:Ut.fieldOfViewDeg(o.instrument)}}function Fi(o,e){return o.weatherTrack.getInterpolatedWeatherAt(e)??o.weather??Sp}function $h(o,e){return o.weatherTrack.getActualWeatherAt(e)??o.weather??Sp}function pg(o,e){return o.soundTrack.getInterpolatedSoundAt(e)??gx}class xh{constructor(e,t){this.json=e,this.url=t,this.tracks=(e.events??[]).filter(i=>i.eventType===Ci.SIGHTING_EVENT&&typeof i.url=="string"&&i.url!=="").map(i=>({event:i,url:new URL(i.url,t).href,kind:i.interpretationOf===void 0?"observer":"reading"}))}tracks;caseChanged=!1;transcripts=new Map;static around(e,t,i,n,s){const r=(e.observer?.id??e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",a={id:e.id??"case",...t!==void 0?{time:t}:{},events:[{type:"event",eventType:Ci.SIGHTING_EVENT,...t!==void 0?{time:t}:{},...i!==void 0?{title:i}:{},url:`observer-${r}.json`}]},l=new xh(a,new URL("case.json",s).href),c=l.tracks[0];return c.recording=e,c.base={url:n},c.event.id=l.proposedId(c),l.caseChanged=!0,l}accountOf(e){if(e.kind!=="reading")return;const t=[e.event.interpretationOf].flat(),i=this.tracks.filter(n=>n.kind==="observer");return i.find(n=>n.event.id!==void 0&&t.includes(n.event.id))??i.find(n=>n.recording?.id!==void 0&&t.includes(n.recording.id))}get interviews(){return(this.json.events??[]).filter(e=>e.eventType===Ci.INTERVIEW_EVENT)}intervieweeOf(e){return this.intervieweesOf(e)[0]}intervieweesOf(e){const t=this.tracks.filter(i=>i.kind==="observer");return[e.interviewOf].flat().filter(i=>typeof i=="string").flatMap(i=>{const n=t.find(s=>s.event.id===i)??t.find(s=>s.recording?.id===i);return n?[n]:[]})}addInterview(e,t,i,n,s){const r=this.eventIds(),a=e?e.event.id??this.proposedId(e):"case";let l=1;for(;r.has(`interview-${a}-${l}`);)l++;const c={type:"event",eventType:Ci.INTERVIEW_EVENT,id:`interview-${a}-${l}`,...e?{interviewOf:this.ensureId(e)}:{},time:t,...s!==void 0?{medium:s}:{},...n!==void 0&&n.length>0?{by:n}:{},...i!==void 0?{title:i}:{}};return this.json.events=[...this.json.events??[],c],this.caseChanged=!0,c}transcriptText(e){return this.transcripts.get(e)?.text}keepTranscript(e,t){this.transcripts.set(e,{text:t,loaded:this.transcripts.get(e)?.loaded})}transcriptChanged(e){return e.loaded!==e.text}deleteInterview(e){return this.interviews.includes(e)?(this.json.events=(this.json.events??[]).filter(t=>t!==e),this.transcripts.delete(e),this.caseChanged=!0,!0):!1}keep(e,t,i=!1){e.recording=t,i&&(e.loaded=JSON.stringify(t)),e.kind==="reading"&&t.interpretation?.title!==void 0&&(e.event.title=t.interpretation.title)}replaceJson(e){const i=(e.events??[]).filter(s=>s.eventType===Ci.SIGHTING_EVENT&&typeof s.url=="string"&&s.url!=="").map(s=>{const r=new URL(s.url,this.url).href,a=s.interpretationOf===void 0?"observer":"reading",l=this.tracks.find(c=>c.url===r);return l?(l.event=s,l.kind=a,l):{event:s,url:r,kind:a}});this.tracks.splice(0,this.tracks.length,...i);const n=new Map;for(const[s,r]of this.transcripts){const a=(e.events??[]).find(l=>l.eventType===Ci.INTERVIEW_EVENT&&(s.id!==void 0&&l.id===s.id||s.url!==void 0&&l.url===s.url));a&&n.set(a,r)}this.transcripts.clear();for(const[s,r]of n)this.transcripts.set(s,r);this.json=e,this.caseChanged=!0}touch(){this.caseChanged=!0}get dirty(){return this.caseChanged||this.tracks.some(e=>this.changed(e))||[...this.transcripts.values()].some(e=>this.transcriptChanged(e))}markExported(e){if(this.caseChanged=!1,!!e){for(const t of this.tracks)t.recording&&(t.loaded=JSON.stringify(t.recording));for(const t of this.transcripts.values())t.loaded=t.text}}changed(e){return e.recording!==void 0&&(e.loaded===void 0||JSON.stringify(e.recording)!==e.loaded)}static ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]*$/;eventIds(e){return new Set((this.json.events??[]).filter(t=>t!==e?.event).map(t=>t.id).filter(t=>t!==void 0))}proposedId(e){const t=a=>(a??"").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),i=typeof e.event.title=="string"?e.event.title:void 0,n=t(e.recording?.observer?.lastName)||t(e.recording?.observer?.id)||t(i),s=this.eventIds(e);if(n!==""){let a=n;for(let l=2;s.has(a);l++)a=`${n}-${l}`;return a}let r=1;for(;s.has(`sighting-${r}`);)r++;return`sighting-${r}`}ensureId(e){return e.event.id===void 0&&(e.event.id=this.proposedId(e),this.caseChanged=!0),e.event.id}setId(e,t){const i=e.event.id,n=a=>a===i||a===e.recording?.id,s=(this.json.events??[]).filter(a=>a.eventType===Ci.SIGHTING_EVENT&&a.interpretationOf!==void 0&&[a.interpretationOf].flat().some(l=>l!==void 0&&n(l))),r=this.interviews.filter(a=>[a.interviewOf].flat().some(l=>l!==void 0&&n(l)));if(t==="")return i===void 0?"ok":s.length>0||r.length>0?"empty":(delete e.event.id,this.caseChanged=!0,"ok");if(!xh.ID_PATTERN.test(t))return"invalid";if(this.eventIds(e).has(t))return"taken";if(t===i)return"ok";for(const a of s){const l=[a.interpretationOf].flat().map(c=>n(c)?t:c);a.interpretationOf=Array.isArray(a.interpretationOf)?l:l[0]}for(const a of r){const l=[a.interviewOf].flat().map(c=>c!==void 0&&n(c)?t:c);a.interviewOf=Array.isArray(a.interviewOf)?l:l[0]}return e.event.id=t,this.caseChanged=!0,"ok"}problems(){return Ci.problems(this.json,this.tracks.map(e=>e.recording?.id).filter(e=>e!==void 0))}addReading(e,t,i,n){const s=e.recording;if(!s)throw new Error("A reading is added to an account that has been loaded");const r=e.event.url.replace(/^.*\//,"").replace(/^observer-/,"").replace(/\.json$/,""),a=new Set(this.tracks.map(I=>I.event.url)),l=new Set(this.tracks.map(I=>I.recording?.id));let c=this.tracks.filter(I=>I.kind==="reading").length+1;for(;a.has(`interpretation-${r}-${c}.json`)||l.has(`${s.id??r}-interpretation-${c}`);)c++;const h=`interpretation-${r}-${c}.json`,d=e.event.url.includes("/")?e.event.url.replace(/[^/]*$/,""):"",{id:u,version:p,observer:f,account:g,description:m,sources:v,tags:b,timeline:M,milestones:y,interpretation:x,...S}=structuredClone(s),A={version:1,id:`${s.id??r}-interpretation-${c}`,...S,tags:["interpretation"],timeline:{keyframes:[],order:[],groups:[]},interpretation:{...i!==void 0?{title:i}:{},bodies:[]}},w={type:"event",eventType:"sighting",interpretationOf:this.ensureId(e),time:t,...n!==void 0&&n.length>0?{by:n}:{},...i!==void 0?{title:i}:{},url:d+h};this.json.events=[...this.json.events??[],w],this.caseChanged=!0;const T={event:w,url:new URL(w.url,this.url).href,kind:"reading",recording:A};return this.tracks.push(T),T}idsOf(e){return[e.event.id,e.recording?.id].filter(t=>t!==void 0)}readingsOf(e){const t=this.idsOf(e);return this.tracks.filter(i=>i.kind==="reading"&&[i.event.interpretationOf].flat().some(n=>n!==void 0&&t.includes(n)))}addObservation(e,t,i,n){const s=new Set(this.tracks.map(g=>g.event.url)),r=new Set(this.tracks.map(g=>g.recording?.id)),a=(e.id??"observation").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation",l=n?"interpretation":"observer";let c=`${l}-${a}.json`,h=e.id??a;for(let g=2;s.has(c)||r.has(h);g++)c=`${l}-${a}-${g}.json`,h=`${e.id??a}-${g}`;const d={...e,id:h},u=this.tracks[0]?.event.url?.includes("/")?this.tracks[0].event.url.replace(/[^/]*$/,""):"",p={type:"event",eventType:"sighting",...n?{interpretationOf:this.ensureId(n.account)}:{},...t!==void 0?{time:t}:{},...n?.by&&n.by.length>0?{by:n.by}:{},...i!==void 0?{title:i}:{},url:u+c};this.json.events=[...this.json.events??[],p],this.caseChanged=!0;const f={event:p,url:new URL(p.url,this.url).href,kind:n?"reading":"observer",recording:d};return this.tracks.push(f),n||(p.id=this.proposedId(f)),f}deleteObservation(e){if(e.kind!=="observer")return{deleted:!1,readings:0};const t=this.readingsOf(e).length;if(t>0)return{deleted:!1,readings:t};const i=this.tracks.indexOf(e);return i<0?{deleted:!1,readings:0}:(this.tracks.splice(i,1),this.json.events=(this.json.events??[]).filter(n=>n!==e.event),this.caseChanged=!0,{deleted:!0})}deleteReading(e){if(e.kind!=="reading")return!1;const t=this.tracks.indexOf(e);return t<0?!1:(this.tracks.splice(t,1),this.json.events=(this.json.events??[]).filter(i=>i!==e.event),this.caseChanged=!0,!0)}files(e=!0,t=!1){const i=this.url.replace(/[^/]*$/,""),n=l=>l.startsWith(i)?l.slice(i.length):l,s=this.tracks.filter(l=>e&&l.recording!==void 0&&(t||this.changed(l))).map(l=>({path:n(l.url),content:JSON.stringify(l.recording,null,2)+`
3
3
  `})),r=decodeURIComponent(this.url.replace(/[?#].*$/,"").replace(/^.*\//,""))||"case.json",a=[...this.transcripts].filter(([l,c])=>e&&l.url!==void 0&&(t||this.transcriptChanged(c))).map(([l,c])=>({path:n(new URL(l.url,this.url).href),content:c.text}));return[{path:r,content:JSON.stringify(this.json,null,2)+`
4
4
  `},...s,...a]}}class ln{constructor(e,t,i,n="en"){this.parts=e,this.messages=t,this.onChange=i,this.locale=n,this.setMessages(t),e.text.addEventListener("input",()=>{this.readText(),this.showDeduction()}),e.picker.addEventListener("change",()=>this.writeFromPicker()),e.mode.addEventListener("click",()=>this.setPrecise(!this.precise)),e.text.addEventListener("blur",()=>this.validate()),e.text.addEventListener("focus",()=>this.showDeduction())}precise=!0;hint="";get isPrecise(){return this.precise}setMessages(e,t=this.locale){this.messages=e,this.locale=t,e.edtfPlaceholder!==void 0&&(this.parts.text.placeholder=e.edtfPlaceholder),this.parts.mode.title=e.edtfModeTitle,this.parts.mode.setAttribute("aria-label",e.edtfModeTitle),this.setPrecise(this.precise)}setPrecise(e){this.precise=e,this.parts.picker.hidden=!e,this.parts.text.hidden=e,this.parts.mode.textContent=e?this.messages.datePrecise:this.messages.dateEdtf,this.parts.mode.setAttribute("aria-pressed",String(!e)),this.parts.help&&(this.parts.help.hidden=e),this.showDeduction()}set(e){const{text:t,picker:i}=this.parts;t.value=e?Ao(e):"",i.type!=="date"&&(i.step=ln.stepFor(e)),i.value=i.type==="date"?ln.pickerDateOf(e):ln.pickerValueOf(e),t.setCustomValidity(""),t.classList.remove("invalid"),this.showDeduction()}static opensPrecise(...e){return e.every(t=>t===void 0||ln.isPickable(t)&&ln.qualifierOf(Ao(t))==="")}static opensPreciseDate(...e){return e.every(t=>t===void 0||ln.isFullDate(t)&&ln.qualifierOf(Ao(t))==="")}static isFullDate(e){return!!e&&e.year!==void 0&&e.month!==void 0&&e.day!==void 0}static pickerDateOf(e){if(!ln.isFullDate(e))return"";const t=(i,n=2)=>String(i).padStart(n,"0");return`${t(e.year,4)}-${t(e.month)}-${t(e.day)}`}static isPickable(e){return!!e&&e.year!==void 0&&e.month!==void 0&&e.day!==void 0&&e.hour!==void 0&&e.minute!==void 0}static pickerValueOf(e){if(!ln.isPickable(e))return"";const t=(n,s=2)=>String(n).padStart(s,"0"),i=e.second?`:${t(e.second)}`:"";return`${t(e.year,4)}-${t(e.month)}-${t(e.day)}T${t(e.hour)}:${t(e.minute)}${i}`}static stepFor(e){return e?.second?"1":"60"}static qualifierOf(e){const t=/[?%]/.test(e),i=/[~%]/.test(e);return t&&i?"%":t?"?":i?"~":""}describe(e){return ln.describeTime(e,this.messages,this.locale)}static describeTime(e,t,i){const n=Ao(e),s=ln.qualifierOf(n),r=h=>String(h).padStart(2,"0"),a=[];if(e.season!==void 0){const h={spring:t.timeSeasonSpring,summer:t.timeSeasonSummer,autumn:t.timeSeasonAutumn,winter:t.timeSeasonWinter}[e.season];a.push(e.year!==void 0?`${h} ${e.year}`:h)}else if(e.year!==void 0){const h=e.day!==void 0?{...e.year>=1583?{weekday:"long"}:{},year:"numeric",month:"long",day:"numeric"}:e.month!==void 0?{year:"numeric",month:"long"}:{year:"numeric"},d=new Date(Date.UTC(e.year,(e.month??1)-1,e.day??1));a.push(new Intl.DateTimeFormat(i,{...h,timeZone:"UTC"}).format(d))}e.hour!==void 0&&a.push(`${r(e.hour)}:${r(e.minute??0)}${e.second!==void 0?`:${r(e.second)}`:""}`);const l=a.join(", "),c=s==="~"?t.timeQualifierApproximate:s==="?"?t.timeQualifierUncertain:s==="%"?t.timeQualifierBoth:"";return c?`${l} — ${c.toLowerCase()}`:l}setHint(e){this.hint=e,this.showDeduction()}showDeduction(){const{text:e}=this.parts,t=e.value.trim();if(this.precise||t===""){e.title=this.hint;return}const i=eu(t);e.title=i?`→ ${this.describe(i)}`:this.messages.edtfInvalid}readText(){const e=this.parts.text.value.trim();if(e===""){this.clean(),this.onChange(void 0);return}const t=eu(e);t&&(this.clean(),this.onChange(t))}clean(){this.parts.text.setCustomValidity(""),this.parts.text.classList.remove("invalid")}writeFromPicker(){const{picker:e,text:t}=this.parts;e.value===""&&e.validity.badInput||(t.value=e.value===""?"":e.value.replace(/\.\d+$/,""),this.readText())}validate(){const{text:e}=this.parts,t=e.value.trim();t===""||eu(t)||(e.setCustomValidity(this.messages.edtfInvalid),e.classList.add("invalid"))}}const pS={color:"Color",transparency:"Transparency",halo:"Halo",blur:"Blur",brightness:"Brilliance",shapeTitle:"Name",utcOffset:"Time zone",cloudBase:"Cloud base",elevation:"Altitude",heightAboveGround:"Height above ground",duration:"Duration",placeName:"Place",latitude:"Latitude",longitude:"Longitude",heading:"Heading",pitch:"Tilt",roll:"Roll",sway:"Sway at rest",swayTitle:"How much the body holding the instrument moves the view when not walking: 1 for a person standing, 0 for a tripod. Blank: 1 (0 if the account says the observer was paralysed)",lightPollution:"Night sky",lightPollutionTitle:'The zenith of a moonless night at this place, in magnitudes per square arcsecond, as a Sky Quality Meter reads it or as the World Atlas of artificial sky brightness (Falchi et al. 2016, lightpollutionmap.info, "SQM") gives it. 22 is a natural sky; a suburb is about 19, a city centre 17. Blank: a natural sky',observationTime:"Observation start",observationEndTime:"Observation end",assessmentGroup:"Assessment",assessmentNames:{coverage:"Observer info"},assessmentVerdicts:{"hynek.nl":"NL — nocturnal light","hynek.dd":"DD — daylight disc","hynek.rv":"RV — radar-visual","hynek.ce1":"CE1 — close encounter","hynek.ce2":"CE2 — with a physical trace","hynek.ce3":"CE3 — with entities"},timeQualifierApproximate:"Approximate",timeQualifierUncertain:"Uncertain",timeQualifierBoth:"Uncertain and approximate",timeSeasonSpring:"Spring",timeSeasonSummer:"Summer",timeSeasonAutumn:"Autumn",timeSeasonWinter:"Winter",summaryGroups:{observation:"Observation",location:"Position",temporal:"Time",weather:"Weather",sound:"Sound"},summaryGroup:"Summary",summaryDescription:"Description",closeDescription:"Close the description",observerGroup:"Observer",observerId:"ID",observerTitle:"Title",observerLastName:"Last name",observerFirstNames:"First names",sightingId:"ID",tags:"Tags",cloudCover:"Cloud cover",highCloudCover:"Ice cloud (cirrus)",focalLength:"Focal length",fieldOfView:"Field of view",aperture:"Aperture",exposure:"Exposure",focusDistance:"Focused at",iceCrystalAlignment:"Crystal alignment",rareIceCrystals:"Rare crystals",cloudDarkness:"Cloud darkness",precipitationType:"Precipitation",precipitationNone:"None",precipitationRain:"Rain",precipitationSnow:"Snow",precipitationHail:"Hail",precipitationIntensity:"Intensity",windDirection:"Wind direction",windSpeed:"Wind speed",storm:"Storm",cloudsGroup:"Clouds",precipitationGroup:"Precipitation",windGroup:"Wind",soundKind:"Sound",soundNone:"None (silent)",soundHum:"Hum",soundWhistle:"Whistle",soundRumble:"Rumble",soundCrackle:"Crackle",soundVolume:"Loudness",soundPitch:"Pitch",soundSrc:"Recording",instrument:"Observed through",filter:"In front of it",filterNone:"nothing",filterSolarVisual:"a solar filter for the eye (eclipse glasses, density 5)",filterSolarPhoto:"a solar film for a camera (density 3.8)",decorAircraft:"Aircraft",decorEntity:"Being",decorAltitude:"Altitude",decorLights:"Lights",decorLightsNone:"none",decor:"Environment",decorBuilding:"Building",decorTree:"Tree",decorShrub:"Shrub",decorBridge:"Bridge",decorWire:"Overhead line",decorCrop:"Crop row",decorTerrace:"Terrace (restanque)",decorMound:"Stone heap",decorWall:"Dry-stone wall",decorStreetlight:"Streetlight",decorVehicle:"Vehicle",decorObserver:"Other observer",decorEast:"Distance east",decorNorth:"Distance north",decorHeading:"Heading",decorColor:"Colour",decorLit:"Lit",decorTitle:"Name",milestones:"Moments",milestoneLabel:"Label",milestoneNote:"What happens",addMilestone:"Name this moment",deleteMilestone:"Delete moment",goToMilestone:"Go to this moment",decorWidth:"Width",decorLength:"Length",decorHeight:"Height",decorModel:"3D model",decorModelAdvanced:"Model from an address",decorModelUrl:"glTF/GLB address",decorModelTitle:"Model name",decorModelAuthor:"Author",decorModelLicense:"Licence",decorModelSource:"Where it came from",decorObserverSide:"Observer location",decorObserverSideNone:"Not present",decorSideFront:"Front",decorSideBehind:"Behind",decorSideLeft:"Left",decorSideRight:"Right",decorSideFrontLeft:"Front-left",decorSideFrontRight:"Front-right",decorSideBehindLeft:"Behind-left",decorSideBehindRight:"Behind-right"},ka={...pS,oval:"Oval",polygon:"Polygon",addVertex:"Add vertex",deleteVertex:"Delete vertex",notAPolygon:"Select a single polygon shape",tooFewVertices:"A shape needs at least 3 points",shape:"Shape",apparentWidth:"Apparent width",realWidth:"Real width",distance:"Distance",sizeLock:"Hold",lockNone:"nothing",lockApparent:"the apparent width",lockReal:"the real width",lockDistance:"the distance",apparentSize:"{moons}× the Moon",utcOffsetPlaceholder:"from longitude",realSizeBetween:"The scene bounds that width: between {min} and {max} m, from what it crosses",realSizeAtLeast:"The scene bounds that width: at least {min} m, from what it passes behind",realSizeAtMost:"The scene bounds that width: at most {max} m, from what it passes in front of",realSizeUnknown:"Nothing in the scene bounds that width: it is only what the distance implies",realSizeOutside:" — the width above is outside that",blurBound:"Blurred through this lens: nearer than {max} m",blurBoundNoInstrument:"Blur through the naked eye bounds no distance — an eye has no aperture to be out of focus with",blurBoundNotAtInfinity:"Blur bounds a distance only for a lens focused at infinity: this one is focused at {focus} m, which blurs on both sides of it",realSizeContradiction:"Contradiction: the declared crossings cannot all be true",realDistanceHere:" — i.e. between {min} and {max} m here",clearDistanceHypothesis:"Withdraw the distance hypothesis",clearDistanceHypothesisTitle:"Back to what the recording establishes",depthStated:"Drawn at {m} m, as the recording states",depthHypothesis:"Drawn at {m} m: your hypothesis — what the decor hides of it is what a thing that far would lose",depthDerived:"Drawn at {m} m, from the observer's own walk",depthBounded:"Drawn at {m} m, from what it passes behind and in front of",depthConventional:"Drawn at {m} m by convention: nothing in the recording establishes a distance",addShape:"Add shape",deleteShape:"Delete shape",play:"Play",pause:"Pause",noDuration:"No observation duration",previousKeyframe:"Previous keyframe",nextKeyframe:"Next keyframe",keyframeMark:"Keyframe",shapesTrack:"shapes",observerTrack:"observer",weatherTrack:"weather",soundTrack:"sound",group:"Group",ungroup:"Ungroup",bringToFront:"Bring to front",sendToBack:"Send to back",contextMenuDelete:"Delete",onlyOneShape:"There is only one shape",alreadyAtFront:"This shape is already at the front",alreadyAtBack:"This shape is already at the back",needTwoShapesToGroup:"Select at least two shapes to group them",notGrouped:"This shape isn't part of a group",multipleShapesSelected:"Multiple shapes selected — select just one to edit this",samplingRate:"Sampling rate",currentPosition:"Current position",switchToElapsed:"click to show elapsed time",switchToClockTime:"click to show the time of day",durationPlaceholder:"observation length",durationImprecise:"These dates don't precisely enough determine a duration — enter it manually.",export:"Save",identityHint:"Name someone only if they agreed to it or published their own account; otherwise initials are enough.",identityAsk:"This recording names or locates a person. You answer for what you publish: name someone only if they agreed to it, or published their own account. Otherwise initials are enough.",identityLastName:"Last name: {value}",identityFirstNames:"First name: {value}",identityNameInId:"Name in an identifier: {value}",identityNameInText:"Name in the text: {value}",identityAddress:"Address: {value}",identityEmail:"E-mail address: {value}",identityPhone:"Telephone number: {value}",identityInitials:"Replace with initials",identityKeep:"Save anyway",identityBack:"Go back",importFile:"Load JSON file",importUrl:"Or load from URL",importUrlPlaceholder:"https://…/sighting.json",importButton:"Load",importError:"Couldn't load that recording — check the file or URL and try again.",importErrorCors:'That address answers, but the browser is not allowed to read it from this page. The file itself is fine — its server needs to send the header "Access-Control-Allow-Origin: *" with it. If it is not your server, that is what to ask its administrator for.',importErrorMixedContent:"A secure page cannot load an address starting with http://. Use https:// if that server offers it.",importErrorUnreachable:"Nothing answered at that address. Check the spelling, and that you are online.",importErrorStatus:"That server answered with an error ({status}). The address is probably wrong, or the file has moved.",importErrorMalformed:"That address answered, but what came back is not a recording.",record:"Record",stop:"Stop",according:"according to",sourceElevation:"Relief",sourceImagery:"Imagery",sourceAircraft:"Air traffic",placeNamePlaceholder:"Valensole, France",searchPlace:"Locate",placeMatch:"Matches",placeSearching:"Looking up the place…",placeMatchFound:"place found",placeMatchesFound:"places found",placeNotFound:"No place by that name",placeSearchFailed:"Place search temporarily unavailable",utcOffsetNoZone:"No time zone reads this offset on that day",utcOffsetImplausible:"This time zone doesn't match the longitude entered, whose own solar time is UTC{solar} — yet the scene and the weather record both obey what is declared here. Clear the field to derive it from the longitude.",timeZoneManual:"unknown",altitudeAboveSeaLevel:"The observer's altitude above sea level — the ground at the location entered sets its floor: an observer in the Alps is not at 0 m.",groundAt:"ground at {m} m",headingPlaceholder:"unknown",edtfInvalid:"Not a valid EDTF date/time (e.g. 1965-07-01T05:00, 2025-06?, 2025~).",edtfPlaceholder:"YYYY-MM-DDThh:mm[?~%] or hh:mm",observationTimeHint:"EDTF — e.g. 1965-07-01T05:00, 2025-06? (uncertain), 2025~ (approximate), or just 05:00 if the date isn't known",observationEndTimeHint:"EDTF — e.g. 1965-07-01T05:10, 2025-06? (uncertain), 2025~ (approximate), or just 05:10 if the date isn't known",presetsGroupLabel:"UFO shape",description:"Description",tagsPlaceholder:"comma-separated",weather:"Weather",shapeGroup:"Phenomenon",shapesSubgroup:"Shapes",bodiesSubgroup:"Bodies",launchesSubgroup:"Launches",soundGroup:"Sound",temporalGroup:"Time",fileGroup:"File",fileLoading:"Loading the editor…",weatherEditedAsk:"This edit touches the weather, data read dynamically from {source}. Stop reading it from {source}?",weatherEditedStop:"Stop reading it",weatherEditedKeep:"Keep reading it (undo my edit)",fileEditorLabel:"The recording as JSON text",fileSearchPhrases:{},timeQualifierExact:"Exact",durationPrecise:"precise",durationIso:"imprecise",durationModeTitle:"Say the length exactly, or as stated: about, between two lengths",durationInvalid:"Not a duration: PT10M, PT1H30M, PT5M/PT10M…",durationHelpTitle:"What the text takes (EDTF)",durationHelpLines:`PT45S — 45 seconds
@@ -3015,7 +3015,7 @@ canvas[data-cursor="rotate"] {
3015
3015
  `;class Yl{constructor(e){this.points=e}static STATIONARY_M=5;static of(e){const t=[];for(const i of e.observerTrack.allKeyframes){const{lat:n,lng:s,headingDeg:r}=i.pose;n===void 0||s===void 0||t.push({t:i.t,lat:n,lng:s,headingDeg:r})}if(t.length===0){const i=e.event.place?.[0];if(!i)return;t.push({t:0,lat:i.lat,lng:i.lng})}return new Yl(t)}static TRAVEL_M=50;get travels(){return this.spanM>Yl.TRAVEL_M}get moved(){return this.spanM>Yl.STATIONARY_M}get spanM(){const e=this.box,t=(e.south+e.north)/2,i=(e.west+e.east)/2;return Math.max(Math.abs(yt(t,e.east,t,e.west).x),Math.abs(yt(e.north,i,e.south,i).z))}get center(){const e=this.box;return{lat:(e.south+e.north)/2,lng:(e.west+e.east)/2}}boundsAround(e,t){const{lat:i,lng:n}=this.center,s=Math.max(this.spanM*(1+t),e)/2;return{north:fs(0,-s,i,n).lat,south:fs(0,s,i,n).lat,east:fs(s,0,i,n).lng,west:fs(-s,0,i,n).lng}}get box(){const e=this.points.map(i=>i.lat),t=this.points.map(i=>i.lng);return{south:Math.min(...e),north:Math.max(...e),west:Math.min(...t),east:Math.max(...t)}}}class ws{constructor(e,t){this.rotationPassed=e,this.scale=t}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(e){const t=e.event.tags?.includes("paralysis")||(e.exposure??0)>ws.HAND_HELD_S,i=e.sway??(t?0:1);if(i>0)return new ws(Math.max(1-(e.instrument.stabilization??0),ws.GAZE_DRIFT_SHARE),i)}offsetAt(e){const t=e/1e3,i=this.scale,n=(d,u)=>Math.sin(2*Math.PI*d*t+u),[s,r,a,l,c,h]=ws.HZ;return{eastM:i*ws.SWAY_M*(.7*n(s,.3)+.3*n(l,1.9)),northM:i*ws.SWAY_M*(.6*n(a,2.2)+.4*n(c,.8)),upM:i*ws.BREATH_M*n(r,0),yawDeg:i*this.rotationPassed*ws.DRIFT_YAW_DEG*(.6*n(h,1.1)+.4*n(l,2.7)),pitchDeg:i*this.rotationPassed*ws.DRIFT_PITCH_DEG*(.5*n(r,1.6)+.5*n(a,.4)),rollDeg:i*this.rotationPassed*ws.DRIFT_ROLL_DEG*n(s,2.9)}}}class Yt{constructor(e,t){this.stretches=e,this.rotationPassed=t}static REFERENCE_SPEED_M_PER_S=1.4;static REFERENCE_STEP_HZ=1.9;static CADENCE_EXPONENT=.43;static RISE_M_PER_M_PER_S=.0175;static SWAY_M=.0175;static SLOWEST_WALK_M_PER_S=.2;static FASTEST_WALK_M_PER_S=2.2;static HEAD_ROLL_DEG=1.5;static HEAD_PITCH_DEG=1.25;static HEAD_YAW_DEG=1;static 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(e){const t=Yl.of(e);if(!t||t.points.length<2)return;const i=[];let n=0;for(let s=1;s<t.points.length;s++){const r=t.points[s-1],a=t.points[s],l=(a.t-r.t)/1e3;if(l<=0)continue;const c=yt(a.lat,a.lng,r.lat,r.lng),h=c.x,d=-c.z,u=Math.hypot(h,d),p=u/l,f=Yt.stepHzFor(p);i.push({startMs:r.t,endMs:a.t,speedMPerS:p,eastUnit:u>0?h/u:0,northUnit:u>0?d/u:0,stepHz:f,stepsBefore:n,rampsIn:!0,rampsOut:!0}),n+=f*l}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 Yt(i,1-(e.instrument.stabilization??0))}static bodyAt(e,t,i=!1){const n=Yt.of(e)?.offsetAt(t)??Yt.STILL;return i?n:Yt.add(n,ws.of(e)?.offsetAt(t))}static stepHzFor(e){return e<Yt.SLOWEST_WALK_M_PER_S||e>Yt.FASTEST_WALK_M_PER_S?0:Yt.REFERENCE_STEP_HZ*Math.pow(e/Yt.REFERENCE_SPEED_M_PER_S,Yt.CADENCE_EXPONENT)}offsetAt(e){return Yt.add(this.cycleAt(e),this.joltAt(e))}joltAt(e){for(const t of this.stretches){if(t.stepHz===0)continue;const i=t.speedMPerS/Yt.REFERENCE_SPEED_M_PER_S,n=(a,l,c,h)=>{if(a<0||a>Yt.JOLT_LASTS_MS)return;const d=a/1e3,u=Math.exp(-d/Yt.JOLT_DECAY_S)*Math.sin(2*Math.PI*Yt.JOLT_HZ*d),p=h*l*i*u;return{eastM:p*t.eastUnit,northM:p*t.northUnit,upM:-Math.abs(p)*.3,rollDeg:0,pitchDeg:-h*c*i*u*this.rotationPassed,yawDeg:0}},s=t.rampsOut?n(e-t.endMs,Yt.STOP_LURCH_M,Yt.STOP_PITCH_DEG,1):void 0;if(s)return s;const r=t.rampsIn?n(e-t.startMs,Yt.START_LURCH_M,Yt.START_PITCH_DEG,-1):void 0;if(r)return r}}static add(e,t){return t?{eastM:e.eastM+t.eastM,northM:e.northM+t.northM,upM:e.upM+t.upM,rollDeg:e.rollDeg+t.rollDeg,pitchDeg:e.pitchDeg+t.pitchDeg,yawDeg:e.yawDeg+t.yawDeg}:e}cycleAt(e){const t=this.stretches.find(l=>e>=l.startMs&&e<=l.endMs);if(!t||t.stepHz===0)return Yt.STILL;const i=t.stepsBefore+t.stepHz*(e-t.startMs)/1e3,n=2*Math.PI*i,s=this.amplitudeAt(t,e),r=Yt.SWAY_M*s*Math.cos(n/2),a=s*this.rotationPassed*t.speedMPerS/Yt.REFERENCE_SPEED_M_PER_S;return{eastM:r*t.northUnit,northM:-r*t.eastUnit,upM:Yt.RISE_M_PER_M_PER_S*t.speedMPerS*s*Math.cos(n),rollDeg:Yt.HEAD_ROLL_DEG*a*Math.cos(n/2),pitchDeg:-1.25*a*Math.cos(n),yawDeg:Yt.HEAD_YAW_DEG*a*Math.cos(n/2)}}amplitudeAt(e,t){const i=1e3/e.stepHz,n=Math.min(i,(e.endMs-e.startMs)/2);if(n<=0)return 1;const s=t-e.startMs,r=e.endMs-t,a=Math.min(e.rampsIn?s/n:1,e.rampsOut?r/n:1,1);return(1-Math.cos(Math.PI*Math.max(a,0)))/2}}class jS{constructor(e,t){this.timeline=e,this.onFrame=t}rafId=null;state="stopped";currentT=0;lastWallTime=0;playbackRate=1;loop=!1;onEnded;durationOverrideMs=0;get seekableDuration(){return Math.max(this.timeline.duration,this.durationOverrideMs)}play(){if(this.state==="playing")return;this.currentT>=this.seekableDuration&&(this.currentT=0,this.resolveFrame(0)),this.state="playing",this.lastWallTime=performance.now();const e=()=>{if(this.state!=="playing")return;const t=performance.now();if(this.currentT+=(t-this.lastWallTime)*this.playbackRate,this.lastWallTime=t,this.currentT>=this.seekableDuration){if(this.loop&&this.seekableDuration>0){this.currentT%=this.seekableDuration,this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e);return}this.currentT=this.seekableDuration,this.stop(),this.resolveFrame(this.currentT),this.onEnded?.();return}this.resolveFrame(this.currentT),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}pause(){this.state==="playing"&&(this.state="paused",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null))}stop(){this.state="stopped",this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}seek(e){this.currentT=Math.max(0,Math.min(e,this.seekableDuration)),this.resolveFrame(this.currentT)}get playbackState(){return this.state}get time(){return this.currentT}resolveFrame(e){const t=new Map;for(const i of this.timeline.sourceIds){const n=this.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}this.onFrame(e,t)}}class Oo{static sessionDeclared=!1;static unlock(e){if(Oo.declarePlayback(),e.state!=="running")try{Promise.resolve(e.resume()).catch(()=>{});const t=e.createBufferSource();t.buffer=e.createBuffer(1,1,22050),t.connect(e.destination),t.start(0)}catch{}}static declarePlayback(){if(!(Oo.sessionDeclared||typeof navigator>"u")){Oo.sessionDeclared=!0;try{const e=navigator.audioSession;e&&(e.type="playback")}catch{}}}}const e1=.05,t1=.08,i1=2,n1=3,JS=14,QS=.02;class eE{context;voice;voiceToken=0;buffers=new Map;noiseBuffer;crackleBuffer;requested;level=1;master;output(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("SightingAudio: Web Audio unavailable, the sighting stays silent:",e);return}}Oo.unlock(this.context)}setSound(e){if(this.requested=e,!this.context)return;const t=this.keyFor(e);if(!t){this.silence();return}if(this.voice?.key!==t){this.stopVoice();const i=++this.voiceToken;t.startsWith("src:")?this.buildRecordedVoice(e.src,t,i):this.voice=this.buildSynthesizedVoice(e,t)}this.applyTo(this.voice,e)}silence(){this.voiceToken++,this.stopVoice()}dispose(){this.silence(),this.context?.close(),this.context=void 0,this.master=void 0,this.buffers.clear(),this.noiseBuffer=void 0,this.crackleBuffer=void 0}keyFor(e){if(!(e.volume<=0))return e.src?`src:${e.src}`:e.kind==="none"?void 0:e.kind}applyTo(e,t){const i=this.context;if(!e||!i)return;const n=i.currentTime;e.volumeParam.setTargetAtTime(Math.max(0,Math.min(1,t.volume))*e.gainScale,n,e1);for(const{param:s,ratio:r}of e.pitch)s.setTargetAtTime(Math.min(t.pitchHz*r,i.sampleRate/2-1),n,e1)}buildSynthesizedVoice(e,t){const i=this.context;if(i)switch(e.kind){case"hum":return this.buildHum(i,t);case"whistle":return this.buildWhistle(i,t);case"rumble":return this.buildRumble(i,t);case"crackle":return this.buildCrackle(i,t);default:return}}buildHum(e,t){const i=e.createOscillator();i.type="sawtooth";const n=e.createOscillator();n.type="sawtooth";const s=e.createBiquadFilter();s.type="lowpass",s.Q.value=1;const r=e.createGain();return r.gain.value=0,i.connect(s),n.connect(s),s.connect(r).connect(this.output(e)),i.start(),n.start(),{key:t,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(e,t){const i=e.createOscillator();i.type="sine";const n=e.createOscillator();n.type="sine",n.frequency.value=5;const s=e.createGain(),r=e.createGain();return r.gain.value=0,n.connect(s).connect(i.frequency),i.connect(r).connect(this.output(e)),i.start(),n.start(),{key:t,nodes:[s,r],sources:[i,n],volumeParam:r.gain,gainScale:.22,pitch:[{param:i.frequency,ratio:1},{param:s.gain,ratio:.012}]}}buildRumble(e,t){const i=e.createBufferSource();i.buffer=this.brownNoise(e),i.loop=!0;const n=e.createBiquadFilter();n.type="lowpass",n.Q.value=.8;const s=e.createGain();return s.gain.value=0,i.connect(n).connect(s).connect(this.output(e)),i.start(),{key:t,nodes:[n,s],sources:[i],volumeParam:s.gain,gainScale:1.4,pitch:[{param:n.frequency,ratio:1}]}}buildCrackle(e,t){const i=e.createBufferSource();i.buffer=this.whiteNoise(e),i.loop=!0;const n=e.createBiquadFilter();n.type="bandpass",n.Q.value=1.2;const s=e.createGain();s.gain.value=0;const r=e.createBufferSource();r.buffer=this.crackleEnvelope(e),r.loop=!0;const a=e.createGain();return a.gain.value=0,r.connect(a).connect(s.gain),i.connect(n).connect(s).connect(this.output(e)),i.start(),r.start(),{key:t,nodes:[n,s,a],sources:[i,r],volumeParam:a.gain,gainScale:.9,pitch:[{param:n.frequency,ratio:4}]}}async buildRecordedVoice(e,t,i){const n=this.context;if(!n)return;let s;try{s=await this.getBuffer(e)}catch(l){console.warn("SightingAudio: the recorded sound failed to load, staying silent:",l);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:t,nodes:[a],sources:[r],volumeParam:a.gain,gainScale:1,pitch:[]},this.requested&&this.applyTo(this.voice,this.requested)}async getBuffer(e){const t=this.context;if(!t)throw new Error("SightingAudio: AudioContext not ready — resume() must be called first");let i=this.buffers.get(e);return i||(i=fetch(e).then(n=>{if(!n.ok)throw new Error(`Audio fetch failed (${n.status}): ${e}`);return n.arrayBuffer()}).then(n=>t.decodeAudioData(n)),this.buffers.set(e,i)),i}whiteNoise(e){if(!this.noiseBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*i1),e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;this.noiseBuffer=t}return this.noiseBuffer}brownNoise(e){const t=e.createBuffer(1,Math.floor(e.sampleRate*i1),e.sampleRate),i=t.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 t}crackleEnvelope(e){if(!this.crackleBuffer){const t=e.createBuffer(1,Math.floor(e.sampleRate*n1),e.sampleRate),i=t.getChannelData(0),n=Math.max(1,Math.floor(QS*e.sampleRate)),s=Math.round(n1*JS);for(let r=0;r<s;r++){const a=Math.floor(Math.random()*i.length),l=.4+Math.random()*.6;for(let c=0;c<n&&a+c<i.length;c++)i[a+c]=Math.max(i[a+c],l*(1-c/n))}this.crackleBuffer=t}return this.crackleBuffer}stopVoice(){const e=this.voice,t=this.context;if(this.voice=void 0,!e||!t)return;const i=t.currentTime;e.volumeParam.cancelScheduledValues(i),e.volumeParam.setTargetAtTime(0,i,t1/3);const n=i+t1;for(const s of e.sources){s.onended=()=>{s.disconnect();for(const r of e.nodes)r.disconnect()};try{s.stop(n)}catch{s.disconnect();for(const r of e.nodes)r.disconnect()}}}}class Ze{static svg(e){return`<svg viewBox="0 0 24 24" width="1.5em" height="1.5em" aria-hidden="true" focusable="false"><path d="${e}" fill="currentColor"/></svg>`}static outline(e){return`<svg viewBox="0 0 24 24" width="1.5em" height="1.5em" aria-hidden="true" focusable="false"><path d="${e}" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" stroke-linecap="round"/></svg>`}static solid(e){return`<svg viewBox="0 0 24 24" width="1.5em" height="1.5em" aria-hidden="true" focusable="false"><path d="${e}" fill="currentColor" fill-rule="evenodd"/></svg>`}static BOOKMARK="M6 3.5h12a.5.5 0 0 1 .5.5v16.5L12 16.8l-6.5 3.7V4a.5.5 0 0 1 .5-.5z";static PICTURE="M5 4h14a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z";static PICTURE_HILLS="M4.5 17.5l4.5-6 3 4 2.5-3 5 5z";static PIN="M12 21.5s-6.5-5.7-6.5-10.8a6.5 6.5 0 0 1 13 0c0 5.1-6.5 10.8-6.5 10.8z";static PIN_HOLE="M12 8.4a2.4 2.4 0 1 0 0 4.8 2.4 2.4 0 0 0 0-4.8z";static MILESTONES_OFF=Ze.outline(Ze.BOOKMARK);static MILESTONES_ON=Ze.solid(Ze.BOOKMARK);static PICTURES_OFF=Ze.outline(`${Ze.PICTURE}${Ze.PICTURE_HILLS}`);static PICTURES_ON=Ze.solid(`${Ze.PICTURE}${Ze.PICTURE_HILLS}`);static TRACE_LINE="M3 19.5l2.2-2.2 1.4 1.4L4.4 20.9zM8 14.5l2.2-2.2 1.4 1.4-2.2 2.2zM13 9.5l2.2-2.2 1.4 1.4-2.2 2.2z";static TRACE_MARK="M18.5 2.5l3.5 3.5-3.5 3.5-3.5-3.5z";static TRACES_OFF=Ze.outline(`${Ze.TRACE_LINE}${Ze.TRACE_MARK}`);static TRACES_ON=Ze.solid(`${Ze.TRACE_LINE}${Ze.TRACE_MARK}`);static MAP_OFF=Ze.outline(`${Ze.PIN}${Ze.PIN_HOLE}`);static MAP_ON=Ze.solid(`${Ze.PIN}${Ze.PIN_HOLE}`);static SHARE=Ze.outline("M14 4l7 7-7 7v-4.2C8.6 13.8 5.4 15.6 3.5 19c.6-5.6 3.4-9.6 10.5-10.8V4z");static FOLDED=Ze.svg("M15.4 7.4 14 6l-6 6 6 6 1.4-1.4L10.8 12z");static UNFOLDED=Ze.svg("M8.6 16.6 10 18l6-6-6-6-1.4 1.4 4.6 4.6z");static PLAY=Ze.svg("M7.4 5v14l11-7z");static PAUSE=Ze.svg("M6 5h4v14H6zM14 5h4v14h-4z");static VOLUME=Ze.svg("M2 9.5v5h3.5l4.5 4.5V5L5.5 9.5H2zm12.5 2.5A4 4 0 0 0 12.5 8.5v7A4 4 0 0 0 14.5 12zM12.5 4.2v2.1a6.5 6.5 0 0 1 0 11.4v2.1a8.6 8.6 0 0 0 0-15.6z");static MUTED=Ze.svg("M2 9.5v5h3.5l4.5 4.5V5L5.5 9.5H2zM15 9.8l1.4-1.4 2.6 2.6 2.6-2.6 1.4 1.4-2.6 2.6 2.6 2.6-1.4 1.4-2.6-2.6-2.6 2.6-1.4-1.4 2.6-2.6z");static ENTER_FULLSCREEN=Ze.svg("M5 5h5v2H7v3H5V5zm9 0h5v5h-2V7h-3V5zM5 14h2v3h3v2H5v-5zm12 0h2v5h-5v-2h3v-3z");static EXIT_FULLSCREEN=Ze.svg("M8 5h2v5H5V8h3V5zm6 0h2v3h3v2h-5V5zM5 14h5v5H8v-3H5v-2zm9 0h5v2h-3v3h-2v-5z")}function Po(o){return[...o].sort((e,t)=>e.t-t.t)}function Kp(o,e){let t;for(const i of Po(o)){if(i.t>e)break;t=i}return t}const Zp=Math.PI/180,Zh=180/Math.PI;class $s{constructor(e,t,i){this.kind=e,this.canvasHeightPx=t,this.fovDeg=i;const n=i*Zp/2;this.focalPx=e==="equidistant"?t/2/n:t/2/Math.tan(n)}focalPx;static of(e,t,i){return new $s(e.projection,t,i)}degToPx(e){const t=e*Zp;return this.kind==="equidistant"?this.focalPx*t:2*this.focalPx*Math.tan(t/2)}pxToDeg(e){return this.kind==="equidistant"?e/this.focalPx*Zh:2*Math.atan(e/(2*this.focalPx))*Zh}angleDegToRadiusPx(e){const t=e*Zp;return this.kind==="equidistant"?this.focalPx*t:this.focalPx*Math.tan(t)}halfWidthAngleDeg(e){return this.radiusPxToAngleDeg(this.canvasHeightPx*e/2)}radiusPxToAngleDeg(e){return this.kind==="equidistant"?e/this.focalPx*Zh:Math.atan(e/this.focalPx)*Zh}ofBounds(e){return{widthDeg:this.pxToDeg(e.width),heightDeg:this.pxToDeg(e.height)}}toBoundsSize(e){return{width:this.degToPx(e.widthDeg),height:this.degToPx(e.heightDeg)}}widthPx(e){return this.degToPx(mt.angularWidthDeg(e))}}class en{static fovOf(e,t){return ot(e,t)?.fovDeg??Ut.fieldOfViewDeg(e.instrument)}static toAngular(e){this.eachKeyframe(e,(t,i)=>({...t,angular:i.ofBounds(t.bounds)}))}static toBounds(e){this.eachKeyframe(e,(t,i)=>{if(!t.angular)return t;const{width:n,height:s}=i.toBoundsSize(t.angular),r={x:t.bounds.x+(t.bounds.width-n)/2,y:t.bounds.y+(t.bounds.height-s)/2,width:n,height:s};if(t.kind!=="polygon")return{...t,bounds:r};const a=t.bounds.width===0?1:n/t.bounds.width,l=t.bounds.height===0?1:s/t.bounds.height;return{...t,bounds:r,points:t.points.map(c=>({x:c.x*a,y:c.y*l}))}})}static toAim(e){this.eachKeyframe(e,(t,i,n)=>{const s=t.aim&&this.positionOf(e,t.aim,t.bounds,i,n);if(s&&Math.abs(s.x-t.bounds.x)<en.UNMOVED_PX&&Math.abs(s.y-t.bounds.y)<en.UNMOVED_PX)return t;const r=this.aimFrom(e,i,n,t.bounds);return r?{...t,aim:r}:t})}static UNMOVED_PX=.01;static aimOf(e,t,i){const n=$s.of(e.instrument,mt.CANVAS_HEIGHT_PX,this.fovOf(e,t));return this.aimFrom(e,n,ot(e,t),i)}static aimFrom(e,t,i,n){if(i?.headingDeg===void 0)return;const s=this.frameCentre(e),r=t.radiusPxToAngleDeg(n.x+n.width/2-s.x),a=t.radiusPxToAngleDeg(s.y-(n.y+n.height/2));return{azimuthDeg:((i.headingDeg+r)%360+360)%360,altitudeDeg:i.pitchDeg+a}}static toPosition(e){this.eachKeyframe(e,(t,i,n)=>{const s=t.aim&&this.positionOf(e,t.aim,t.bounds,i,n);return s?{...t,bounds:{...t.bounds,...s}}:t})}static positionOf(e,t,i,n,s){if(s?.headingDeg===void 0)return;const r=this.frameCentre(e),a=this.shortestArc(t.azimuthDeg-s.headingDeg),l=t.altitudeDeg-s.pitchDeg;return{x:r.x+this.offAxisPx(n,a)-i.width/2,y:r.y-this.offAxisPx(n,l)-i.height/2}}static frameCentre(e){return{x:Ut.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,y:mt.CANVAS_HEIGHT_PX/2}}static shortestArc(e){return(e%360+540)%360-180}static offAxisPx(e,t){return Math.abs(t)>=en.OFF_CANVAS_DEG?Math.sign(t)*en.OFF_CANVAS_PX:e.angleDegToRadiusPx(t)}static OFF_CANVAS_DEG=89;static OFF_CANVAS_PX=1e5;static reproject(e,t,i){const n=Ut.frameWidthPx(t,mt.CANVAS_HEIGHT_PX)/2,s=Ut.frameWidthPx(e.instrument,mt.CANVAS_HEIGHT_PX)/2,r=mt.CANVAS_HEIGHT_PX/2;for(const a of[...e.timeline.allKeyframes]){const l=this.fovOf(e,a.t),c=i?.get(a.t)??l,h=$s.of(t,mt.CANVAS_HEIGHT_PX,c),d=$s.of(e.instrument,mt.CANVAS_HEIGHT_PX,l);e.timeline.addKeyframe(a.t,a.shapes.map(u=>{const{bounds:p}=u.shape,f=p.x+p.width/2-n,g=p.y+p.height/2-r,m=Math.hypot(f,g),v=m===0?1:d.angleDegToRadiusPx(h.radiusPxToAngleDeg(m))/m,b={...p,x:s+f*v-p.width/2,y:r+g*v-p.height/2};return{...u,shape:{...u.shape,bounds:b}}}))}this.toBounds(e)}static eachKeyframe(e,t){const{timeline:i}=e;for(const n of[...i.allKeyframes]){const s=ot(e,n.t),r=this.fovOf(e,n.t),a=$s.of(e.instrument,mt.CANVAS_HEIGHT_PX,r);i.addKeyframe(n.t,n.shapes.map(l=>({...l,shape:t(l.shape,a,s)})))}}}function tE(o){return Un.restore(Lm(o),o.provenance)}function Lm(o){return en.toAngular(o),en.toAim(o),{version:1,id:o.id,time:o.event.time,endTime:o.event.endTime,durationSeconds:o.event.durationSeconds,durationText:o.event.durationText,utcOffsetHours:o.event.utcOffsetHours,timeZone:o.event.timeZone,place:o.event.place,observer:o.observer,account:o.account,sources:o.sources?.length?o.sources:void 0,sway:o.sway,vehicle:o.vehicle,description:o.event.description,image:o.event.image,summary:o.event.summary,summaryTime:o.event.summaryTime,tags:o.event.tags,timeline:o.timeline.toJSON(),observerTrack:o.observerTrack.toJSON(),weatherTrack:o.weatherTrack.toJSON(),soundTrack:o.soundTrack.toJSON(),weather:o.weather,decor:o.decor,milestones:o.milestones.length>0?o.milestones:void 0,references:o.references.length>0?o.references:void 0,roads:o.roads.length>0?o.roads:void 0,traces:o.traces.length>0?o.traces:void 0,weatherSource:o.weatherSource,instrument:o.instrumentId,exposureSeconds:o.exposureSeconds,iso:o.iso,lightPollution:o.lightPollution,observerMap:o.observerMap,interpretation:o.interpretation}}function iE(o){const{recording:e,provenance:t}=Un.strip(o),i=nE(e);return i.provenance=t,i}function nE(o){const e=[],t=new _p({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},xp.fromJSON(o.timeline,e),o.observerTrack?bh.fromJSON(o.observerTrack):new bh,o.weatherTrack?Mh.fromJSON(o.weatherTrack):new Mh,o.soundTrack?wh.fromJSON(o.soundTrack):new wh,o.observer&&{id:o.observer.id,title:o.observer.title,lastName:o.observer.lastName,firstNames:o.observer.firstNames},o.id,o.weather,o.decor??[],o.weatherSource,o.instrument,o.exposureSeconds??o.observerTrack?.keyframes.map(i=>i.pose.exposureSeconds).find(i=>i!==void 0),Po(o.milestones??[]),o.references??[],o.roads??[],o.traces??[]);return t.account=o.account,t.sources=o.sources,t.sway=o.sway,t.iso=o.iso,t.lightPollution=o.lightPollution,t.observerMap=o.observerMap,t.vehicle=o.vehicle,t.interpretation=o.interpretation,t.loadIssues=e,en.toBounds(t),en.toPosition(t),t}class uc{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(e,t=uc.EN){return t[e.kind].replace("{path}",e.path).replace("{expected}",e.expected??"").replace("{found}",e.found??"")}static warn(e,t){if(e.length===0)return;const i=e.map(n=>` ${uc.text(n)}`);console.warn(`UFO@home: ${e.length} problem(s) in ${t??"this recording"}:
3016
3016
  ${i.join(`
3017
3017
  `)}`)}}class Os{constructor(e){this.format=e}issues(e){const t=[];return this.object(e,this.format,"",t),t}object(e,t,i,n){if(!Os.isObject(e)){n.push({kind:"wrong-type",path:i||"(the file)",expected:"object",found:Os.typeOf(e)});return}for(const[s,r]of Object.entries(e)){const a=i?`${i}.${s}`:s,l=t[s];l?this.field(r,l,a,n):n.push({kind:"unknown-key",path:a})}}field(e,t,i,n){if(Os.isStated(e)){this.field(e.value,t,i,n);return}if(!(t.loose||e===void 0||e===null))switch(t.type){case"enum":(typeof e!="string"||!t.values?.includes(e))&&n.push({kind:"not-in-list",path:i,expected:(t.values??[]).map(s=>`"${s}"`).join(", "),found:JSON.stringify(e)});return;case"object":t.fields?this.object(e,t.fields,i,n):Os.isObject(e)||n.push({kind:"wrong-type",path:i,expected:"object",found:Os.typeOf(e)});return;case"array":Array.isArray(e)?t.fields&&e.forEach((s,r)=>{const a=Os.isStated(s)?s.value:s;this.object(a,t.fields,`${i}.${r}`,n)}):n.push({kind:"wrong-type",path:i,expected:"array",found:Os.typeOf(e)});return;default:typeof e!==t.type&&n.push({kind:"wrong-type",path:i,expected:t.type,found:Os.typeOf(e)})}}static isObject(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}static isStated(e){return Os.isObject(e)&&"value"in e&&Object.keys(e).every(t=>t==="value"||t==="basis"||t==="rationale")}static typeOf(e){return Array.isArray(e)?"array":e===null?"null":typeof e}}class zs{static PIXELS_PER_INSTANT=2;static INSTANTS_PER_FLASH=2;static MAX_INSTANTS=512;static windowEndingAt(e,t){const i=Number.isFinite(t)?Math.max(0,t):0,n=Math.max(0,e-i*1e3),s=Math.max(0,e-n);return{fromMs:n,toMs:e,ms:s,seconds:s/1e3}}static instants(e,t,i,n,s){if(!(n>0))return 1;const r=s>0?zs.travelDegOver(e,t,i,i+n*1e3)/s/zs.PIXELS_PER_INSTANT:0,a=zs.flashesOver(e,n)*zs.INSTANTS_PER_FLASH,l=Math.ceil(Math.max(r,a));return l<2?1:Math.min(zs.MAX_INSTANTS,l)}static travelDegOver(e,t,i,n){let s=0;for(const r of e){if(!r.track||r.track.length<2)continue;const a=zs.directionAt(r,t,i),l=zs.directionAt(r,t,n),c=Math.min(1,Math.max(-1,a.x*l.x+a.y*l.y+a.z*l.z));s=Math.max(s,Math.acos(c)*180/Math.PI)}return s}static flashesOver(e,t){let i=0;for(const n of e)for(const s of n.lights??[])s.pattern.kind==="flash"&&(i=Math.max(i,s.pattern.perMinute));return i/60*t}static directionAt(e,t,i){const n=Xs(e,i),s=n.eastM,r=n.altitudeM-t,a=n.northM,l=Math.hypot(s,r,a);return l===0?{x:0,y:1,z:0}:{x:s/l,y:r/l,z:a/l}}}const $M={play:"Play",pause:"Pause",noDuration:"No observation duration",currentPosition:"Current position",duration:"Duration",switchToElapsed:"click to show elapsed time",switchToClockTime:"click to show the time of day",fullscreen:"Fullscreen",exitFullscreen:"Exit fullscreen",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:uc.EN},sE=Object.freeze(Object.defineProperty({__proto__:null,ufoMessages_en:$M},Symbol.toStringTag,{value:"Module"})),YM=Math.PI/180,rE=180/Math.PI,aE=256,qM=19,oE=1.25;function KM(o,e){return 156543.03392*Math.cos(o*YM)/2**e}function ZM(o,e){return KM(o,e)*aE}function lE(o,e){let t=0;for(;t<qM&&ZM(o,t+1)>=e;)t++;return t}function jM(o,e){return ZM(o,e)}function cE(o,e){const t=e*oE;let i=0;for(;i<qM&&KM(o,i)>t;)i++;return i}function iu(o){const e=o*YM;return(1-Math.log(Math.tan(e)+1/Math.cos(e))/Math.PI)/2}function JM(o,e,t){const i=2**t;return{x:(o+180)/360*i,y:iu(e)*i}}function QM(o,e,t){const i=iu(o.north),n=iu(o.south);return{x:(e-o.west)/(o.east-o.west),y:(iu(t)-i)/(n-i)}}function hE(o,e,t){const{x:i,y:n}=JM(o,e,t);return{x:Math.floor(i),y:Math.floor(n),z:t}}function dE(o){const e=2**o.z,t=o.x/e*360-180,i=(o.x+1)/e*360-180,n=s1(o.y,e);return{south:s1(o.y+1,e),north:n,west:t,east:i}}function s1(o,e){const t=o/e;return Math.atan(Math.sinh(Math.PI*(1-2*t)))*rE}function ew(o,e,t,i){const n=hE(o,e,t),s=Math.floor(i/2),r=[];for(let c=-s;c<=s;c++)for(let h=-s;h<=s;h++)r.push({x:n.x+h,y:n.y+c,z:t});const a=r.map(dE),l={south:Math.min(...a.map(c=>c.south)),north:Math.max(...a.map(c=>c.north)),west:Math.min(...a.map(c=>c.west)),east:Math.max(...a.map(c=>c.east))};return{tiles:r,bounds:l}}const uE="#2ec4ff";class so{constructor(e){this.ctx=e}static SCALE_STEPS_M=[5e3,2e3,1e3,500,200,100,50,20,10,5];static MARKER_RADIUS_PX=8.5;static ON_MARKER_M=3;targets=[];hitTest(e,t){let i,n=1/0;for(const s of this.targets){const r=Math.hypot(s.x-e,s.y-t);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(e){const{ctx:t}=this;t.save(),this.targets=[],t.clearRect(0,0,this.width,this.height),this.paintGround(e),this.paintNight(e.nightFraction),this.paintPath(e),this.paintTraces(e),e.position?(this.paintCone(e,e.position),this.paintDecor(e),this.paintMarkers(e),this.paintObserver(e,e.position)):(this.paintDecor(e),this.paintMarkers(e)),this.paintNorth(),this.paintFooter(e.bounds,e.attribution),t.restore()}toCanvas(e,t,i){const n=QM(e,i,t);return{x:n.x*this.width,y:n.y*this.height}}paintGround(e){const{ctx:t}=this;t.fillStyle="#1d2321",t.fillRect(0,0,this.width,this.height);const i=e.imagery;if(!i)return;const n=this.toCanvas(e.bounds,i.bounds.north,i.bounds.west),s=this.toCanvas(e.bounds,i.bounds.south,i.bounds.east);t.drawImage(i.source,n.x,n.y,s.x-n.x,s.y-n.y)}paintNight(e=0){if(e<=0)return;const{ctx:t}=this;t.save(),t.fillStyle=`rgba(6, 12, 30, ${Math.min(e,1)*.78})`,t.fillRect(0,0,this.width,this.height),t.restore()}paintDecor(e){const{ctx:t}=this;for(const i of e.decor){const n=this.toCanvas(e.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}),t.beginPath(),t.rect(n.x-3.5,n.y-3.5,7,7),t.fillStyle="rgba(120, 220, 255, 0.85)",t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.7)",t.stroke(),i.headingDeg===void 0)continue;const s=(i.headingDeg-90)*Math.PI/180;t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(n.x+Math.cos(s)*10,n.y+Math.sin(s)*10),t.lineWidth=3,t.strokeStyle="rgba(0, 0, 0, 0.6)",t.stroke(),t.lineWidth=1.5,t.strokeStyle="rgba(120, 220, 255, 0.9)",t.stroke()}}paintPath(e){if(!e.path.moved)return;const{ctx:t}=this,i=e.path.points.map(n=>this.toCanvas(e.bounds,n.lat,n.lng));t.beginPath(),t.moveTo(i[0].x,i[0].y);for(const n of i.slice(1))t.lineTo(n.x,n.y);t.lineJoin="round",t.lineCap="round",t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=5,t.stroke(),t.strokeStyle="rgba(255, 255, 255, 0.9)",t.lineWidth=2,t.stroke()}paintTraces(e){const{ctx:t}=this;for(const i of e.traces??[]){const n=i.points.map(r=>this.toCanvas(e.bounds,r.lat,r.lng));if(n.length===0)continue;const s=i.color??uE;if(i.kind==="point")t.beginPath(),t.moveTo(n[0].x,n[0].y-6),t.lineTo(n[0].x+6,n[0].y),t.lineTo(n[0].x,n[0].y+6),t.lineTo(n[0].x-6,n[0].y),t.closePath(),t.fillStyle=s,t.fill(),t.lineWidth=1.5,t.strokeStyle="rgba(0, 0, 0, 0.8)",t.stroke();else{t.beginPath(),t.moveTo(n[0].x,n[0].y);for(const r of n.slice(1))t.lineTo(r.x,r.y);i.kind==="polygon"&&t.closePath(),t.lineJoin="round",t.setLineDash([]),t.strokeStyle="rgba(0, 0, 0, 0.65)",t.lineWidth=4.5,t.stroke(),t.setLineDash([9,5]),t.strokeStyle=s,t.lineWidth=2.5,t.stroke(),t.setLineDash([])}if(i.label){t.font="11px sans-serif",t.textAlign="left",t.textBaseline="middle";let r=n[0];if(i.kind==="line"&&e.position){const a=this.toCanvas(e.bounds,e.position.lat,e.position.lng);r=n.reduce((l,c)=>Math.hypot(c.x-a.x,c.y-a.y)>Math.hypot(l.x-a.x,l.y-a.y)?c:l)}this.paintOutlinedText(i.label,r.x+9,r.y-9)}}}paintCone(e,t){const{headingDeg:i,coneHalfAngleDeg:n}=e;if(i===void 0||n===void 0)return;const{ctx:s}=this,r=this.toCanvas(e.bounds,t.lat,t.lng),a=Math.hypot(this.width,this.height),l=(i-90)*Math.PI/180,c=n*Math.PI/180;s.save(),s.beginPath(),s.moveTo(r.x,r.y),s.arc(r.x,r.y,a,l-c,l+c),s.closePath();const h=s.createRadialGradient(r.x,r.y,0,r.x,r.y,a);h.addColorStop(0,"rgba(255, 224, 130, 0.55)"),h.addColorStop(.35,"rgba(255, 224, 130, 0.22)"),h.addColorStop(1,"rgba(255, 224, 130, 0)"),s.fillStyle=h,s.fill(),s.restore()}paintMarkers(e){const{ctx:t}=this;t.textAlign="center",t.textBaseline="middle",t.font="bold 10px sans-serif";for(const i of[...e.markers].sort((n,s)=>Number(n.current)-Number(s.current))){const n=this.toCanvas(e.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:so.MARKER_RADIUS_PX}),t.beginPath(),t.arc(n.x,n.y,so.MARKER_RADIUS_PX,0,Math.PI*2),t.fillStyle=i.current?"rgba(255, 224, 130, 0.95)":"rgba(0, 0, 0, 0.55)",t.fill(),t.lineWidth=2,t.strokeStyle="rgba(255, 255, 255, 0.9)",t.stroke(),t.fillStyle=i.current?"#1d2321":"#fff",t.fillText(i.label,n.x,n.y)}}paintObserver(e,t){const{ctx:i}=this,n=this.toCanvas(e.bounds,t.lat,t.lng);e.observerLabel&&this.targets.push({kind:"observer",label:e.observerLabel,lat:t.lat,lng:t.lng,x:n.x,y:n.y,radius:8});const s=e.markers.some(r=>{if(!r.current)return!1;const a=yt(r.lat,r.lng,t.lat,t.lng);return Math.hypot(a.x,a.z)<=so.ON_MARKER_M});i.beginPath(),i.arc(n.x,n.y,s?so.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:e}=this,t=this.width-14,i=16;e.beginPath(),e.moveTo(t,i-9),e.lineTo(t-4.5,i+5),e.lineTo(t,i+2),e.lineTo(t+4.5,i+5),e.closePath(),e.fillStyle="rgba(255, 255, 255, 0.92)",e.strokeStyle="rgba(0, 0, 0, 0.6)",e.lineWidth=1,e.fill(),e.stroke(),e.font="bold 9px sans-serif",e.textAlign="center",e.textBaseline="top",e.strokeText("N",t,i+6),e.fillText("N",t,i+6)}paintFooter(e,t){const{ctx:i}=this;i.font="9px sans-serif",i.textBaseline="bottom";const n=t?this.wrap(t,this.width-20):[];let s=this.height-4;i.textAlign="right";for(const p of n.slice().reverse())this.paintOutlinedText(p,this.width-6,s),s-=11;const r=(e.south+e.north)/2,l=Math.abs(yt(r,e.east,r,e.west).x)/this.width,c=so.SCALE_STEPS_M.find(p=>p/l<=this.width/3);if(c===void 0)return;const h=c/l,d=8,u=s-3;i.lineWidth=3,i.strokeStyle="rgba(0, 0, 0, 0.6)",i.beginPath(),i.moveTo(d,u),i.lineTo(d+h,u),i.stroke(),i.lineWidth=1.5,i.strokeStyle="rgba(255, 255, 255, 0.95)",i.stroke(),i.textAlign="left",this.paintOutlinedText(c>=1e3?`${c/1e3} km`:`${c} m`,d,u-3)}paintOutlinedText(e,t,i){const{ctx:n}=this;n.lineWidth=3,n.strokeStyle="rgba(0, 0, 0, 0.75)",n.strokeText(e,t,i),n.fillStyle="#fff",n.fillText(e,t,i)}wrap(e,t){const i=[];let n="";for(const s of e.split(" ")){const r=n?`${n} ${s}`:s;n&&this.ctx.measureText(r).width>t?(i.push(n),n=s):n=r}return n&&i.push(n),i}}class Mi{static MIN_ZOOM=.25;static MAX_ZOOM=64;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(e,t,i){const n=Math.min(Mi.MAX_ZOOM,Math.max(Mi.MIN_ZOOM,this.zoom*i)),s=this.centerX+(e-.5)/this.zoom,r=this.centerY+(t-.5)/this.zoom;this.centerX=s-(e-.5)/n,this.centerY=r-(t-.5)/n,this.zoom=n}panBy(e,t){this.centerX-=e/this.zoom,this.centerY-=t/this.zoom}refit(e,t){if(!this.changed)return;const i=this.boundsWithin(e),n=Mi.mercatorY01(t.north),s=Mi.mercatorY01(t.south),r=Mi.mercatorY01(i.north),a=Mi.mercatorY01(i.south);this.zoom=(t.east-t.west)/(i.east-i.west),this.centerX=((i.west+i.east)/2-t.west)/(t.east-t.west),this.centerY=((r+a)/2-n)/(s-n)}keepInView(e,t,i){if(!this.changed)return!1;const n=this.boundsWithin(e),s=Mi.mercatorY01(n.north),r=Mi.mercatorY01(n.south),a=(t.lng-n.west)/(n.east-n.west),l=(Mi.mercatorY01(t.lat)-s)/(r-s);return a>=i&&a<=1-i&&l>=i&&l<=1-i?!1:(this.panBy(.5-a,.5-l),!0)}boundsWithin(e){if(!this.changed)return e;const t=.5/this.zoom,i=Mi.mercatorY01(e.north),n=Mi.mercatorY01(e.south),s=e.east-e.west;return{west:e.west+(this.centerX-t)*s,east:e.west+(this.centerX+t)*s,north:Mi.latitudeAt(i+(this.centerY-t)*(n-i)),south:Mi.latitudeAt(i+(this.centerY+t)*(n-i))}}static including(e,t,i=3){const n=(e.north+e.south)/2,s=(e.east+e.west)/2,r=yt(n,e.east,n,s).x;let a=r;for(const l of t){const{x:c,z:h}=yt(l.lat,l.lng,n,s),d=Math.max(Math.abs(c),Math.abs(h));d<=r*i&&(a=Math.max(a,d*1.15))}return a<=r?e:{north:fs(0,-a,n,s).lat,south:fs(0,a,n,s).lat,east:fs(a,0,n,s).lng,west:fs(-a,0,n,s).lng}}static expand(e,t){const i=e.east-e.west,n=e.north-e.south;return{west:e.west-i*t,east:e.east+i*t,south:e.south-n*t,north:e.north+n*t}}static pointAt(e,t,i){const n=Mi.mercatorY01(e.north),s=Mi.mercatorY01(e.south);return{lat:Mi.latitudeAt(n+i*(s-n)),lng:e.west+t*(e.east-e.west)}}static mercatorY01(e){const t=e*Math.PI/180;return(1-Math.log(Math.tan(t)+1/Math.cos(t))/Math.PI)/2}static latitudeAt(e){return Math.atan(Math.sinh(Math.PI*(1-2*e)))*180/Math.PI}}const bs=256,r1=3,pE=32768;class tw{fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"}async getElevationGrid(e,t){const i=(e.south+e.north)/2,n=(e.west+e.east)/2,s=Math.abs(yt(i,e.east,i,e.west).x),r=Math.abs(yt(e.north,n,e.south,n).z),a=lE(i,Math.max(s,r)),{tiles:l}=ew(n,i,a,r1),c=r1*bs,h=new Float32Array(c*c),d=l[0];await Promise.all(l.map(p=>this.decodeTileInto(p,d,h,c)));const u=new Float32Array(t.width*t.height);for(let p=0;p<t.height;p++){const f=e.north+(e.south-e.north)*(p/(t.height-1));for(let g=0;g<t.width;g++){const m=e.west+(e.east-e.west)*(g/(t.width-1));u[p*t.width+g]=this.sampleAt(f,m,a,d,h,c)}}return{heights:u,width:t.width,height:t.height,bounds:e}}async decodeTileInto(e,t,i,n){const s=this.tileUrlTemplate.replace("{z}",String(e.z)).replace("{x}",String(e.x)).replace("{y}",String(e.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()),l=document.createElement("canvas");l.width=bs,l.height=bs;const c=l.getContext("2d");if(!c)throw new Error("2D canvas context unavailable");c.drawImage(a,0,0);const{data:h}=c.getImageData(0,0,bs,bs),d=(e.x-t.x)*bs,u=(e.y-t.y)*bs;for(let p=0;p<bs;p++)for(let f=0;f<bs;f++){const g=(p*bs+f)*4,m=h[g]*256+h[g+1]+h[g+2]/256-pE,v=d+f,b=u+p;i[b*n+v]=m}}sampleAt(e,t,i,n,s,r){const{x:a,y:l}=JM(t,e,i),c=(a-n.x)*bs,h=(l-n.y)*bs,d=Math.max(0,Math.min(r-1,Math.floor(c))),u=Math.max(0,Math.min(r-1,Math.floor(h))),p=Math.min(r-1,d+1),f=Math.min(r-1,u+1),g=c-d,m=h-u,v=s[u*r+d],b=s[u*r+p],M=s[f*r+d],y=s[f*r+p],x=v+(b-v)*g,S=M+(y-M)*g;return x+(S-x)*m}}class Rp{constructor(e,t,i,n){this.width=e,this.height=t,this.samples=i,this.values=n}at(e,t,i=0){return this.values[(t*this.width+e)*this.samples+i]}static parse(e){const t=new DataView(e);if(e.byteLength<8||t.getUint16(0)!==18761||t.getUint16(2,!0)!==42)throw new Error("Not a little-endian TIFF");const i=t.getUint32(4,!0),n=t.getUint16(i,!0),s=new Map;for(let v=0;v<n;v++){const b=i+2+v*12;s.set(t.getUint16(b,!0),{type:t.getUint16(b+2,!0),count:t.getUint32(b+4,!0),value:t.getUint32(b+8,!0)})}const r=(v,b)=>{const M=s.get(v);if(M===void 0){if(b===void 0)throw new Error(`TIFF without tag ${v}`);return b}return M.type===3?M.value&65535:M.value},a=v=>{const b=s.get(v);if(b===void 0)throw new Error(`TIFF without tag ${v}`);const M=b.type===3?2:4,y=[];if(b.count*M<=4){const x=new DataView(new ArrayBuffer(4));x.setUint32(0,b.value,!0);for(let S=0;S<b.count;S++)y.push(M===2?x.getUint16(S*2,!0):x.getUint32(0,!0))}else for(let x=0;x<b.count;x++)y.push(M===2?t.getUint16(b.value+x*2,!0):t.getUint32(b.value+x*4,!0));return y};if(r(259,1)!==1)throw new Error("Compressed TIFF");if(s.has(322))throw new Error("Tiled TIFF");const l=r(256),c=r(257),h=r(277,1),d=a(258)[0],u=r(339,1)===3;if(!(u&&d===32||!u&&d===8))throw new Error(`Unsupported TIFF samples: ${d} bits`);const p=a(273),f=a(279),g=new Uint8Array(l*c*h*(d/8));let m=0;for(let v=0;v<p.length&&m<g.length;v++){const b=Math.min(f[v],g.length-m);g.set(new Uint8Array(e,p[v],b),m),m+=b}if(m<g.length)throw new Error("Truncated TIFF");return new Rp(l,c,h,u?new Float32Array(g.buffer):g)}}class fE{constructor(e,t,i,n,s){this.heights=e,this.plants=t,this.buildings=i,this.size=n,this.metresPerPixel=s}structureAt(e,t){const i=Math.floor(e/this.metresPerPixel+this.size/2),n=Math.floor(this.size/2-t/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(e,t,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 l=this.structureAt(e+a*this.metresPerPixel,t+r*this.metresPerPixel);l!==void 0&&(n===void 0||l>n)&&(n=l)}return n}}class at{static METRES_PER_DEGREE=111320;static MIN_BRIDGE_M=4;static DEFAULT_DECK_M=6;static FOOTBRIDGE_DECK_M=2.5;static DECK_MARGIN_M=2.4;static ROAD_MATCH_M=12;static DEFAULT_DECK_HEIGHT_M=4;static MIN_POLE_M=6;static MAX_POLE_M=70;static MAX_SPAN_M=800;static MAX_LINES=16;static BY_VOLTAGE=[{upToKv:25,poleM:11,dropM:1.2,spreadM:.8},{upToKv:70,poleM:20,dropM:3,spreadM:3},{upToKv:100,poleM:22,dropM:3.5,spreadM:3.5},{upToKv:170,poleM:27,dropM:4.5,spreadM:4.5},{upToKv:250,poleM:32,dropM:5.5,spreadM:5.5},{upToKv:1e3,poleM:42,dropM:7,spreadM:7.5}];static toMetres(e,t){const[i,n]=e;return{east:(i-t.lng)*at.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180),north:(n-t.lat)*at.METRES_PER_DEGREE}}static path(e,t){return e.geometry.type!=="LineString"?[]:e.geometry.coordinates.map(i=>at.toMetres(i,t))}static bearing(e,t){return(Math.atan2(t.east-e.east,t.north-e.north)*180/Math.PI+360)%360}static distanceToSegment(e,t,i){const n=i.east-t.east,s=i.north-t.north,r=n*n+s*s,a=r===0?0:Math.max(0,Math.min(1,((e.east-t.east)*n+(e.north-t.north)*s)/r));return Math.hypot(e.east-(t.east+a*n),e.north-(t.north+a*s))}static bridges(e,t,i,n){const s=e.elevatedRoads.map(a=>({path:at.path(a,t),properties:a.properties})),r=[];for(const a of e.bridges){const l=at.path(a,t);if(l.length<2)continue;const c=l[0],h=l[l.length-1],d=Math.hypot(h.east-c.east,h.north-c.north);if(d<at.MIN_BRIDGE_M)continue;const u={east:(c.east+h.east)/2,north:(c.north+h.north)/2};Math.hypot(u.east,u.north)>i+d/2||r.push({eastM:at.tenth(u.east),northM:at.tenth(u.north),lengthM:at.tenth(d),widthM:at.roadOf(u,s).width,heightM:at.tenth(at.deckHeight(c,h,n)),headingDeg:at.tenth(at.bearing(c,h)%180),...at.roadOf(u,s).name?{name:at.roadOf(u,s).name}:{}})}return r.sort((a,l)=>Math.hypot(a.eastM,a.northM)-Math.hypot(l.eastM,l.northM)),r}static roadOf(e,t){let i;for(const a of t)for(let l=0;l+1<a.path.length;l++){const c=at.distanceToSegment(e,a.path[l],a.path[l+1]);(i===void 0||c<i.distance)&&(i={distance:c,properties:a.properties})}if(i===void 0||i.distance>at.ROAD_MATCH_M)return{width:at.DEFAULT_DECK_M};const n=[i.properties.nom_voie_ban_gauche,i.properties.nom_voie_ban_droite,i.properties.cpx_toponyme_route_nommee].find(a=>typeof a=="string"&&a.length>0),s=Number(i.properties.largeur_de_chaussee),r=Number.isFinite(s)&&s>0?at.tenth(s+at.DECK_MARGIN_M):i.properties.nature==="Sentier"?at.FOOTBRIDGE_DECK_M:at.DEFAULT_DECK_M;return n?{width:r,name:n}:{width:r}}static deckHeight(e,t,i){if(i===void 0)return at.DEFAULT_DECK_HEIGHT_M;const n=[],s=20;for(let r=4;r<=s-4;r++){const a=i.structureAt(e.east+(t.east-e.east)*r/s,e.north+(t.north-e.north)*r/s);a!==void 0&&a>=1.5&&n.push(a)}return n.length===0?at.DEFAULT_DECK_HEIGHT_M:(n.sort((r,a)=>r-a),n[Math.floor(n.length/2)])}static lines(e,t,i,n){const s=[];for(const r of e.lines){const a=String(r.properties.voltage??""),l=at.kilovolts(a);if(l===void 0)continue;const c=at.BY_VOLTAGE.find(d=>l<=d.upToKv)??at.BY_VOLTAGE[at.BY_VOLTAGE.length-1],h=at.path(r,t);for(let d=0;d+1<h.length;d++){const u=h[d],p=h[d+1],f=Math.hypot(p.east-u.east,p.north-u.north);if(f<5||f>at.MAX_SPAN_M||at.distanceToSegment({east:0,north:0},u,p)>i)continue;const g=at.poleHeight(u,p,n)??c.poleM;s.push({eastM:at.tenth((u.east+p.east)/2),northM:at.tenth((u.north+p.north)/2),lengthM:at.tenth(f),headingDeg:at.tenth(at.bearing(u,p)),heightM:at.tenth(Math.max(4,g-c.dropM)),poleHeightM:at.tenth(g),acrossM:[-c.spreadM,0,c.spreadM],voltage:a})}}return s.sort((r,a)=>Math.hypot(r.eastM,r.northM)-Math.hypot(a.eastM,a.northM)),s.slice(0,at.MAX_LINES)}static kilovolts(e){const t=/([\d.,]+)\s*kV/i.exec(e);if(t===null)return;const i=Number(t[1].replace(",","."));return Number.isFinite(i)&&i>0?i:void 0}static poleHeight(e,t,i){if(i===void 0)return;const n=[e,t].map(s=>i.tallestStructureNear(s.east,s.north,3)).filter(s=>s!==void 0&&s>=at.MIN_POLE_M&&s<=at.MAX_POLE_M);return n.length===0?void 0:n.reduce((s,r)=>s+r,0)/n.length}static tenth(e){return Math.round(e*10)/10}}class ci{static covers(e,t){return e>=41.2&&e<=51.3&&t>=-5.4&&t<=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(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.wms=e.wmsEndpoint??ci.WMS,this.wfs=e.wfsEndpoint??ci.WFS}static radius(e){return Math.min(e,ci.MAX_RADIUS_M)}static lidarRadius(e){return Math.min(e,ci.MAX_LIDAR_RADIUS_M)}async lidar(e,t){const i=ci.lidarRadius(t),n=Math.ceil(2*i/ci.METRES_PER_PIXEL),[s,r]=await Promise.all([this.raster(e,i,n,ci.HEIGHT_LAYER),this.raster(e,i,n,ci.CLASS_LAYER)]);if(s.samples!==1||r.samples<3)throw new Ns("unreachable","The survey answered in a layout this does not read");const a=s.values;if(a.every(d=>d===ci.NO_DATA))throw new Ns("no-coverage","No LiDAR HD survey here yet");const l=new Uint8Array(n*n),c=new Uint8Array(n*n);for(let d=0;d<n*n;d++){const u=r.values[d*r.samples],p=r.values[d*r.samples+1],f=r.values[d*r.samples+2];l[d]=p>u&&p>f?1:0,c[d]=u>120&&p<90&&f<90?1:0}const h=2*i/n;return{size:n,metresPerPixel:h,heights:a,vegetation:l,building:c,structures:new fE(a,l,c,n,h)}}async laserDate(e){return ci.latest(await this.dated("IGNF_LIDAR-HD_METADONNEE:metadata","geom","date_fin_acquisition",e))}async photoDate(e){return ci.latest(await this.dated("ORTHOIMAGERY.ORTHOPHOTOS.GRAPHE-MOSAIQUAGE:graphe_bdortho","geom","date_vol",e))}static latest(e){return e.map(i=>/^\d{4}-\d{2}-\d{2}/.exec(String(i??""))?.[0]).filter(i=>i!==void 0).sort().at(-1)}async dated(e,t,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(e,`BBOX(${t},${r},'EPSG:4326')`,i,20)).map(a=>a.properties[i])}catch{return[]}}async photo(e,t){const i=ci.radius(t),n=Math.min(ci.MAX_PHOTO_PIXELS,Math.ceil(2*i/ci.METRES_PER_PIXEL)),s=await this.raster(e,i,n,ci.PHOTO_LAYER);if(s.samples<3)throw new Ns("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(e,t,i){const n=ci.radius(t),s=n/ci.METRES_PER_DEGREE,r=n/(ci.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),l=`BBOX(geometrie,${[e.lng-r,e.lat-s,e.lng+r,e.lat+s].map(f=>f.toFixed(6)).join(",")},'EPSG:4326')`,[c,h,d,u,p]=await Promise.all([this.features("construction_lineaire",`${l} AND nature='Pont'`,"nature,geometrie"),this.features("troncon_de_route",`${l} 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("ligne_electrique",l,"voltage,geometrie"),i?this.features("batiment",l,"nature,hauteur,nombre_d_etages,materiaux_des_murs,materiaux_de_la_toiture,date_modification,geometrie",5e3):Promise.resolve([]),i?this.features("zone_d_activite_ou_d_interet",l,"toponyme,geometrie",100).catch(()=>[]):Promise.resolve([])]);return{bridges:c,elevatedRoads:h,lines:d,buildings:u,zones:p,mapDate:ci.latest(u.map(f=>f.properties.date_modification))}}async elevatedRoadLines(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(s=>s.toFixed(6)).join(",")},'EPSG:4326')`,i=await this.features("troncon_de_route",`${t} AND position_par_rapport_au_sol>'0'`,"geometrie",300),n=[];for(const s of i){const{type:r,coordinates:a}=s.geometry,l=r==="LineString"?[a]:r==="MultiLineString"?a:[];for(const c of l)n.push(c.map(h=>({lat:h[1],lng:h[0]})))}return n}async roads(e){const t=`BBOX(geometrie,${[e.west,e.south,e.east,e.north].map(i=>i.toFixed(6)).join(",")},'EPSG:4326')`;return this.features("troncon_de_route",`${t} 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 raster(e,t,i,n){const s=t/ci.METRES_PER_DEGREE,r=t/(ci.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180)),a=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:n,STYLES:"",CRS:"EPSG:4326",BBOX:[e.lat-s,e.lng-r,e.lat+s,e.lng+r].map(c=>c.toFixed(6)).join(","),WIDTH:String(i),HEIGHT:String(i),FORMAT:"image/geotiff"});let l;try{l=await this.fetchImpl(`${this.wms}?${a}`)}catch(c){throw new Ns("unreachable",c instanceof Error?c.message:String(c))}if(!l.ok)throw new Ns("unreachable",`The survey answered ${l.status}`);try{return Rp.parse(await l.arrayBuffer())}catch(c){throw new Ns("unreachable",c instanceof Error?c.message:String(c))}}async features(e,t,i,n=200){const s=new URLSearchParams({SERVICE:"WFS",VERSION:"2.0.0",REQUEST:"GetFeature",TYPENAMES:e.includes(":")?e:`BDTOPO_V3:${e}`,SRSNAME:"EPSG:4326",OUTPUTFORMAT:"application/json",COUNT:String(n),CQL_FILTER:t,PROPERTYNAME:i});let r;try{r=await this.fetchImpl(`${this.wfs}?${s}`)}catch(l){throw new Ns("unreachable",l instanceof Error?l.message:String(l))}if(!r.ok)throw new Ns("unreachable",`The map answered ${r.status}`);return(await r.json()).features??[]}}class va{static NEAR_M=15;static ALIGNED_DEG=30;static LONG_ENOUGH_M=15;static SAMPLE_M=5;static follows(e,t){if(e.length<2||t.length<2)return!1;const i=t[0],n=t.map(a=>yt(a.lat,a.lng,i.lat,i.lng)),s=e.map(a=>yt(a.lat,a.lng,i.lat,i.lng));let r=0;for(let a=0;a<s.length-1;a++){const l=s[a],c=s[a+1],h=Math.hypot(c.x-l.x,c.z-l.z);if(h<1e-6)continue;const d=Math.max(1,Math.ceil(h/va.SAMPLE_M)),u=Math.atan2(c.x-l.x,-(c.z-l.z));for(let p=0;p<=d;p++){const f=p/d,g=va.nearest(n,l.x+(c.x-l.x)*f,l.z+(c.z-l.z)*f);g.distanceM>va.NEAR_M||va.angleBetween(u,g.heading)<=va.ALIGNED_DEG&&(r+=h/d)}}return r>=va.LONG_ENOUGH_M}static nearest(e,t,i){let n={distanceM:1/0,heading:0};for(let s=0;s<e.length-1;s++){const r=e[s],a=e[s+1],l=a.x-r.x,c=a.z-r.z,h=l*l+c*c,d=h<1e-9?0:Math.max(0,Math.min(1,((t-r.x)*l+(i-r.z)*c)/h)),u=Math.hypot(t-(r.x+l*d),i-(r.z+c*d));u<n.distanceM&&(n={distanceM:u,heading:Math.atan2(l,-c)})}return n}static angleBetween(e,t){const i=Math.abs((e-t)*180/Math.PI%180);return Math.min(i,180-i)}}class Qt{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 MIN_PIXELS=8;static MAX_PIXELS=700;static NO_DATA_BELOW=-9e3;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(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.wms=e.wmsEndpoint??Qt.WMS,this.timeoutMs=e.timeoutMs??Qt.DEFAULT_TIMEOUT_MS,this.maxWindowM=e.maxWindowM??Qt.MAX_WINDOW_M,this.geoplatform=new ci({fetchImpl:this.fetchImpl,wmsEndpoint:this.wms,wfsEndpoint:e.wfsEndpoint})}async getElevationGrid(e,t,i){const n={lat:(e.south+e.north)/2,lng:(e.west+e.east)/2};if(!ci.covers(n.lat,n.lng))throw new Error("The IGN's relief covers France only");const s=Math.abs(yt(n.lat,e.east,n.lat,e.west).x),r=Math.abs(yt(e.north,n.lng,e.south,n.lng).z);t=this.finer(t,s,r);const a={x:s/Math.max(1,t.width-1),y:r/Math.max(1,t.height-1)},l={x:Math.min(a.x,this.maxWindowM),y:Math.min(a.y,this.maxWindowM)},c={south:e.south-l.y/Qt.METRES_PER_DEGREE,north:e.north+l.y/Qt.METRES_PER_DEGREE,west:e.west-l.x/(Qt.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180)),east:e.east+l.x/(Qt.METRES_PER_DEGREE*Math.cos(n.lat*Math.PI/180))},h=f=>Math.min(Qt.MAX_PIXELS,Math.max(Qt.MIN_PIXELS,Math.ceil(f/Qt.METRES_PER_PIXEL))),d={width:h(s+2*l.x),height:h(r+2*l.y)},u={x:(s+2*l.x)/d.width,y:(r+2*l.y)/d.height};let p=new Error("No layer of the IGN's relief answered");for(const f of Qt.LAYERS)try{const g=await this.heights(c,d,f);f===Qt.LAYERS[0]&&await this.layBridgeDecks(g,c,d,i?.route);const m=this.sample(g,t,e,c,u,a);if(m)return{heights:m,width:t.width,height:t.height,bounds:e};p=new Error(`${f} does not cover this place`)}catch(g){p=g}throw p}finer(e,t,i){if(e.width<Qt.MESH_FROM_VERTICES||e.height<Qt.MESH_FROM_VERTICES)return e;const n=(s,r)=>{const a=Math.ceil(s/Qt.FINE_SPACING_M),l=Math.max(r-1,Math.min(Qt.MAX_SEGMENTS,a));return l%2===0?l:l+1};return{width:n(t,e.width)+1,height:n(i,e.height)+1}}async raster(e,t,i){const n=new URLSearchParams({SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",LAYERS:i,STYLES:"",CRS:"EPSG:4326",BBOX:[e.south,e.west,e.north,e.east].map(r=>r.toFixed(6)).join(","),WIDTH:String(t.width),HEIGHT:String(t.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 Rp.parse(await s.arrayBuffer())}async heights(e,t,i){const n=await this.raster(e,t,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(e,t,i,n){if(!(!n||n.length<2)&&!(!(e.values instanceof Float32Array)||!e.values.some(s=>s>Qt.NO_DATA_BELOW)))try{const s=(await this.geoplatform.elevatedRoadLines({west:t.west,south:t.south,east:t.east,north:t.north})).filter(v=>va.follows(n,v));if(s.length===0)return;const r=await this.raster(t,i,Qt.CLASS_LAYER);if(r.samples<3||r.width!==e.width||r.height!==e.height)return;const a=(v,[b,M,y])=>r.values[v*r.samples]===b&&r.values[v*r.samples+1]===M&&r.values[v*r.samples+2]===y,l=e.width,c=e.height,h=new Uint8Array(l*c);let d=!1;for(let v=0;v<h.length;v++)a(v,Qt.DECK)&&(h[v]=1,d=!0);if(!d)return;const u=Qt.DECK_END_PIXELS,p=[];for(let v=0;v<h.length;v++){if(h[v]!==1)continue;const b=v%l,M=(v-b)/l;for(let y=-u;y<=u;y++)for(let x=-u;x<=u;x++){const S=b+x,A=M+y;if(S<0||A<0||S>=l||A>=c)continue;const w=A*l+S;h[w]===0&&a(w,Qt.NO_CLASS)&&p.push(w)}}for(const v of p)h[v]=1;const f=this.paint(s,t,l,c),g=this.touching(h,f,l,c);if(g.every(v=>v===0))return;const m=await this.heights(t,i,Qt.SURFACE_LAYER);if(m.width!==l||m.height!==c)return;for(let v=0;v<g.length;v++){if(g[v]===0)continue;const b=m.values[v];Number.isFinite(b)&&b>Qt.NO_DATA_BELOW&&b>e.values[v]&&(e.values[v]=b)}}catch{}}paint(e,t,i,n){const s=new Uint8Array(i*n),r=l=>(l-t.west)/(t.east-t.west)*i,a=l=>(t.north-l)/(t.north-t.south)*n;for(const l of e)for(let c=0;c<l.length-1;c++){const h=r(l[c].lng),d=a(l[c].lat),u=r(l[c+1].lng),p=a(l[c+1].lat),f=Math.max(1,Math.ceil(Math.hypot(u-h,p-d)*2));for(let g=0;g<=f;g++){const m=Math.floor(h+(u-h)*g/f),v=Math.floor(d+(p-d)*g/f);for(let b=-1;b<=1;b++)for(let M=-1;M<=1;M++){const y=m+M,x=v+b;y>=0&&x>=0&&y<i&&x<n&&(s[x*i+y]=1)}}}return s}touching(e,t,i,n){const s=new Uint8Array(e.length),r=new Uint8Array(e.length);for(let a=0;a<e.length;a++){if(e[a]===0||r[a]===1)continue;const l=[],c=[a];r[a]=1;let h=!1;for(;c.length>0;){const d=c.pop();l.push(d),t[d]===1&&(h=!0);const u=d%i,p=(d-u)/i;for(let f=-1;f<=1;f++)for(let g=-1;g<=1;g++){const m=u+g,v=p+f;if(m<0||v<0||m>=i||v>=n)continue;const b=v*i+m;e[b]===1&&r[b]===0&&(r[b]=1,c.push(b))}}if(h)for(const d of l)s[d]=1}return s}sample(e,t,i,n,s,r){const{width:a,height:l}=t,c=new Float32Array(a*l),h=new Uint8Array(a*l),d=Math.min(r.x,this.maxWindowM)/s.x,u=Math.min(r.y,this.maxWindowM)/s.y;let p=0;for(let f=0;f<l;f++){const g=i.north+(i.south-i.north)*(l===1?.5:f/(l-1)),m=(n.north-g)/(n.north-n.south)*e.height-.5;for(let v=0;v<a;v++){const M=(i.west+(i.east-i.west)*(a===1?.5:v/(a-1))-n.west)/(n.east-n.west)*e.width-.5,y=d>1||u>1?this.tent(e,M,m,Math.max(1,d),Math.max(1,u)):this.bilinear(e,M,m),x=f*a+v;y===void 0?p++:(c[x]=y,h[x]=1)}}if(!(p===a*l||p/(a*l)>Qt.MAX_HOLE_SHARE))return this.fill(c,h,a,l),c}tent(e,t,i,n,s){let r=0,a=0,l=0;const c=Math.max(0,Math.ceil(i-s)),h=Math.min(e.height-1,Math.floor(i+s)),d=Math.max(0,Math.ceil(t-n)),u=Math.min(e.width-1,Math.floor(t+n));for(let p=c;p<=h;p++){const f=1-Math.abs(p-i)/s;if(!(f<=0))for(let g=d;g<=u;g++){const m=f*(1-Math.abs(g-t)/n);if(m<=0)continue;l+=m;const v=e.at(g,p);!Number.isFinite(v)||v<Qt.NO_DATA_BELOW||(r+=m*v,a+=m)}}return l>0&&a>=l*.5?r/a:void 0}bilinear(e,t,i){const n=Math.max(0,Math.min(e.width-1,Math.floor(t))),s=Math.max(0,Math.min(e.height-1,Math.floor(i))),r=Math.min(e.width-1,n+1),a=Math.min(e.height-1,s+1),l=Math.max(0,Math.min(1,t-n)),c=Math.max(0,Math.min(1,i-s)),h=e.at(n,s),d=e.at(r,s),u=e.at(n,a),p=e.at(r,a);for(const m of[h,d,u,p])if(!Number.isFinite(m)||m<Qt.NO_DATA_BELOW)return;const f=h+(d-h)*l,g=u+(p-u)*l;return f+(g-f)*c}fill(e,t,i,n){let s=t.reduce((r,a)=>r+(a?0:1),0);for(;s>0;){const r=[];for(let a=0;a<n;a++)for(let l=0;l<i;l++){const c=a*i+l;if(t[c])continue;let h=0,d=0;for(let u=-1;u<=1;u++)for(let p=-1;p<=1;p++){const f=a+u,g=l+p;f<0||g<0||f>=n||g>=i||!t[f*i+g]||(h+=e[f*i+g],d++)}d>0&&r.push([c,h/d])}if(r.length===0)return;for(const[a,l]of r)e[a]=l,t[a]=1;s-=r.length}}}class mE{providers;constructor(...e){this.providers=e}async getElevationGrid(e,t,i){let n=new Error("No source of relief to ask");for(const s of this.providers)try{return await s.getElevationGrid(e,t,i)}catch(r){n=r}throw n}}const nu=256,gE=5;async function iw(o,e,t,i){const n=(o.south+o.north)/2,s=(o.west+o.east)/2,r=Math.abs(yt(n,o.east,n,o.west).x),a=Math.abs(yt(o.north,s,o.south,s).z),l=Math.max(r,a),{zoom:c,gridSize:h}=vE(n,l,Math.max(e.width,e.height)),{tiles:d,bounds:u}=ew(s,n,c,h),p=h*nu,f=document.createElement("canvas");f.width=p,f.height=p;const g=f.getContext("2d");if(!g)throw new Error("2D canvas context unavailable");const m=d[0];await Promise.all(d.map(async y=>{const x=t(y),S=await i(x);if(!S.ok)throw new Error(`Imagery tile fetch failed (${S.status}): ${x}`);const A=await createImageBitmap(await S.blob());g.drawImage(A,(y.x-m.x)*nu,(y.y-m.y)*nu)}));const v=Math.min(Math.max(e.width,e.height),p);if(v===p)return{source:f,width:p,height:p,bounds:u};const b=document.createElement("canvas");b.width=v,b.height=v;const M=b.getContext("2d");if(!M)throw new Error("2D canvas context unavailable");return M.drawImage(f,0,0,p,p,0,0,v,v),{source:b,width:v,height:v,bounds:u}}function vE(o,e,t){let i=cE(o,e/Math.max(1,t)),n=a1(o,i,e);for(;n>gE&&i>0;)i--,n=a1(o,i,e);return{zoom:i,gridSize:n,mPerPixel:jM(o,i)/nu}}function a1(o,e,t){const i=Math.ceil(t/2/jM(o,e));return Math.max(3,2*i+1)}class nw{attribution="Imagery © Esri, Maxar, Earthstar Geographics, and the GIS User Community";fetchImpl;tileUrlTemplate;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.tileUrlTemplate=e.tileUrlTemplate??"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}async getImageryTexture(e,t){return iw(e,t,i=>this.tileUrlTemplate.replace("{z}",String(i.z)).replace("{y}",String(i.y)).replace("{x}",String(i.x)),this.fetchImpl)}}class Ll{static ENDPOINTS=["https://overpass-api.de/api/interpreter","https://overpass.kumi.systems/api/interpreter","https://overpass.private.coffee/api/interpreter"];fetchImpl;endpoints;constructor(e={}){this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.endpoints=e.endpoints??Ll.ENDPOINTS}static queue=Promise.resolve();static RETRY_MS=4e3;query(e){return this.queued(()=>this.ask(e))}queued(e){const t=Ll.queue.then(e,e);return Ll.queue=t.catch(()=>{}),t}async ask(e){let t;for(const i of this.endpoints)for(let n=0;n<2;n++){try{const s=await this.fetchImpl(`${i}?data=${encodeURIComponent(e)}`);if(s.ok)return await s.json();if(t=new Error(`${new URL(i).host} refused (${s.status})`),s.status!==429&&s.status!==504)break}catch(s){t=new Error(`${new URL(i).host} unreachable (${String(s)})`);break}await new Promise(s=>setTimeout(s,Ll.RETRY_MS))}throw t??new Error("No Overpass instance answered")}}class ya{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(e={}){this.client=new Ll(e)}async getRoads(e){const t=`${e.south},${e.west},${e.north},${e.east}`,i=`[out:json][timeout:30];way["highway"~"^(${ya.DRIVABLE.join("|")})$"](${t});out geom;`;return this.waysFrom(await this.client.query(i))}waysFrom(e){const t=[];for(const i of e.elements??[]){const n=i.geometry,s=i.tags;!s||!n||n.length<2||t.push({id:`osm-${i.id??t.length}`,name:s.name,surface:ya.surfaceOf(s),widthM:ya.widthOf(s),...ya.paintOf(s),points:n.map(r=>({lat:r.lat,lng:r.lon}))})}return t}static paintOf(e){const t=e.highway??"",i=e.junction==="roundabout"||e.junction==="circular",n=e.oneway,s=n==="yes"||n==="1"||n==="true"||n===void 0&&(t==="motorway"||i),r=n==="-1"||n==="reverse",a=Number.parseInt(e.lanes??"",10),l=Number.parseInt(e.maxspeed??"",10),c=i?"roundabout":t==="motorway"?"motorway":t.endsWith("_link")?"slip":(t==="trunk"||t==="primary")&&(s||r)?"dual":t?"road":void 0;return{...c?{kind:c}:{},...Number.isFinite(a)&&a>0?{lanes:a}:{},...n!==void 0||t==="motorway"||i?{direction:r?"backward":s?"forward":"both"}:{},...Number.isFinite(l)&&l>0?{speedKmh:l}:{}}}static widthOf(e){const t=Number.parseFloat(e.width??e.est_width??"");if(Number.isFinite(t)&&t>0)return t;const i=Number.parseInt(e.lanes??"",10);return Number.isFinite(i)&&i>0?i*3.5:ya.WIDTH_M[e.highway]??ya.DEFAULT_WIDTH_M}static surfaceOf(e){const t=e.surface;return t==="dirt"||t==="earth"||t==="mud"?"dirt":t==="gravel"||t==="fine_gravel"||t==="compacted"||t==="ground"||t==="sand"||t==="unpaved"?"gravel":t?"paved":e.highway==="track"?"gravel":"paved"}}const jp="https://ufoathome.org/roads/index.json";class Ol{attributionRead;contemporaryRead;fetchImpl;indexUrls;fallback;index;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??Ol.defaultIndexUrls(),this.fallback=e.fallback}get attribution(){return this.attributionRead??this.fallback?.attribution??"Roads © OpenStreetMap contributors"}get contemporary(){return this.contemporaryRead??this.fallback?.contemporary??!0}async getRoads(e){const t=await this.held(e);if(t)return t;if(!this.fallback)return[];const i=await this.fallback.getRoads(e);return this.attributionRead=this.fallback.attribution,this.contemporaryRead=this.fallback.contemporary,i}async held(e){let t;try{t=await this.load()}catch{return}const i=t.find(({entry:n})=>n.north>=e.north&&n.south<=e.south&&n.east>=e.east&&n.west<=e.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 e=this.indexUrls.join(`
3018
- `);let t=Ol.shared.get(e);return t||(t=this.fetchFirstAvailable(),Ol.shared.set(e,t),t.then(i=>{i.length===0&&Ol.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.123.0")}`,t=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(t&&t!==jp?[t,jp]:[jp]).map(i=>i+e)}}class xa{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(e={}){this.platform=new ci(e)}static covers(e){return ci.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRoads(e){return(await this.platform.roads(e)).flatMap((i,n)=>xa.wayOf(i,n))}static wayOf(e,t){if(e.geometry.type!=="LineString")return[];const i=e.geometry.coordinates.map(([u,p])=>({lat:p,lng:u}));if(i.length<2)return[];const n=String(e.properties.nature??""),s=xa.BY_NATURE[n]??xa.DEFAULT,r=Number(e.properties.largeur_de_chaussee),a=Number(e.properties.nombre_de_voies),l=Number(e.properties.vitesse_moyenne_vl),c=xa.DIRECTIONS[String(e.properties.sens_de_circulation??"")],h=xa.KINDS[n],d=[e.properties.cpx_toponyme_route_nommee,e.properties.nom_voie_ban_gauche,e.properties.nom_voie_ban_droite].find(u=>typeof u=="string"&&u.length>0);return[{id:String(e.properties.cleabs??`ign-${t}`),...d?{name:d}:{},surface:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.widthM,...e.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...c?{direction:c}:{},...Number.isFinite(l)&&l>0?{speedKmh:l}:{},points:i}]}}class yE{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(e){if(xa.covers(e))try{const t=await this.regional.getRoads(e);if(t.length>0)return t}catch{}return this.worldwide.getRoads(e)}}function bE(){return{elevation:sw(),imagery:rw(),roads:ME()}}function sw(){return new mE(new Qt,new tw)}function rw(){return new nw}function ME(){return new Ol({fallback:new yE(new xa,new ya)})}const wE=new Set,ql="show-observer-map",Kl="hide-milestones";class At extends HTMLElement{static get observedAttributes(){return["src",ql,Kl]}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;static OBSERVER_MAP_MIN_SPAN_M=400;static OBSERVER_MAP_MARGIN=.6;static OBSERVER_MAP_IMAGERY_PX=768;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 Mi;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=_p.create();issues=[];issueCheck=0;sightingAudio=new eE;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>At.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=$M;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const e=this.controlsRow,t=e.classList.contains("more-open"),i=()=>e.scrollWidth>e.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,e.classList.remove("narrow","more-open","nomoments","compact","tiny"),e.clientWidth>0&&i()){e.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(s)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");At.setIcon(this.moreButton,e?Ze.UNFOLDED:Ze.FOLDED);const t=e?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=t,this.moreButton.setAttribute("aria-label",t),this.moreButton.setAttribute("aria-expanded",String(e))}addControl(e){this.controlsRight.insertBefore(e,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=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),i=t&&this.shapeAt(t.x,t.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=`${e.clientX-s.left+12}px`,this.tooltip.style.top=`${e.clientY-s.top+12}px`};handleObserverMapPointerMove=e=>{if(this.dragObserverMap(e))return;const t=this.observerMapTargetFrom(e);if(!t){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(e,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(e,t.label)};showObserverMapTooltip(e,t){this.tooltip.textContent=t,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-i.left+12}px`,this.tooltip.style.top=`${e.clientY-i.top+12}px`}handleObserverMapClick=e=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const t=this.observerMapTargetFrom(e);if(!t){this.observerPlacing&&this.placeObserverFrom(e);return}if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(e){const t=this.observerMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.observerMapRenderer.hitTest((e.clientX-t.left)/t.width*this.observerMapCanvas.width,(e.clientY-t.top)/t.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=e=>{e.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,moved:!1})};handleObserverMapPointerUp=e=>{const t=this.observerMapDrag;!t||t.pointerId!==e.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),t.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(e.pointerId)&&this.observerMapCanvas.releasePointerCapture(e.pointerId)))};dragObserverMap(e){const t=this.observerMapDrag;if(!t||t.pointerId!==e.pointerId)return!1;if(!t.moved){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<At.OBSERVER_MAP_DRAG_PX)return!1;t.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(e.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((e.clientX-t.lastX)/i.width,(e.clientY-t.lastY)/i.height),this.observerMapViewChanged()),t.lastX=e.clientX,t.lastY=e.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=e=>{e.preventDefault();const t=this.observerMapCanvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=e.deltaMode===0?e.deltaY:e.deltaY*40;this.zoomObserverMap((e.clientX-t.left)/t.width,(e.clientY-t.top)/t.height,Math.exp(-i*.002))};zoomObserverMap(e,t,i){this.observerMapView.zoomAt(e,t,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=Mi.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=Mi.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},At.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(e){const t=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!t||i.width===0||i.height===0)return;const n=Mi.pointAt(t,(e.clientX-i.left)/i.width,(e.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 e=document.createElement("template");e.innerHTML=`<style>${ZS}</style>${KS}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new dc(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",t=>{t.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 so(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",t=>{t.key!=="Enter"&&t.key!==" "||(t.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.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",t=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(t),this.beginTouchScrub(t)}),this.seekInput.addEventListener("pointerup",t=>{this.seekSnapArmed=!1,this.endTouchScrub(t)}),this.seekInput.addEventListener("pointercancel",t=>this.endTouchScrub(t)),this.seekInput.addEventListener("pointermove",t=>{this.nameMarkUnder(t),this.hoverSeek(t),this.touchScrub(t)}),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 t of["touchend","click"])this.stageElement.addEventListener(t,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",t=>{if(this.enableClickToPlay){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}t.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",t=>{this.enableClickToPlay&&(t.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),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 e=this.getAttribute("src");e&&this.loadFromSrc(e)}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(e,t,i){e==="src"&&i&&i!==t&&this.isConnected&&this.loadFromSrc(i),e===ql&&this.applyObserverMapDefault(),e===Kl&&this.setMilestonesShown(!this.hasAttribute(Kl))}async loadFromSrc(e){this.sightingData=await ho.json(e)}get sightingData(){return tE(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=iE(e),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(e,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault()}set playerTitle(e){this.titleOverride=e,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const e=this.said.read(this.titleOverride)??this.currentSighting.observer?.title??"";this.playerTitleBox.textContent=e,this.playerTitleBox.hidden=e===""}get recordingIssues(){return this.issues}async reportIssues(e,t){const i=++this.issueCheck;let n=[];try{const{default:s}=await _e(async()=>{const{default:r}=await import("./sightingSchema-kkSSrggd.js");return{default:r}},[],import.meta.url);n=new Os(s).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...n,...t.loadIssues],uc.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(xE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const e=this.issues.length;this.issuesBox.hidden=e===0,this.shadow.getElementById("issues-count").textContent=String(e);const t=this.messages.recordingIssues.replace("{count}",String(e));this.issuesButton.title=t,this.issuesButton.setAttribute("aria-label",t),this.shadow.getElementById("issues-title").textContent=t,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=uc.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){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.dispatchEvent(new CustomEvent("playrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(e){if(e!==this.clockHeld){if(this.clockHeld=e,e){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(e){this.toolbar.classList.toggle("hidden",!e),e?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(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==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)}hostControls(e){const t=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(e)for(const i of t)e.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of t)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 e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity));for(const t of[...this.referenceViews.keys()])e.some(i=>i.id===t)||this.referenceViews.delete(t);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(e){let t=this.referenceViews.get(e.id);return t||(t={shown:!0,opacity:e.opacity},this.referenceViews.set(e.id,t)),t}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=e=>{const t=e.composedPath();t.includes(this.referencesMenu)||t.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=e=>{e.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const e=this.referencesButton.getBoundingClientRect(),t=this.referencesMenu,i=4;t.style.bottom=`${Math.max(i,window.innerHeight-e.top+i)}px`,t.style.top="auto";const n=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),n=this.said.read(t.title)??t.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 l=document.createElement("span");l.textContent=n,l.title=n,r.append(a,l);const c=document.createElement("input");return c.type="range",c.min="0",c.max="1",c.step="0.05",c.value=String(i.opacity),c.title=this.messages.referenceOpacity,c.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),c.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,c.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),c.addEventListener("input",()=>{i.opacity=Number(c.value),this.dispatchReferenceView()}),s.append(r,c),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...e)}updateReferencesButton(){const e=this.currentSighting.references.length>0,t=this.severalReferences,i=t?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState||t,this.referencesButton.setAttribute("aria-pressed",String(i)),t?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),At.setIcon(this.referencesButton,i?Ze.PICTURES_ON:Ze.PICTURES_OFF);const n=t?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)),At.setIcon(this.tracesButton,this.tracesShownState?Ze.TRACES_ON:Ze.TRACES_OFF);const e=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=e,this.tracesButton.setAttribute("aria-label",e)}dispatchReferenceView(){const e=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(t=>[t.id,{...this.viewOfReference(t)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:e}}))}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Po(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/e,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(e,t.map(i=>i.t)),this.refreshMomentsPicker(t)}refreshMomentsPicker(e){const t=this.milestonesShown&&e.length>0;this.momentsBox.hidden=!t,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...e.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(e){const i=(e?this.said.read(e.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=e!==void 0&&Number(n.dataset.t)===e.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=e=>{if(!this.momentsMenu.hidden){if(e instanceof KeyboardEvent){e.key==="Escape"&&this.closeMomentsMenu();return}e.composedPath().some(t=>t===this.momentsMenu||t===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(e,t){const n=[0,...this.milestonesShown&&e>0?[...new Set(t.filter(r=>r>0&&r<e))].sort((r,a)=>r-a):[],Math.max(e,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 l=document.createElement("i");l.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(l,c),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:c,hover:l})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,n=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintSeekProgress(e){for(const i of this.seekSegmentList)i.played.style.width=At.fillOf(i,e);const t=this.player.seekableDuration;this.seekDot.style.left=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`}hoverSeek(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=At.fillOf(p,s),p.element.classList.toggle("hovered",s>=p.start&&(s<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],l=a.length>0?Kp(a,s):void 0,c=l?this.said.read(l.label)??"":"",h=l?this.said.read(l.note):void 0,d=h?`${c} — ${h}`:c;this.seekPreviewTitle.textContent=d,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const e of this.seekSegmentList)e.hover.style.width="0",e.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(e){const t=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=t===void 0,t?.(e,this.seekPreviewCanvas)}paintChrome(e){const t=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(!t||typeof t.setTransform!="function"||n===0||s===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),l=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==l&&(this.chromeCanvas.height=l),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,a,l),this.chromeDirty=!1,i&&(t.setTransform(a/this.canvas.width,0,0,l/this.canvas.height,0,0),this.chromeRenderer??=new dc(t),this.chromeDirty=!0,e(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(e){if(e.pointerType!=="mouse"){this.scrubbingPointer=e.pointerId;try{this.seekInput.setPointerCapture(e.pointerId)}catch{}this.seekToPointer(e)}}touchScrub(e){e.pointerId===this.scrubbingPointer&&this.seekToPointer(e)}endTouchScrub(e){e.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(e))}seekToPointer(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(t<=0||i<=0)return;const n=At.MARK_SNAP_PX/i*t;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>n||(!s||Math.abs(a-e)<Math.abs(s.t-e))&&(s={t:a,name:r.title})}return s}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=(e.clientX-t.left)/t.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?Kp(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,this.showCurrentMoment(t),!t)return;const i=document.createElement("b");i.textContent=this.said.read(t.label)??"";const n=this.said.read(t.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(e=this.currentTime){const t=zs.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<At.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(At.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/At.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/At.EXPOSURE_STEP_PX),s=Math.min(At.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(t.fromMs+t.ms*a/(s-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),n=this.shapesAt(e+t);let s=0;for(const[r,a]of i){const l=n.get(r);if(!l)continue;const c=l.bounds.x+l.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=l.bounds.y+l.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(c,h))}return s}shapeAt(e,t,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,e,t,i);if(s)return s}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Ut.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:wE;this.canvasRenderer.setStarPoints(Ut.starPointsOf(this.sighting.instrument));const n=(ot(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const l of s)for(const[,c]of l.shapes){const h=l.share,d=h===1?c:{...c,transparency:1-(1-c.transparency)*h};this.canvasRenderer.paintShape(this.shifted(d,r))}for(const[l,c]of s[0].shapes)!this.selectionShown||!i.has(l)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));const a=this.selectionShown&&i.size>1?kt.groupBoundsFor([...t].filter(([l])=>i.has(l)).map(([,l])=>l.bounds)):void 0;this.chromeDraw=l=>{a&&l.paintGroupHandles(a),this.overlayPainter?.(l)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(l=>[...l.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(e),this.paintSeekProgress(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintObserverMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(pg(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new jS(this.currentSighting.timeline,(t,i)=>this.onFrame(t,i));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=e=>{e.key.toLowerCase()!=="f"||e.altKey||e.ctrlKey||e.metaKey||!this.enableClickToPlay||e.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(e.preventDefault(),this.toggleFullscreen())};handleSeekKey=e=>{if(e.altKey||e.ctrlKey||e.metaKey)return;const t=e.key==="ArrowLeft"?-1:e.key==="ArrowRight"?1:0;if(t){e.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+t*At.SEEK_KEY_STEP_MS)))}else e.key===" "&&(e.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 e=this.playbackFlash;e.innerHTML=this.player.playbackState==="playing"?Ze.PLAY:Ze.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){At.icons.get(e)!==t&&(At.icons.set(e,t),e.innerHTML=t)}set captionHeld(e){this.stageElement.classList.toggle("caption-held",e)}set controlsHeld(e){this.stageElement.classList.toggle("controls-held",e)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(e){this.quietControlsValue=e,this.stageElement.classList.toggle("quiet",e)}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},At.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!e),e!==this.wasPlaying&&e&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=e,At.setIcon(this.playPauseButton,e?Ze.PAUSE:Ze.PLAY);const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const i=t?e?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 e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const e=this.observerMapPanel.hidden;this.observerMapAsked=e,this.setObserverMapOpen(e),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:e}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const e=this.getAttribute(ql),t=e===null?this.sighting.observerMap??this.observerPath?.travels===!0:e!=="false";this.setObserverMapOpen(t&&this.observerPath!==void 0)}setObserverMapOpen(e){this.observerMapPanel.hidden=!e,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(e)),this.updateObserverMapButton(),e&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const e=!this.observerMapPanel.hidden;At.setIcon(this.observerMapButton,e?Ze.MAP_ON:Ze.MAP_OFF);const t=e?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=t,this.observerMapButton.setAttribute("aria-label",t);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 e=this.observerPath!==void 0;if(this.observerPath=Yl.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!e&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const t=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=Mi.including(this.observerPath.boundsAround(At.OBSERVER_MAP_MIN_SPAN_M,At.OBSERVER_MAP_MARGIN),t);(!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(e,t){const i=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<i&&Math.abs(e.south-t.south)<i&&Math.abs(e.west-t.west)<i&&Math.abs(e.east-t.east)<i}async loadObserverMapImagery(){const e=this.observerMapViewBounds;if(!e||this.observerMapPanel.hidden||this.observerMapImageryLoading||!this.observerMapImageryNeededFor(e))return;const t=this.observerMapView.changed,i=t?Mi.expand(e,At.OBSERVER_MAP_IMAGERY_AHEAD):e,n=At.OBSERVER_MAP_IMAGERY_PX*(t?1+2*At.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const s=rw();try{const r=await s.getImageryTexture(i,{width:n,height:n});if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=r,this.observerMapImageryCredit=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(e){const t=this.observerMapImageryBounds;if(!t)return!0;const i=this.observerMapImagery?.bounds??t,n=this.observerMapView.changed?Mi.expand(e,At.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const e=this.observerMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],i=(c,h,d)=>{for(const u of t)if(!(u.x+u.width<c-d||u.x>h+d)&&!(u.y>e.bottom+d||u.y+u.height<e.top-d))return!0;return!1},n=[this.canvas.width-e.width,this.canvas.width],s=[0,e.width],r=At.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),l=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&l&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(l||!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 e=this.observerMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==t&&(this.observerMapCanvas.width=t,this.observerMapCanvas.height=t)}measureObserverMapBox(){const e=this.observerMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=this.canvas.width/t.width,n=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*n,bottom:(e.bottom-t.top)*n}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=ot(this.currentSighting,e);t?.lat!==void 0&&t.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:t.lat,lng:t.lng},At.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?Kp(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?Po(this.currentSighting.milestones):[]){const a=ot(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:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?$s.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Ut.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(e),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.momentsBox.hidden=!e||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,Po(this.sighting.milestones).map(t=>t.t)),this.milestonesButton.setAttribute("aria-pressed",String(e)),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,At.setIcon(this.milestonesButton,this.milestonesShown?Ze.MILESTONES_ON:Ze.MILESTONES_OFF);const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}observerMapDecorAt(e){const t=ot(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Xs(i,e),{lat:s,lng:r}=fs(n.eastM,-n.northM,t.lat,t.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.observerMapNightFraction&&(this.observerMapNightFraction=t,this.paintObserverMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,i=this.lookPitchDeg+e.pitchDeg;if(t===0&&i===0)return{x:0,y:0};const n=ot(this.currentSighting,this.currentTime),s=$s.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(t),y:s.angleDegToRadiusPx(i)}}gaitAt(e){return Yt.bodyAt(this.currentSighting,e,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(e){e!==this.mutedState&&(this.mutedState=e,!e&&this.volumeState===0&&(this.volumeState=At.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(e){this.setVolume(e)}setVolume(e){this.volumeState=Math.min(Math.max(e,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 e=!this.hasSound;if(this.muteButton.disabled=e,this.volumeInput.hidden=e,e){At.setIcon(this.muteButton,Ze.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}At.setIcon(this.muteButton,this.mutedState?Ze.MUTED:Ze.VOLUME);const t=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=t,this.muteButton.setAttribute("aria-label",t),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;At.setIcon(this.fullscreenButton,e?Ze.EXIT_FULLSCREEN:Ze.ENTER_FULLSCREEN),this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new zn(Is.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=yh(Is.preferencesFor(this),Sh);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await SS(e);this.messagesLanguage===e&&this.applyMessages(t)}messagesLanguage;updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t,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(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const e=this.currentSighting.event,t=cc(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?_m(e.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return jh(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?l1(o1(this.realStartMs+i)):jh(i)}formatEndOfTimeline(){return this.realDurationMs===void 0?jh(this.currentSighting.timeline.duration):this.canShowClockTime?l1(o1(this.realStartMs+this.realDurationMs)):jh(this.realDurationMs)}}function o1(o){const e=new Date(o);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function l1(o){if(o.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return o.second?`${e(o.hour)}:${e(o.minute??0)}:${e(o.second)}`:`${e(o.hour)}:${e(o.minute??0)}`}function jh(o){const e=Math.round(o/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Om="rr0-ufo";function Cp(){customElements.get(Om)||customElements.define(Om,At)}const xE="recordingissues";class rh{constructor(e,t){this.seekInput=e,this.layer=t,e.addEventListener("pointerdown",i=>{this.snapArmed=!0,this.nameMarkUnder(i)}),e.addEventListener("pointerup",()=>this.snapArmed=!1),e.addEventListener("pointermove",i=>this.nameMarkUnder(i)),e.addEventListener("pointerleave",()=>e.removeAttribute("title"))}static SNAP_PX=6;marks=[];duration=0;drawn="";snapArmed=!1;show(e,t){const i=t>0?[...e].sort((s,r)=>s.t-r.t):[],n=`${t}|${i.map(s=>`${s.kind}:${s.t}:${s.label}`).join("|")}`;n!==this.drawn&&(this.drawn=n,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(s=>{const r=document.createElement("span");return r.className=`timeline-mark ${s.kind}`,r.style.left=`${Math.min(Math.max(s.t/t,0),1)*100}%`,r})))}snap(e){return this.snapArmed?(this.snapArmed=!1,this.markNear(e)?.t??e):e}next(e){return this.marks.find(t=>t.t>e+rh.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-rh.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=rh.SNAP_PX/t*this.duration;let n;for(const s of this.marks)Math.abs(s.t-e)>i||(!n||Math.abs(s.t-e)<Math.abs(n.t-e)||s.t===n.t&&s.kind==="milestone")&&(n=s);return n}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect();if(t.width<=0||this.duration<=0)return;const i=this.marksNear((e.clientX-t.left)/t.width*this.duration);i?this.seekInput.title=i:this.seekInput.removeAttribute("title")}marksNear(e){const t=this.markNear(e);if(t)return[...new Set(this.marks.filter(i=>i.t===t.t).map(i=>i.label))].join(" · ")}}class Pl{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const n=e.event.place?.[0],s=e.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=yt(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(t-Pl.HALF_SPAN_MS),l=r(t+Pl.HALF_SPAN_MS),c=r(t);if(!a||!l||!c)return 0;const h=Math.hypot(l.eastM-a.eastM,l.northM-a.northM),d=2*Pl.HALF_SPAN_MS/1e3;if(h/d<Pl.MIN_SPEED_MS)return 0;const u=i.heightAt(l.eastM,l.northM)-i.heightAt(a.eastM,a.northM),p=Math.atan2(u,h)*180/Math.PI;if(c.heading===void 0)return p;const f=Math.atan2(l.eastM-a.eastM,l.northM-a.northM)*180/Math.PI;return p*Math.max(0,Math.cos((c.heading-f)*Math.PI/180))}}const SE=.08,c1=.15,h1=2,EE=2e3;class AE{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(e){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",e);return}}Oo.unlock(this.context),this.apply()}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}setPaused(e){e!==this.paused&&(this.paused=e,this.apply())}setVoices(e){this.requested=e,this.apply()}dispose(){for(const e of[...this.voices.keys()])this.release(e);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}apply(){const e=this.context;if(!e)return;const t=this.paused?[]:this.requested.filter(n=>n.inside||n.distanceM<EE),i=new Set(t.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of t){const s=this.voices.get(n.id)??this.build(e,n.id);this.retarget(e,s,n)}}build(e,t){const i=e.createGain();i.gain.value=0;const n=e.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(e));const s=e.createOscillator();s.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),l=e.createBiquadFilter();l.type="lowpass",l.frequency.value=900,s.connect(l),r.connect(l),l.connect(a).connect(n);const c=()=>{const x=e.createBufferSource();return x.buffer=this.noise(e),x.loop=!0,x.loopStart=Math.random()*h1*.5,x},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(n);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const g=e.createGain();p.connect(f).connect(g).connect(n);const m=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const b=e.createGain();m.connect(v).connect(b).connect(n);const M=[s,r,h,p,m];for(const x of M)x.start();const y={nodes:[i,n,a,l,d,u,f,g,v,b,...M],sources:M,firing:s,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:g,windGain:b,cabin:n,output:i};return this.voices.set(t,y),y}retarget(e,t,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:l}){const c=e.currentTime,h=(b,M)=>b.setTargetAtTime(M,c,SE),d=n.rpm/60,u=d*i.cylinders/2,p=Math.min(1,n.rpm/i.shiftUpRpm),f=Math.min(1.5,n.speedMps/30);h(t.firing.frequency,u),h(t.crank.frequency,d),h(t.knock.frequency,u*3),h(t.engineGain.gain,i.engineGain*(.25+.75*n.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const g=!r||a;h(t.windGain.gain,f**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+l/60);h(t.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(l,1));h(t.output.gain,v*s)}release(e){const t=this.voices.get(e);if(!t)return;this.voices.delete(e);const i=this.context;i&&(t.output.gain.setTargetAtTime(0,i.currentTime,c1/3),setTimeout(()=>{for(const n of t.sources)try{n.stop()}catch{}for(const n of t.nodes)n.disconnect()},c1*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*h1,e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Th{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(e){return Th.BY_KIND[e??"generic"]??Th.BY_KIND.generic}}class To{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,n){const s=To.SAMPLE_MS,r=[];for(let c=i;c<=n+s/2;c+=s){const h=t(c-s/2),d=t(c+s/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(s/1e3))}const a=[];let l=1;for(let c=0;c<r.length;c++){const h=r[c],d=(r[Math.min(c+1,r.length-1)]-r[Math.max(c-1,0)])/(2*s/1e3);if(h<To.STANDING_MPS){l=1,a.push({speedMps:h,rpm:e.idleRpm,load:.1,gear:0});continue}const u=h*3.6,p=v=>u/e.kmhPer1000Rpm[v-1]*1e3;for(;l<e.kmhPer1000Rpm.length&&p(l)>e.shiftUpRpm;)l++;for(;l>1&&p(l)<e.shiftDownRpm;)l--;const f=Math.max(p(l),e.idleRpm*(1+.3*Math.min(1,h/3))),g=.15+.5*Math.min(1,(h/35)**2),m=d>.15?Math.min(1,g+d/2.5):d<-.3?.05:g;a.push({speedMps:h,rpm:f,load:m,gear:l})}return new To(a,i)}at(e){const t=(e-this.startMs)/To.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),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(t-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 Wu{drives=new Map;at(e,t){const i=[],n=e.event.place?.[0],s=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??n?.lat,u=h?.lng??n?.lng;if(d===void 0||u===void 0||!n)return;const p=yt(d,u,n.lat,n.lng);return{eastM:p.x,northM:-p.z}},r=Math.max(e.observerTrack.duration,(e.event.durationSeconds??0)*1e3),a=e.vehicle;if(a){const c=Th.of(a.kind),h=this.drive(`observer:${a.kind}`,Wu.trackKey(e),()=>To.of(c,s,0,r));h&&i.push({id:"observer",profile:c,state:h.at(t),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const l=s(t);for(const c of e.decor){if(!c.engine||!l)continue;const h=Th.of(c.engine.kind),d=g=>{const m=Xs(c,g);return{eastM:m.eastM,northM:m.northM}},u=this.drive(`decor:${c.id}`,Wu.decorKey(c,r),()=>To.of(h,d,0,r));if(!u)continue;const p=Xs(c,t),f=Math.hypot(p.eastM-l.eastM,p.northM-l.northM,p.altitudeM);i.push({id:`decor:${c.id}`,profile:h,state:u.at(t),noise:c.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:f})}return i}drive(e,t,i){const n=this.drives.get(e);if(n&&n.key===t)return n.drive;const s=i();return this.drives.set(e,{key:t,drive:s}),s}static trackKey(e){return e.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(e,t){return`${t}|${e.eastM},${e.northM}|`+(e.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const TE="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==",_E=`
3018
+ `);let t=Ol.shared.get(e);return t||(t=this.fetchFirstAvailable(),Ol.shared.set(e,t),t.then(i=>{i.length===0&&Ol.shared.delete(e)})),this.index=t}async fetchFirstAvailable(){for(const e of this.indexUrls)try{const t=await this.fetchImpl(e);if(!t.ok)continue;const i=await t.json();if(Array.isArray(i?.entries))return i.entries.map(n=>({entry:n,indexUrl:e}))}catch{}return[]}static defaultIndexUrls(){const e=`?v=${encodeURIComponent("0.123.1")}`,t=typeof location>"u"?void 0:new URL("/roads/index.json",location.href).href;return(t&&t!==jp?[t,jp]:[jp]).map(i=>i+e)}}class xa{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(e={}){this.platform=new ci(e)}static covers(e){return ci.covers((e.south+e.north)/2,(e.west+e.east)/2)}async getRoads(e){return(await this.platform.roads(e)).flatMap((i,n)=>xa.wayOf(i,n))}static wayOf(e,t){if(e.geometry.type!=="LineString")return[];const i=e.geometry.coordinates.map(([u,p])=>({lat:p,lng:u}));if(i.length<2)return[];const n=String(e.properties.nature??""),s=xa.BY_NATURE[n]??xa.DEFAULT,r=Number(e.properties.largeur_de_chaussee),a=Number(e.properties.nombre_de_voies),l=Number(e.properties.vitesse_moyenne_vl),c=xa.DIRECTIONS[String(e.properties.sens_de_circulation??"")],h=xa.KINDS[n],d=[e.properties.cpx_toponyme_route_nommee,e.properties.nom_voie_ban_gauche,e.properties.nom_voie_ban_droite].find(u=>typeof u=="string"&&u.length>0);return[{id:String(e.properties.cleabs??`ign-${t}`),...d?{name:d}:{},surface:s.surface,widthM:Number.isFinite(r)&&r>0?r:s.widthM,...e.properties.urbain===!0?{urban:!0}:{},...h?{kind:h}:{},...Number.isInteger(a)&&a>0?{lanes:a}:{},...c?{direction:c}:{},...Number.isFinite(l)&&l>0?{speedKmh:l}:{},points:i}]}}class yE{constructor(e,t){this.regional=e,this.worldwide=t}attribution="Roads © IGN, BD TOPO, in France; © OpenStreetMap contributors elsewhere, as drawn today";contemporary=!0;async getRoads(e){if(xa.covers(e))try{const t=await this.regional.getRoads(e);if(t.length>0)return t}catch{}return this.worldwide.getRoads(e)}}function bE(){return{elevation:sw(),imagery:rw(),roads:ME()}}function sw(){return new mE(new Qt,new tw)}function rw(){return new nw}function ME(){return new Ol({fallback:new yE(new xa,new ya)})}const wE=new Set,ql="show-observer-map",Kl="hide-milestones";class At extends HTMLElement{static get observedAttributes(){return["src",ql,Kl]}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;static OBSERVER_MAP_MIN_SPAN_M=400;static OBSERVER_MAP_MARGIN=.6;static OBSERVER_MAP_IMAGERY_PX=768;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 Mi;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=_p.create();issues=[];issueCheck=0;sightingAudio=new eE;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>At.LIVE_BODY_MAX_RATE}selectionShown=!0;overlayPainter;enableClickToPlay=!0;fullscreenTarget;messages=$M;realDurationMs;realStartMs;showClockTime=!0;handleFullscreenChange=()=>{this.updateFullscreenButton(),this.updateMuteButton(),this.resizeObserverMap()};controlsFitObserver=typeof ResizeObserver>"u"?void 0:new ResizeObserver(()=>this.fitControls());controlsMutations;fitControls(){const e=this.controlsRow,t=e.classList.contains("more-open"),i=()=>e.scrollWidth>e.clientWidth+1,n=!this.momentsMenu.hidden;if(this.momentsMenu.hidden=!0,e.classList.remove("narrow","more-open","nomoments","compact","tiny"),e.clientWidth>0&&i()){e.classList.add("narrow");for(const s of["nomoments","compact","tiny"]){if(!i())break;e.classList.add(s)}t&&e.classList.add("more-open")}this.momentsMenu.hidden=!n,this.updateMoreButton()}setControlsFolded(e){this.controlsRow.classList.toggle("more-open",!e),this.updateMoreButton()}updateMoreButton(){const e=this.controlsRow.classList.contains("more-open");At.setIcon(this.moreButton,e?Ze.UNFOLDED:Ze.FOLDED);const t=e?this.messages.fewerControls:this.messages.moreControls;this.moreButton.title=t,this.moreButton.setAttribute("aria-label",t),this.moreButton.setAttribute("aria-expanded",String(e))}addControl(e){this.controlsRight.insertBefore(e,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=e=>{e.key==="Escape"&&this.exitSimulatedFullscreen()};handlePointerMove=e=>{const t=this.canvasPointFromEvent(e),i=t&&this.shapeAt(t.x,t.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=`${e.clientX-s.left+12}px`,this.tooltip.style.top=`${e.clientY-s.top+12}px`};handleObserverMapPointerMove=e=>{if(this.dragObserverMap(e))return;const t=this.observerMapTargetFrom(e);if(!t){if(!this.observerPlacing){this.tooltip.hidden=!0,this.observerMapCanvas.style.cursor="grab";return}this.observerMapCanvas.style.cursor="crosshair",this.showObserverMapTooltip(e,this.messages.placeObserverHere);return}this.observerMapCanvas.style.cursor="pointer",this.showObserverMapTooltip(e,t.label)};showObserverMapTooltip(e,t){this.tooltip.textContent=t,this.tooltip.hidden=!1;const i=this.stageElement.getBoundingClientRect();this.tooltip.style.left=`${e.clientX-i.left+12}px`,this.tooltip.style.top=`${e.clientY-i.top+12}px`}handleObserverMapClick=e=>{if(this.suppressObserverMapClick){this.suppressObserverMapClick=!1;return}const t=this.observerMapTargetFrom(e);if(!t){this.observerPlacing&&this.placeObserverFrom(e);return}if(t.kind==="milestone"&&t.t!==void 0){this.player.seek(t.t);return}this.dispatchEvent(new CustomEvent("lookat",{detail:{lat:t.lat,lng:t.lng,kind:t.kind},bubbles:!0,composed:!0}))};observerMapTargetFrom(e){const t=this.observerMapCanvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return this.observerMapRenderer.hitTest((e.clientX-t.left)/t.width*this.observerMapCanvas.width,(e.clientY-t.top)/t.height*this.observerMapCanvas.height)}handlePointerLeave=()=>{this.tooltip.hidden=!0};handleObserverMapPointerDown=e=>{e.button===0&&(this.suppressObserverMapClick=!1,this.observerMapDrag={pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,moved:!1})};handleObserverMapPointerUp=e=>{const t=this.observerMapDrag;!t||t.pointerId!==e.pointerId||(this.observerMapDrag=void 0,this.observerMapCanvas.classList.remove("dragging"),t.moved&&(this.suppressObserverMapClick=!0,this.paintObserverMap(this.currentTime),this.observerMapCanvas.hasPointerCapture?.(e.pointerId)&&this.observerMapCanvas.releasePointerCapture(e.pointerId)))};dragObserverMap(e){const t=this.observerMapDrag;if(!t||t.pointerId!==e.pointerId)return!1;if(!t.moved){if(Math.hypot(e.clientX-t.startX,e.clientY-t.startY)<At.OBSERVER_MAP_DRAG_PX)return!1;t.moved=!0,this.tooltip.hidden=!0,this.observerMapCanvas.classList.add("dragging"),this.observerMapCanvas.setPointerCapture?.(e.pointerId)}const i=this.observerMapCanvas.getBoundingClientRect();return i.width>0&&i.height>0&&(this.observerMapView.panBy((e.clientX-t.lastX)/i.width,(e.clientY-t.lastY)/i.height),this.observerMapViewChanged()),t.lastX=e.clientX,t.lastY=e.clientY,!0}static OBSERVER_MAP_DRAG_PX=4;handleObserverMapWheel=e=>{e.preventDefault();const t=this.observerMapCanvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=e.deltaMode===0?e.deltaY:e.deltaY*40;this.zoomObserverMap((e.clientX-t.left)/t.width,(e.clientY-t.top)/t.height,Math.exp(-i*.002))};zoomObserverMap(e,t,i){this.observerMapView.zoomAt(e,t,i),this.observerMapViewChanged()}observerMapViewChanged(){this.mapFitButton.hidden=!this.observerMapView.changed,this.mapZoomInButton.disabled=this.observerMapView.zoomFactor>=Mi.MAX_ZOOM,this.mapZoomOutButton.disabled=this.observerMapView.zoomFactor<=Mi.MIN_ZOOM,this.paintObserverMap(this.currentTime),this.scheduleObserverMapImagery()}scheduleObserverMapImagery(){this.observerMapImageryTimer===void 0&&(this.observerMapImageryTimer=setTimeout(()=>{this.observerMapImageryTimer=void 0,this.loadObserverMapImagery()},At.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(e){const t=this.observerMapViewBounds,i=this.observerMapCanvas.getBoundingClientRect();if(!t||i.width===0||i.height===0)return;const n=Mi.pointAt(t,(e.clientX-i.left)/i.width,(e.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 e=document.createElement("template");e.innerHTML=`<style>${ZS}</style>${KS}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.canvas=this.shadow.getElementById("canvas"),this.canvasRenderer=new dc(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",t=>{t.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 so(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",t=>{t.key!=="Enter"&&t.key!==" "||(t.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.volumeInput.addEventListener("input",()=>{this.setVolume(Number(this.volumeInput.value))}),this.fullscreenTarget=this.stageElement,this.playPauseButton.addEventListener("click",()=>this.togglePlayPause()),this.fullscreenButton.addEventListener("click",()=>this.toggleFullscreen()),this.addEventListener("keydown",this.handleFullscreenKey),this.observerMapButton.addEventListener("click",()=>this.toggleObserverMap()),this.referencesButton.addEventListener("click",()=>this.toggleReferences()),this.tracesButton.addEventListener("click",()=>this.toggleTraces()),this.referenceOpacityInput.addEventListener("input",()=>{this.referenceOpacityTouched=!0,this.dispatchReferenceView()}),this.milestonesButton.addEventListener("click",()=>this.toggleMilestones()),this.observerMapCanvas.addEventListener("pointermove",this.handleObserverMapPointerMove),this.observerMapCanvas.addEventListener("pointerleave",this.handlePointerLeave),this.observerMapCanvas.addEventListener("click",this.handleObserverMapClick),this.observerMapCanvas.addEventListener("pointerdown",this.handleObserverMapPointerDown),this.observerMapCanvas.addEventListener("pointerup",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("pointercancel",this.handleObserverMapPointerUp),this.observerMapCanvas.addEventListener("wheel",this.handleObserverMapWheel,{passive:!1}),this.mapZoomInButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,2)),this.mapZoomOutButton.addEventListener("click",()=>this.zoomObserverMap(.5,.5,.5)),this.mapFitButton.addEventListener("click",()=>{this.observerMapView.reset(),this.observerMapViewChanged()}),this.seekInput.addEventListener("input",()=>this.player.seek(this.snapSeekToMark(Number(this.seekInput.value)))),this.seekInput.addEventListener("pointerdown",t=>{this.suspendForScrub(),this.seekSnapArmed=!0,this.nameMarkUnder(t),this.beginTouchScrub(t)}),this.seekInput.addEventListener("pointerup",t=>{this.seekSnapArmed=!1,this.endTouchScrub(t)}),this.seekInput.addEventListener("pointercancel",t=>this.endTouchScrub(t)),this.seekInput.addEventListener("pointermove",t=>{this.nameMarkUnder(t),this.hoverSeek(t),this.touchScrub(t)}),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 t of["touchend","click"])this.stageElement.addEventListener(t,()=>this.sightingAudio.resume(),!0);this.stageElement.addEventListener("pointermove",()=>this.touchedStage()),this.canvas.addEventListener("click",t=>{if(this.enableClickToPlay){if(this.tapRevealedOnly){this.tapRevealedOnly=!1;return}t.detail<=1&&(this.playbackBeforeClick={state:this.playbackState,time:this.currentTime}),this.togglePlayPause()}}),this.canvas.addEventListener("dblclick",t=>{this.enableClickToPlay&&(t.preventDefault(),this.restorePlayback(),this.toggleFullscreen())}),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerleave",this.handlePointerLeave),document.addEventListener("fullscreenchange",this.handleFullscreenChange),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 e=this.getAttribute("src");e&&this.loadFromSrc(e)}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(e,t,i){e==="src"&&i&&i!==t&&this.isConnected&&this.loadFromSrc(i),e===ql&&this.applyObserverMapDefault(),e===Kl&&this.setMilestonesShown(!this.hasAttribute(Kl))}async loadFromSrc(e){this.sightingData=await ho.json(e)}get sightingData(){return tE(this.currentSighting)}set sightingData(e){this.player.stop(),this.soundPreview=void 0,this.sightingAudio.silence(),this.currentSighting=iE(e),this.issuesPanel.hidden=!0,this.issuesButton.setAttribute("aria-expanded","false"),this.reportIssues(e,this.currentSighting),this.observerMapView.reset(),this.mapFitButton.hidden=!0,this.observerMapAsked=!1,this.player=this.createPlayer(),this.syncPlayerTitle(),this.updateTimeLabels(),this.updatePlayPauseButton(),this.refresh(),this.applyObserverMapDefault()}set playerTitle(e){this.titleOverride=e,this.syncPlayerTitle()}titleOverride;syncPlayerTitle(){const e=this.said.read(this.titleOverride)??this.currentSighting.observer?.title??"";this.playerTitleBox.textContent=e,this.playerTitleBox.hidden=e===""}get recordingIssues(){return this.issues}async reportIssues(e,t){const i=++this.issueCheck;let n=[];try{const{default:s}=await _e(async()=>{const{default:r}=await import("./sightingSchema-kkSSrggd.js");return{default:r}},[],import.meta.url);n=new Os(s).issues(e)}catch{}i===this.issueCheck&&(this.issues=[...n,...t.loadIssues],uc.warn(this.issues,t.id),this.renderIssues(),this.dispatchEvent(new CustomEvent(xE,{detail:{issues:this.issues},bubbles:!0,composed:!0})))}renderIssues(){const e=this.issues.length;this.issuesBox.hidden=e===0,this.shadow.getElementById("issues-count").textContent=String(e);const t=this.messages.recordingIssues.replace("{count}",String(e));this.issuesButton.title=t,this.issuesButton.setAttribute("aria-label",t),this.shadow.getElementById("issues-title").textContent=t,this.shadow.getElementById("issues-list").replaceChildren(...this.issues.map(i=>{const n=document.createElement("li");return n.textContent=uc.text(i,this.messages.issueTemplates),n}))}get sighting(){return this.currentSighting}previewSound(e){this.soundPreview=e,this.sightingAudio.resume(),this.sightingAudio.setSound(e)}stopSoundPreview(){this.soundPreview=void 0,this.sightingAudio.silence()}get canvasElement(){return this.canvas}get renderer(){return this.canvasRenderer}get currentTime(){return this.player.time}set currentTime(e){this.player.seek(e)}get seekableDuration(){return this.player.seekableDuration}get autoReplayEnabled(){return this.loopEnabled}set autoReplayEnabled(e){e!==this.loopEnabled&&this.toggleLoop()}play(){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.dispatchEvent(new CustomEvent("playrequest"))}clockHeld=!1;playAfterHold=!1;holdClock(e){if(e!==this.clockHeld){if(this.clockHeld=e,e){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(e){this.toolbar.classList.toggle("hidden",!e),e?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(e){this.currentSighting.event.durationSeconds=e,this.updateTimeLabels(),this.refresh(),this.updatePlayPauseButton()}set selectedSourceIds(e){const t=new Set(e);t.size===this.highlightedSourceIds.size&&[...t].every(n=>this.highlightedSourceIds.has(n))||(this.highlightedSourceIds=t,this.refresh())}hasVisibleShapeAt(e,t){return this.shapeAt(e,t)!==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)}hostControls(e){const t=[this.milestonesButton,this.referencesButton,this.referenceOpacityInput,this.tracesButton,this.observerMapButton];if(e)for(const i of t)e.appendChild(i);else{const i=this.fullscreenButton.parentElement===this.controlsRight?this.fullscreenButton:null;for(const n of t)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 e=this.currentSighting.references;!this.referenceOpacityTouched&&e.length>0&&(this.referenceOpacityInput.value=String(e[0].opacity));for(const t of[...this.referenceViews.keys()])e.some(i=>i.id===t)||this.referenceViews.delete(t);this.severalReferences?this.referencesMenu.hidden||this.renderReferencesMenu():this.closeReferencesMenu(),this.updateReferencesButton(),this.severalReferences&&this.dispatchReferenceView()}viewOfReference(e){let t=this.referenceViews.get(e.id);return t||(t={shown:!0,opacity:e.opacity},this.referenceViews.set(e.id,t)),t}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=e=>{const t=e.composedPath();t.includes(this.referencesMenu)||t.includes(this.referencesButton)||this.closeReferencesMenu()};handleReferencesMenuKey=e=>{e.key==="Escape"&&(this.closeReferencesMenu(),this.referencesButton.focus())};placeReferencesMenu(){const e=this.referencesButton.getBoundingClientRect(),t=this.referencesMenu,i=4;t.style.bottom=`${Math.max(i,window.innerHeight-e.top+i)}px`,t.style.top="auto";const n=t.getBoundingClientRect().width;t.style.left=`${Math.max(i,Math.min(e.left,window.innerWidth-n-i))}px`}renderReferencesMenu(){const e=this.currentSighting.references.map(t=>{const i=this.viewOfReference(t),n=this.said.read(t.title)??t.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 l=document.createElement("span");l.textContent=n,l.title=n,r.append(a,l);const c=document.createElement("input");return c.type="range",c.min="0",c.max="1",c.step="0.05",c.value=String(i.opacity),c.title=this.messages.referenceOpacity,c.setAttribute("aria-label",`${this.messages.referenceOpacity}: ${n}`),c.disabled=!i.shown,a.addEventListener("change",()=>{i.shown=a.checked,c.disabled=!i.shown,this.updateReferencesButton(),this.dispatchReferenceView()}),c.addEventListener("input",()=>{i.opacity=Number(c.value),this.dispatchReferenceView()}),s.append(r,c),s});this.referencesMenu.setAttribute("aria-label",this.messages.referencesMenu),this.referencesMenu.replaceChildren(...e)}updateReferencesButton(){const e=this.currentSighting.references.length>0,t=this.severalReferences,i=t?this.currentSighting.references.some(s=>this.viewOfReference(s).shown):this.referencesShownState;this.referencesButton.hidden=!e,this.referenceOpacityInput.hidden=!e||!this.referencesShownState||t,this.referencesButton.setAttribute("aria-pressed",String(i)),t?this.referencesButton.setAttribute("aria-haspopup","true"):this.referencesButton.removeAttribute("aria-haspopup"),At.setIcon(this.referencesButton,i?Ze.PICTURES_ON:Ze.PICTURES_OFF);const n=t?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)),At.setIcon(this.tracesButton,this.tracesShownState?Ze.TRACES_ON:Ze.TRACES_OFF);const e=this.tracesShownState?this.messages.hideTraces:this.messages.showTraces;this.tracesButton.title=e,this.tracesButton.setAttribute("aria-label",e)}dispatchReferenceView(){const e=this.severalReferences?Object.fromEntries(this.currentSighting.references.map(t=>[t.id,{...this.viewOfReference(t)}])):void 0;this.dispatchEvent(new CustomEvent("referenceview",{detail:{shown:this.referencesShown,opacity:this.referenceOpacity,views:e}}))}refreshMilestoneMarks(){const e=this.player.seekableDuration,t=e>0?Po(this.sighting.milestones):[];this.milestoneMarks.replaceChildren(...t.map(i=>{const n=document.createElement("button");n.type="button",n.className="milestone-mark",n.style.left=`${Math.min(Math.max(i.t/e,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(e,t.map(i=>i.t)),this.refreshMomentsPicker(t)}refreshMomentsPicker(e){const t=this.milestonesShown&&e.length>0;this.momentsBox.hidden=!t,this.closeMomentsMenu(),this.momentsMenu.replaceChildren(...e.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(e){const i=(e?this.said.read(e.label)??"":"")||this.messages.moments;this.momentsCurrent.textContent!==i&&(this.momentsCurrent.textContent=i);for(const n of this.momentsMenu.querySelectorAll("button")){const s=e!==void 0&&Number(n.dataset.t)===e.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=e=>{if(!this.momentsMenu.hidden){if(e instanceof KeyboardEvent){e.key==="Escape"&&this.closeMomentsMenu();return}e.composedPath().some(t=>t===this.momentsMenu||t===this.momentsButton)||this.closeMomentsMenu()}};seekSegmentList=[];refreshSeekSegments(e,t){const n=[0,...this.milestonesShown&&e>0?[...new Set(t.filter(r=>r>0&&r<e))].sort((r,a)=>r-a):[],Math.max(e,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 l=document.createElement("i");l.className="seek-hover";const c=document.createElement("i");c.className="seek-played",a.append(l,c),s.push(a),this.seekSegmentList.push({start:n[r],end:n[r+1],element:a,played:c,hover:l})}this.seekSegments.replaceChildren(...s),this.paintSeekProgress(this.player.time)}static fillOf(e,t){const i=e.end-e.start,n=i>0?(t-e.start)/i:t>=e.end?1:0;return`${Math.min(Math.max(n,0),1)*100}%`}paintSeekProgress(e){for(const i of this.seekSegmentList)i.played.style.width=At.fillOf(i,e);const t=this.player.seekableDuration;this.seekDot.style.left=`${t>0?Math.min(Math.max(e/t,0),1)*100:0}%`}hoverSeek(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1),s=n*i,r=this.seekSegmentList.length-1;this.seekSegmentList.forEach((p,f)=>{p.hover.style.width=At.fillOf(p,s),p.element.classList.toggle("hovered",s>=p.start&&(s<p.end||f===r))});const a=this.milestonesShown?this.sighting.milestones:[],l=a.length>0?Kp(a,s):void 0,c=l?this.said.read(l.label)??"":"",h=l?this.said.read(l.note):void 0,d=h?`${c} — ${h}`:c;this.seekPreviewTitle.textContent=d,this.seekPreviewTime.textContent=this.formatPosition(s),this.seekPreview.hidden=!1;const u=this.seekPreview.offsetWidth;this.seekPreview.style.left=`${Math.min(Math.max(n*t.width-u/2,0),Math.max(t.width-u,0))}px`,this.paintSeekPreview(s)}leaveSeek(){for(const e of this.seekSegmentList)e.hover.style.width="0",e.element.classList.remove("hovered");this.seekPreview.hidden=!0}seekPreviewPainter;paintSeekPreview(e){const t=this.seekPreviewPainter;this.seekPreviewCanvas.hidden=t===void 0,t?.(e,this.seekPreviewCanvas)}paintChrome(e){const t=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(!t||typeof t.setTransform!="function"||n===0||s===0){e(this.canvasRenderer);return}const r=window.devicePixelRatio||1,a=Math.max(1,Math.round(n*r)),l=Math.max(1,Math.round(s*r));this.chromeCanvas.width!==a&&(this.chromeCanvas.width=a),this.chromeCanvas.height!==l&&(this.chromeCanvas.height=l),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,a,l),this.chromeDirty=!1,i&&(t.setTransform(a/this.canvas.width,0,0,l/this.canvas.height,0,0),this.chromeRenderer??=new dc(t),this.chromeDirty=!0,e(this.chromeRenderer))}chromeDraw;repaintChrome(){this.chromeDraw&&this.overlayPainter&&this.paintChrome(this.chromeDraw)}scrubbingPointer;beginTouchScrub(e){if(e.pointerType!=="mouse"){this.scrubbingPointer=e.pointerId;try{this.seekInput.setPointerCapture(e.pointerId)}catch{}this.seekToPointer(e)}}touchScrub(e){e.pointerId===this.scrubbingPointer&&this.seekToPointer(e)}endTouchScrub(e){e.pointerId===this.scrubbingPointer&&(this.scrubbingPointer=void 0,this.seekToPointer(e))}seekToPointer(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=Math.min(Math.max((e.clientX-t.left)/t.width,0),1);this.player.seek(this.snapSeekToMark(n*i))}seekSnapArmed=!1;static MARK_SNAP_PX=6;markNear(e){const t=this.player.seekableDuration,i=this.seekInput.getBoundingClientRect().width;if(t<=0||i<=0)return;const n=At.MARK_SNAP_PX/i*t;let s;for(const r of this.milestoneMarks.children){const a=Number(r.dataset.t);Math.abs(a-e)>n||(!s||Math.abs(a-e)<Math.abs(s.t-e))&&(s={t:a,name:r.title})}return s}snapSeekToMark(e){return this.seekSnapArmed?(this.seekSnapArmed=!1,this.markNear(e)?.t??e):e}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect(),i=this.player.seekableDuration;if(t.width<=0||i<=0)return;const n=(e.clientX-t.left)/t.width*i,s=this.markNear(n);s?this.seekInput.title=s.name:this.seekInput.removeAttribute("title")}showMilestoneAt(e){const t=this.milestonesShown&&this.sighting.milestones.length>0?Kp(this.sighting.milestones,e):void 0;if(this.milestoneCaption.hidden=t===void 0,this.showCurrentMoment(t),!t)return;const i=document.createElement("b");i.textContent=this.said.read(t.label)??"";const n=this.said.read(t.note),s=n?` — ${n}`:"";this.milestoneCaption.replaceChildren(i,document.createTextNode(s))}exposureInstants(e){const t=this.exposureTimes(e),i=1/t.length;return t.map(n=>({shapes:this.shapesAt(n),share:i}))}exposureTimes(e=this.currentTime){const t=zs.windowEndingAt(e,this.currentSighting.exposure??0);if(t.ms<At.SHORTEST_VISIBLE_EXPOSURE_MS)return[e];const i=Math.min(At.MAX_EXPOSURE_STEPS,Math.max(2,Math.round(t.ms/At.SHORTEST_VISIBLE_EXPOSURE_MS))),n=Math.ceil(this.travelPxOver(t.fromMs,t.ms)/At.EXPOSURE_STEP_PX),s=Math.min(At.MAX_TRAVEL_STEPS,Math.max(i,n)),r=[];for(let a=0;a<s;a++)r.push(t.fromMs+t.ms*a/(s-1));return r}travelPxOver(e,t){const i=this.shapesAt(e),n=this.shapesAt(e+t);let s=0;for(const[r,a]of i){const l=n.get(r);if(!l)continue;const c=l.bounds.x+l.bounds.width/2-(a.bounds.x+a.bounds.width/2),h=l.bounds.y+l.bounds.height/2-(a.bounds.y+a.bounds.height/2);s=Math.max(s,Math.hypot(c,h))}return s}shapeAt(e,t,i){if(!this.accountHidden)for(const n of this.exposureTimes()){const s=this.currentSighting.timeline.hitTest(n,e,t,i);if(s)return s}}shapesAt(e){const t=new Map;for(const i of this.currentSighting.timeline.sourceIds){const n=this.currentSighting.timeline.getInterpolatedShapeAt(e,i);n&&t.set(i,n)}return t}static SHORTEST_VISIBLE_EXPOSURE_MS=20;static MAX_EXPOSURE_STEPS=48;static EXPOSURE_STEP_PX=2;static MAX_TRAVEL_STEPS=320;applyFrameFormat(){const e=Ut.frameWidthPx(this.currentSighting.instrument,this.canvas.height);if(this.canvas.width===e)return;this.canvas.width=e,this.canvas.parentElement?.style.setProperty("--frame-aspect",`${e} / ${this.canvas.height}`)}canvasPointFromEvent(e){const t=this.canvas.getBoundingClientRect();if(!(t.width===0||t.height===0))return{x:(e.clientX-t.left)/t.width*this.canvas.width,y:(e.clientY-t.top)/t.height*this.canvas.height}}onFrame(e,t){this.canvasRenderer.clear(this.canvas.width,this.canvas.height);const i=this.playbackState!=="playing"?this.highlightedSourceIds:wE;this.canvasRenderer.setStarPoints(Ut.starPointsOf(this.sighting.instrument));const n=(ot(this.sighting,e)?.rollDeg??0)+this.gaitAt(e).rollDeg;this.canvasRenderer.setRoll(n*Math.PI/180);const s=this.exposureInstants(e),r=this.frameShift;if(this.paintsShapes)for(const l of s)for(const[,c]of l.shapes){const h=l.share,d=h===1?c:{...c,transparency:1-(1-c.transparency)*h};this.canvasRenderer.paintShape(this.shifted(d,r))}for(const[l,c]of s[0].shapes)!this.selectionShown||!i.has(l)||(this.paintsShapes?i.size===1?this.canvasRenderer.paintShape({...c,selected:!0}):this.canvasRenderer.paintMemberOutline(c):this.canvasRenderer.paintSelectionOnly(this.shifted(c,r)));const a=this.selectionShown&&i.size>1?kt.groupBoundsFor([...t].filter(([l])=>i.has(l)).map(([,l])=>l.bounds)):void 0;this.chromeDraw=l=>{a&&l.paintGroupHandles(a),this.overlayPainter?.(l)},this.paintChrome(this.chromeDraw),this.mapShapeBounds=s.flatMap(l=>[...l.shapes.values()].filter(c=>c.transparency<1).map(c=>this.shifted(c,r).bounds)),this.keepObserverMapClear(),this.seekInput.value=String(e),this.paintSeekProgress(e),this.timeStartLabel.textContent=this.formatPosition(e),this.showMilestoneAt(e),this.paintObserverMap(e),this.playbackState==="playing"?(this.soundPreview=void 0,this.sightingAudio.setSound(pg(this.currentSighting,e))):this.soundPreview?this.sightingAudio.setSound(this.soundPreview):this.sightingAudio.silence(),this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("timeupdate",{detail:{time:e}}))}shifted(e,t){return t.x===0&&t.y===0?e:{...e,bounds:{...e.bounds,x:e.bounds.x+t.x,y:e.bounds.y+t.y}}}createPlayer(){const e=new jS(this.currentSighting.timeline,(t,i)=>this.onFrame(t,i));return e.loop=this.loopEnabled,e.onEnded=()=>{this.updatePlayPauseButton(),this.dispatchEvent(new CustomEvent("ended",{bubbles:!0,composed:!0}))},e}static SEEK_KEY_STEP_MS=5e3;handleFullscreenKey=e=>{e.key.toLowerCase()!=="f"||e.altKey||e.ctrlKey||e.metaKey||!this.enableClickToPlay||e.composedPath().some(i=>i instanceof HTMLElement&&(i.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(i.tagName)&&i.type!=="range"))||(e.preventDefault(),this.toggleFullscreen())};handleSeekKey=e=>{if(e.altKey||e.ctrlKey||e.metaKey)return;const t=e.key==="ArrowLeft"?-1:e.key==="ArrowRight"?1:0;if(t){e.preventDefault();const i=this.player.seekableDuration;this.player.seek(Math.min(i,Math.max(0,this.player.time+t*At.SEEK_KEY_STEP_MS)))}else e.key===" "&&(e.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 e=this.playbackFlash;e.innerHTML=this.player.playbackState==="playing"?Ze.PLAY:Ze.PAUSE,e.classList.remove("flashing"),e.offsetWidth,e.classList.add("flashing")}static icons=new WeakMap;static setIcon(e,t){At.icons.get(e)!==t&&(At.icons.set(e,t),e.innerHTML=t)}set captionHeld(e){this.stageElement.classList.toggle("caption-held",e)}set controlsHeld(e){this.stageElement.classList.toggle("controls-held",e)}static CONTROLS_IDLE_MS=3e3;controlsIdleTimer;wasPlaying=!1;quietControlsValue=!1;get quietControls(){return this.quietControlsValue}set quietControls(e){this.quietControlsValue=e,this.stageElement.classList.toggle("quiet",e)}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},At.CONTROLS_IDLE_MS)))}updatePlayPauseButton(){const e=this.player.playbackState==="playing";this.stageElement.classList.toggle("paused",!e),e!==this.wasPlaying&&e&&this.hoverless&&(!this.quietControlsValue||this.stageElement.classList.contains("touched"))&&this.revealControls(),this.wasPlaying=e,At.setIcon(this.playPauseButton,e?Ze.PAUSE:Ze.PLAY);const t=this.player.seekableDuration>0;this.playPauseButton.disabled=!t;const i=t?e?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 e=this.playbackBeforeClick;e&&(this.currentTime=e.time,e.state==="playing"?this.play():this.pause())}get canUseNativeFullscreen(){return typeof this.fullscreenTarget.requestFullscreen=="function"&&document.fullscreenEnabled}toggleFullscreen(){if(!this.canUseNativeFullscreen){this.simulatedFullscreen?this.exitSimulatedFullscreen():this.enterSimulatedFullscreen();return}document.fullscreenElement?document.exitFullscreen():this.fullscreenTarget.requestFullscreen().catch(e=>{console.error("<rr0-ufo>: requestFullscreen() failed —",e)})}enterSimulatedFullscreen(){const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen=e.getAttribute("style")??"",this.bodyOverflowBeforeSimulatedFullscreen=document.body.style.overflow;const t=e.style;t.setProperty("position","fixed"),t.setProperty("inset","0"),t.setProperty("margin","0"),t.setProperty("max-width","none"),t.setProperty("max-height","none"),t.setProperty("aspect-ratio","auto"),t.setProperty("z-index","2147483647"),t.setProperty("background","#000"),t.setProperty("width","100vw"),t.setProperty("width","100dvw"),t.setProperty("height","100vh"),t.setProperty("height","100dvh"),document.body.style.overflow="hidden",this.simulatedFullscreen=!0,document.addEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}exitSimulatedFullscreen(){if(!this.simulatedFullscreen)return;const e=this.fullscreenTarget;this.styleBeforeSimulatedFullscreen?e.setAttribute("style",this.styleBeforeSimulatedFullscreen):e.removeAttribute("style"),document.body.style.overflow=this.bodyOverflowBeforeSimulatedFullscreen??"",this.simulatedFullscreen=!1,document.removeEventListener("keydown",this.handleSimulatedFullscreenKey),this.updateFullscreenButton(),this.updateMuteButton()}toggleObserverMap(){const e=this.observerMapPanel.hidden;this.observerMapAsked=e,this.setObserverMapOpen(e),this.keepObserverMapClear(),this.dispatchEvent(new CustomEvent("observermapchange",{bubbles:!0,composed:!0,detail:{open:e}}))}get observerMapOpen(){return!this.observerMapPanel.hidden}get milestonesVisible(){return this.milestonesShown}observerMapAsked=!1;applyObserverMapDefault(){const e=this.getAttribute(ql),t=e===null?this.sighting.observerMap??this.observerPath?.travels===!0:e!=="false";this.setObserverMapOpen(t&&this.observerPath!==void 0)}setObserverMapOpen(e){this.observerMapPanel.hidden=!e,this.observerMapPanel.removeAttribute("title"),this.observerMapButton.setAttribute("aria-pressed",String(e)),this.updateObserverMapButton(),e&&(this.sizeObserverMapCanvas(),this.loadObserverMapImagery(),this.paintObserverMap(this.currentTime))}updateObserverMapButton(){const e=!this.observerMapPanel.hidden;At.setIcon(this.observerMapButton,e?Ze.MAP_ON:Ze.MAP_OFF);const t=e?this.messages.hideObserverMap:this.messages.showObserverMap;this.observerMapButton.title=t,this.observerMapButton.setAttribute("aria-label",t);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 e=this.observerPath!==void 0;if(this.observerPath=Yl.of(this.currentSighting),this.observerMapButton.hidden=this.observerPath===void 0,!e&&this.observerPath&&this.applyObserverMapDefault(),!this.observerPath){this.setObserverMapOpen(!1),this.observerMapBounds=void 0;return}const t=this.tracesShownState?this.currentSighting.traces.flatMap(n=>n.points):[],i=Mi.including(this.observerPath.boundsAround(At.OBSERVER_MAP_MIN_SPAN_M,At.OBSERVER_MAP_MARGIN),t);(!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(e,t){const i=Math.abs(e.east-e.west)/20;return Math.abs(e.north-t.north)<i&&Math.abs(e.south-t.south)<i&&Math.abs(e.west-t.west)<i&&Math.abs(e.east-t.east)<i}async loadObserverMapImagery(){const e=this.observerMapViewBounds;if(!e||this.observerMapPanel.hidden||this.observerMapImageryLoading||!this.observerMapImageryNeededFor(e))return;const t=this.observerMapView.changed,i=t?Mi.expand(e,At.OBSERVER_MAP_IMAGERY_AHEAD):e,n=At.OBSERVER_MAP_IMAGERY_PX*(t?1+2*At.OBSERVER_MAP_IMAGERY_AHEAD:1);this.observerMapImageryBounds=i,this.observerMapImageryViewWidth=e.east-e.west,this.observerMapImageryLoading=!0;const s=rw();try{const r=await s.getImageryTexture(i,{width:n,height:n});if(this.observerMapImageryBounds!==i)return;this.observerMapImagery=r,this.observerMapImageryCredit=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(e){const t=this.observerMapImageryBounds;if(!t)return!0;const i=this.observerMapImagery?.bounds??t,n=this.observerMapView.changed?Mi.expand(e,At.OBSERVER_MAP_IMAGERY_LOOKAHEAD):e,s=n.west>=i.west&&n.east<=i.east&&n.south>=i.south&&n.north<=i.north,r=e.east-e.west>this.observerMapImageryViewWidth/2;return!s||!r}get observerMapCredit(){return this.observerMapImageryCredit}get observerMapFooterLine(){return this.observerMapImageryFailed?this.messages.mapImageryUnavailable:this.creditShownExternally?void 0:this.observerMapImageryCredit}mapShapeBounds=[];mapSceneBounds=[];setMapSubjectBounds(e){this.mapSceneBounds=e.map(t=>({x:t.x*this.canvas.width,y:t.y*this.canvas.height,width:t.width*this.canvas.width,height:t.height*this.canvas.height})),this.keepObserverMapClear()}keepObserverMapClear(){if(this.observerMapPanel.hidden)return;const e=this.observerMapBoxPx;if(!e)return;const t=[...this.mapShapeBounds,...this.mapSceneBounds],i=(c,h,d)=>{for(const u of t)if(!(u.x+u.width<c-d||u.x>h+d)&&!(u.y>e.bottom+d||u.y+u.height<e.top-d))return!0;return!1},n=[this.canvas.width-e.width,this.canvas.width],s=[0,e.width],r=At.OBSERVER_MAP_CLEARANCE_PX,a=i(...n,0),l=i(...s,0);if(this.observerMapPanel.classList.toggle("subject-overlap",a&&l&&!this.observerMapAsked),this.observerMapPanel.classList.contains("on-the-left")){!a&&(l||!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 e=this.observerMapPanel.clientWidth;if(e===0)return;const t=Math.round(e*(globalThis.devicePixelRatio??1));this.measureObserverMapBox(),this.observerMapCanvas.width!==t&&(this.observerMapCanvas.width=t,this.observerMapCanvas.height=t)}measureObserverMapBox(){const e=this.observerMapPanel.getBoundingClientRect(),t=this.canvas.getBoundingClientRect();if(t.width===0||t.height===0)return;const i=this.canvas.width/t.width,n=this.canvas.height/t.height;this.observerMapBoxPx={width:e.width*i,top:(e.top-t.top)*n,bottom:(e.bottom-t.top)*n}}paintObserverMap(e){if(this.observerMapPanel.hidden||!this.observerPath||!this.observerMapBounds)return;const t=ot(this.currentSighting,e);t?.lat!==void 0&&t.lng!==void 0&&!this.observerMapDrag?.moved&&this.observerMapView.keepInView(this.observerMapBounds,{lat:t.lat,lng:t.lng},At.OBSERVER_MAP_FOLLOW_MARGIN)&&this.scheduleObserverMapImagery();const i=this.currentSighting.instrument,n=[],s=this.currentSighting.milestones.length>0?Kp(this.currentSighting.milestones,e):void 0;for(const r of this.milestonesShown?Po(this.currentSighting.milestones):[]){const a=ot(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:t?.lat!==void 0&&t.lng!==void 0?{lat:t.lat,lng:t.lng}:void 0,headingDeg:t?.headingDeg===void 0?void 0:t.headingDeg+this.lookYawDeg,coneHalfAngleDeg:t?$s.of(i,this.canvas.height,t.fovDeg).halfWidthAngleDeg(Ut.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(e),observerLabel:this.said.read(this.currentSighting.observer?.title)??this.messages.observerHere,nightFraction:this.observerMapNightFraction,attribution:this.observerMapFooterLine})}toggleMilestones(){this.setMilestonesShown(!this.milestonesShown)}setMilestonesShown(e){this.milestonesShown=e,this.milestoneMarks.hidden=!e,this.momentsBox.hidden=!e||this.sighting.milestones.length===0,this.refreshSeekSegments(this.player.seekableDuration,Po(this.sighting.milestones).map(t=>t.t)),this.milestonesButton.setAttribute("aria-pressed",String(e)),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,At.setIcon(this.milestonesButton,this.milestonesShown?Ze.MILESTONES_ON:Ze.MILESTONES_OFF);const e=this.milestonesShown?this.messages.hideMilestones:this.messages.showMilestones;this.milestonesButton.title=e,this.milestonesButton.setAttribute("aria-label",e)}observerMapDecorAt(e){const t=ot(this.currentSighting,0);return t?.lat===void 0||t.lng===void 0?[]:this.currentSighting.decor.filter(i=>i.kind!=="crop").map(i=>{const n=Xs(i,e),{lat:s,lng:r}=fs(n.eastM,-n.northM,t.lat,t.lng);return{lat:s,lng:r,headingDeg:n.headingDeg,label:this.said.read(i.title)??this.messages.decorHere}})}observerMapNightFraction;setSunAltitude(e){const t=e===void 0?void 0:Math.max(0,Math.min(1,-e/12));t!==this.observerMapNightFraction&&(this.observerMapNightFraction=t,this.paintObserverMap(this.currentTime))}setLookOffset(e,t){e===this.lookYawDeg&&t===this.lookPitchDeg||(this.lookYawDeg=e,this.lookPitchDeg=t,this.refresh())}get frameShiftPx(){return this.frameShift}get frameShift(){const e=this.gaitAt(this.currentTime),t=this.lookYawDeg+e.yawDeg,i=this.lookPitchDeg+e.pitchDeg;if(t===0&&i===0)return{x:0,y:0};const n=ot(this.currentSighting,this.currentTime),s=$s.of(this.currentSighting.instrument,this.canvas.height,n?.fovDeg??60);return{x:-s.angleDegToRadiusPx(t),y:s.angleDegToRadiusPx(i)}}gaitAt(e){return Yt.bodyAt(this.currentSighting,e,this.steadyBody)}mutedState=!1;get muted(){return this.mutedState}set muted(e){e!==this.mutedState&&(this.mutedState=e,!e&&this.volumeState===0&&(this.volumeState=At.RESTORED_VOLUME),this.applyLevel())}volumeState=1;static RESTORED_VOLUME=.5;get volume(){return this.volumeState}set volume(e){this.setVolume(e)}setVolume(e){this.volumeState=Math.min(Math.max(e,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 e=!this.hasSound;if(this.muteButton.disabled=e,this.volumeInput.hidden=e,e){At.setIcon(this.muteButton,Ze.MUTED),this.muteButton.title=this.messages.noSound,this.muteButton.setAttribute("aria-label",this.messages.noSound),this.muteButton.setAttribute("aria-pressed","true");return}At.setIcon(this.muteButton,this.mutedState?Ze.MUTED:Ze.VOLUME);const t=this.mutedState?this.messages.unmute:this.messages.mute;this.muteButton.title=t,this.muteButton.setAttribute("aria-label",t),this.muteButton.setAttribute("aria-pressed",String(this.mutedState)),this.volumeInput.value=String(this.level)}updateFullscreenButton(){const e=this.simulatedFullscreen||document.fullscreenElement===this.fullscreenTarget;At.setIcon(this.fullscreenButton,e?Ze.EXIT_FULLSCREEN:Ze.ENTER_FULLSCREEN),this.fullscreenButton.title=e?this.messages.exitFullscreen:this.messages.fullscreen,this.fullscreenButton.setAttribute("aria-label",this.fullscreenButton.title)}get said(){return this.saidTexts??=new zn(Is.preferencesFor(this))}saidTexts;async loadLocaleMessages(){const e=yh(Is.preferencesFor(this),Sh);if(e===this.messagesLanguage||e==="en"&&this.messagesLanguage===void 0)return;this.messagesLanguage=e;const t=await SS(e);this.messagesLanguage===e&&this.applyMessages(t)}messagesLanguage;updateTimeLabelTitles(){const e=this.showClockTime?this.messages.switchToElapsed:this.messages.switchToClockTime,t=this.canSwitchTimeDisplay?` — ${e}`:"";this.timeStartLabel.title=this.messages.currentPosition+t,this.timeEndLabel.title=this.messages.duration+t,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(e){this.messages=e,this.updateTimeLabelTitles(),this.updatePlayPauseButton(),this.updateFullscreenButton(),this.updateMuteButton(),this.updateObserverMapButton(),this.updateReferencesButton(),this.updateTracesButton(),this.updateMilestonesButton(),this.renderIssues()}updateTimeLabels(){const e=this.currentSighting.event,t=cc(e);this.realDurationMs=t!==void 0&&t>0?t:void 0,this.realStartMs=e.time?_m(e.time):void 0;const i=this.currentSighting.timeline.duration;this.player.playbackRate=this.realDurationMs!==void 0&&i>0?i/this.realDurationMs:1,this.player.durationOverrideMs=i>0?0:this.realDurationMs??0,this.timeEndLabel.textContent=this.formatEndOfTimeline(),this.timeStartLabel.textContent=this.formatPosition(this.player.time),this.updateTimeLabelTitles()}formatPosition(e){if(this.realDurationMs===void 0)return jh(e);const t=this.currentSighting.timeline.duration,i=t>0&&e<=t?e/t*this.realDurationMs:e;return this.canShowClockTime?l1(o1(this.realStartMs+i)):jh(i)}formatEndOfTimeline(){return this.realDurationMs===void 0?jh(this.currentSighting.timeline.duration):this.canShowClockTime?l1(o1(this.realStartMs+this.realDurationMs)):jh(this.realDurationMs)}}function o1(o){const e=new Date(o);return{hour:e.getUTCHours(),minute:e.getUTCMinutes(),second:e.getUTCSeconds()}}function l1(o){if(o.hour===void 0)return"0:00";const e=t=>String(t).padStart(2,"0");return o.second?`${e(o.hour)}:${e(o.minute??0)}:${e(o.second)}`:`${e(o.hour)}:${e(o.minute??0)}`}function jh(o){const e=Math.round(o/1e3),t=Math.floor(e/60),i=e%60;return`${t}:${String(i).padStart(2,"0")}`}const Om="rr0-ufo";function Cp(){customElements.get(Om)||customElements.define(Om,At)}const xE="recordingissues";class rh{constructor(e,t){this.seekInput=e,this.layer=t,e.addEventListener("pointerdown",i=>{this.snapArmed=!0,this.nameMarkUnder(i)}),e.addEventListener("pointerup",()=>this.snapArmed=!1),e.addEventListener("pointermove",i=>this.nameMarkUnder(i)),e.addEventListener("pointerleave",()=>e.removeAttribute("title"))}static SNAP_PX=6;marks=[];duration=0;drawn="";snapArmed=!1;show(e,t){const i=t>0?[...e].sort((s,r)=>s.t-r.t):[],n=`${t}|${i.map(s=>`${s.kind}:${s.t}:${s.label}`).join("|")}`;n!==this.drawn&&(this.drawn=n,this.marks=i,this.duration=t,this.layer.replaceChildren(...i.map(s=>{const r=document.createElement("span");return r.className=`timeline-mark ${s.kind}`,r.style.left=`${Math.min(Math.max(s.t/t,0),1)*100}%`,r})))}snap(e){return this.snapArmed?(this.snapArmed=!1,this.markNear(e)?.t??e):e}next(e){return this.marks.find(t=>t.t>e+rh.SAME_INSTANT)?.t}previous(e){return[...this.marks].reverse().find(t=>t.t<e-rh.SAME_INSTANT)?.t}static SAME_INSTANT=.5;markNear(e){const t=this.seekInput.getBoundingClientRect().width;if(this.duration<=0||t<=0)return;const i=rh.SNAP_PX/t*this.duration;let n;for(const s of this.marks)Math.abs(s.t-e)>i||(!n||Math.abs(s.t-e)<Math.abs(n.t-e)||s.t===n.t&&s.kind==="milestone")&&(n=s);return n}nameMarkUnder(e){const t=this.seekInput.getBoundingClientRect();if(t.width<=0||this.duration<=0)return;const i=this.marksNear((e.clientX-t.left)/t.width*this.duration);i?this.seekInput.title=i:this.seekInput.removeAttribute("title")}marksNear(e){const t=this.markNear(e);if(t)return[...new Set(this.marks.filter(i=>i.t===t.t).map(i=>i.label))].join(" · ")}}class Pl{static HALF_SPAN_MS=2e3;static MIN_SPEED_MS=1;static at(e,t,i){const n=e.event.place?.[0],s=e.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=yt(m.lat,m.lng,n.lat,n.lng);return{eastM:v.x,northM:-v.z,heading:m.headingDeg}},a=r(t-Pl.HALF_SPAN_MS),l=r(t+Pl.HALF_SPAN_MS),c=r(t);if(!a||!l||!c)return 0;const h=Math.hypot(l.eastM-a.eastM,l.northM-a.northM),d=2*Pl.HALF_SPAN_MS/1e3;if(h/d<Pl.MIN_SPEED_MS)return 0;const u=i.heightAt(l.eastM,l.northM)-i.heightAt(a.eastM,a.northM),p=Math.atan2(u,h)*180/Math.PI;if(c.heading===void 0)return p;const f=Math.atan2(l.eastM-a.eastM,l.northM-a.northM)*180/Math.PI;return p*Math.max(0,Math.cos((c.heading-f)*Math.PI/180))}}const SE=.08,c1=.15,h1=2,EE=2e3;class AE{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(e){console.warn("VehicleAudio: Web Audio unavailable, vehicles stay silent:",e);return}}Oo.unlock(this.context),this.apply()}setLevel(e){this.level=e,this.master&&(this.master.gain.value=e)}setPaused(e){e!==this.paused&&(this.paused=e,this.apply())}setVoices(e){this.requested=e,this.apply()}dispose(){for(const e of[...this.voices.keys()])this.release(e);this.context?.close(),this.context=void 0,this.master=void 0}masterOf(e){return this.master||(this.master=e.createGain(),this.master.gain.value=this.level,this.master.connect(e.destination)),this.master}apply(){const e=this.context;if(!e)return;const t=this.paused?[]:this.requested.filter(n=>n.inside||n.distanceM<EE),i=new Set(t.map(n=>n.id));for(const n of[...this.voices.keys()])i.has(n)||this.release(n);for(const n of t){const s=this.voices.get(n.id)??this.build(e,n.id);this.retarget(e,s,n)}}build(e,t){const i=e.createGain();i.gain.value=0;const n=e.createBiquadFilter();n.type="lowpass",n.connect(i).connect(this.masterOf(e));const s=e.createOscillator();s.type="sawtooth";const r=e.createOscillator();r.type="sine";const a=e.createGain(),l=e.createBiquadFilter();l.type="lowpass",l.frequency.value=900,s.connect(l),r.connect(l),l.connect(a).connect(n);const c=()=>{const x=e.createBufferSource();return x.buffer=this.noise(e),x.loop=!0,x.loopStart=Math.random()*h1*.5,x},h=c(),d=e.createBiquadFilter();d.type="bandpass",d.Q.value=4;const u=e.createGain();h.connect(d).connect(u).connect(n);const p=c(),f=e.createBiquadFilter();f.type="lowpass",f.frequency.value=600;const g=e.createGain();p.connect(f).connect(g).connect(n);const m=c(),v=e.createBiquadFilter();v.type="bandpass",v.frequency.value=1400,v.Q.value=.7;const b=e.createGain();m.connect(v).connect(b).connect(n);const M=[s,r,h,p,m];for(const x of M)x.start();const y={nodes:[i,n,a,l,d,u,f,g,v,b,...M],sources:M,firing:s,crank:r,knock:d,engineGain:a,knockGain:u,roadGain:g,windGain:b,cabin:n,output:i};return this.voices.set(t,y),y}retarget(e,t,{profile:i,state:n,noise:s,inside:r,windowsOpen:a,distanceM:l}){const c=e.currentTime,h=(b,M)=>b.setTargetAtTime(M,c,SE),d=n.rpm/60,u=d*i.cylinders/2,p=Math.min(1,n.rpm/i.shiftUpRpm),f=Math.min(1.5,n.speedMps/30);h(t.firing.frequency,u),h(t.crank.frequency,d),h(t.knock.frequency,u*3),h(t.engineGain.gain,i.engineGain*(.25+.75*n.load)*(.5+.5*p)*.3),h(t.knockGain.gain,i.roughness*(.2+.8*n.load)*.4),h(t.roadGain.gain,i.roadGain*f**1.5*.8);const g=!r||a;h(t.windGain.gain,f**2*(g?.5:.06));const m=r?a?3500:700:8e3/(1+l/60);h(t.cabin.frequency,m);const v=r?.5:Math.min(1,8/Math.max(l,1));h(t.output.gain,v*s)}release(e){const t=this.voices.get(e);if(!t)return;this.voices.delete(e);const i=this.context;i&&(t.output.gain.setTargetAtTime(0,i.currentTime,c1/3),setTimeout(()=>{for(const n of t.sources)try{n.stop()}catch{}for(const n of t.nodes)n.disconnect()},c1*1e3*3))}noise(e){if(this.noiseBuffer)return this.noiseBuffer;const t=e.createBuffer(1,e.sampleRate*h1,e.sampleRate),i=t.getChannelData(0);for(let n=0;n<i.length;n++)i[n]=Math.random()*2-1;return this.noiseBuffer=t,t}}class Th{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(e){return Th.BY_KIND[e??"generic"]??Th.BY_KIND.generic}}class To{constructor(e,t){this.samples=e,this.startMs=t}static SAMPLE_MS=100;static STANDING_MPS=.3;static of(e,t,i,n){const s=To.SAMPLE_MS,r=[];for(let c=i;c<=n+s/2;c+=s){const h=t(c-s/2),d=t(c+s/2);if(!h||!d)return;r.push(Math.hypot(d.eastM-h.eastM,d.northM-h.northM)/(s/1e3))}const a=[];let l=1;for(let c=0;c<r.length;c++){const h=r[c],d=(r[Math.min(c+1,r.length-1)]-r[Math.max(c-1,0)])/(2*s/1e3);if(h<To.STANDING_MPS){l=1,a.push({speedMps:h,rpm:e.idleRpm,load:.1,gear:0});continue}const u=h*3.6,p=v=>u/e.kmhPer1000Rpm[v-1]*1e3;for(;l<e.kmhPer1000Rpm.length&&p(l)>e.shiftUpRpm;)l++;for(;l>1&&p(l)<e.shiftDownRpm;)l--;const f=Math.max(p(l),e.idleRpm*(1+.3*Math.min(1,h/3))),g=.15+.5*Math.min(1,(h/35)**2),m=d>.15?Math.min(1,g+d/2.5):d<-.3?.05:g;a.push({speedMps:h,rpm:f,load:m,gear:l})}return new To(a,i)}at(e){const t=(e-this.startMs)/To.SAMPLE_MS,i=Math.min(Math.max(Math.floor(t),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(t-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 Wu{drives=new Map;at(e,t){const i=[],n=e.event.place?.[0],s=c=>{const h=e.observerTrack.getInterpolatedPoseAt(c),d=h?.lat??n?.lat,u=h?.lng??n?.lng;if(d===void 0||u===void 0||!n)return;const p=yt(d,u,n.lat,n.lng);return{eastM:p.x,northM:-p.z}},r=Math.max(e.observerTrack.duration,(e.event.durationSeconds??0)*1e3),a=e.vehicle;if(a){const c=Th.of(a.kind),h=this.drive(`observer:${a.kind}`,Wu.trackKey(e),()=>To.of(c,s,0,r));h&&i.push({id:"observer",profile:c,state:h.at(t),noise:a.noise??1,inside:!0,windowsOpen:a.windowsOpen===!0,distanceM:0})}const l=s(t);for(const c of e.decor){if(!c.engine||!l)continue;const h=Th.of(c.engine.kind),d=g=>{const m=Xs(c,g);return{eastM:m.eastM,northM:m.northM}},u=this.drive(`decor:${c.id}`,Wu.decorKey(c,r),()=>To.of(h,d,0,r));if(!u)continue;const p=Xs(c,t),f=Math.hypot(p.eastM-l.eastM,p.northM-l.northM,p.altitudeM);i.push({id:`decor:${c.id}`,profile:h,state:u.at(t),noise:c.engine.noise??1,inside:!1,windowsOpen:!0,distanceM:f})}return i}drive(e,t,i){const n=this.drives.get(e);if(n&&n.key===t)return n.drive;const s=i();return this.drives.set(e,{key:t,drive:s}),s}static trackKey(e){return e.observerTrack.allKeyframes.map(i=>`${i.t}:${i.pose.lat}:${i.pose.lng}`).join(";")}static decorKey(e,t){return`${t}|${e.eastM},${e.northM}|`+(e.track??[]).map(i=>`${i.t}:${i.eastM}:${i.northM}`).join(";")}}const TE="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==",_E=`
3019
3019
  <div class="stage" id="stage">
3020
3020
  <div class="frame" id="frame">
3021
3021
  <canvas id="scene-canvas"></canvas>
@@ -9299,7 +9299,7 @@ vLitRank = litRank;`)}`,l.fragmentShader=`uniform float uLitShare;
9299
9299
  varying float vLitRank;
9300
9300
  ${l.fragmentShader.replace("#include <emissivemap_fragment>",`#include <emissivemap_fragment>
9301
9301
  totalEmissiveRadiance *= step(vLitRank, uLitShare);`)}`},r.customProgramCacheKey=()=>"facade-lit-windows";const a=new Se(s,r);return a.castShadow=!0,a.receiveShadow=!0,t.add(a),t}static litWindowShare={value:0};static setLitWindowShare(e){Ue.litWindowShare.value=Math.max(0,Math.min(1,e))}static build(e,t){const i=Ue.hasFacade(e)?Ue.buildFacade(e):e.kind==="building"?tb(e.floors??hc,e.windows,e.observerSide,e.occupiedFloor,e.observerFacing):e.kind==="tree"?nb():e.kind==="shrub"?ib():e.kind==="bridge"?hC(e):e.kind==="wire"?dC(e):e.kind==="wall"?Vi.build(e):e.kind==="crop"?rb():e.kind==="terrace"?bC():e.kind==="mound"?ab():e.kind==="streetlight"?ob(t):e.kind==="vehicle"?lb(t,e.windows,e.observerSide,e.observerFacing):e.kind==="aircraft"?fb():e.kind==="entity"?ub():ig();e.color&&this.paint(i,e.color);const n=this.scaleFor(e),s=new Lt;return e.kind==="building"&&e.roof&&this.addRoof(s,e),i.name=Ue.BODY_NAME,i.scale.copy(n),s.add(i),e.headingDeg!==void 0&&(s.rotation.y=-e.headingDeg*Vf),this.addLights(s,e.lights),Ue.fitLights(s,e,e.sizeM??{}),s}static scaleFor(e){const t=e.sizeM;if(!t||Ue.hasFacade(e)||e.kind==="bridge"||e.kind==="wire"||e.kind==="terrace"||e.kind==="wall")return new D(1,1,1);const i=this.naturalSize(e.kind,e.floors);return new D(t.widthM===void 0?1:Yf(t.widthM,i.widthM),t.heightM===void 0?1:Yf(e.kind==="building"?this.wallHeightOf(e,t.heightM):t.heightM,i.heightM),t.lengthM===void 0?1:Yf(t.lengthM,i.lengthM))}static naturalSize(e,t){const i=e==="building"?Math.max(1,(t??hc)+1):0;if(e==="bridge")return li.NATURAL_SIZE;if(e==="wire")return Ro.NATURAL_SIZE;if(e==="terrace"||e==="wall")return{widthM:1,lengthM:1,heightM:1};const n=`${e}:${i}`,s=cb.get(n);if(s)return s;const r=e==="building"?tb(i-1,void 0,void 0,void 0):e==="tree"?nb():e==="shrub"?ib():e==="crop"?rb():e==="mound"?ab():e==="streetlight"?ob(!1):e==="vehicle"?lb(!1,void 0,void 0):e==="aircraft"?fb():e==="entity"?ub():ig(),a=new dn().setFromObject(r),l={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),cb.set(n,l),l}static usesModel(e){return Eh(e)!==void 0&&!(e.observerSide!==void 0&&Fa(e.kind))}static applyModel(e,t,i,n={}){const s=this.bodyOf(e),r=new Lt;r.name=Ue.BODY_NAME,i.rotation.y=-(n.headingOffsetDeg??0)*Vf,i.updateMatrixWorld(!0);const a=new dn().setFromObject(i),l={lengthM:a.max.z-a.min.z,heightM:a.max.y-a.min.y,widthM:a.max.x-a.min.x},c=t.kind==="tree"&&t.sizeM?.heightM!==void 0?{heightM:t.sizeM.heightM}:t.sizeM,h=hb(c,l)??hb(n.depictedSizeM,l)??1;i.scale.multiplyScalar(h);const d=a.getCenter(new D).multiplyScalar(h);i.position.x-=d.x,i.position.z-=d.z,i.position.y-=t.kind==="aircraft"?d.y:a.min.y*h,i.traverse(u=>{u instanceof Se&&(u.castShadow=!0,u.receiveShadow=!0)}),r.add(i),t.kind==="tree"&&r.add(Ue.trunkShadow(l.heightM*h)),s.parent?(s.parent.add(r),s.removeFromParent()):e.add(r),this.dispose(s),Ue.fitLights(e,t,{widthM:l.widthM*h,heightM:l.heightM*h,lengthM:l.lengthM*h})}static fitLights(e,t,i){const n=Ah.byId(Gr.rigOf(t)||void 0)?.referenceSizeM;if(!n||!t.lights)return;const s=(h,d)=>h===void 0||d===0?1:h/d,r=s(i.widthM,n.widthM),a=s(i.heightM,n.heightM),l=s(i.lengthM,n.lengthM),c=new Map(t.lights.map(h=>[h.id,h.offsetM]));e.traverse(h=>{const d=h.userData.lightId,u=d===void 0?void 0:c.get(d);u&&h.position.set(u.x*r,u.y*a,u.z*l)})}static trunkShadow(e){Ue.trunkProxy??={geometry:new vs(1,1.15,1,8),material:new Vn({colorWrite:!1,depthWrite:!1})};const t=new Se(Ue.trunkProxy.geometry,Ue.trunkProxy.material),i=Math.min(.3,Math.max(.12,e*.035)),n=e*.45;return t.scale.set(i,n,i),t.position.y=n/2,t.castShadow=!0,t.receiveShadow=!1,t.userData.sharedModel=!0,t.name="trunk-shadow",t}static trunkProxy;static sizeOf(e){const t=this.naturalSize(e.kind,e.floors);return{widthM:e.sizeM?.widthM??t.widthM,lengthM:e.sizeM?.lengthM??t.lengthM,heightM:e.sizeM?.heightM??t.heightM}}static addLights(e,t){for(const i of t??[]){const n=iC(i.color),s=Bt(e,new Li(Wf,8,6),n,i.offsetM.y,!0);s.position.set(i.offsetM.x,i.offsetM.y,i.offsetM.z),s.userData={emissive:!0,lightId:i.id,lightColor:n},s.visible=!1;const r=s.material;r.blending=Yi,r.transparent=!0,r.depthWrite=!1,r.fog=!1}}static setLights(e,t,i,n,s=0,r=1,a=Z4,l=[1,1,1]){if(!t||t.length===0)return;const c=new Map(t.map(p=>[p.id,p])),h=Math.max(1,n*a/Wf),d=Wf*h,u=r/(Math.PI*d*d);for(const p of e.children){if(!(p instanceof Se))continue;const f=p.userData.lightId;if(!f)continue;const g=c.get(f);if(!g)continue;const m=s>0?GM(g,i,i+s):FS(g,i)?1:0;p.visible=m>0;const v=p.material,b=p.userData.lightColor;if(b){const M=m*j4*(g.intensity??1)*u;v.color.setRGB(b[0]*M*l[0],b[1]*M*l[1],b[2]*M*l[2])}p.scale.setScalar(h)}}static setLit(e,t,i,n=1){const[s,r,a]=t==="streetlight"?[J4,Q4,E2]:[eC,tC,A2],l=i?s*n/(Math.PI*r*r):0,c=[a[0]*l,a[1]*l,a[2]*l];e.traverse(h=>{const d=h.userData;!(h instanceof Se)||!d.emissive||d.lightId||h.material.color.setRGB(...c)})}static dispose(e){e.traverse(t=>{if(!(t instanceof Se))return;if(t.userData.sharedModel){for(const n of t.userData.tintedMaterials??[])n.dispose();return}t.geometry.dispose();const i=t.material;for(const n of Array.isArray(i)?i:[i])n.dispose()})}}const Kf="https://ufoathome.org/models/index.json";class ph{attribution="3D models re-hosted by UFO@home, each under its own author's licence";fetchImpl;indexUrls;loading;static shared=new Map;sharing;constructor(e={}){this.sharing=!e.fetchImpl,this.fetchImpl=e.fetchImpl??fetch.bind(globalThis),this.indexUrls=e.indexUrls??SC()}async entries(e){const t=await this.load();return e?t.filter(i=>[i.kind].flat().includes(e)):t}async entry(e){return(await this.load()).find(t=>t.id===e)}load(){if(this.loading)return this.loading;if(!this.sharing)return this.loading=this.fetchFirstAvailable();const e=this.indexUrls.join(`
9302
- `);let t=ph.shared.get(e);return t||(t=this.fetchFirstAvailable(),ph.shared.set(e,t),t.then(i=>{i.length===0&&ph.shared.delete(e)})),this.loading=t}async fetchFirstAvailable(){for(const e of this.indexUrls){const t=await this.fetchIndex(e);if(t)return t}return[]}async fetchIndex(e){try{const t=await this.fetchImpl(e);if(!t.ok)return;const i=await t.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,e).href})):void 0}catch{return}}}function SC(){const o=`?v=${encodeURIComponent("0.123.0")}`,e=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(e&&e!==Kf?[e,Kf]:[Kf]).map(t=>t+o)}const pu=[{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 ph}];async function Zf(o){const{GLTFLoader:e}=await _e(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-C8s-rYg8.js");return{GLTFLoader:i}},[],import.meta.url),t=new e;return new Promise((i,n)=>{t.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 k2=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class ds{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(e,t){this.mesh=new Se(new Wn(2,2),new Dt({uniforms:{uColor:{value:new ne(0,0,0)},uRadius:{value:1}},vertexShader:ds.VERTEX,fragmentShader:ds.FRAGMENT,transparent:!0,depthWrite:!1,blending:Yi,toneMapped:!1})),this.mesh.name=e,this.mesh.frustumCulled=!1,this.mesh.renderOrder=t,this.mesh.visible=!1}shine(e,t,i){this.mesh.visible=!0,this.mesh.position.set(e.x,e.y,e.z),this.mesh.material.uniforms.uRadius.value=t,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(e,t,i,n){const s=Math.max(e,n*ds.MIN_ANGLE_RAD),r=ds.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(ds.MAX_SHARE,t/r)}}static conserving(e){return Math.sqrt(e/(ds.MAX_SHARE*ds.FILL*Math.PI))}static VERTEX=`
9302
+ `);let t=ph.shared.get(e);return t||(t=this.fetchFirstAvailable(),ph.shared.set(e,t),t.then(i=>{i.length===0&&ph.shared.delete(e)})),this.loading=t}async fetchFirstAvailable(){for(const e of this.indexUrls){const t=await this.fetchIndex(e);if(t)return t}return[]}async fetchIndex(e){try{const t=await this.fetchImpl(e);if(!t.ok)return;const i=await t.json();return Array.isArray(i?.models)?i.models.map(({file:n,...s})=>({...s,url:new URL(n,e).href})):void 0}catch{return}}}function SC(){const o=`?v=${encodeURIComponent("0.123.1")}`,e=typeof location>"u"?void 0:new URL("/models/index.json",location.href).href;return(e&&e!==Kf?[e,Kf]:[Kf]).map(t=>t+o)}const pu=[{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 ph}];async function Zf(o){const{GLTFLoader:e}=await _e(async()=>{const{GLTFLoader:i}=await import("./GLTFLoader-C8s-rYg8.js");return{GLTFLoader:i}},[],import.meta.url),t=new e;return new Promise((i,n)=>{t.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 k2=["ellipsoid","sphere","disc","cylinder","cone","box","torus","figure"];class ds{static MIN_ANGLE_RAD=.002;static FILL=(1-Math.exp(-4))/4;static MAX_SHARE=.3;mesh;constructor(e,t){this.mesh=new Se(new Wn(2,2),new Dt({uniforms:{uColor:{value:new ne(0,0,0)},uRadius:{value:1}},vertexShader:ds.VERTEX,fragmentShader:ds.FRAGMENT,transparent:!0,depthWrite:!1,blending:Yi,toneMapped:!1})),this.mesh.name=e,this.mesh.frustumCulled=!1,this.mesh.renderOrder=t,this.mesh.visible=!1}shine(e,t,i){this.mesh.visible=!0,this.mesh.position.set(e.x,e.y,e.z),this.mesh.material.uniforms.uRadius.value=t,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(e,t,i,n){const s=Math.max(e,n*ds.MIN_ANGLE_RAD),r=ds.FILL*Math.PI*s*s;return{radiusM:s,luminanceCdM2:i*Math.min(ds.MAX_SHARE,t/r)}}static conserving(e){return Math.sqrt(e/(ds.MAX_SHARE*ds.FILL*Math.PI))}static VERTEX=`
9303
9303
  uniform float uRadius;
9304
9304
  varying vec2 vOffset;
9305
9305
  void main() {
@@ -10199,4 +10199,4 @@ rr0-duration-input [hidden] { display: none !important; }
10199
10199
  </form>
10200
10200
  </dialog>
10201
10201
  `;class Xl extends HTMLElement{shadow=this.attachShadow({mode:"open"});editor;session;current;currentInterview;interviewElement;interviewReady;group="events";fileEditor;fileEditorLoading;fileApplied="";editorMessages=ka;messages=rg;said=new zn(["en"]);localeToken=0;language="en";dialogMode="add";pendingLoad;dirtyTimer;caseDate;dateModeFor;constructor(){super(),G2(),kM(),this.shadow.innerHTML=lL,customElements.upgrade(this.shadow),this.shadow.getElementById("case-date").build(),this.editor=this.shadow.getElementById("editor"),this.interviewElement=this.shadow.getElementById("interview"),this.interviewElement.addEventListener(vS,t=>this.interviewChanged(t.detail)),this.interviewElement.addEventListener(yS,t=>void this.followToObservation(t.detail)),this.editor.addEventListener("caseloaded",t=>{t.preventDefault();const{json:i,url:n}=t.detail;this.openCase(i,n??location.href)}),this.editor.addEventListener("recordingloaded",()=>this.closeCase()),this.editor.guardsLeaving=!1,this.editor.addEventListener("beforeload",t=>{this.dirty&&(t.preventDefault(),this.pendingLoad=t.detail.proceed,this.openDialog("discard",this.messages.discardTitle,this.messages.discardQuestion))});for(const t of["input","change","datechange","click","pointerup","keyup"])this.shadow.addEventListener(t,()=>this.scheduleDirtyCheck(),!0);for(const[t,i]of[["case-id","id"],["case-title","title"]])this.input(t).addEventListener("input",()=>this.writeCaseField(i,this.input(t).value));this.caseDate=this.byId("case-date"),this.caseDate.addEventListener("datechange",t=>{const{time:i}=t.detail;this.writeCaseField("time",i?Xl.rr0TimeOf(Ao(i)):"")}),this.byId("track").addEventListener("change",()=>{const t=this.session?this.items(this.session)[Number(this.byId("track").value)]:void 0;t&&(t.interview?this.showInterview(t.interview):this.showTrack(t.track))});const e=this.input("recording-id");e.addEventListener("input",()=>this.writeRecordingId()),e.addEventListener("blur",()=>{this.showRecordingIdError(void 0),this.refreshRow()});for(const t of this.shadow.querySelectorAll("#case-tabs .group-tab"))t.addEventListener("click",()=>this.openGroup(t.getAttribute("aria-controls")==="group-case-file"?"file":"events"));this.byId("import-file").addEventListener("change",()=>void this.importFromFile()),this.byId("import-url-button").addEventListener("click",()=>void this.importFromUrl()),this.byId("add").addEventListener("click",()=>this.askAdd()),this.byId("make-case").addEventListener("click",()=>this.makeCase()),this.byId("delete").addEventListener("click",()=>this.askDelete()),this.byId("export").addEventListener("click",()=>this.askExport()),this.byId("source").addEventListener("change",()=>this.syncSourceFields()),this.byId("kind").addEventListener("change",()=>this.syncSourceFields()),this.byId("of").addEventListener("change",()=>this.syncSourceFields()),this.byId("cancel").addEventListener("click",()=>this.closeDialog()),this.byId("dialog").addEventListener("close",()=>{this.pendingLoad=void 0}),this.byId("form").addEventListener("submit",t=>{t.preventDefault(),this.submitDialog()})}static get observedAttributes(){return["src"]}attributeChangedCallback(e,t,i){e==="src"&&i&&this.editor.setAttribute("src",i)}warnBeforeLeaving=e=>{this.leaving||!this.dirty||(e.preventDefault(),e.returnValue="")};disconnectedCallback(){document.removeEventListener("click",this.askBeforeFollowing,!0),window.removeEventListener("beforeunload",this.warnBeforeLeaving),window.clearTimeout(this.dirtyTimer)}get dirty(){return this.session?(this.commit(),this.session.dirty):this.editor.dirty}scheduleDirtyCheck(){window.clearTimeout(this.dirtyTimer),this.dirtyTimer=window.setTimeout(()=>this.refreshDirty(),600)}refreshDirty(){const e=this.session;e&&this.commit(),this.byId("dirty").hidden=!(e&&e.dirty);const t=e?this.current!==void 0&&e.changed(this.current):this.editor.dirty;this.byId("recording-dirty").hidden=!t}leaving=!1;askBeforeFollowing=e=>{if(e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;const t=e.composedPath().find(n=>n instanceof HTMLAnchorElement);if(!t||!t.href||t.target&&t.target!=="_self"||t.hasAttribute("download"))return;const i=new URL(t.href,location.href);i.href===location.href||i.origin===location.origin&&i.pathname===location.pathname&&i.search===location.search&&i.hash!==""||this.dirty&&(e.preventDefault(),e.stopPropagation(),this.pendingLoad=()=>{this.leaving=!0,location.assign(i.href)},this.openDialog("discard",this.messages.discardTitle,this.messages.leaveQuestion,this.messages.leaveOk))};connectedCallback(){document.addEventListener("click",this.askBeforeFollowing,!0),window.addEventListener("beforeunload",this.warnBeforeLeaving);const e=this.getAttribute("src");e&&this.editor.getAttribute("src")!==e&&this.editor.setAttribute("src",e),this.loadLocale()}get sightingData(){return this.editor.sightingData}set sightingData(e){this.closeCase(),this.editor.sightingData=e}get sightingEditor(){return this.editor}get caseSession(){return this.session}byId(e){return this.shadow.getElementById(e)}async loadLocale(){const e=++this.localeToken,t=Is.preferencesFor(this),i=yh(t,Sh),[n,s]=i==="en"?[rg,ka]:await Promise.all([RS(i),NM(i)]);e===this.localeToken&&(this.said=new zn(t),this.language=i,this.messages=n,this.caseDate.messages=s,this.editorMessages=s,this.applyMessages(),this.refreshRow())}applyMessages(){const e=this.messages,t=(s,r)=>{this.byId(s).textContent=r};t("case-heading",e.caseHeading),t("label-case-id",e.caseId),t("label-case-title",e.caseTitle),t("label-case-time",e.caseTime),t("label-events-group",e.eventsTab),t("label-case-file-group",e.fileTab),t("label-import-file",e.importFile),t("label-import-url",e.importUrl),t("import-url-button",e.importButton),this.byId("track").setAttribute("aria-label",e.event),t("label-kind",e.kindField),t("label-witness",e.witnessField),t("label-medium",e.mediumField),t("label-recording-id",e.recordingId),t("make-case",e.addToCase);for(const s of["dirty","recording-dirty"])this.byId(s).title=e.unsavedChanges,this.byId(s).setAttribute("aria-label",e.unsavedChanges);t("add","+"),t("export",e.exportButton),t("label-export-recordings",e.exportAlso),t("label-title",e.titleField),t("label-author",e.authorField),t("label-date",e.caseTime),t("label-of",e.interpretationOf),t("label-source",e.sourceField),t("label-observer",e.observerField),t("label-file",e.fileField),t("label-url",e.urlField),t("ok",e.ok),t("cancel",e.cancel);const i=this.byId("source");[e.sourceBlank,e.sourceFile,e.sourceUrl].forEach((s,r)=>{i.options[r].textContent=s});const n=this.byId("kind");[e.kindObservation,e.kindInterview].forEach((s,r)=>{n.options[r].textContent=s}),this.byId("add").title=e.addHint,this.byId("add").setAttribute("aria-label",e.addHint),this.byId("delete").title=e.deleteRecording,this.byId("delete").setAttribute("aria-label",e.deleteRecording)}openGroup(e){this.group=e;for(const t of this.shadow.querySelectorAll("#case-tabs .group-tab"))t.setAttribute("aria-expanded",String(t.getAttribute("aria-controls")===(e==="file"?"group-case-file":"group-events")));e==="file"?this.loadFileEditor().then(()=>this.syncFileEditor(),()=>this.showFileNote(this.messages.loadFailed)):this.leaveFile(),this.refreshRow()}applySections(){const e=this.session,t=e===void 0||this.group==="events";this.byId("events-row").hidden=e===void 0,this.byId("group-events").hidden=!t,this.byId("group-case-file").hidden=e===void 0||this.group!=="file",this.byId("recording").hidden=this.currentInterview!==void 0,this.byId("interview-section").hidden=this.currentInterview===void 0}showFileNote(e){const t=this.byId("case-file-note");t.textContent=e??"",t.hidden=e===void 0}fileText(){return this.session?JSON.stringify(this.session.json,null,2)+`
10202
- `:""}loadFileEditor(){return this.fileEditorLoading??=(async()=>{this.showFileNote(this.messages.fileLoading);try{const[{SightingFileEditor:e},{default:t}]=await Promise.all([_e(()=>import("./SightingFileEditor-C0NC8jbz.js"),__vite__mapDeps([6,7]),import.meta.url),_e(()=>import("./caseSchema-BDFgjA8v.js"),[],import.meta.url)]),i=this.fileText();return this.fileApplied=i,this.fileEditor=new e(this.byId("case-file-editor"),i,n=>this.onFileEdited(n),this.editorMessages.fileEditorLabel,{baseline:i,phrases:this.editorMessages.fileSearchPhrases,schema:t}),this.fileEditor}catch(e){throw this.fileEditorLoading=void 0,e}finally{this.showFileNote(void 0)}})(),this.fileEditorLoading}syncFileEditor(){if(!this.fileEditor||!this.session)return;this.commit();const e=this.fileText();this.fileApplied=e,this.fileEditor.replaceText(e,!1),this.showFileNote(void 0)}onFileEdited(e){const t=this.session;if(!t)return;if(e===this.fileApplied){this.showFileNote(void 0);return}let i;try{i=JSON.parse(e)}catch{this.showFileNote(this.messages.fileInvalid);return}if(!Ci.isCase(i)){this.showFileNote(this.messages.fileInvalid);return}this.fileApplied=e,this.showFileNote(void 0),JSON.stringify(i)!==JSON.stringify(t.json)&&(t.replaceJson(i),this.current&&!t.tracks.includes(this.current)&&(this.current=void 0),this.currentInterview&&!t.interviews.includes(this.currentInterview)&&(this.currentInterview=void 0),this.refreshRow(),this.scheduleDirtyCheck())}leaveFile(){const e=this.session;if(e)if(this.current===void 0&&this.currentInterview===void 0){const t=e.tracks.find(i=>i.kind==="observer")??e.tracks[0];t&&this.showTrack(t)}else this.currentInterview&&(this.interviewElement.event=this.currentInterview)}guarded(e){if(!this.dirty){e();return}this.pendingLoad=e,this.openDialog("discard",this.messages.discardTitle,this.messages.discardQuestion)}async importFromFile(){const e=this.input("import-file"),t=e.files?.[0];if(t){try{const i=JSON.parse(await t.text());this.guarded(()=>void this.importCase(i,new URL("case.json",location.href).href))}catch{this.showFileNote(this.messages.loadFailed)}e.value=""}}async importFromUrl(){const e=this.input("import-url").value.trim();if(e!=="")try{const t=new URL(e,location.href).href,i=await ho.json(t);this.guarded(()=>void this.importCase(i,t))}catch{this.showFileNote(this.messages.loadFailed)}}async importCase(e,t){if(!Ci.isCase(e)){this.showFileNote(this.messages.fileNotACase);return}try{await this.openCase(e,t)}catch{this.showFileNote(this.messages.fileNotACase);return}this.syncFileEditor(),this.showFileNote(void 0)}async openCase(e,t){const i=new xh(e,t);if(i.tracks.length===0)throw new Error("A case with no recording has nothing to edit");this.session=i,this.current=void 0;const n=this.getAttribute("track"),s=n?new URL(n,t).href:void 0,r=i.tracks.find(a=>a.url===s)??i.tracks.find(a=>a.kind==="observer")??i.tracks[0];await this.showTrack(r)}closeCase(){this.session&&(this.session=void 0,this.current=void 0,this.currentInterview=void 0,this.editor.reading=!1,this.editor.accountShapeIds=void 0,this.refreshRow())}commit(){this.session&&this.current&&this.editor.edited&&this.session.keep(this.current,this.editor.sightingData)}async loadTrack(e){e.recording||(e.recording=await ho.json(e.url),e.loaded=JSON.stringify(e.recording))}async showTrack(e){const t=this.session;if(t){this.commit(),this.currentInterview=void 0,this.byId("passages").hidden=!0;try{const i=!e.recording;await this.loadTrack(e);const n=t.accountOf(e);n&&await this.loadTrack(n),this.current=e,this.editor.documentUrl=e.base?e.base.url:e.url,this.editor.reading=e.kind==="reading",this.editor.accountShapeIds=e.kind==="reading"&&n?.recording?Xl.shapesOf(n.recording):void 0,this.editor.sightingData=structuredClone(e.recording),i&&t.keep(e,this.editor.sightingData,!0),n&&n.loaded===void 0&&t.keep(n,n.recording,!0)}catch{this.showError(this.messages.loadFailed)}this.refreshRow(),this.showPassages(e)}}passagesToken=0;async transcriptOf(e){const t=this.session;if(t)try{const i=t.transcriptText(e);if(i!==void 0)return JSON.parse(i);if(e.url)return await ho.json(new URL(e.url,t.url??location.href).href)}catch{}}async showPassages(e){const t=this.session,i=this.byId("passages"),n=++this.passagesToken;if(i.hidden=!0,!t||e.kind!=="observer"||t.interviews.length===0)return;const{InterviewFile:s}=await _e(async()=>{const{InterviewFile:c}=await import("./interviewJson-CfwBPiuG.js");return{InterviewFile:c}},[],import.meta.url);if(n!==this.passagesToken)return;const r=e.event.id??t.proposedId(e),a=[];for(const c of t.interviews){const h=await this.transcriptOf(c);if(!h||!Array.isArray(h.segments))continue;const d={...h,interviewOf:h.interviewOf??c.interviewOf};for(const u of s.passagesAbout(d,r))a.push({interview:c,json:h,passage:u})}if(n!==this.passagesToken||this.current!==e||a.length===0)return;this.byId("passages-list").replaceChildren(...a.sort((c,h)=>c.passage.at-h.passage.at).map(({interview:c,json:h,passage:d})=>{const u=document.createElement("li"),p=document.createElement("button");p.type="button",p.className="at",p.textContent=`▶ ${s.clock(d.at,!0)}`,p.addEventListener("click",()=>this.editor.seekTo(d.at));const f=document.createElement("button");f.type="button",f.className="excerpt";const m=this.items(t).findIndex(M=>M.interview===c),v=`${this.messages.passagesHeading} ${this.optionLabel({interview:c},m)}`,b=d.text===void 0?"":d.range?d.text.slice(d.range[0],d.range[1]):d.text;return f.textContent=b===""?v:`${s.speakerName(h,d.speaker)} : « ${b.length>120?`${b.slice(0,117)}…`:b} »`,f.title=v,f.addEventListener("click",()=>{this.showInterview(c).then(()=>this.interviewElement.revealSegment(d.index))}),u.append(p,f),u})),i.hidden=!1}async followToObservation(e){const t=this.session;if(!t)return;const i=t.tracks.find(n=>n.kind==="observer"&&(n.event.id??t.proposedId(n))===e.sighting)??t.tracks.find(n=>n.kind==="observer");i&&(await this.showTrack(i),this.editor.seekTo(e.at),this.editor.showRender())}static shapesOf(e){const t=new Set;for(const i of e.timeline?.keyframes??[])for(const n of i.shapes??[])t.add(n.sourceId);return[...t]}items(e){return[...e.tracks.map(t=>({track:t})),...e.interviews.map(t=>({interview:t}))]}optionLabel(e,t){const i=this.session;if(e.interview){const r=i.intervieweesOf(e.interview),a=r.length>0?r.map(l=>this.labelOf(l,i.tracks.indexOf(l))).join(", "):this.said.read(e.interview.title);return a?`${this.messages.interviewOf} ${a}`:this.messages.untitledInterview.replace("{n}",String(i.interviews.indexOf(e.interview)+1))}const n=e.track,s=this.labelOf(n,t);return n.kind==="observer"?`${this.messages.accountOf} ${s}`:s}async showInterview(e){const t=this.session;t&&(this.commit(),this.current=void 0,this.passagesToken++,this.byId("passages").hidden=!0,this.currentInterview=e,this.refreshRow(),await this.ensureInterview(),this.currentInterview===e&&(this.interviewElement.witnesses=t.tracks.filter(i=>i.kind==="observer").map(i=>({id:i.event.id??t.proposedId(i),label:this.labelOf(i,t.tracks.indexOf(i))})),this.interviewElement.documentUrl=t.url,this.interviewElement.transcriptText=t.transcriptText(e),this.interviewElement.event=e))}ensureInterview(){return this.interviewReady??=_e(async()=>{const{register:e}=await import("./InterviewEditorElement-CT26rBmp.js");return{register:e}},__vite__mapDeps([12,13,14,15]),import.meta.url).then(({register:e})=>{e(),customElements.upgrade(this.shadow)},e=>{throw this.interviewReady=void 0,e}),this.interviewReady}interviewChanged(e){const{field:t}=e,i=this.session,n=this.currentInterview;if(!(!i||!n)){t==="transcript"&&e.text!==void 0&&i.keepTranscript(n,e.text);for(const s of[n.interviewOf].flat()){const r=i.tracks.find(a=>a.kind==="observer"&&(a.event.id??i.proposedId(a))===s);r&&i.ensureId(r)}i.touch(),this.refreshRow(),this.scheduleDirtyCheck()}}labelOf(e,t){const i=this.said.read(e.event.title)??this.said.read(e.recording?.interpretation?.title);if(i)return i;if(e.kind==="observer")return this.said.read(e.recording?.observer?.title)??e.event.url??"";const n=this.session.tracks.filter(s=>s.kind==="reading").indexOf(e)+1;return this.messages.untitledReading.replace("{n}",String(n||t+1))}makeCase(){if(this.session)return;const e=this.editor.sightingData,t=e.time?Xl.rr0TimeOf(Ao(e.time)):void 0,i=this.said.read(e.observer?.title),n=this.getAttribute("src")?new URL(this.getAttribute("src"),location.href).href:void 0;this.session=xh.around(e,t,i,n,location.href),this.current=this.session.tracks[0],this.session.keep(this.current,e),this.dateModeFor=void 0,this.refreshRow()}writeCaseField(e,t){const i=this.session?.json;i&&(t.trim()===""?delete i[e]:i[e]=t,this.session?.touch(),this.scheduleDirtyCheck())}static rr0TimeOf(e){return e.replace(/^(\d{4}-\d\d-\d\d)T/,"$1 ")}static edtfOf(e){return e.replace(/^(\d{4}-\d\d-\d\d) (?=\d)/,"$1T")}showCaseTime(e){const t=String(e.json.time??""),i=t===""?void 0:eu(Xl.edtfOf(t));if(this.caseDate.time=i,t!==""&&!i){const n=this.input("case-time");n.value=t}this.dateModeFor!==e&&(this.caseDate.setPrecise(!(t!==""&&!i)&&ln.opensPrecise(i)),this.dateModeFor=e)}refreshRow(){const e=this.session;if(this.applySections(),this.byId("case-panel").hidden=e===void 0,this.byId("make-case-row").hidden=e!==void 0,this.byId("case").classList.toggle("in-case",e!==void 0),this.byId("recording").classList.toggle("in-case",e!==void 0),this.byId("interview-section").classList.toggle("in-case",e!==void 0),!e){this.refreshDirty();return}const t=this.shadow.activeElement;for(const[r,a]of[["case-id","id"],["case-title","title"]]){const l=this.input(r);l!==t&&(l.value=String(e.json[a]??""))}t?.closest?.("rr0-date-input")||this.showCaseTime(e);const i=this.byId("track"),n=this.items(e);i.replaceChildren(...n.map((r,a)=>new Option(this.optionLabel(r,a),String(a))));const s=this.currentInterview?n.findIndex(r=>r.interview===this.currentInterview):this.current?n.findIndex(r=>r.track===this.current):0;i.value=String(Math.max(0,s)),this.byId("delete").hidden=this.currentInterview===void 0&&e.tracks.length<=1,this.refreshRecordingId(e),this.refreshDirty()}refreshRecordingId(e){const t=this.current,i=t!==void 0&&t.kind==="observer";if(this.byId("row-recording-id").hidden=!i,i){const l=this.input("recording-id");this.shadow.activeElement!==l&&(l.value=t.event.id??""),l.placeholder=e.proposedId(t)}const{duplicateIds:n,unresolved:s}=e.problems(),r=[...n.map(l=>this.messages.idDuplicated.replace("{id}",l)),...s.map(({reference:l})=>this.messages.readingUnresolved.replace("{id}",l))],a=this.byId("case-problems");a.hidden=r.length===0,a.textContent=r.join(" ")}showRecordingIdError(e){const t=this.byId("recording-id-error");t.textContent=e??"",t.hidden=e===void 0}writeRecordingId(){const e=this.session,t=this.current;if(!e||!t)return;const i=e.setId(t,this.input("recording-id").value.trim());this.showRecordingIdError(i==="ok"?void 0:{empty:this.messages.idNeeded,invalid:this.messages.idInvalid,taken:this.messages.idTaken}[i]),this.scheduleDirtyCheck()}get dialog(){return this.byId("dialog")}openDialog(e,t,i,n){this.dialogMode=e,this.byId("dialog-title").textContent=t;const s=this.byId("dialog-message");s.textContent=i??"",s.hidden=i===void 0,this.showError(void 0),this.byId("fields-add").hidden=e!=="add",this.byId("fields-export").hidden=e!=="export",this.byId("ok").hidden=!1,this.byId("ok").textContent=n??(e==="discard"?this.messages.discardOk:this.messages.ok),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open","")}closeDialog(){this.pendingLoad=void 0,typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}showError(e){const t=this.byId("dialog-error");t.textContent=e??"",t.hidden=e===void 0}input(e){return this.byId(e)}today(){return new Date().toISOString().slice(0,10)}askAdd(){const e=this.session;if(!e)return;this.openDialog("add",this.messages.addTitle);const t=this.byId("of");t.replaceChildren(new Option(this.messages.interpretationOfNone,""),...e.tracks.filter(n=>n.kind==="observer").map(n=>new Option(this.labelOf(n,e.tracks.indexOf(n)),String(e.tracks.indexOf(n))))),t.value="",this.byId("kind").value="observation";const i=e.tracks.filter(n=>n.kind==="observer");this.byId("witness").replaceChildren(...i.map(n=>new Option(this.labelOf(n,e.tracks.indexOf(n)),String(e.tracks.indexOf(n))))),this.byId("medium").replaceChildren(),this.byId("source").value="blank";for(const n of["observer","title","author","file","url"])this.input(n).value="";this.input("date").value="",this.syncSourceFields()}async fillMedia(){const{InterviewMedia:e}=await _e(async()=>{const{InterviewMedia:i}=await import("./InterviewMedia-CvAxC62V.js");return{InterviewMedia:i}},[],import.meta.url),t=this.byId("medium");t.options.length>0||t.replaceChildren(...e.ALL.map(i=>new Option(e.label(i,this.language),i)))}syncSourceFields(){const e=this.byId("kind").value==="interview",t=this.byId("source").value,i=!e&&this.byId("of").value!=="";this.byId("row-source").hidden=e,this.byId("row-of").hidden=e,this.byId("row-witness").hidden=!e,this.byId("row-medium").hidden=!e,e&&this.fillMedia(),this.byId("row-file").hidden=e||t!=="file",this.byId("row-url").hidden=e||t!=="url",this.byId("row-observer").hidden=e||i,this.byId("row-title").hidden=!(e||i),this.byId("row-author").hidden=!(e||i),this.byId("label-title").textContent=e?this.messages.plainTitleField:this.messages.titleField,this.byId("label-author").textContent=e?this.messages.interviewerField:this.messages.authorField}askExport(){this.session&&(this.openDialog("export",this.messages.exportTitle),this.input("export-recordings").checked=!0)}askDelete(){const e=this.session;if(e&&this.currentInterview){this.openDialog("delete",this.messages.deleteRecording,this.messages.deleteInterviewQuestion);return}const t=this.current;if(!(!e||!t)){if(t.kind==="observer"){const i=e.readingsOf(t).length;if(i>0){this.openDialog("delete",this.messages.deleteRecording,this.messages.deleteRefused.replace("{n}",String(i))),this.byId("ok").hidden=!0;return}}this.openDialog("delete",this.messages.deleteRecording,t.kind==="reading"?this.messages.deleteReadingQuestion:this.messages.deleteObservationQuestion)}}async submitDialog(){switch(this.dialogMode){case"delete":this.closeDialog(),this.deleteCurrent();return;case"discard":{const e=this.pendingLoad;this.closeDialog(),e?.();return}case"export":await this.exportCase(this.input("export-recordings").checked)?this.closeDialog():this.showError(this.messages.loadFailed);return;case"add":await this.addRecording()&&this.closeDialog()}}async addRecording(){const e=this.session;if(!e)return!1;if(this.commit(),this.byId("kind").value==="interview"){const u=e.tracks[Number(this.byId("witness").value)],p=this.input("title").value.trim(),f=this.input("author").value.trim(),g=e.addInterview(u,this.input("date").value||this.today(),p!==""?p:void 0,f!==""?f.split(",").map(m=>({people:m.trim()})).filter(m=>m.people!==""):void 0,this.byId("medium").value);return await this.showInterview(g),!0}const t=this.byId("of").value,i=t===""?void 0:e.tracks[Number(t)],n=this.byId("source").value;if(i&&n==="blank"){if(i.kind!=="observer"||!i.recording)return!1;const u=this.input("title").value.trim(),p=this.input("author").value.trim(),f=e.addReading(i,this.input("date").value||this.today(),u!==""?u:void 0,p!==""?[{title:p}]:void 0);return this.showTrack(f),!0}const s=this.input("observer").value.trim(),r=this.input("date").value.trim();let a;try{if(n==="blank"){const u=(s||"observation").replace(/[^A-Za-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation";a={version:1,id:`${r?`${r}-`:""}${u}`,...s?{observer:{title:s}}:{},...r?{time:r}:{},timeline:{keyframes:[],order:[],groups:[]}}}else{const u=n==="file"?await this.readFile():await ho.json(this.input("url").value.trim());if(Ci.isCase(u))return this.showError(this.messages.isACase),!1;a=u,s&&!a.observer?.title&&(a={...a,observer:{...a.observer,title:s}})}}catch{return this.showError(this.messages.loadFailed),!1}const l=(i?this.input("title").value:s).trim(),c=l!==""?l:this.said.read(a.observer?.title),h=this.input("author").value.trim(),d=e.addObservation(a,r!==""?r:void 0,c,i?{account:i,by:h!==""?[{title:h}]:void 0}:void 0);return this.showTrack(d),!0}async readFile(){const e=this.input("file").files?.[0];if(!e)throw new Error("No file");const t=await new Promise((i,n)=>{const s=new FileReader;s.onload=()=>i(s.result),s.onerror=()=>n(s.error),s.readAsText(e)});return JSON.parse(t)}deleteCurrent(){const e=this.session,t=this.currentInterview;if(e&&t){if(!e.deleteInterview(t))return;this.currentInterview=void 0;const r=e.tracks.find(a=>a.kind==="observer")??e.tracks[0];r&&this.showTrack(r);return}const i=this.current;if(!e||!i)return;const n=i.kind==="reading"?e.accountOf(i)??e.tracks.find(r=>r.kind==="observer"):e.tracks.find(r=>r!==i);(i.kind==="reading"?e.deleteReading(i):e.deleteObservation(i).deleted)&&(this.current=void 0,n&&this.showTrack(n))}async exportCase(e=!0){const t=this.session;if(!t)return!0;if(this.commit(),e)try{for(const a of t.tracks)await this.loadTrack(a)}catch{return!1}const i=t.files(e,!0);if(t.markExported(e),this.fileEditor?.markSaved(),this.refreshDirty(),i.length===1)return this.download(new Blob([i[0].content],{type:"application/json"}),i[0].path),!0;const{zipSync:n,strToU8:s}=await _e(async()=>{const{zipSync:a,strToU8:l}=await import("./browser-_Ncw3Jhn.js");return{zipSync:a,strToU8:l}},[],import.meta.url),r={};for(const a of i)r[a.path]=s(a.content);return this.download(new Blob([n(r)],{type:"application/zip"}),`${t.json.id??"case"}.zip`),!0}download(e,t){const i=URL.createObjectURL(e),n=document.createElement("a");n.href=i,n.download=t,n.click(),URL.revokeObjectURL(i)}}function cL(){G2(),customElements.get(bM)||customElements.define(bM,Xl)}cL();export{IL as $,Oo as A,k2 as B,sy as C,kl as D,Im as E,ts as F,Lt as G,Is as H,yS as I,D as J,Lm as K,St as L,Se as M,gh as N,Ll as O,Gs as P,ps as Q,Et as R,zn as S,As as T,Sh as U,Ls as V,UD as W,Ji as X,TL as Y,bt as Z,_e as _,ho as a,TC as a$,ep as a0,wL as a1,Dt as a2,dr as a3,rA as a4,we as a5,ye as a6,xt as a7,DL as a8,ct as a9,yL as aA,Dn as aB,z1 as aC,ui as aD,SL as aE,_L as aF,Tw as aG,Mr as aH,Jh as aI,ef as aJ,ZE as aK,gt as aL,ei as aM,Wo as aN,Vm as aO,ki as aP,Dr as aQ,iA as aR,Zt as aS,vL as aT,bL as aU,Dw as aV,ML as aW,Ks as aX,Iw as aY,J1 as aZ,Z3 as a_,gL as aa,ne as ab,uE as ac,lt as ad,x0 as ae,hs as af,lu as ag,Qr as ah,Lc as ai,yt as aj,rt as ak,Vn as al,Hn as am,EL as an,Na as ao,Yi as ap,pL as aq,mL as ar,fL as as,Hh as at,AL as au,xL as av,lA as aw,Zu as ax,hn as ay,Uw as az,vS as b,Yu as b0,M0 as b1,un as b2,Nw as b3,Pg as b4,Ng as b5,_t as b6,Ua as b7,zh as b8,NM as c,Ns as d,ci as e,at as f,uL as g,Pa as h,tu as i,hL as j,Dm as k,dL as l,Pn as m,fs as n,qk as o,av as p,Zf as q,Xs as r,yh as s,Ue as t,Mt as u,Ea as v,dn as w,Jr as x,Tr as y,SA as z};
10202
+ `:""}loadFileEditor(){return this.fileEditorLoading??=(async()=>{this.showFileNote(this.messages.fileLoading);try{const[{SightingFileEditor:e},{default:t}]=await Promise.all([_e(()=>import("./SightingFileEditor-C0NC8jbz.js"),__vite__mapDeps([6,7]),import.meta.url),_e(()=>import("./caseSchema-BDFgjA8v.js"),[],import.meta.url)]),i=this.fileText();return this.fileApplied=i,this.fileEditor=new e(this.byId("case-file-editor"),i,n=>this.onFileEdited(n),this.editorMessages.fileEditorLabel,{baseline:i,phrases:this.editorMessages.fileSearchPhrases,schema:t}),this.fileEditor}catch(e){throw this.fileEditorLoading=void 0,e}finally{this.showFileNote(void 0)}})(),this.fileEditorLoading}syncFileEditor(){if(!this.fileEditor||!this.session)return;this.commit();const e=this.fileText();this.fileApplied=e,this.fileEditor.replaceText(e,!1),this.showFileNote(void 0)}onFileEdited(e){const t=this.session;if(!t)return;if(e===this.fileApplied){this.showFileNote(void 0);return}let i;try{i=JSON.parse(e)}catch{this.showFileNote(this.messages.fileInvalid);return}if(!Ci.isCase(i)){this.showFileNote(this.messages.fileInvalid);return}this.fileApplied=e,this.showFileNote(void 0),JSON.stringify(i)!==JSON.stringify(t.json)&&(t.replaceJson(i),this.current&&!t.tracks.includes(this.current)&&(this.current=void 0),this.currentInterview&&!t.interviews.includes(this.currentInterview)&&(this.currentInterview=void 0),this.refreshRow(),this.scheduleDirtyCheck())}leaveFile(){const e=this.session;if(e)if(this.current===void 0&&this.currentInterview===void 0){const t=e.tracks.find(i=>i.kind==="observer")??e.tracks[0];t&&this.showTrack(t)}else this.currentInterview&&(this.interviewElement.event=this.currentInterview)}guarded(e){if(!this.dirty){e();return}this.pendingLoad=e,this.openDialog("discard",this.messages.discardTitle,this.messages.discardQuestion)}async importFromFile(){const e=this.input("import-file"),t=e.files?.[0];if(t){try{const i=JSON.parse(await t.text());this.guarded(()=>void this.importCase(i,new URL("case.json",location.href).href))}catch{this.showFileNote(this.messages.loadFailed)}e.value=""}}async importFromUrl(){const e=this.input("import-url").value.trim();if(e!=="")try{const t=new URL(e,location.href).href,i=await ho.json(t);this.guarded(()=>void this.importCase(i,t))}catch{this.showFileNote(this.messages.loadFailed)}}async importCase(e,t){if(!Ci.isCase(e)){this.showFileNote(this.messages.fileNotACase);return}try{await this.openCase(e,t)}catch{this.showFileNote(this.messages.fileNotACase);return}this.syncFileEditor(),this.showFileNote(void 0)}async openCase(e,t){const i=new xh(e,t);if(i.tracks.length===0)throw new Error("A case with no recording has nothing to edit");this.session=i,this.current=void 0;const n=this.getAttribute("track"),s=n?new URL(n,t).href:void 0,r=i.tracks.find(a=>a.url===s)??i.tracks.find(a=>a.kind==="observer")??i.tracks[0];await this.showTrack(r)}closeCase(){this.session&&(this.session=void 0,this.current=void 0,this.currentInterview=void 0,this.editor.reading=!1,this.editor.accountShapeIds=void 0,this.refreshRow())}commit(){this.session&&this.current&&this.editor.edited&&this.session.keep(this.current,this.editor.sightingData)}async loadTrack(e){e.recording||(e.recording=await ho.json(e.url),e.loaded=JSON.stringify(e.recording))}async showTrack(e){const t=this.session;if(t){this.commit(),this.currentInterview=void 0,this.byId("passages").hidden=!0;try{const i=!e.recording;await this.loadTrack(e);const n=t.accountOf(e);n&&await this.loadTrack(n),this.current=e,this.editor.documentUrl=e.base?e.base.url:e.url,this.editor.reading=e.kind==="reading",this.editor.accountShapeIds=e.kind==="reading"&&n?.recording?Xl.shapesOf(n.recording):void 0,this.editor.sightingData=structuredClone(e.recording),i&&t.keep(e,this.editor.sightingData,!0),n&&n.loaded===void 0&&t.keep(n,n.recording,!0)}catch{this.showError(this.messages.loadFailed)}this.refreshRow(),this.showPassages(e)}}passagesToken=0;async transcriptOf(e){const t=this.session;if(t)try{const i=t.transcriptText(e);if(i!==void 0)return JSON.parse(i);if(e.url)return await ho.json(new URL(e.url,t.url??location.href).href)}catch{}}async showPassages(e){const t=this.session,i=this.byId("passages"),n=++this.passagesToken;if(i.hidden=!0,!t||e.kind!=="observer"||t.interviews.length===0)return;const{InterviewFile:s}=await _e(async()=>{const{InterviewFile:c}=await import("./interviewJson-CfwBPiuG.js");return{InterviewFile:c}},[],import.meta.url);if(n!==this.passagesToken)return;const r=e.event.id??t.proposedId(e),a=[];for(const c of t.interviews){const h=await this.transcriptOf(c);if(!h||!Array.isArray(h.segments))continue;const d={...h,interviewOf:h.interviewOf??c.interviewOf};for(const u of s.passagesAbout(d,r))a.push({interview:c,json:h,passage:u})}if(n!==this.passagesToken||this.current!==e||a.length===0)return;this.byId("passages-list").replaceChildren(...a.sort((c,h)=>c.passage.at-h.passage.at).map(({interview:c,json:h,passage:d})=>{const u=document.createElement("li"),p=document.createElement("button");p.type="button",p.className="at",p.textContent=`▶ ${s.clock(d.at,!0)}`,p.addEventListener("click",()=>this.editor.seekTo(d.at));const f=document.createElement("button");f.type="button",f.className="excerpt";const m=this.items(t).findIndex(M=>M.interview===c),v=`${this.messages.passagesHeading} ${this.optionLabel({interview:c},m)}`,b=d.text===void 0?"":d.range?d.text.slice(d.range[0],d.range[1]):d.text;return f.textContent=b===""?v:`${s.speakerName(h,d.speaker)} : « ${b.length>120?`${b.slice(0,117)}…`:b} »`,f.title=v,f.addEventListener("click",()=>{this.showInterview(c).then(()=>this.interviewElement.revealSegment(d.index))}),u.append(p,f),u})),i.hidden=!1}async followToObservation(e){const t=this.session;if(!t)return;const i=t.tracks.find(n=>n.kind==="observer"&&(n.event.id??t.proposedId(n))===e.sighting)??t.tracks.find(n=>n.kind==="observer");i&&(await this.showTrack(i),this.editor.seekTo(e.at),this.editor.showRender())}static shapesOf(e){const t=new Set;for(const i of e.timeline?.keyframes??[])for(const n of i.shapes??[])t.add(n.sourceId);return[...t]}items(e){return[...e.tracks.map(t=>({track:t})),...e.interviews.map(t=>({interview:t}))]}optionLabel(e,t){const i=this.session;if(e.interview){const r=i.intervieweesOf(e.interview),a=r.length>0?r.map(l=>this.labelOf(l,i.tracks.indexOf(l))).join(", "):this.said.read(e.interview.title);return a?`${this.messages.interviewOf} ${a}`:this.messages.untitledInterview.replace("{n}",String(i.interviews.indexOf(e.interview)+1))}const n=e.track,s=this.labelOf(n,t);return n.kind==="observer"?`${this.messages.accountOf} ${s}`:s}async showInterview(e){const t=this.session;t&&(this.commit(),this.current=void 0,this.passagesToken++,this.byId("passages").hidden=!0,this.currentInterview=e,this.refreshRow(),await this.ensureInterview(),this.currentInterview===e&&(this.interviewElement.witnesses=t.tracks.filter(i=>i.kind==="observer").map(i=>({id:i.event.id??t.proposedId(i),label:this.labelOf(i,t.tracks.indexOf(i))})),this.interviewElement.documentUrl=t.url,this.interviewElement.transcriptText=t.transcriptText(e),this.interviewElement.event=e))}ensureInterview(){return this.interviewReady??=_e(async()=>{const{register:e}=await import("./InterviewEditorElement-Dl2fhE44.js");return{register:e}},__vite__mapDeps([12,13,14,15]),import.meta.url).then(({register:e})=>{e(),customElements.upgrade(this.shadow)},e=>{throw this.interviewReady=void 0,e}),this.interviewReady}interviewChanged(e){const{field:t}=e,i=this.session,n=this.currentInterview;if(!(!i||!n)){t==="transcript"&&e.text!==void 0&&i.keepTranscript(n,e.text);for(const s of[n.interviewOf].flat()){const r=i.tracks.find(a=>a.kind==="observer"&&(a.event.id??i.proposedId(a))===s);r&&i.ensureId(r)}i.touch(),this.refreshRow(),this.scheduleDirtyCheck()}}labelOf(e,t){const i=this.said.read(e.event.title)??this.said.read(e.recording?.interpretation?.title);if(i)return i;if(e.kind==="observer")return this.said.read(e.recording?.observer?.title)??e.event.url??"";const n=this.session.tracks.filter(s=>s.kind==="reading").indexOf(e)+1;return this.messages.untitledReading.replace("{n}",String(n||t+1))}makeCase(){if(this.session)return;const e=this.editor.sightingData,t=e.time?Xl.rr0TimeOf(Ao(e.time)):void 0,i=this.said.read(e.observer?.title),n=this.getAttribute("src")?new URL(this.getAttribute("src"),location.href).href:void 0;this.session=xh.around(e,t,i,n,location.href),this.current=this.session.tracks[0],this.session.keep(this.current,e),this.dateModeFor=void 0,this.refreshRow()}writeCaseField(e,t){const i=this.session?.json;i&&(t.trim()===""?delete i[e]:i[e]=t,this.session?.touch(),this.scheduleDirtyCheck())}static rr0TimeOf(e){return e.replace(/^(\d{4}-\d\d-\d\d)T/,"$1 ")}static edtfOf(e){return e.replace(/^(\d{4}-\d\d-\d\d) (?=\d)/,"$1T")}showCaseTime(e){const t=String(e.json.time??""),i=t===""?void 0:eu(Xl.edtfOf(t));if(this.caseDate.time=i,t!==""&&!i){const n=this.input("case-time");n.value=t}this.dateModeFor!==e&&(this.caseDate.setPrecise(!(t!==""&&!i)&&ln.opensPrecise(i)),this.dateModeFor=e)}refreshRow(){const e=this.session;if(this.applySections(),this.byId("case-panel").hidden=e===void 0,this.byId("make-case-row").hidden=e!==void 0,this.byId("case").classList.toggle("in-case",e!==void 0),this.byId("recording").classList.toggle("in-case",e!==void 0),this.byId("interview-section").classList.toggle("in-case",e!==void 0),!e){this.refreshDirty();return}const t=this.shadow.activeElement;for(const[r,a]of[["case-id","id"],["case-title","title"]]){const l=this.input(r);l!==t&&(l.value=String(e.json[a]??""))}t?.closest?.("rr0-date-input")||this.showCaseTime(e);const i=this.byId("track"),n=this.items(e);i.replaceChildren(...n.map((r,a)=>new Option(this.optionLabel(r,a),String(a))));const s=this.currentInterview?n.findIndex(r=>r.interview===this.currentInterview):this.current?n.findIndex(r=>r.track===this.current):0;i.value=String(Math.max(0,s)),this.byId("delete").hidden=this.currentInterview===void 0&&e.tracks.length<=1,this.refreshRecordingId(e),this.refreshDirty()}refreshRecordingId(e){const t=this.current,i=t!==void 0&&t.kind==="observer";if(this.byId("row-recording-id").hidden=!i,i){const l=this.input("recording-id");this.shadow.activeElement!==l&&(l.value=t.event.id??""),l.placeholder=e.proposedId(t)}const{duplicateIds:n,unresolved:s}=e.problems(),r=[...n.map(l=>this.messages.idDuplicated.replace("{id}",l)),...s.map(({reference:l})=>this.messages.readingUnresolved.replace("{id}",l))],a=this.byId("case-problems");a.hidden=r.length===0,a.textContent=r.join(" ")}showRecordingIdError(e){const t=this.byId("recording-id-error");t.textContent=e??"",t.hidden=e===void 0}writeRecordingId(){const e=this.session,t=this.current;if(!e||!t)return;const i=e.setId(t,this.input("recording-id").value.trim());this.showRecordingIdError(i==="ok"?void 0:{empty:this.messages.idNeeded,invalid:this.messages.idInvalid,taken:this.messages.idTaken}[i]),this.scheduleDirtyCheck()}get dialog(){return this.byId("dialog")}openDialog(e,t,i,n){this.dialogMode=e,this.byId("dialog-title").textContent=t;const s=this.byId("dialog-message");s.textContent=i??"",s.hidden=i===void 0,this.showError(void 0),this.byId("fields-add").hidden=e!=="add",this.byId("fields-export").hidden=e!=="export",this.byId("ok").hidden=!1,this.byId("ok").textContent=n??(e==="discard"?this.messages.discardOk:this.messages.ok),typeof this.dialog.showModal=="function"?this.dialog.showModal():this.dialog.setAttribute("open","")}closeDialog(){this.pendingLoad=void 0,typeof this.dialog.close=="function"?this.dialog.close():this.dialog.removeAttribute("open")}showError(e){const t=this.byId("dialog-error");t.textContent=e??"",t.hidden=e===void 0}input(e){return this.byId(e)}today(){return new Date().toISOString().slice(0,10)}askAdd(){const e=this.session;if(!e)return;this.openDialog("add",this.messages.addTitle);const t=this.byId("of");t.replaceChildren(new Option(this.messages.interpretationOfNone,""),...e.tracks.filter(n=>n.kind==="observer").map(n=>new Option(this.labelOf(n,e.tracks.indexOf(n)),String(e.tracks.indexOf(n))))),t.value="",this.byId("kind").value="observation";const i=e.tracks.filter(n=>n.kind==="observer");this.byId("witness").replaceChildren(...i.map(n=>new Option(this.labelOf(n,e.tracks.indexOf(n)),String(e.tracks.indexOf(n))))),this.byId("medium").replaceChildren(),this.byId("source").value="blank";for(const n of["observer","title","author","file","url"])this.input(n).value="";this.input("date").value="",this.syncSourceFields()}async fillMedia(){const{InterviewMedia:e}=await _e(async()=>{const{InterviewMedia:i}=await import("./InterviewMedia-CvAxC62V.js");return{InterviewMedia:i}},[],import.meta.url),t=this.byId("medium");t.options.length>0||t.replaceChildren(...e.ALL.map(i=>new Option(e.label(i,this.language),i)))}syncSourceFields(){const e=this.byId("kind").value==="interview",t=this.byId("source").value,i=!e&&this.byId("of").value!=="";this.byId("row-source").hidden=e,this.byId("row-of").hidden=e,this.byId("row-witness").hidden=!e,this.byId("row-medium").hidden=!e,e&&this.fillMedia(),this.byId("row-file").hidden=e||t!=="file",this.byId("row-url").hidden=e||t!=="url",this.byId("row-observer").hidden=e||i,this.byId("row-title").hidden=!(e||i),this.byId("row-author").hidden=!(e||i),this.byId("label-title").textContent=e?this.messages.plainTitleField:this.messages.titleField,this.byId("label-author").textContent=e?this.messages.interviewerField:this.messages.authorField}askExport(){this.session&&(this.openDialog("export",this.messages.exportTitle),this.input("export-recordings").checked=!0)}askDelete(){const e=this.session;if(e&&this.currentInterview){this.openDialog("delete",this.messages.deleteRecording,this.messages.deleteInterviewQuestion);return}const t=this.current;if(!(!e||!t)){if(t.kind==="observer"){const i=e.readingsOf(t).length;if(i>0){this.openDialog("delete",this.messages.deleteRecording,this.messages.deleteRefused.replace("{n}",String(i))),this.byId("ok").hidden=!0;return}}this.openDialog("delete",this.messages.deleteRecording,t.kind==="reading"?this.messages.deleteReadingQuestion:this.messages.deleteObservationQuestion)}}async submitDialog(){switch(this.dialogMode){case"delete":this.closeDialog(),this.deleteCurrent();return;case"discard":{const e=this.pendingLoad;this.closeDialog(),e?.();return}case"export":await this.exportCase(this.input("export-recordings").checked)?this.closeDialog():this.showError(this.messages.loadFailed);return;case"add":await this.addRecording()&&this.closeDialog()}}async addRecording(){const e=this.session;if(!e)return!1;if(this.commit(),this.byId("kind").value==="interview"){const u=e.tracks[Number(this.byId("witness").value)],p=this.input("title").value.trim(),f=this.input("author").value.trim(),g=e.addInterview(u,this.input("date").value||this.today(),p!==""?p:void 0,f!==""?f.split(",").map(m=>({people:m.trim()})).filter(m=>m.people!==""):void 0,this.byId("medium").value);return await this.showInterview(g),!0}const t=this.byId("of").value,i=t===""?void 0:e.tracks[Number(t)],n=this.byId("source").value;if(i&&n==="blank"){if(i.kind!=="observer"||!i.recording)return!1;const u=this.input("title").value.trim(),p=this.input("author").value.trim(),f=e.addReading(i,this.input("date").value||this.today(),u!==""?u:void 0,p!==""?[{title:p}]:void 0);return this.showTrack(f),!0}const s=this.input("observer").value.trim(),r=this.input("date").value.trim();let a;try{if(n==="blank"){const u=(s||"observation").replace(/[^A-Za-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"observation";a={version:1,id:`${r?`${r}-`:""}${u}`,...s?{observer:{title:s}}:{},...r?{time:r}:{},timeline:{keyframes:[],order:[],groups:[]}}}else{const u=n==="file"?await this.readFile():await ho.json(this.input("url").value.trim());if(Ci.isCase(u))return this.showError(this.messages.isACase),!1;a=u,s&&!a.observer?.title&&(a={...a,observer:{...a.observer,title:s}})}}catch{return this.showError(this.messages.loadFailed),!1}const l=(i?this.input("title").value:s).trim(),c=l!==""?l:this.said.read(a.observer?.title),h=this.input("author").value.trim(),d=e.addObservation(a,r!==""?r:void 0,c,i?{account:i,by:h!==""?[{title:h}]:void 0}:void 0);return this.showTrack(d),!0}async readFile(){const e=this.input("file").files?.[0];if(!e)throw new Error("No file");const t=await new Promise((i,n)=>{const s=new FileReader;s.onload=()=>i(s.result),s.onerror=()=>n(s.error),s.readAsText(e)});return JSON.parse(t)}deleteCurrent(){const e=this.session,t=this.currentInterview;if(e&&t){if(!e.deleteInterview(t))return;this.currentInterview=void 0;const r=e.tracks.find(a=>a.kind==="observer")??e.tracks[0];r&&this.showTrack(r);return}const i=this.current;if(!e||!i)return;const n=i.kind==="reading"?e.accountOf(i)??e.tracks.find(r=>r.kind==="observer"):e.tracks.find(r=>r!==i);(i.kind==="reading"?e.deleteReading(i):e.deleteObservation(i).deleted)&&(this.current=void 0,n&&this.showTrack(n))}async exportCase(e=!0){const t=this.session;if(!t)return!0;if(this.commit(),e)try{for(const a of t.tracks)await this.loadTrack(a)}catch{return!1}const i=t.files(e,!0);if(t.markExported(e),this.fileEditor?.markSaved(),this.refreshDirty(),i.length===1)return this.download(new Blob([i[0].content],{type:"application/json"}),i[0].path),!0;const{zipSync:n,strToU8:s}=await _e(async()=>{const{zipSync:a,strToU8:l}=await import("./browser-_Ncw3Jhn.js");return{zipSync:a,strToU8:l}},[],import.meta.url),r={};for(const a of i)r[a.path]=s(a.content);return this.download(new Blob([n(r)],{type:"application/zip"}),`${t.json.id??"case"}.zip`),!0}download(e,t){const i=URL.createObjectURL(e),n=document.createElement("a");n.href=i,n.download=t,n.click(),URL.revokeObjectURL(i)}}function cL(){G2(),customElements.get(bM)||customElements.define(bM,Xl)}cL();export{IL as $,Oo as A,k2 as B,sy as C,kl as D,Im as E,ts as F,Lt as G,Is as H,yS as I,D as J,Lm as K,St as L,Se as M,gh as N,Ll as O,Gs as P,ps as Q,Et as R,zn as S,As as T,Sh as U,Ls as V,UD as W,Ji as X,TL as Y,bt as Z,_e as _,ho as a,TC as a$,ep as a0,wL as a1,Dt as a2,dr as a3,rA as a4,we as a5,ye as a6,xt as a7,DL as a8,ct as a9,yL as aA,Dn as aB,z1 as aC,ui as aD,SL as aE,_L as aF,Tw as aG,Mr as aH,Jh as aI,ef as aJ,ZE as aK,gt as aL,ei as aM,Wo as aN,Vm as aO,ki as aP,Dr as aQ,iA as aR,Zt as aS,vL as aT,bL as aU,Dw as aV,ML as aW,Ks as aX,Iw as aY,J1 as aZ,Z3 as a_,gL as aa,ne as ab,uE as ac,lt as ad,x0 as ae,hs as af,lu as ag,Qr as ah,Lc as ai,yt as aj,rt as ak,Vn as al,Hn as am,EL as an,Na as ao,Yi as ap,pL as aq,mL as ar,fL as as,Hh as at,AL as au,xL as av,lA as aw,Zu as ax,hn as ay,Uw as az,vS as b,Yu as b0,M0 as b1,un as b2,Nw as b3,Pg as b4,Ng as b5,_t as b6,Ua as b7,zh as b8,NM as c,Ns as d,ci as e,at as f,uL as g,Pa as h,tu as i,hL as j,Dm as k,dL as l,Pn as m,fs as n,qk as o,av as p,Zf as q,Xs as r,yh as s,Ue as t,Mt as u,Ea as v,dn as w,Jr as x,Tr as y,SA as z};